Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Maddiaa0 committed Jan 29, 2024
1 parent e2a271f commit ce8aceb
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 118 deletions.
225 changes: 113 additions & 112 deletions yarn-project/acir-simulator/src/avm/opcodes/control_flow.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Fr } from '@aztec/foundation/fields';

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

import { AvmMachineState } from '../avm_machine_state.js';
Expand All @@ -24,137 +26,136 @@ describe('Control Flow Opcodes', () => {
it('Should implement JUMP', async () => {
const jumpLocation = 22;

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

const instruction = new Jump(jumpLocation);
await instruction.execute(machineState, journal);
expect(machineState.pc).toBe(jumpLocation);
});

it('Should implement JUMPI - truthy', async () => {
const jumpLocation = 22;
const jumpLocation1 = 69;
expect(machineState.pc).toBe(0);

expect(machineState.pc).toBe(0);
const instruction = new Jump(jumpLocation);
await instruction.execute(machineState, journal);
expect(machineState.pc).toBe(jumpLocation);
});

machineState.memory.set(0, new Uint16(1n));
machineState.memory.set(1, new Uint16(2n));
it('Should implement JUMPI - truthy', async () => {
const jumpLocation = 22;
const jumpLocation1 = 69;

const instruction = new JumpI(jumpLocation, 0);
await instruction.execute(machineState, journal);
expect(machineState.pc).toBe(jumpLocation);
expect(machineState.pc).toBe(0);

// Truthy can be greater than 1
const instruction1 = new JumpI(jumpLocation1, 1);
await instruction1.execute(machineState, journal);
expect(machineState.pc).toBe(jumpLocation1);
});
machineState.memory.set(0, new Uint16(1n));
machineState.memory.set(1, new Uint16(2n));

it('Should implement JUMPI - falsy', async () => {
const jumpLocation = 22;
const instruction = new JumpI(jumpLocation, 0);
await instruction.execute(machineState, journal);
expect(machineState.pc).toBe(jumpLocation);

expect(machineState.pc).toBe(0);
// Truthy can be greater than 1
const instruction1 = new JumpI(jumpLocation1, 1);
await instruction1.execute(machineState, journal);
expect(machineState.pc).toBe(jumpLocation1);
});

machineState.memory.set(0, new Uint16(0n));
it('Should implement JUMPI - falsy', async () => {
const jumpLocation = 22;

const instruction = new JumpI(jumpLocation, 0);
await instruction.execute(machineState, journal);
expect(machineState.pc).toBe(1);
});
expect(machineState.pc).toBe(0);

it('Should implement Internal Call and Return', async () => {
const jumpLocation = 22;
machineState.memory.set(0, new Uint16(0n));

expect(machineState.pc).toBe(0);
const instruction = new JumpI(jumpLocation, 0);
await instruction.execute(machineState, journal);
expect(machineState.pc).toBe(1);
});

const instruction = new InternalCall(jumpLocation);
const returnInstruction = new InternalReturn();
it('Should implement Internal Call and Return', async () => {
const jumpLocation = 22;

await instruction.execute(machineState, journal);
expect(machineState.pc).toBe(jumpLocation);
expect(machineState.pc).toBe(0);

await returnInstruction.execute(machineState, journal);
expect(machineState.pc).toBe(1);
});
const instruction = new InternalCall(jumpLocation);
const returnInstruction = new InternalReturn();

it('Should chain series of control flow instructions', async () => {
const jumpLocation0 = 22;
const jumpLocation1 = 69;
const jumpLocation2 = 1337;

const aloneJumpLocation = 420;

const instructions = [
// pc | internal call stack
new InternalCall(jumpLocation0), // 22 | [1]
new InternalCall(jumpLocation1), // 69 | [1, 23]
new InternalReturn(), // 23 | [1]
new Jump(aloneJumpLocation), // 420 | [1]
new InternalCall(jumpLocation2), // 1337| [1, 421]
new InternalReturn(), // 421 | [1]
new InternalReturn(), // 1 | []
];

// The expected program counter after each instruction is invoked
const expectedPcs = [
jumpLocation0,
jumpLocation1,
jumpLocation0 + 1,
aloneJumpLocation,
jumpLocation2,
aloneJumpLocation + 1,
1,
];

for (let i = 0; i < instructions.length; i++) {
await instructions[i].execute(machineState, journal);
expect(machineState.pc).toBe(expectedPcs[i]);
}
});
await instruction.execute(machineState, journal);
expect(machineState.pc).toBe(jumpLocation);

it('Should error if Internal Return is called without a corresponding Internal Call', async () => {
const returnInstruction = () => new InternalReturn().execute(machineState, journal);
await expect(returnInstruction()).rejects.toThrow(InstructionExecutionError);
});
await returnInstruction.execute(machineState, journal);
expect(machineState.pc).toBe(1);
});

it('Should increment PC on All other Instructions', async () => {
const instructions = [
new Add(0, 1, 2),
new Sub(0, 1, 2),
new Mul(0, 1, 2),
new Lt(TypeTag.UINT16, 0, 1, 2),
new Lte(TypeTag.UINT16, 0, 1, 2),
new Eq(TypeTag.UINT16, 0, 1, 2),
new Xor(TypeTag.UINT16, 0, 1, 2),
new And(TypeTag.UINT16, 0, 1, 2),
new Or(TypeTag.UINT16, 0, 1, 2),
new Shl(TypeTag.UINT16, 0, 1, 2),
new Shr(TypeTag.UINT16, 0, 1, 2),
new Not(TypeTag.UINT16, 0, 2),
new CalldataCopy(0, 1, 2),
new Set(TypeTag.UINT16, 0n, 1),
new Mov(0, 1),
new CMov(0, 1, 2, 3),
new Cast(TypeTag.UINT16, 0, 1),
];

for (const instruction of instructions) {
// Use a fresh machine state each run
const innerMachineState = new AvmMachineState(initExecutionEnvironment());
innerMachineState.memory.set(0, new Uint16(4n));
innerMachineState.memory.set(1, new Uint16(8n));
innerMachineState.memory.set(2, new Uint16(12n));
expect(machineState.pc).toBe(0);
it('Should chain series of control flow instructions', async () => {
const jumpLocation0 = 22;
const jumpLocation1 = 69;
const jumpLocation2 = 1337;

const aloneJumpLocation = 420;

const instructions = [
// pc | internal call stack
new InternalCall(jumpLocation0), // 22 | [1]
new InternalCall(jumpLocation1), // 69 | [1, 23]
new InternalReturn(), // 23 | [1]
new Jump(aloneJumpLocation), // 420 | [1]
new InternalCall(jumpLocation2), // 1337| [1, 421]
new InternalReturn(), // 421 | [1]
new InternalReturn(), // 1 | []
];

// The expected program counter after each instruction is invoked
const expectedPcs = [
jumpLocation0,
jumpLocation1,
jumpLocation0 + 1,
aloneJumpLocation,
jumpLocation2,
aloneJumpLocation + 1,
1,
];

for (let i = 0; i < instructions.length; i++) {
await instructions[i].execute(machineState, journal);
expect(machineState.pc).toBe(expectedPcs[i]);
}
});

await instruction.execute(machineState, journal);
}
});
it('Should error if Internal Return is called without a corresponding Internal Call', async () => {
const returnInstruction = () => new InternalReturn().execute(machineState, journal);
await expect(returnInstruction()).rejects.toThrow(InstructionExecutionError);
});

it('Should increment PC on All other Instructions', async () => {
const instructions = [
new Add(0, 1, 2),
new Sub(0, 1, 2),
new Mul(0, 1, 2),
new Lt(TypeTag.UINT16, 0, 1, 2),
new Lte(TypeTag.UINT16, 0, 1, 2),
new Eq(TypeTag.UINT16, 0, 1, 2),
new Xor(TypeTag.UINT16, 0, 1, 2),
new And(TypeTag.UINT16, 0, 1, 2),
new Or(TypeTag.UINT16, 0, 1, 2),
new Shl(TypeTag.UINT16, 0, 1, 2),
new Shr(TypeTag.UINT16, 0, 1, 2),
new Not(TypeTag.UINT16, 0, 2),
new CalldataCopy(0, 1, 2),
new Set(TypeTag.UINT16, 0n, 1),
new Mov(0, 1),
new CMov(0, 1, 2, 3),
new Cast(TypeTag.UINT16, 0, 1),
];

for (const instruction of instructions) {
// Use a fresh machine state each run
const innerMachineState = new AvmMachineState(initExecutionEnvironment());
innerMachineState.memory.set(0, new Uint16(4n));
innerMachineState.memory.set(1, new Uint16(8n));
innerMachineState.memory.set(2, new Uint16(12n));
expect(innerMachineState.pc).toBe(0);

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

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

machineState.memory.set(0, new Field(1n));
machineState.memory.set(1, new Field(2n));
Expand All @@ -169,10 +170,10 @@ describe('Control Flow Opcodes', () => {
});

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

machineState.memory.set(0, new Field(1n));
machineState.memory.set(1, new Field(2n));
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);
Expand Down
10 changes: 4 additions & 6 deletions yarn-project/acir-simulator/src/avm/opcodes/control_flow.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { Fr } from '@aztec/foundation/fields';

import { AvmMachineState } from '../avm_machine_state.js';
import { IntegralValue } from '../avm_memory_types.js';
import { AvmJournal } from '../journal/journal.js';
Expand All @@ -14,9 +12,7 @@ export class Return extends Instruction {
}

async execute(machineState: AvmMachineState, _journal: AvmJournal): Promise<void> {
const returnData = machineState.memory
.getSlice(this.returnOffset, this.copySize)
.map(word => new Fr(word.toBigInt()));
const returnData = machineState.memory.getSlice(this.returnOffset, this.copySize).map(word => word.toFr());

machineState.setReturnData(returnData);

Expand All @@ -33,7 +29,9 @@ export class Revert extends Instruction {
}

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

this.revert(machineState);
Expand Down

0 comments on commit ce8aceb

Please sign in to comment.