Skip to content

Commit

Permalink
first PoC
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro committed Apr 5, 2024
1 parent 39c0087 commit a044121
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 126 deletions.
3 changes: 0 additions & 3 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ pub fn brillig_to_avm(brillig: &Brillig) -> Vec<u8> {
BinaryIntOp::Xor => AvmOpcode::XOR,
BinaryIntOp::Shl => AvmOpcode::SHL,
BinaryIntOp::Shr => AvmOpcode::SHR,
_ => panic!(
"Transpiler doesn't know how to process {:?}", brillig_instr
),
};
avm_instrs.push(AvmInstruction {
opcode: avm_opcode,
Expand Down
1 change: 0 additions & 1 deletion avm-transpiler/src/transpile_contract.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use base64::Engine;
use log::info;
use regex::Regex;
use serde::{Deserialize, Serialize};

use acvm::acir::circuit::Program;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ contract AvmTest {
// Libs
use dep::aztec::prelude::Map;
use dep::aztec::state_vars::PublicMutable;
use dep::aztec::history::nullifier_inclusion::prove_nullifier_inclusion;
use dep::aztec::protocol_types::{
address::{AztecAddress, EthAddress}, constants::L1_TO_L2_MESSAGE_LENGTH,
contract_instance::ContractInstance
contract_instance::ContractInstance,
hash::silo_nullifier,
};
use dep::aztec::oracle::get_contract_instance::{get_contract_instance_avm, get_contract_instance_internal_avm};
use dep::aztec::protocol_types::abis::function_selector::FunctionSelector;
Expand Down Expand Up @@ -187,6 +189,18 @@ contract AvmTest {
123456
}

#[aztec(public)]
fn new_nullifier_acvm(nullifier: Field) -> pub Field {
context.push_new_nullifier(nullifier, 0);
}

#[aztec(public)]
fn assert_unsiloed_nullifier_acvm(nullifier: Field) {
// ACVM requires siloed nullifier.
let siloed_nullifier = silo_nullifier(context.this_address(), nullifier);
prove_nullifier_inclusion(siloed_nullifier, context);
}

#[aztec(public-vm)]
fn call_acvm_from_avm() -> pub Field {
let data_to_return: [Field; RETURN_VALUES_LENGTH] = context.call_public_function(
Expand All @@ -207,6 +221,15 @@ contract AvmTest {
data_to_return[0]
}

#[aztec(public-vm)]
fn avm_to_acvm_call(selector: FunctionSelector, args: Field) {
context.call_public_function(
context.this_address(),
selector,
[args]
);
}

/************************************************************************
* Contract instance
************************************************************************/
Expand Down
42 changes: 35 additions & 7 deletions yarn-project/end-to-end/src/e2e_avm_simulator.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AztecAddress, Fr, TxStatus, type Wallet } from '@aztec/aztec.js';
import { AztecAddress, Fr, FunctionSelector, TxStatus, type Wallet } from '@aztec/aztec.js';
import { AvmInitializerTestContract, AvmTestContract } from '@aztec/noir-contracts.js';

import { jest } from '@jest/globals';
Expand Down Expand Up @@ -64,6 +64,40 @@ describe('e2e_avm_simulator', () => {
expect(tx.status).toEqual(TxStatus.MINED);
});
});

describe('ACVM interoperability', () => {
it('Can execute ACVM function among AVM functions', async () => {
expect(await avmContract.methods.constant_field_acvm().simulate()).toEqual([123456n, 0n, 0n, 0n]);
});

it('Can call AVM function from ACVM', async () => {
expect(await avmContract.methods.call_avm_from_acvm().simulate()).toEqual([123456n, 0n, 0n, 0n]);
});

it('Can call ACVM function from AVM', async () => {
expect(await avmContract.methods.call_acvm_from_avm().simulate()).toEqual([123456n, 0n, 0n, 0n]);
});

// Cannot work because ACVM does not support pending nullifiers.
// it('AVM->ACVM nullifiers work (pending)', async () => {
// await avmContract.methods.avm_to_acvm_nullifier().send().wait();
// });

it('AVM sees settled nullifiers by ACVM', async () => {
const nullifier = new Fr(123456);
await avmContract.methods.new_nullifier(nullifier).send().wait();
await avmContract.methods.assert_unsiloed_nullifier_acvm(nullifier).send().wait();
});

it('AVM nested call to ACVM sees settled nullifiers', async () => {
const nullifier = new Fr(123456);
await avmContract.methods.new_nullifier(nullifier).send().wait();
await avmContract.methods
.avm_to_acvm_call(FunctionSelector.fromSignature('assert_unsiloed_nullifier_acvm(Field)'), nullifier)
.send()
.wait();
});
});
});

describe('AvmInitializerTestContract', () => {
Expand All @@ -79,10 +113,4 @@ describe('e2e_avm_simulator', () => {
});
});
});

describe('ACVM interoperability', () => {
it('Can execute ACVM function among AVM functions', async () => {
expect(await avmContact.methods.constant_field_acvm().simulate()).toEqual(123456n);
});
});
});
2 changes: 1 addition & 1 deletion yarn-project/simulator/src/avm/avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AvmTestContractArtifact } from '@aztec/noir-contracts.js';
import { jest } from '@jest/globals';
import { strict as assert } from 'assert';

import { isAvmBytecode } from '../public/transitional_adaptors.js';
import { AvmMachineState } from './avm_machine_state.js';
import { TypeTag } from './avm_memory_types.js';
import { AvmSimulator } from './avm_simulator.js';
Expand All @@ -23,7 +24,6 @@ import {
} from './fixtures/index.js';
import { Add, CalldataCopy, Return } from './opcodes/index.js';
import { encodeToBytecode } from './serialization/bytecode_serialization.js';
import { isAvmBytecode } from './temporary_executor_migration.js';

describe('AVM simulator: injected bytecode', () => {
let calldata: Fr[];
Expand Down
11 changes: 6 additions & 5 deletions yarn-project/simulator/src/avm/journal/journal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,19 @@ export class AvmPersistableStateManager {
/** Reference to node storage */
public readonly hostStorage: HostStorage;

// TODO: make members private once this is not used in transitional_adaptors.ts.
/** World State */
/** Public storage, including cached writes */
private publicStorage: PublicStorage;
public publicStorage: PublicStorage;
/** Nullifier set, including cached/recently-emitted nullifiers */
private nullifiers: Nullifiers;
public nullifiers: Nullifiers;

/** World State Access Trace */
private trace: WorldStateAccessTrace;
public trace: WorldStateAccessTrace;

/** Accrued Substate **/
private newL1Messages: L2ToL1Message[] = [];
private newLogs: UnencryptedL2Log[] = [];
public newL1Messages: L2ToL1Message[] = [];
public newLogs: UnencryptedL2Log[] = [];

constructor(hostStorage: HostStorage, parent?: AvmPersistableStateManager) {
this.hostStorage = hostStorage;
Expand Down
26 changes: 22 additions & 4 deletions yarn-project/simulator/src/avm/opcodes/external_calls.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { FunctionSelector } from '@aztec/circuits.js';
import { padArrayEnd } from '@aztec/foundation/collection';

import { executePublicFunction } from '../../public/executor.js';
import {
adjustAvmContextFromPublicExecutionResult,
convertPublicExecutionResult,
createPublicExecutionContext,
} from '../../public/transitional_adaptors.js';
import type { AvmContext } from '../avm_context.js';
import { gasLeftToGas, sumGas } from '../avm_gas.js';
import { Field, Uint8 } from '../avm_memory_types.js';
import { AvmSimulator } from '../avm_simulator.js';
import { type AvmContractCallResults } from '../avm_message_call_result.js';
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
import { Addressing } from './addressing_mode.js';
import { Instruction } from './instruction.js';
Expand Down Expand Up @@ -61,15 +67,27 @@ abstract class ExternalCall extends Instruction {
const totalGas = sumGas(this.gasCost(memoryOperations), allocatedGas);
context.machineState.consumeGas(totalGas);

// TRANSITIONAL: This should be removed once the AVM is fully operational and the public executor is gone.
const nestedContext = context.createNestedContractCallContext(
callAddress.toFr(),
calldata,
allocatedGas,
this.type,
FunctionSelector.fromField(functionSelector),
);
const pxContext = createPublicExecutionContext(nestedContext, calldata);
const pxResults = await executePublicFunction(pxContext, /*nested=*/ true);
const nestedCallResults: AvmContractCallResults = convertPublicExecutionResult(pxResults);
adjustAvmContextFromPublicExecutionResult(nestedContext, pxResults);
const nestedPersistableState = nestedContext.persistableState;
// const nestedContext = context.createNestedContractCallContext(
// callAddress.toFr(),
// calldata,
// FunctionSelector.fromField(functionSelector),
// );
// const nestedCallResults: AvmContractCallResults = await new AvmSimulator(nestedContext).execute();
// const nestedPersistableState = nestedContext.persistableState;

const nestedCallResults = await new AvmSimulator(nestedContext).execute();
const success = !nestedCallResults.reverted;

// We only take as much data as was specified in the return size and pad with zeroes if the return data is smaller
Expand All @@ -90,9 +108,9 @@ abstract class ExternalCall extends Instruction {

// TODO: Should we merge the changes from a nested call in the case of a STATIC call?
if (success) {
context.persistableState.acceptNestedCallState(nestedContext.persistableState);
context.persistableState.acceptNestedCallState(nestedPersistableState);
} else {
context.persistableState.rejectNestedCallState(nestedContext.persistableState);
context.persistableState.rejectNestedCallState(nestedPersistableState);
}

memory.assert(memoryOperations);
Expand Down
Loading

0 comments on commit a044121

Please sign in to comment.