brillig_vm

Struct VM

Source
pub struct VM<'a, F, B: BlackBoxFunctionSolver<F>> {
    pub(crate) calldata: Vec<F>,
    pub(crate) program_counter: usize,
    pub(crate) foreign_call_counter: usize,
    pub(crate) foreign_call_results: Vec<ForeignCallResult<F>>,
    pub(crate) bytecode: &'a [Opcode<F>],
    pub(crate) status: VMStatus<F>,
    pub(crate) memory: Memory<F>,
    pub(crate) call_stack: Vec<usize>,
    pub(crate) black_box_solver: &'a B,
    pub(crate) profiling_active: bool,
    pub(crate) profiling_samples: BrilligProfilingSamples,
    pub(crate) fuzzing_trace: Option<FuzzingTrace>,
}
Expand description

VM encapsulates the state of the Brillig VM during execution.

Fields§

§calldata: Vec<F>

Calldata to the brillig function.

§program_counter: usize

Instruction pointer.

§foreign_call_counter: usize

A counter maintained throughout a Brillig process that determines whether the caller has resolved the results of a foreign call.

Incremented when the results of a foreign call have been processed and the output values were written to memory.

  • When the counter is less than the length of the results, it indicates that we have unprocessed responses returned from the external foreign call handler.
§foreign_call_results: Vec<ForeignCallResult<F>>

Accumulates the outputs of all foreign calls during a Brillig process. The list is appended onto by the caller upon reaching a VMStatus::ForeignCallWait.

§bytecode: &'a [Opcode<F>]

Executable opcodes.

§status: VMStatus<F>

Status of the VM.

§memory: Memory<F>

Memory of the VM.

§call_stack: Vec<usize>

Call stack.

§black_box_solver: &'a B

The solver for blackbox functions.

§profiling_active: bool§profiling_samples: BrilligProfilingSamples§fuzzing_trace: Option<FuzzingTrace>

Fuzzing trace structure. If the field is None then fuzzing is inactive.

Implementations§

Source§

impl<F: AcirField, B: BlackBoxFunctionSolver<F>> VM<'_, F, B>

Source

pub(crate) fn process_foreign_call( &mut self, function: &str, destinations: &[ValueOrArray], destination_value_types: &[HeapValueType], inputs: &[ValueOrArray], input_value_types: &[HeapValueType], ) -> &VMStatus<F>

Handles the execution of a single ForeignCall opcode.

This method performs the following steps:

  1. Checks if the foreign call results are already available. If not, it resolves the input values from memory and pauses execution by returning VMStatus::ForeignCallWait. For vectors, the preceding u32 length field is used to truncate the slice input to its semantic length.
  2. If results are available, it writes them to memory, ensuring that the returned data matches the expected types and sizes. Nested arrays are reconstructed from flat outputs when necessary. Nested vectors are an unsupported return type and will trigger an error.
  3. Increments the foreign call counter and advances the program counter.
§Parameters

The borrowed fields of a ForeignCall opcode. They are listed again below:

  • function: Name of the foreign function being called.
  • destinations: Pointers or heap structures where the return values will be written.
  • destination_value_types: Expected type layout for each destination.
  • inputs: Pointers or heap structures representing the inputs for the foreign call.
  • input_value_types: Expected type layout for each input.
§Returns
§Panics
  • If inputs and input_value_types lengths do not match.
  • If destinations and destination_value_types lengths do not match.
Source

fn get_memory_values( &self, input: ValueOrArray, value_type: &HeapValueType, ) -> ForeignCallParam<F>

Get input data from memory to pass to foreign calls.

Source

fn read_slice_of_values_from_memory( &self, start: MemoryAddress, size: usize, value_types: &[HeapValueType], ) -> Vec<MemoryValue<F>>

Reads an array/vector from memory but recursively reads pointers to nested arrays/vectors according to the sequence of value types.

Source

fn wait_for_foreign_call( &mut self, function: String, inputs: Vec<ForeignCallParam<F>>, ) -> &VMStatus<F>

Sets the status of the VM to ForeignCallWait. Indicating that the VM is now waiting for a foreign call to be resolved.

Source

fn write_foreign_call_result( &mut self, destinations: &[ValueOrArray], destination_value_types: &[HeapValueType], foreign_call_index: usize, ) -> Result<(), String>

Write a foreign call’s results to the VM memory.

We match the expected types with the actual results. However foreign call results do not support nested structures: They are either a single integer value or a vector of integer values (field elements). Therefore, nested arrays returned from foreign call results are flattened. If the expected array sizes do not match the actual size, we reconstruct the nested structure from the flat output array.

Source

fn write_value_to_memory( &mut self, destination: MemoryAddress, value: &F, value_bit_size: BitSize, ) -> Result<(), String>

Write a single numeric value to the destination address, ensuring that the bit size matches the expectation.

Source

fn write_values_to_memory( &mut self, pointer: MemoryAddress, values: &[F], value_types: &[HeapValueType], ) -> Result<(), String>

Write an array or slice to the destination under the pointer.

Source

fn write_flattened_values_to_memory( &mut self, destination: MemoryAddress, values: &Vec<F>, values_idx: &mut usize, value_type: &HeapValueType, ) -> Result<(), String>

Writes flattened values to memory, using the provided type.

The method calls itself recursively in order to work with recursive types (nested arrays). values_idx is the current index in the values vector and is incremented every time a value is written to memory.

Source§

impl<F: AcirField, B: BlackBoxFunctionSolver<F>> VM<'_, F, B>

Source

pub(crate) fn fuzzing_trace_binary_field_op_comparison( &mut self, op: &BinaryFieldOp, lhs: MemoryValue<F>, rhs: MemoryValue<F>, result: MemoryValue<F>, )

Collect information about the comparison of two field values in the fuzzing trace

Source

pub(crate) fn fuzzing_trace_binary_int_op_comparison( &mut self, op: &BinaryIntOp, lhs: MemoryValue<F>, rhs: MemoryValue<F>, result: MemoryValue<F>, )

Collect information about the comparison of two integer values in the fuzzing trace

Source

pub(crate) fn fuzzing_trace_branching( &mut self, destination: NextOpcodePositionOrState, )

Mark the execution of a particular branch in the fuzzing trace

Source

pub(crate) fn fuzzing_trace_conditional_mov(&mut self, branch: bool)

Mark the execution of a conditional move in the fuzzing trace

Source§

impl<'a, F: AcirField, B: BlackBoxFunctionSolver<F>> VM<'a, F, B>

Source

pub fn new( calldata: Vec<F>, bytecode: &'a [Opcode<F>], black_box_solver: &'a B, profiling_active: bool, with_branch_to_feature_map: Option<&BranchToFeatureMap>, ) -> Self

Constructs a new VM instance.

Source

pub fn is_profiling_active(&self) -> bool

Source

pub fn is_fuzzing_active(&self) -> bool

Source

pub fn take_profiling_samples(&mut self) -> BrilligProfilingSamples

Source

pub(crate) fn status(&mut self, status: VMStatus<F>) -> &VMStatus<F>

Updates the current status of the VM. Returns the given status.

Source

pub fn get_status(&self) -> VMStatus<F>

Source

pub(crate) fn finish( &mut self, return_data_offset: usize, return_data_size: usize, ) -> &VMStatus<F>

Sets the current status of the VM to Finished (completed execution).

Source

pub(crate) fn has_unprocessed_foreign_call_result(&self) -> bool

Check whether the latest foreign call result is available yet.

Source

pub fn resolve_foreign_call( &mut self, foreign_call_result: ForeignCallResult<F>, )

Provide the results of a Foreign Call to the VM and resume execution of the VM.

Source

pub(crate) fn trap( &mut self, revert_data_offset: usize, revert_data_size: usize, ) -> &VMStatus<F>

Sets the current status of the VM to Failure, indicating that the VM encountered a Trap Opcode.

Source

pub(crate) fn fail(&mut self, message: String) -> &VMStatus<F>

Sets the current status of the VM to Failure, indicating that the VM encountered an invalid state.

Source

pub fn process_opcodes(&mut self) -> VMStatus<F>

Process opcodes in a loop until a status of Finished, Failure or ForeignCallWait is encountered.

Source

pub fn get_memory(&self) -> &[MemoryValue<F>]

Read memory slots.

Used by the debugger to inspect the contents of the memory.

Source

pub fn take_memory(self) -> Memory<F>

Take all the contents of the memory, leaving it empty.

Used only for testing purposes.

Source

pub fn foreign_call_counter(&self) -> usize

Source

pub fn write_memory_at(&mut self, ptr: usize, value: MemoryValue<F>)

Write a numeric value to direct memory slot.

Used by the debugger to alter memory.

Source

pub fn get_call_stack(&self) -> Vec<usize>

Returns the VM’s current call stack, including the actual program counter in the last position of the returned vector.

Source

pub fn get_call_stack_no_current_counter(&self) -> Vec<usize>

Returns the VM’s call stack, but unlike Self::get_call_stack without the attaching the program counter in the last position of the returned vector. This is meant only for fetching the call stack after execution has completed.

Source

pub fn process_opcode(&mut self) -> &VMStatus<F>

Process a single opcode and modify the program counter.

Source

pub fn get_fuzzing_trace(&self) -> Vec<u32>

Source

pub(crate) fn process_opcode_internal(&mut self) -> &VMStatus<F>

Execute a single opcode:

  1. Retrieve the current opcode using the program counter
  2. Execute the opcode.
    • For instance a binary ‘result = lhs+rhs’ opcode will read the VM memory at the ‘lhs’ and ‘rhs’ addresses, compute the sum and write it to the ‘result’ memory address.
  3. Update the program counter, usually by incrementing it.
  • Control flow opcodes jump around the bytecode by setting the program counter.
  • Foreign call opcodes pause the VM until the foreign call results are available.
  • Function call opcodes backup the current program counter into the call stack and jump to the function entry point. The stack frame for function calls is handled during codegen.
Source

pub fn program_counter(&self) -> usize

Returns the current value of the program counter.

Source

pub(crate) fn increment_program_counter(&mut self) -> &VMStatus<F>

Increments the program counter by 1.

Source

pub(crate) fn set_program_counter(&mut self, value: usize) -> &VMStatus<F>

Sets the program counter to value. If the program counter no longer points to an opcode in the bytecode, then the VMStatus reports Finished.

Source

pub(crate) fn process_binary_field_op( &mut self, op: BinaryFieldOp, lhs: MemoryAddress, rhs: MemoryAddress, result: MemoryAddress, ) -> Result<(), BrilligArithmeticError>

Process a binary field operation. This method will not modify the program counter.

Source

pub(crate) fn process_binary_int_op( &mut self, op: BinaryIntOp, bit_size: IntegerBitSize, lhs: MemoryAddress, rhs: MemoryAddress, result: MemoryAddress, ) -> Result<(), BrilligArithmeticError>

Process a binary integer operation. This method will not modify the program counter.

Source

pub(crate) fn process_not( &mut self, source: MemoryAddress, destination: MemoryAddress, op_bit_size: IntegerBitSize, ) -> Result<(), MemoryTypeError>

Process a unary negation operation.

It returns MemoryTypeError if the value type does not match the type indicated by op_bit_size.

Trait Implementations§

Source§

impl<'a, F: Clone, B: Clone + BlackBoxFunctionSolver<F>> Clone for VM<'a, F, B>

Source§

fn clone(&self) -> VM<'a, F, B>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a, F: Debug, B: Debug + BlackBoxFunctionSolver<F>> Debug for VM<'a, F, B>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a, F: PartialEq, B: PartialEq + BlackBoxFunctionSolver<F>> PartialEq for VM<'a, F, B>

Source§

fn eq(&self, other: &VM<'a, F, B>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, F: Eq, B: Eq + BlackBoxFunctionSolver<F>> Eq for VM<'a, F, B>

Source§

impl<'a, F, B: BlackBoxFunctionSolver<F>> StructuralPartialEq for VM<'a, F, B>

Auto Trait Implementations§

§

impl<'a, F, B> Freeze for VM<'a, F, B>

§

impl<'a, F, B> RefUnwindSafe for VM<'a, F, B>

§

impl<'a, F, B> Send for VM<'a, F, B>
where B: Sync, F: Send + Sync,

§

impl<'a, F, B> Sync for VM<'a, F, B>
where B: Sync, F: Sync,

§

impl<'a, F, B> Unpin for VM<'a, F, B>
where F: Unpin,

§

impl<'a, F, B> UnwindSafe for VM<'a, F, B>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<D> OwoColorize for D

§

fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>
where C: Color,

Set the foreground color generically Read more
§

fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>
where C: Color,

Set the background color generically. Read more
§

fn black(&self) -> FgColorDisplay<'_, Black, Self>

Change the foreground color to black
§

fn on_black(&self) -> BgColorDisplay<'_, Black, Self>

Change the background color to black
§

fn red(&self) -> FgColorDisplay<'_, Red, Self>

Change the foreground color to red
§

fn on_red(&self) -> BgColorDisplay<'_, Red, Self>

Change the background color to red
§

fn green(&self) -> FgColorDisplay<'_, Green, Self>

Change the foreground color to green
§

fn on_green(&self) -> BgColorDisplay<'_, Green, Self>

Change the background color to green
§

fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>

Change the foreground color to yellow
§

fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>

Change the background color to yellow
§

fn blue(&self) -> FgColorDisplay<'_, Blue, Self>

Change the foreground color to blue
§

fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>

Change the background color to blue
§

fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to magenta
§

fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to magenta
§

fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to purple
§

fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to purple
§

fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>

Change the foreground color to cyan
§

fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>

Change the background color to cyan
§

fn white(&self) -> FgColorDisplay<'_, White, Self>

Change the foreground color to white
§

fn on_white(&self) -> BgColorDisplay<'_, White, Self>

Change the background color to white
§

fn default_color(&self) -> FgColorDisplay<'_, Default, Self>

Change the foreground color to the terminal default
§

fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>

Change the background color to the terminal default
§

fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>

Change the foreground color to bright black
§

fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>

Change the background color to bright black
§

fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>

Change the foreground color to bright red
§

fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>

Change the background color to bright red
§

fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>

Change the foreground color to bright green
§

fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>

Change the background color to bright green
§

fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>

Change the foreground color to bright yellow
§

fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>

Change the background color to bright yellow
§

fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>

Change the foreground color to bright blue
§

fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>

Change the background color to bright blue
§

fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright magenta
§

fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright magenta
§

fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright purple
§

fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright purple
§

fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>

Change the foreground color to bright cyan
§

fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>

Change the background color to bright cyan
§

fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>

Change the foreground color to bright white
§

fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>

Change the background color to bright white
§

fn bold(&self) -> BoldDisplay<'_, Self>

Make the text bold
§

fn dimmed(&self) -> DimDisplay<'_, Self>

Make the text dim
§

fn italic(&self) -> ItalicDisplay<'_, Self>

Make the text italicized
§

fn underline(&self) -> UnderlineDisplay<'_, Self>

Make the text underlined
Make the text blink
Make the text blink (but fast!)
§

fn reversed(&self) -> ReversedDisplay<'_, Self>

Swap the foreground and background colors
§

fn hidden(&self) -> HiddenDisplay<'_, Self>

Hide the text
§

fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>

Cross out the text
§

fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the foreground color at runtime. Only use if you do not know which color will be used at compile-time. If the color is constant, use either [OwoColorize::fg] or a color-specific method, such as [OwoColorize::green], Read more
§

fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the background color at runtime. Only use if you do not know what color to use at compile-time. If the color is constant, use either [OwoColorize::bg] or a color-specific method, such as [OwoColorize::on_yellow], Read more
§

fn fg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> FgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the foreground color to a specific RGB value.
§

fn bg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> BgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the background color to a specific RGB value.
§

fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self>

Sets the foreground color to an RGB value.
§

fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self>

Sets the background color to an RGB value.
§

fn style(&self, style: Style) -> Styled<&Self>

Apply a runtime-determined style
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more