Skip to content

Commit

Permalink
test: add unit tests for storage opcodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Maddiaa0 committed Jan 19, 2024
1 parent 9e08d0d commit 2dc2c70
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 14 deletions.
2 changes: 1 addition & 1 deletion yarn-project/acir-simulator/src/avm/avm_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class AvmContext {

const instructions: Instruction[] = decodeBytecode(bytecode);

const context = new AvmMachineState(calldata);
const context = new AvmMachineState(calldata, this.executionEnvironment);
const interpreter = new AvmInterpreter(context, this.stateManager, instructions);

return interpreter.run();
Expand Down
39 changes: 39 additions & 0 deletions yarn-project/acir-simulator/src/avm/fixtures/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,40 @@
// Place large AVM text fixtures in here

import { AztecAddress } from "@aztec/foundation/aztec-address";
import { ExecutionEnvironment } from "../avm_execution_environment.js";
import { EthAddress } from "@aztec/foundation/eth-address";
import { Fr } from "@aztec/foundation/fields";

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,
[],
);
}

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,
[],
);
}
4 changes: 3 additions & 1 deletion yarn-project/acir-simulator/src/avm/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { AvmInterpreter } from './interpreter/interpreter.js';
import { decodeBytecode } from './opcodes/decode_bytecode.js';
import { encodeToBytecode } from './opcodes/encode_to_bytecode.js';
import { Opcode } from './opcodes/opcodes.js';
import { initExecutionEnvironmentEmpty } from './fixtures/index.js';

describe('avm', () => {
it('Should execute bytecode', () => {
Expand All @@ -28,7 +29,8 @@ describe('avm', () => {
const instructions = decodeBytecode(fullBytecode);

// Execute instructions
const context = new AvmMachineState(calldata);
const executionEnvironment = initExecutionEnvironmentEmpty();
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
@@ -1,6 +1,6 @@
import { Fr } from '@aztec/foundation/fields';

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

import { AvmMachineState } from '../avm_machine_state.js';
import { AvmStateManager } from '../avm_state_manager.js';
Expand All @@ -9,11 +9,17 @@ import { Jump, Return } from '../opcodes/control_flow.js';
import { Instruction } from '../opcodes/instruction.js';
import { CalldataCopy } from '../opcodes/memory.js';
import { AvmInterpreter } from './interpreter.js';
import { initExecutionEnvironmentEmpty } from '../fixtures/index.js';

describe('interpreter', () => {
let stateManager: MockProxy<AvmStateManager>;

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

it('Should execute a series of instructions', () => {
const calldata: Fr[] = [new Fr(1), new Fr(2)];
const stateManager = mock<AvmStateManager>();

const instructions: Instruction[] = [
// Copy the first two elements of the calldata to memory regions 0 and 1
Expand All @@ -24,7 +30,7 @@ describe('interpreter', () => {
new Return(2, 1), // [3]
];

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

Expand All @@ -37,13 +43,12 @@ describe('interpreter', () => {

it('Should revert with an invalid jump', () => {
const calldata: Fr[] = [];
const stateManager = mock<AvmStateManager>();

const invalidJumpDestination = 22;

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

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

const avmReturnData = interpreter.run();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { Fr } from '@aztec/foundation/fields';

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

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

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

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Fr } from '@aztec/foundation/fields';

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

import { AvmMachineState } from '../avm_machine_state.js';
import { AvmStateManager } from '../avm_state_manager.js';
Expand All @@ -9,14 +9,15 @@ import { And, Not, Or, Shl, Shr, Xor } from './bitwise.js';
import { Eq, Lt, Lte } from './comparators.js';
import { InternalCall, InternalCallStackEmptyError, InternalReturn, Jump, JumpI } from './control_flow.js';
import { CalldataCopy, Cast, Mov, Set } from './memory.js';
import { initExecutionEnvironmentEmpty } from '../fixtures/index.js';

describe('Control Flow Opcodes', () => {
let stateManager = mock<AvmStateManager>();
let stateManager: MockProxy<AvmStateManager>;
let machineState: AvmMachineState;

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

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

for (const instruction of instructions) {
// Use a fresh machine state each run
const innerMachineState = new AvmMachineState([]);
const innerMachineState = new AvmMachineState([], initExecutionEnvironmentEmpty());
expect(machineState.pc).toBe(0);
instruction.execute(innerMachineState, stateManager);
expect(innerMachineState.pc).toBe(1);
Expand Down
52 changes: 52 additions & 0 deletions yarn-project/acir-simulator/src/avm/opcodes/storage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { MockProxy, mock } from "jest-mock-extended"
import { AvmStateManager } from "../avm_state_manager.js"
import { SLoad, SStore } from "./storage.js";
import { AvmMachineState } from "../avm_machine_state.js";
import { AztecAddress } from "@aztec/foundation/aztec-address";
import { Fr } from "@aztec/foundation/fields";
import { initExecutionEnvironment } from "../fixtures/index.js";


describe("Storage Instructions", () => {
let stateManager: MockProxy<AvmStateManager>;
let machineState: AvmMachineState;
const contractAddress = AztecAddress.random();

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

const executionEnvironment = initExecutionEnvironment(contractAddress);
machineState = new AvmMachineState([], executionEnvironment);
});

it("Sstore should Write into storage", () => {
const a = new Fr(1n);
const b = new Fr(2n);

machineState.writeMemory(0, a);
machineState.writeMemory(1, b);

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

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

it("Sload should Read into storage", async () => {
// Mock response
const expectedResult = new Fr(1n);
stateManager.read.mockReturnValueOnce(Promise.resolve(expectedResult));

const a = new Fr(1n);
const b = new Fr(2n);

machineState.writeMemory(0, a);
machineState.writeMemory(1, b);

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

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

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

0 comments on commit 2dc2c70

Please sign in to comment.