-
Notifications
You must be signed in to change notification settings - Fork 597
feat(avm-simulator): external calls + integration #5051
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -180,7 +180,7 @@ pub fn brillig_to_avm(brillig: &Brillig) -> Vec<u8> { | |
| BrilligOpcode::Stop { return_data_offset, return_data_size } => { | ||
| avm_instrs.push(AvmInstruction { | ||
| opcode: AvmOpcode::RETURN, | ||
| indirect: Some(ALL_DIRECT), | ||
| indirect: Some(ZEROTH_OPERAND_INDIRECT), | ||
| operands: vec![ | ||
| AvmOperand::U32 { value: *return_data_offset as u32 }, | ||
| AvmOperand::U32 { value: *return_data_size as u32 }, | ||
|
|
@@ -239,9 +239,10 @@ fn handle_foreign_call( | |
| inputs: &Vec<ValueOrArray>, | ||
| ) { | ||
| match function { | ||
| "avmOpcodeCall" => handle_external_call(avm_instrs, destinations, inputs), | ||
| "amvOpcodeEmitUnencryptedLog" => { | ||
| handle_emit_unencrypted_log(avm_instrs, destinations, inputs) | ||
| }, | ||
| } | ||
| "avmOpcodeNoteHashExists" => handle_note_hash_exists(avm_instrs, destinations, inputs), | ||
| "avmOpcodeEmitNoteHash" | "avmOpcodeEmitNullifier" => handle_emit_note_hash_or_nullifier( | ||
| function == "avmOpcodeEmitNullifier", | ||
|
|
@@ -257,7 +258,7 @@ fn handle_foreign_call( | |
| } | ||
| "avmOpcodePoseidon" => { | ||
| handle_single_field_hash_instruction(avm_instrs, function, destinations, inputs) | ||
| }, | ||
| } | ||
| "storageRead" => handle_storage_read(avm_instrs, destinations, inputs), | ||
| "storageWrite" => handle_storage_write(avm_instrs, destinations, inputs), | ||
| // Getters. | ||
|
|
@@ -272,6 +273,81 @@ fn handle_foreign_call( | |
| } | ||
| } | ||
|
|
||
| /// Handle an AVM CALL | ||
| /// (an external 'call' brillig foreign call was encountered) | ||
| /// Adds the new instruction to the avm instructions list. | ||
| fn handle_external_call( | ||
| avm_instrs: &mut Vec<AvmInstruction>, | ||
| destinations: &Vec<ValueOrArray>, | ||
| inputs: &Vec<ValueOrArray>, | ||
| ) { | ||
| if destinations.len() != 2 || inputs.len() != 4 { | ||
| panic!( | ||
| "Transpiler expects ForeignCall::CALL to have 2 destinations and 4 inputs, got {} and {}. | ||
| Make sure your call instructions's input/return arrays have static length (`[Field; <size>]`)!", | ||
| destinations.len(), | ||
| inputs.len() | ||
| ); | ||
| } | ||
| let gas_offset_maybe = inputs[0]; | ||
| let gas_offset = match gas_offset_maybe { | ||
| ValueOrArray::HeapArray(HeapArray { pointer, size }) => { | ||
| assert!(size == 3, "Call instruction's gas input should be a HeapArray of size 3 (`[l1Gas, l2Gas, daGas]`)"); | ||
| pointer.0 as u32 | ||
| } | ||
| ValueOrArray::HeapVector(_) => panic!("Call instruction's gas input must be a HeapArray, not a HeapVector. Make sure you are explicitly defining its size as 3 (`[l1Gas, l2Gas, daGas]`)!"), | ||
| _ => panic!("Call instruction's gas input should be a HeapArray"), | ||
| }; | ||
| let address_offset = match &inputs[1] { | ||
| ValueOrArray::MemoryAddress(offset) => offset.to_usize() as u32, | ||
| _ => panic!("Call instruction's target address input should be a basic MemoryAddress",), | ||
| }; | ||
| let args_offset_maybe = inputs[2]; | ||
| let (args_offset, args_size) = match args_offset_maybe { | ||
| ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer.0 as u32, size as u32), | ||
| ValueOrArray::HeapVector(_) => panic!("Call instruction's args must be a HeapArray, not a HeapVector. Make sure you are explicitly defining its size (`[arg0, arg1, ... argN]`)!"), | ||
| _ => panic!("Call instruction's args input should be a HeapArray input"), | ||
| }; | ||
| let temporary_function_selector_offset = match &inputs[3] { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. inconsistency in not using
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok! Let's do later. |
||
| ValueOrArray::MemoryAddress(offset) => offset.to_usize() as u32, | ||
| _ => panic!( | ||
| "Call instruction's temporary function selector input should be a basic MemoryAddress", | ||
| ), | ||
| }; | ||
|
|
||
| let ret_offset_maybe = destinations[0]; | ||
| let (ret_offset, ret_size) = match ret_offset_maybe { | ||
| ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer.0 as u32, size as u32), | ||
| ValueOrArray::HeapVector(_) => panic!("Call instruction's return data must be a HeapArray, not a HeapVector. Make sure you are explicitly defining its size (`let returnData: [Field; <size>] = ...`)!"), | ||
| _ => panic!("Call instruction's returnData destination should be a HeapArray input"), | ||
| }; | ||
| let success_offset = match &destinations[1] { | ||
| ValueOrArray::MemoryAddress(offset) => offset.to_usize() as u32, | ||
| _ => panic!("Call instruction's success destination should be a basic MemoryAddress",), | ||
| }; | ||
| avm_instrs.push(AvmInstruction { | ||
| opcode: AvmOpcode::CALL, | ||
| indirect: Some(0b01101), // (left to right) selector direct, ret offset INDIRECT, args offset INDIRECT, address offset direct, gas offset INDIRECT | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @IlyasRidhuan heres a fun indirect problem to think about |
||
| operands: vec![ | ||
| AvmOperand::U32 { value: gas_offset }, | ||
| AvmOperand::U32 { | ||
| value: address_offset, | ||
| }, | ||
| AvmOperand::U32 { value: args_offset }, | ||
| AvmOperand::U32 { value: args_size }, | ||
| AvmOperand::U32 { value: ret_offset }, | ||
| AvmOperand::U32 { value: ret_size }, | ||
| AvmOperand::U32 { | ||
| value: success_offset, | ||
| }, | ||
| AvmOperand::U32 { | ||
| value: temporary_function_selector_offset, | ||
| }, | ||
| ], | ||
| ..Default::default() | ||
| }); | ||
| } | ||
|
|
||
| /// Handle an AVM NOTEHASHEXISTS instruction | ||
| /// Adds the new instruction to the avm instructions list. | ||
| fn handle_note_hash_exists( | ||
|
|
@@ -328,7 +404,10 @@ fn handle_emit_unencrypted_log( | |
| [ValueOrArray::MemoryAddress(offset), ValueOrArray::HeapArray(array)] => { | ||
| (offset.to_usize() as u32, array) | ||
| } | ||
| _ => panic!("Unexpected inputs for ForeignCall::EMITUNENCRYPTEDLOG: {:?}", inputs), | ||
| _ => panic!( | ||
| "Unexpected inputs for ForeignCall::EMITUNENCRYPTEDLOG: {:?}", | ||
| inputs | ||
| ), | ||
| }; | ||
| avm_instrs.push(AvmInstruction { | ||
| opcode: AvmOpcode::EMITUNENCRYPTEDLOG, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.