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: usizeInstruction pointer.
foreign_call_counter: usizeA 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 BThe 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>
 
impl<F: AcirField, B: BlackBoxFunctionSolver<F>> VM<'_, F, B>
Sourcepub(crate) fn process_foreign_call(
    &mut self,
    function: &str,
    destinations: &[ValueOrArray],
    destination_value_types: &[HeapValueType],
    inputs: &[ValueOrArray],
    input_value_types: &[HeapValueType],
) -> &VMStatus<F>
 
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:
- 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 precedingu32length field is used to truncate the slice input to its semantic length. - 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.
 - 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
- VMStatus indicating the next state of the VM:
- VMStatus::ForeignCallWait if the results are not yet available.
 - VMStatus::Finished or VMStatus::Failure depending on whether writing the results succeeded.
 
 
§Panics
- If 
inputsandinput_value_typeslengths do not match. - If 
destinationsanddestination_value_typeslengths do not match. 
Sourcefn get_memory_values(
    &self,
    input: ValueOrArray,
    value_type: &HeapValueType,
) -> ForeignCallParam<F>
 
fn get_memory_values( &self, input: ValueOrArray, value_type: &HeapValueType, ) -> ForeignCallParam<F>
Get input data from memory to pass to foreign calls.
Sourcefn read_slice_of_values_from_memory(
    &self,
    start: MemoryAddress,
    size: usize,
    value_types: &[HeapValueType],
) -> Vec<MemoryValue<F>>
 
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.
Sourcefn wait_for_foreign_call(
    &mut self,
    function: String,
    inputs: Vec<ForeignCallParam<F>>,
) -> &VMStatus<F>
 
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.
Sourcefn write_foreign_call_result(
    &mut self,
    destinations: &[ValueOrArray],
    destination_value_types: &[HeapValueType],
    foreign_call_index: usize,
) -> Result<(), String>
 
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.
Sourcefn write_value_to_memory(
    &mut self,
    destination: MemoryAddress,
    value: &F,
    value_bit_size: BitSize,
) -> Result<(), String>
 
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.
Sourcefn write_values_to_memory(
    &mut self,
    pointer: MemoryAddress,
    values: &[F],
    value_types: &[HeapValueType],
) -> Result<(), String>
 
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.
Sourcefn write_flattened_values_to_memory(
    &mut self,
    destination: MemoryAddress,
    values: &Vec<F>,
    values_idx: &mut usize,
    value_type: &HeapValueType,
) -> Result<(), String>
 
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>
 
impl<F: AcirField, B: BlackBoxFunctionSolver<F>> VM<'_, F, B>
Sourcepub(crate) fn fuzzing_trace_binary_field_op_comparison(
    &mut self,
    op: &BinaryFieldOp,
    lhs: MemoryValue<F>,
    rhs: MemoryValue<F>,
    result: MemoryValue<F>,
)
 
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
Sourcepub(crate) fn fuzzing_trace_binary_int_op_comparison(
    &mut self,
    op: &BinaryIntOp,
    lhs: MemoryValue<F>,
    rhs: MemoryValue<F>,
    result: MemoryValue<F>,
)
 
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
Sourcepub(crate) fn fuzzing_trace_branching(
    &mut self,
    destination: NextOpcodePositionOrState,
)
 
pub(crate) fn fuzzing_trace_branching( &mut self, destination: NextOpcodePositionOrState, )
Mark the execution of a particular branch in the fuzzing trace
Sourcepub(crate) fn fuzzing_trace_conditional_mov(&mut self, branch: bool)
 
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>
 
impl<'a, F: AcirField, B: BlackBoxFunctionSolver<F>> VM<'a, F, B>
Sourcepub 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
 
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.
pub fn is_profiling_active(&self) -> bool
pub fn is_fuzzing_active(&self) -> bool
pub fn take_profiling_samples(&mut self) -> BrilligProfilingSamples
Sourcepub(crate) fn status(&mut self, status: VMStatus<F>) -> &VMStatus<F>
 
pub(crate) fn status(&mut self, status: VMStatus<F>) -> &VMStatus<F>
Updates the current status of the VM. Returns the given status.
pub fn get_status(&self) -> VMStatus<F>
Sourcepub(crate) fn finish(
    &mut self,
    return_data_offset: usize,
    return_data_size: usize,
) -> &VMStatus<F>
 
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).
Sourcepub(crate) fn has_unprocessed_foreign_call_result(&self) -> bool
 
pub(crate) fn has_unprocessed_foreign_call_result(&self) -> bool
Check whether the latest foreign call result is available yet.
Sourcepub fn resolve_foreign_call(
    &mut self,
    foreign_call_result: ForeignCallResult<F>,
)
 
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.
Sourcepub(crate) fn trap(
    &mut self,
    revert_data_offset: usize,
    revert_data_size: usize,
) -> &VMStatus<F>
 
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.
Sourcepub(crate) fn fail(&mut self, message: String) -> &VMStatus<F>
 
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.
Sourcepub fn process_opcodes(&mut self) -> VMStatus<F>
 
pub fn process_opcodes(&mut self) -> VMStatus<F>
Process opcodes in a loop until a status of Finished,
Failure or ForeignCallWait is encountered.
Sourcepub fn get_memory(&self) -> &[MemoryValue<F>]
 
pub fn get_memory(&self) -> &[MemoryValue<F>]
Read memory slots.
Used by the debugger to inspect the contents of the memory.
Sourcepub fn take_memory(self) -> Memory<F>
 
pub fn take_memory(self) -> Memory<F>
Take all the contents of the memory, leaving it empty.
Used only for testing purposes.
pub fn foreign_call_counter(&self) -> usize
Sourcepub fn write_memory_at(&mut self, ptr: usize, value: MemoryValue<F>)
 
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.
Sourcepub fn get_call_stack(&self) -> Vec<usize>
 
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.
Sourcepub fn get_call_stack_no_current_counter(&self) -> Vec<usize>
 
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.
Sourcepub fn process_opcode(&mut self) -> &VMStatus<F>
 
pub fn process_opcode(&mut self) -> &VMStatus<F>
Process a single opcode and modify the program counter.
pub fn get_fuzzing_trace(&self) -> Vec<u32>
Sourcepub(crate) fn process_opcode_internal(&mut self) -> &VMStatus<F>
 
pub(crate) fn process_opcode_internal(&mut self) -> &VMStatus<F>
Execute a single opcode:
- Retrieve the current opcode using the program counter
 - 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.
 
 - 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.
 
Sourcepub fn program_counter(&self) -> usize
 
pub fn program_counter(&self) -> usize
Returns the current value of the program counter.
Sourcepub(crate) fn increment_program_counter(&mut self) -> &VMStatus<F>
 
pub(crate) fn increment_program_counter(&mut self) -> &VMStatus<F>
Increments the program counter by 1.
Sourcepub(crate) fn set_program_counter(&mut self, value: usize) -> &VMStatus<F>
 
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.
Sourcepub(crate) fn process_binary_field_op(
    &mut self,
    op: BinaryFieldOp,
    lhs: MemoryAddress,
    rhs: MemoryAddress,
    result: MemoryAddress,
) -> Result<(), BrilligArithmeticError>
 
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.
Sourcepub(crate) fn process_binary_int_op(
    &mut self,
    op: BinaryIntOp,
    bit_size: IntegerBitSize,
    lhs: MemoryAddress,
    rhs: MemoryAddress,
    result: MemoryAddress,
) -> Result<(), BrilligArithmeticError>
 
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.
Sourcepub(crate) fn process_not(
    &mut self,
    source: MemoryAddress,
    destination: MemoryAddress,
    op_bit_size: IntegerBitSize,
) -> Result<(), MemoryTypeError>
 
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§
impl<'a, F: Eq, B: Eq + BlackBoxFunctionSolver<F>> Eq for VM<'a, F, B>
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>where
    B: RefUnwindSafe,
    F: RefUnwindSafe,
impl<'a, F, B> Send for VM<'a, F, B>
impl<'a, F, B> Sync for VM<'a, F, B>
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> BorrowMut<T> for Twhere
    T: ?Sized,
 
impl<T> BorrowMut<T> for Twhere
    T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
 
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
    T: Clone,
 
impl<T> CloneToUninit for Twhere
    T: Clone,
§impl<Q, K> Equivalent<K> for Q
 
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
 
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.§impl<T> Instrument for T
 
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
 
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
 
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
 
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
 
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
 
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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
 
impl<D> OwoColorize for D
§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
    C: Color,
 
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
    C: Color,
§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
    C: Color,
 
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
    C: Color,
§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
 
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
 
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
 
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
 
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
 
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
 
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
 
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
 
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
 
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
 
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
 
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
 
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
 
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
 
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
 
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
 
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
 
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
 
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
 
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
 
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
 
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
 
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
 
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
    Color: DynColor,
 
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
    Color: DynColor,
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,
 
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
    Color: DynColor,
OwoColorize::bg] or
a color-specific method, such as [OwoColorize::on_yellow], Read more