Skip to content

Commit

Permalink
feat(avm): access execution environment within noir contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
Maddiaa0 committed Feb 2, 2024
1 parent a19bac6 commit 8c44a2e
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 5 deletions.
28 changes: 27 additions & 1 deletion avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use acvm::acir::brillig::Opcode as BrilligOpcode;
use acvm::acir::circuit::brillig::Brillig;

use acvm::brillig_vm::brillig::{BinaryFieldOp, BinaryIntOp};
use acvm::brillig_vm::brillig::{BinaryFieldOp, BinaryIntOp, ValueOrArray};

use crate::instructions::{
AvmInstruction, AvmOperand, AvmTypeTag, FIRST_OPERAND_INDIRECT, ZEROTH_OPERAND_INDIRECT,
Expand Down Expand Up @@ -252,6 +252,32 @@ pub fn brillig_to_avm(brillig: &Brillig) -> Vec<u8> {
],
..Default::default()
});
},
BrilligOpcode::ForeignCall { function, destinations, inputs } => {
println!("{}", function);
match function.as_str() {
"address" => {
assert!(inputs.len() == 0);
assert!(destinations.len() == 1);
let dest_offset_maybe = destinations[0];
let dest_offset = match dest_offset_maybe {
ValueOrArray::MemoryAddress(dest_offset) => dest_offset.0,
_ => panic!("ForeignCall address destination should be a single value"),
};

avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::ADDRESS,
indirect: Some(0),
operands: vec![
AvmOperand::U32 { value: dest_offset as u32},
],
..Default::default()
});
}
_ => panic!("Transpiler doesn't know how to process ForeignCall function {:?}", function),
}
println!("{:?}", destinations);
println!("{:?}", inputs);
}
_ => panic!(
"Transpiler doesn't know how to process {:?} brillig instruction",
Expand Down
32 changes: 28 additions & 4 deletions yarn-project/acir-simulator/src/avm/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { Fr } from '@aztec/foundation/fields';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { AvmTestContractArtifact } from '@aztec/noir-contracts';

import { mock } from 'jest-mock-extended';
import { mock, MockProxy } from 'jest-mock-extended';

import { AvmMachineState } from './avm_machine_state.js';
import { TypeTag } from './avm_memory_types.js';
import { initExecutionEnvironment } from './fixtures/index.js';
import { executeAvm } from './interpreter/interpreter.js';
import { AvmJournal } from './journal/journal.js';
import { Add, CalldataCopy, Return } from './opcodes/index.js';
import { decodeFromBytecode, encodeToBytecode } from './serialization/bytecode_serialization.js';
import { AvmMachineState } from './avm_machine_state.js';

describe('avm', () => {
let journal: MockProxy<AvmJournal>;

beforeEach(() => {
journal = mock<AvmJournal>();
})

it('Should execute bytecode that performs basic addition', async () => {
const calldata: Fr[] = [new Fr(1), new Fr(2)];
const journal = mock<AvmJournal>();

// Construct bytecode
const bytecode = encodeToBytecode([
Expand All @@ -38,10 +44,10 @@ describe('avm', () => {
});

describe('testing transpiled Noir contracts', () => {

// TODO(https://github.com/AztecProtocol/aztec-packages/issues/4361): sync wire format w/transpiler.
it('Should execute contract function that performs addition', async () => {
const calldata: Fr[] = [new Fr(1), new Fr(2)];
const journal = mock<AvmJournal>();

// Get contract function artifact
const addArtifact = AvmTestContractArtifact.functions.find(f => f.name === 'avm_addArgsReturn')!;
Expand All @@ -60,5 +66,23 @@ describe('avm', () => {
expect(returnData.length).toBe(1);
expect(returnData).toEqual([new Fr(3)]);
});

it('Should execute contract function that returns data from the environment', async () => {
const getterArtifact = AvmTestContractArtifact.functions.find(f => f.name === 'avm_accessEnv')

// Decode
const instructions = decodeFromBytecode(Buffer.from(getterArtifact!.bytecode, 'base64'));

// Execute
const address = AztecAddress.fromField(new Fr(1234n));
const context = new AvmMachineState(initExecutionEnvironment({address}));
const avmReturnData = await executeAvm(context, journal, instructions);

expect(avmReturnData.reverted).toBe(false);

const returnData = avmReturnData.output;
expect(returnData.length).toBe(1);
expect(returnData).toEqual([address]);
});
});
});
2 changes: 2 additions & 0 deletions yarn-project/aztec-nr/aztec/src/avm.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod context;
mod env_getters;
22 changes: 22 additions & 0 deletions yarn-project/aztec-nr/aztec/src/avm/context.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::avm::env_getters::{
get_address,
get_storage_address
};

// Getters that will be converted by the transpiler into their
// own opcodes
struct AvmContext {}

impl AvmContext {
pub fn new() -> Self {
Self {}
}

pub fn address() -> Field {
get_address()
}

pub fn storage_address() -> Field {
get_storage_address()
}
}
5 changes: 5 additions & 0 deletions yarn-project/aztec-nr/aztec/src/avm/env_getters.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[oracle(address)]
unconstrained pub fn get_address() -> Field {}

#[oracle(storage_address)]
unconstrained pub fn get_storage_address() -> Field {}
1 change: 1 addition & 0 deletions yarn-project/aztec-nr/aztec/src/lib.nr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod abi;
mod avm;
mod context;
mod hash;
mod history;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ contract AvmTest {
address::AztecAddress,
};

// avm lib
use dep::aztec::avm::context::AvmContext;

#[aztec(private)]
fn constructor() {}

Expand All @@ -15,6 +18,11 @@ contract AvmTest {
argA + argB
}

#[aztec(public-vm)]
fn accessEnv() -> pub Field {
AvmContext::address()
}

// Function required for all contracts
unconstrained fn compute_note_hash_and_nullifier(
_contract_address: AztecAddress,
Expand Down

0 comments on commit 8c44a2e

Please sign in to comment.