Skip to content

Commit

Permalink
feat: add execution environment with test construction fixtures
Browse files Browse the repository at this point in the history
  • Loading branch information
Maddiaa0 committed Jan 23, 2024
1 parent 4492d09 commit 202fb78
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 73 deletions.
10 changes: 6 additions & 4 deletions yarn-project/acir-simulator/src/avm/avm_context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Fr } from '@aztec/foundation/fields';

import { ExecutionEnvironment } from './avm_execution_environment.js';
import { AvmExecutionEnvironment } from './avm_execution_environment.js';
import { AvmMachineState } from './avm_machine_state.js';
import { AvmMessageCallResult } from './avm_message_call_result.js';
import { AvmStateManager } from './avm_state_manager.js';
Expand All @@ -14,12 +14,14 @@ import { Instruction } from './opcodes/index.js';
* It stores a state manager
*/
export class AvmContext {
/** Contains constant variables provided by the kernel */
private executionEnvironment: AvmExecutionEnvironment;
/** A wrapper that manages mutable state during execution - (caching, fetching) */
private stateManager: AvmStateManager;
private executionEnvironment: ExecutionEnvironment;

constructor(executionEnvironment: ExecutionEnvironment, stateManager: AvmStateManager) {
this.stateManager = stateManager;
constructor(executionEnvironment: AvmExecutionEnvironment, stateManager: AvmStateManager) {
this.executionEnvironment = executionEnvironment;
this.stateManager = stateManager;
}

/**
Expand Down
27 changes: 7 additions & 20 deletions yarn-project/acir-simulator/src/avm/avm_execution_environment.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { GlobalVariables } from '@aztec/circuits.js';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';

/** - */
export class ExecutionEnvironment {
/**
* Contains variables that remain constant during AVM execution
* These variables are provided by the public kernel circuit
*/
export class AvmExecutionEnvironment {
constructor(
/** - */
public readonly address: AztecAddress,
Expand All @@ -24,29 +28,12 @@ export class ExecutionEnvironment {
/** - */
public readonly contractCallDepth: Fr,
/** - */
// globals: TODO:
public readonly globals: GlobalVariables,
/** - */
public readonly isStaticCall: boolean,
/** - */
public readonly isDelegateCall: boolean,
/** - */
public readonly calldata: Fr[],
) {}

static empty(): ExecutionEnvironment {
return new ExecutionEnvironment(
AztecAddress.zero(),
AztecAddress.zero(),
AztecAddress.zero(),
AztecAddress.zero(),
EthAddress.ZERO,
Fr.zero(),
Fr.zero(),
Fr.zero(),
Fr.zero(),
false,
false,
[],
);
}
}
6 changes: 3 additions & 3 deletions yarn-project/acir-simulator/src/avm/avm_machine_state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Fr } from '@aztec/foundation/fields';

import { ExecutionEnvironment } from './avm_execution_environment.js';
import { AvmExecutionEnvironment } from './avm_execution_environment.js';

/**
* Store's data for an Avm execution frame
Expand All @@ -10,7 +10,7 @@ export class AvmMachineState {
* Execution environment contains hard coded information that is received from the kernel
* Items like, the block header and global variables fall within this category
*/
public readonly executionEnvironment: ExecutionEnvironment;
public readonly executionEnvironment: AvmExecutionEnvironment;

/** - */
public readonly calldata: Fr[];
Expand Down Expand Up @@ -41,7 +41,7 @@ export class AvmMachineState {
* @param calldata -
* @param executionEnvironment - Machine context that is passed to the avm
*/
constructor(calldata: Fr[], executionEnvironment: ExecutionEnvironment) {
constructor(calldata: Fr[], executionEnvironment: AvmExecutionEnvironment) {
this.calldata = calldata;
this.returnData = [];
this.memory = [];
Expand Down
84 changes: 52 additions & 32 deletions yarn-project/acir-simulator/src/avm/fixtures/index.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,60 @@
// Place large AVM text fixtures in here
import { GlobalVariables } from '@aztec/circuits.js';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';

import { ExecutionEnvironment } from '../avm_execution_environment.js';
import { AvmExecutionEnvironment } from '../avm_execution_environment.js';

export const initExecutionEnvironmentEmpty = (): ExecutionEnvironment => {
return new ExecutionEnvironment(
AztecAddress.zero(),
AztecAddress.zero(),
AztecAddress.zero(),
AztecAddress.zero(),
EthAddress.ZERO,
Fr.zero(),
Fr.zero(),
Fr.zero(),
Fr.zero(),
false,
false,
[],
);
};
/**
* An interface that allows to override the default values of the AvmExecutionEnvironment
*/
export interface AvmExecutionEnvironmentOverrides {
/** - */
address?: AztecAddress;
/** - */
storageAddress?: AztecAddress;
/** - */
origin?: AztecAddress;
/** - */
sender?: AztecAddress;
/** - */
portal?: EthAddress;
/** - */
feePerL1Gas?: Fr;
/** - */
feePerL2Gas?: Fr;
/** - */
feePerDaGas?: Fr;
/** - */
contractCallDepth?: Fr;
/** - */
globals?: GlobalVariables;
/** - */
isStaticCall?: boolean;
/** - */
isDelegateCall?: boolean;
/** - */
calldata?: Fr[];
}

export const initExecutionEnvironment = (contractAddress: AztecAddress): ExecutionEnvironment => {
return new ExecutionEnvironment(
contractAddress,
contractAddress,
AztecAddress.zero(),
AztecAddress.zero(),
EthAddress.ZERO,
Fr.zero(),
Fr.zero(),
Fr.zero(),
Fr.zero(),
false,
false,
[],
/**
* Create an empty instance of the Execution Environment where all values are zero, unless overriden in the overrides object
*/
export function initExecutionEnvironment(overrides?: AvmExecutionEnvironmentOverrides): AvmExecutionEnvironment {
return new AvmExecutionEnvironment(
overrides?.address ?? AztecAddress.zero(),
overrides?.storageAddress ?? AztecAddress.zero(),
overrides?.origin ?? AztecAddress.zero(),
overrides?.sender ?? AztecAddress.zero(),
overrides?.portal ?? EthAddress.ZERO,
overrides?.feePerL1Gas ?? Fr.zero(),
overrides?.feePerL2Gas ?? Fr.zero(),
overrides?.feePerDaGas ?? Fr.zero(),
overrides?.contractCallDepth ?? Fr.zero(),
overrides?.globals ?? GlobalVariables.empty(),
overrides?.isStaticCall ?? false,
overrides?.isDelegateCall ?? false,
overrides?.calldata ?? [],
);
};
}
4 changes: 2 additions & 2 deletions yarn-project/acir-simulator/src/avm/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { mock } from 'jest-mock-extended';

import { AvmMachineState } from './avm_machine_state.js';
import { AvmStateManager } from './avm_state_manager.js';
import { initExecutionEnvironmentEmpty } from './fixtures/index.js';
import { initExecutionEnvironment } from './fixtures/index.js';
import { AvmInterpreter } from './interpreter/interpreter.js';
import { decodeBytecode } from './opcodes/decode_bytecode.js';
import { encodeToBytecode } from './opcodes/encode_to_bytecode.js';
Expand All @@ -29,7 +29,7 @@ describe('avm', () => {
const instructions = decodeBytecode(fullBytecode);

// Execute instructions
const executionEnvironment = initExecutionEnvironmentEmpty();
const executionEnvironment = initExecutionEnvironment();
const context = new AvmMachineState(calldata, executionEnvironment);
const interpreter = new AvmInterpreter(context, stateManager, instructions);
const avmReturnData = interpreter.run();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { MockProxy, mock } from 'jest-mock-extended';

import { AvmMachineState } from '../avm_machine_state.js';
import { AvmStateManager } from '../avm_state_manager.js';
import { initExecutionEnvironmentEmpty } from '../fixtures/index.js';
import { initExecutionEnvironment } from '../fixtures/index.js';
import { Add } from '../opcodes/arithmetic.js';
import { Jump, Return } from '../opcodes/control_flow.js';
import { Instruction } from '../opcodes/instruction.js';
Expand All @@ -30,7 +30,8 @@ describe('interpreter', () => {
new Return(2, 1), // [3]
];

const context = new AvmMachineState(calldata, initExecutionEnvironmentEmpty());
const executionEnvironment = initExecutionEnvironment();
const context = new AvmMachineState(calldata, executionEnvironment);
const interpreter = new AvmInterpreter(context, stateManager, instructions);
const avmReturnData = interpreter.run();

Expand All @@ -48,7 +49,8 @@ describe('interpreter', () => {

const instructions: Instruction[] = [new Jump(invalidJumpDestination)];

const context = new AvmMachineState(calldata, initExecutionEnvironmentEmpty());
const executionEnvironment = initExecutionEnvironment();
const context = new AvmMachineState(calldata, executionEnvironment);
const interpreter = new AvmInterpreter(context, stateManager, instructions);

const avmReturnData = interpreter.run();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import { MockProxy, mock } from 'jest-mock-extended';

import { AvmMachineState } from '../avm_machine_state.js';
import { AvmStateManager } from '../avm_state_manager.js';
import { initExecutionEnvironmentEmpty } from '../fixtures/index.js';
import { initExecutionEnvironment } from '../fixtures/index.js';
import { Add, Div, Mul, Sub } from './arithmetic.js';

describe('Arithmetic Instructions', () => {
let machineState: AvmMachineState;
let stateManager: MockProxy<AvmStateManager>;

beforeEach(() => {
machineState = new AvmMachineState([], initExecutionEnvironmentEmpty());
machineState = new AvmMachineState([], initExecutionEnvironment());
stateManager = mock<AvmStateManager>();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { MockProxy, mock } from 'jest-mock-extended';

import { AvmMachineState } from '../avm_machine_state.js';
import { AvmStateManager } from '../avm_state_manager.js';
import { initExecutionEnvironmentEmpty } from '../fixtures/index.js';
import { initExecutionEnvironment } from '../fixtures/index.js';
import { Add, Mul, Sub } from './arithmetic.js';
import { And, Not, Or, Shl, Shr, Xor } from './bitwise.js';
import { Eq, Lt, Lte } from './comparators.js';
Expand All @@ -17,7 +17,7 @@ describe('Control Flow Opcodes', () => {

beforeEach(() => {
stateManager = mock<AvmStateManager>();
machineState = new AvmMachineState([], initExecutionEnvironmentEmpty());
machineState = new AvmMachineState([], initExecutionEnvironment());
});

it('Should implement JUMP', () => {
Expand Down Expand Up @@ -138,7 +138,7 @@ describe('Control Flow Opcodes', () => {

for (const instruction of instructions) {
// Use a fresh machine state each run
const innerMachineState = new AvmMachineState([], initExecutionEnvironmentEmpty());
const innerMachineState = new AvmMachineState([], initExecutionEnvironment());
expect(machineState.pc).toBe(0);
instruction.execute(innerMachineState, stateManager);
expect(innerMachineState.pc).toBe(1);
Expand Down
8 changes: 4 additions & 4 deletions yarn-project/acir-simulator/src/avm/opcodes/storage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import { SLoad, SStore } from './storage.js';
describe('Storage Instructions', () => {
let stateManager: MockProxy<AvmStateManager>;
let machineState: AvmMachineState;
const contractAddress = AztecAddress.random();
const address = AztecAddress.random();

beforeEach(() => {
stateManager = mock<AvmStateManager>();

const executionEnvironment = initExecutionEnvironment(contractAddress);
const executionEnvironment = initExecutionEnvironment({ address, storageAddress: address });
machineState = new AvmMachineState([], executionEnvironment);
});

Expand All @@ -29,7 +29,7 @@ describe('Storage Instructions', () => {

new SStore(0, 1).execute(machineState, stateManager);

expect(stateManager.store).toBeCalledWith(contractAddress, a, b);
expect(stateManager.store).toBeCalledWith(address, a, b);
});

it('Sload should Read into storage', async () => {
Expand All @@ -45,7 +45,7 @@ describe('Storage Instructions', () => {

await new SLoad(0, 1).execute(machineState, stateManager);

expect(stateManager.read).toBeCalledWith(contractAddress, a);
expect(stateManager.read).toBeCalledWith(address, a);

const actual = machineState.readMemory(1);
expect(actual).toEqual(expectedResult);
Expand Down

0 comments on commit 202fb78

Please sign in to comment.