Skip to content

Commit

Permalink
refactor(avm): make interpreter a function not a class (AztecProtocol…
Browse files Browse the repository at this point in the history
  • Loading branch information
Maddiaa0 committed Jan 30, 2024
1 parent 6e1d958 commit 14e8c5c
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 67 deletions.
8 changes: 3 additions & 5 deletions yarn-project/acir-simulator/src/avm/avm_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Fr } from '@aztec/foundation/fields';
import { AvmExecutionEnvironment } from './avm_execution_environment.js';
import { AvmMachineState } from './avm_machine_state.js';
import { AvmMessageCallResult } from './avm_message_call_result.js';
import { AvmInterpreter, AvmInterpreterError } from './interpreter/index.js';
import { AvmInterpreterError, executeAvm } from './interpreter/index.js';
import { AvmJournal } from './journal/journal.js';
import { decodeBytecode } from './opcodes/decode_bytecode.js';
import { Instruction } from './opcodes/index.js';
Expand Down Expand Up @@ -49,10 +49,8 @@ export class AvmContext {

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

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

return interpreter.run();
const machineState = new AvmMachineState(this.executionEnvironment);
return executeAvm(machineState, this.journal, instructions);
}

/**
Expand Down
5 changes: 2 additions & 3 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 { initExecutionEnvironment } from './fixtures/index.js';
import { AvmInterpreter } from './interpreter/interpreter.js';
import { executeAvm } from './interpreter/interpreter.js';
import { AvmJournal } from './journal/journal.js';
import { decodeBytecode } from './opcodes/decode_bytecode.js';
import { encodeToBytecode } from './opcodes/encode_to_bytecode.js';
Expand All @@ -30,8 +30,7 @@ describe('avm', () => {

// Execute instructions
const context = new AvmMachineState(initExecutionEnvironment({ calldata }));
const interpreter = new AvmInterpreter(context, journal, instructions);
const avmReturnData = await interpreter.run();
const avmReturnData = await executeAvm(context, journal, instructions);

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Add } from '../opcodes/arithmetic.js';
import { Jump, Return } from '../opcodes/control_flow.js';
import { Instruction } from '../opcodes/instruction.js';
import { CalldataCopy } from '../opcodes/memory.js';
import { AvmInterpreter, InvalidProgramCounterError } from './interpreter.js';
import { InvalidProgramCounterError, executeAvm } from './interpreter.js';

describe('interpreter', () => {
let journal: MockProxy<AvmJournal>;
Expand All @@ -28,8 +28,7 @@ describe('interpreter', () => {
];

const machineState = new AvmMachineState(initExecutionEnvironment({ calldata }));
const interpreter = new AvmInterpreter(machineState, journal, instructions);
const avmReturnData = await interpreter.run();
const avmReturnData = await executeAvm(machineState, journal, instructions);

expect(avmReturnData.reverted).toBe(false);
expect(avmReturnData.revertReason).toBeUndefined();
Expand All @@ -44,9 +43,7 @@ describe('interpreter', () => {
const instructions: Instruction[] = [new Jump(invalidJumpDestination)];

const machineState = new AvmMachineState(initExecutionEnvironment({ calldata }));
const interpreter = new AvmInterpreter(machineState, journal, instructions);

const avmReturnData = await interpreter.run();
const avmReturnData = await executeAvm(machineState, journal, instructions);

expect(avmReturnData.reverted).toBe(true);
expect(avmReturnData.revertReason).toBeInstanceOf(InvalidProgramCounterError);
Expand Down
82 changes: 29 additions & 53 deletions yarn-project/acir-simulator/src/avm/interpreter/interpreter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { Fr } from '@aztec/foundation/fields';

import { strict as assert } from 'assert';

import { AvmMachineState } from '../avm_machine_state.js';
Expand All @@ -8,66 +6,44 @@ import { AvmJournal } from '../journal/index.js';
import { Instruction } from '../opcodes/index.js';

/**
* Avm Interpreter
*
* Executes an Avm context
* Run the avm
* @returns bool - successful execution will return true
* - reverted execution will return false
* - any other panic will throw
*/
export class AvmInterpreter {
private instructions: Instruction[] = [];
private machineState: AvmMachineState;
private journal: AvmJournal;

constructor(machineState: AvmMachineState, stateManager: AvmJournal, instructions: Instruction[]) {
this.machineState = machineState;
this.journal = stateManager;
this.instructions = instructions;
}

/**
* Run the avm
* @returns bool - successful execution will return true
* - reverted execution will return false
* - any other panic will throw
*/
async run(): Promise<AvmMessageCallResult> {
assert(this.instructions.length > 0);

try {
while (!this.machineState.halted) {
const instruction = this.instructions[this.machineState.pc];
assert(!!instruction); // This should never happen
export async function executeAvm(
machineState: AvmMachineState,
journal: AvmJournal,
instructions: Instruction[] = [],
): Promise<AvmMessageCallResult> {
assert(instructions.length > 0);

await instruction.execute(this.machineState, this.journal);
try {
while (!machineState.halted) {
const instruction = instructions[machineState.pc];
assert(!!instruction); // This should never happen

if (this.machineState.pc >= this.instructions.length) {
throw new InvalidProgramCounterError(this.machineState.pc, /*max=*/ this.instructions.length);
}
}
await instruction.execute(machineState, journal);

const returnData = this.machineState.getReturnData();
if (this.machineState.reverted) {
return AvmMessageCallResult.revert(returnData);
if (machineState.pc >= instructions.length) {
throw new InvalidProgramCounterError(machineState.pc, /*max=*/ instructions.length);
}
}

return AvmMessageCallResult.success(returnData);
} catch (_e) {
if (!(_e instanceof AvmInterpreterError)) {
throw _e;
}
const returnData = machineState.getReturnData();
if (machineState.reverted) {
return AvmMessageCallResult.revert(returnData);
}

const revertReason: AvmInterpreterError = _e;
const revertData = this.machineState.getReturnData();
return AvmMessageCallResult.revert(revertData, revertReason);
return AvmMessageCallResult.success(returnData);
} catch (_e) {
if (!(_e instanceof AvmInterpreterError)) {
throw _e;
}
}

/**
* Get the return data from avm execution
* TODO: this should fail if the code has not been executed
* - maybe move the return in run into a variable and track it
*/
returnData(): Fr[] {
return this.machineState.getReturnData();
const revertReason: AvmInterpreterError = _e;
const revertData = machineState.getReturnData();
return AvmMessageCallResult.revert(revertData, revertReason);
}
}

Expand Down

0 comments on commit 14e8c5c

Please sign in to comment.