Skip to content

Commit

Permalink
feat(avm): return oracle (#8629)
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro committed Sep 18, 2024
1 parent 184cc88 commit b6bc7c3
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
28 changes: 28 additions & 0 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ fn handle_foreign_call(
handle_get_contract_instance(avm_instrs, destinations, inputs);
}
"avmOpcodeCalldataCopy" => handle_calldata_copy(avm_instrs, destinations, inputs),
"avmOpcodeReturn" => handle_return(avm_instrs, destinations, inputs),
"avmOpcodeStorageRead" => handle_storage_read(avm_instrs, destinations, inputs),
"avmOpcodeStorageWrite" => handle_storage_write(avm_instrs, destinations, inputs),
"debugLog" => handle_debug_log(avm_instrs, destinations, inputs),
Expand Down Expand Up @@ -1126,6 +1127,33 @@ fn handle_calldata_copy(
});
}

// #[oracle(avmOpcodeReturn)]
// unconstrained fn return_opcode<let N: u32>(returndata: [Field; N]) {}
fn handle_return(
avm_instrs: &mut Vec<AvmInstruction>,
destinations: &Vec<ValueOrArray>,
inputs: &Vec<ValueOrArray>,
) {
assert!(inputs.len() == 1);
assert!(destinations.len() == 0);

// First arg is the size, which is ignored because it's redundant.
let (return_data_offset, return_data_size) = match inputs[0] {
ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer.0 as u32, size as u32),
_ => panic!("Return instruction's args input should be a HeapArray"),
};

avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::RETURN,
indirect: Some(ZEROTH_OPERAND_INDIRECT),
operands: vec![
AvmOperand::U32 { value: return_data_offset as u32 },
AvmOperand::U32 { value: return_data_size as u32 },
],
..Default::default()
});
}

/// Emit a storage write opcode
/// The current implementation writes an array of values into storage ( contiguous slots in memory )
fn handle_storage_write(
Expand Down
7 changes: 7 additions & 0 deletions noir-projects/aztec-nr/aztec/src/context/public_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,10 @@ unconstrained fn calldata_copy<let N: u32>(cdoffset: u32, copy_size: u32) -> [Fi
calldata_copy_opcode(cdoffset, copy_size)
}

unconstrained fn avm_return<let N: u32>(returndata: [Field; N]) {
return_opcode(returndata)
}

unconstrained fn storage_read(storage_slot: Field) -> Field {
storage_read_opcode(storage_slot)
}
Expand Down Expand Up @@ -377,6 +381,9 @@ unconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field)
#[oracle(avmOpcodeCalldataCopy)]
unconstrained fn calldata_copy_opcode<let N: u32>(cdoffset: u32, copy_size: u32) -> [Field; N] {}

#[oracle(avmOpcodeReturn)]
unconstrained fn return_opcode<let N: u32>(returndata: [Field; N]) {}

#[oracle(avmOpcodeCall)]
unconstrained fn call_opcode<let RET_SIZE: u32>(
gas: [Field; 2], // gas allocation: [l2_gas, da_gas]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,19 @@ contract AvmTest {
1
}

#[aztec(public)]
fn assert_calldata_copy(args: [Field; 3]) {
let offset = 2; // Make this 0 when PublicContextInputs is removed.
let cd: [Field; 3] = dep::aztec::context::public_context::calldata_copy(offset, 3);
assert(cd == args, "Calldata copy failed");
}

#[aztec(public)]
fn return_oracle() -> [Field; 3] {
dep::aztec::context::public_context::avm_return([1, 2, 3]);
[4, 5, 6] // Should not get here.
}

/************************************************************************
* Hashing functions
************************************************************************/
Expand Down
20 changes: 20 additions & 0 deletions yarn-project/simulator/src/avm/avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,26 @@ describe('AVM simulator: transpiled Noir contracts', () => {
expect(isAvmBytecode(bytecode));
});

it('Should handle calldata oracle', async () => {
const calldata: Fr[] = [new Fr(1), new Fr(2), new Fr(3)];
const context = initContext({ env: initExecutionEnvironment({ calldata }) });

const bytecode = getAvmTestContractBytecode('assert_calldata_copy');
const results = await new AvmSimulator(context).executeBytecode(bytecode);

expect(results.reverted).toBe(false);
});

it('Should handle return oracle', async () => {
const context = initContext();

const bytecode = getAvmTestContractBytecode('return_oracle');
const results = await new AvmSimulator(context).executeBytecode(bytecode);

expect(results.reverted).toBe(false);
expect(results.output).toEqual([new Fr(1), new Fr(2), new Fr(3)]);
});

it('elliptic curve operations', async () => {
const context = initContext();

Expand Down

0 comments on commit b6bc7c3

Please sign in to comment.