diff --git a/yarn-project/acir-simulator/src/avm/avm_context.ts b/yarn-project/acir-simulator/src/avm/avm_context.ts index b094b705e29b..6a2e7d1f9f58 100644 --- a/yarn-project/acir-simulator/src/avm/avm_context.ts +++ b/yarn-project/acir-simulator/src/avm/avm_context.ts @@ -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(); diff --git a/yarn-project/acir-simulator/src/avm/fixtures/index.ts b/yarn-project/acir-simulator/src/avm/fixtures/index.ts index cfab7bc47b8f..4310ef7a4547 100644 --- a/yarn-project/acir-simulator/src/avm/fixtures/index.ts +++ b/yarn-project/acir-simulator/src/avm/fixtures/index.ts @@ -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, + [], + ); +} \ No newline at end of file diff --git a/yarn-project/acir-simulator/src/avm/index.test.ts b/yarn-project/acir-simulator/src/avm/index.test.ts index 1db8306447af..37428df2368a 100644 --- a/yarn-project/acir-simulator/src/avm/index.test.ts +++ b/yarn-project/acir-simulator/src/avm/index.test.ts @@ -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', () => { @@ -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(); diff --git a/yarn-project/acir-simulator/src/avm/interpreter/interpreter.test.ts b/yarn-project/acir-simulator/src/avm/interpreter/interpreter.test.ts index a52a2c13222e..245060af7456 100644 --- a/yarn-project/acir-simulator/src/avm/interpreter/interpreter.test.ts +++ b/yarn-project/acir-simulator/src/avm/interpreter/interpreter.test.ts @@ -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'; @@ -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; + + beforeEach(() => { + stateManager = mock(); + }) + it('Should execute a series of instructions', () => { const calldata: Fr[] = [new Fr(1), new Fr(2)]; - const stateManager = mock(); const instructions: Instruction[] = [ // Copy the first two elements of the calldata to memory regions 0 and 1 @@ -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(); @@ -37,13 +43,12 @@ describe('interpreter', () => { it('Should revert with an invalid jump', () => { const calldata: Fr[] = []; - const stateManager = mock(); 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(); diff --git a/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts index 76a802231a3b..0f31f7a10752 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts @@ -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(); + let stateManager: MockProxy; beforeEach(() => { - machineState = new AvmMachineState([]); + machineState = new AvmMachineState([], initExecutionEnvironmentEmpty()); stateManager = mock(); }); diff --git a/yarn-project/acir-simulator/src/avm/opcodes/control_flow.test.ts b/yarn-project/acir-simulator/src/avm/opcodes/control_flow.test.ts index 864ee0d0b425..fe5592527b9c 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/control_flow.test.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/control_flow.test.ts @@ -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'; @@ -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(); + let stateManager: MockProxy; let machineState: AvmMachineState; beforeEach(() => { stateManager = mock(); - machineState = new AvmMachineState([]); + machineState = new AvmMachineState([], initExecutionEnvironmentEmpty()); }); it('Should implement JUMP', () => { @@ -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); diff --git a/yarn-project/acir-simulator/src/avm/opcodes/storage.test.ts b/yarn-project/acir-simulator/src/avm/opcodes/storage.test.ts new file mode 100644 index 000000000000..cf659721f384 --- /dev/null +++ b/yarn-project/acir-simulator/src/avm/opcodes/storage.test.ts @@ -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; + let machineState: AvmMachineState; + const contractAddress = AztecAddress.random(); + + beforeEach(() => { + stateManager = mock(); + + 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); + }) +}) \ No newline at end of file