Skip to content

Commit

Permalink
feat: revert instruction:
Browse files Browse the repository at this point in the history
  • Loading branch information
Maddiaa0 committed Jan 29, 2024
1 parent 07260af commit 29758eb
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 6 deletions.
5 changes: 5 additions & 0 deletions yarn-project/acir-simulator/src/avm/avm_machine_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ export class AvmMachineState {
* If an instruction triggers a halt, then it ends execution of the VM
*/
public halted: boolean;
/**
* Signifies if the execution has reverted ( due to a revert instruction )
*/
public reverted: boolean;

/**
* Create a new avm context
Expand All @@ -45,6 +49,7 @@ export class AvmMachineState {
this.callStack = [];

this.halted = false;
this.reverted = false;

this.executionEnvironment = executionEnvironment;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export class AvmInterpreter {
}

const returnData = this.machineState.getReturnData();
if (this.machineState.reverted) {
return AvmMessageCallResult.revert(returnData);
}

return AvmMessageCallResult.success(returnData);
} catch (_e) {
if (!(_e instanceof AvmInterpreterError)) {
Expand Down
47 changes: 41 additions & 6 deletions yarn-project/acir-simulator/src/avm/opcodes/control_flow.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { MockProxy, mock } from 'jest-mock-extended';

import { AvmMachineState } from '../avm_machine_state.js';
import { TypeTag, Uint16 } from '../avm_memory_types.js';
import { Field, TypeTag, Uint16 } from '../avm_memory_types.js';
import { initExecutionEnvironment } from '../fixtures/index.js';
import { AvmJournal } from '../journal/journal.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';
import { InternalCall, InternalReturn, Jump, JumpI } from './control_flow.js';
import { InternalCall, InternalReturn, Jump, JumpI, Return, Revert } from './control_flow.js';
import { InstructionExecutionError } from './instruction.js';
import { CMov, CalldataCopy, Cast, Mov, Set } from './memory.js';

Expand All @@ -20,8 +20,9 @@ describe('Control Flow Opcodes', () => {
machineState = new AvmMachineState(initExecutionEnvironment());
});

it('Should implement JUMP', async () => {
const jumpLocation = 22;
describe('Jumps', () => {
it('Should implement JUMP', async () => {
const jumpLocation = 22;

expect(machineState.pc).toBe(0);

Expand Down Expand Up @@ -144,8 +145,42 @@ describe('Control Flow Opcodes', () => {
innerMachineState.memory.set(1, new Uint16(8n));
innerMachineState.memory.set(2, new Uint16(12n));
expect(machineState.pc).toBe(0);
await instruction.execute(innerMachineState, journal);
expect(innerMachineState.pc).toBe(1);

await instruction.execute(machineState, journal);
}
});

});

describe('Halting Opcodes', () => {
it('Should return data from the return opcode', async () => {
const returnData = [new Field(1n), new Field(2n), new Field(3n)];

machineState.memory.set(0, new Field(1n));
machineState.memory.set(1, new Field(2n));
machineState.memory.set(2, new Field(3n));

const instruction = new Return(0, returnData.length);
await instruction.execute(machineState, journal);

expect(machineState.getReturnData()).toEqual(returnData);
expect(machineState.halted).toBe(true);
expect(machineState.reverted).toBe(false);
});

it('Should return data and revert from the revert opcode', async () => {
const returnData = [new Field(1n), new Field(2n), new Field(3n)];

machineState.memory.set(0, new Field(1n));
machineState.memory.set(1, new Field(2n));
machineState.memory.set(2, new Field(3n));

const instruction = new Revert(0, returnData.length);
await instruction.execute(machineState, journal);

expect(machineState.getReturnData()).toEqual(returnData);
expect(machineState.halted).toBe(true);
expect(machineState.reverted).toBe(true);
});
});
});
16 changes: 16 additions & 0 deletions yarn-project/acir-simulator/src/avm/opcodes/control_flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ export class Return extends Instruction {
}
}

export class Revert extends Instruction {
static type: string = 'RETURN';
static numberOfOperands = 2;

constructor(private returnOffset: number, private retSize: number) {
super();
}

async execute(machineState: AvmMachineState, _journal: AvmJournal): Promise<void> {
const returnData = machineState.readMemoryChunk(this.returnOffset, this.returnOffset + this.retSize);
machineState.setReturnData(returnData);

this.revert(machineState);
}
}

export class Jump extends Instruction {
static type: string = 'JUMP';
static numberOfOperands = 1;
Expand Down
5 changes: 5 additions & 0 deletions yarn-project/acir-simulator/src/avm/opcodes/instruction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export abstract class Instruction {
machineState.halted = true;
}

revert(machineState: AvmMachineState): void {
machineState.halted = true;
machineState.reverted = true;
}

static checkTags(machineState: AvmMachineState, tag: TypeTag, ...offsets: number[]) {
for (const off of offsets) {
if (machineState.memory.getTag(off) !== tag) {
Expand Down

0 comments on commit 29758eb

Please sign in to comment.