Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,6 @@ export abstract class AvmInterpreterError extends Error {
export class InvalidProgramCounterError extends AvmInterpreterError {
constructor(pc: number, max: number) {
super(`Invalid program counter ${pc}, max is ${max}`);
this.name = 'InvalidProgramCounterError';
}
}
166 changes: 166 additions & 0 deletions yarn-project/acir-simulator/src/avm/opcodes/bitwise.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { Fr } from '@aztec/foundation/fields';

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

import { AvmMachineState } from '../avm_machine_state.js';
import { AvmStateManager } from '../avm_state_manager.js';
import {
And,
/*Not,*/
Or,
Shl,
Shr,
Xor,
} from './bitwise.js';

describe('Bitwise instructions', () => {
let machineState: AvmMachineState;
let stateManager = mock<AvmStateManager>();

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

it('Should AND correctly over Fr type', () => {
const a = new Fr(0b11111110010011100100n);
const b = new Fr(0b11100100111001001111n);

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

new And(0, 1, 2).execute(machineState, stateManager);

const expected = new Fr(0b11100100010001000100n);
const actual = machineState.readMemory(2);
expect(actual).toEqual(expected);
});

it('Should OR correctly over Fr type', () => {
const a = new Fr(0b11111110010011100100n);
const b = new Fr(0b11100100111001001111n);

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

new Or(0, 1, 2).execute(machineState, stateManager);

const expected = new Fr(0b11111110111011101111n);
const actual = machineState.readMemory(2);
expect(actual).toEqual(expected);
});

it('Should XOR correctly over Fr type', () => {
const a = new Fr(0b11111110010011100100n);
const b = new Fr(0b11100100111001001111n);

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

new Xor(0, 1, 2).execute(machineState, stateManager);

const expected = new Fr(0b00011010101010101011n);
const actual = machineState.readMemory(2);
expect(actual).toEqual(expected);
});

describe('SHR', () => {
it('Should shift correctly 0 positions over Fr type', () => {
const a = new Fr(0b11111110010011100100n);
const b = new Fr(0n);

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

new Shr(0, 1, 2).execute(machineState, stateManager);

const expected = a;
const actual = machineState.readMemory(2);
expect(actual).toEqual(expected);
});

it('Should shift correctly 2 positions over Fr type', () => {
const a = new Fr(0b11111110010011100100n);
const b = new Fr(2n);

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

new Shr(0, 1, 2).execute(machineState, stateManager);

const expected = new Fr(0b00111111100100111001n);
const actual = machineState.readMemory(2);
expect(actual).toEqual(expected);
});

it('Should shift correctly 19 positions over Fr type', () => {
const a = new Fr(0b11111110010011100100n);
const b = new Fr(19n);

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

new Shr(0, 1, 2).execute(machineState, stateManager);

const expected = new Fr(0b01n);
const actual = machineState.readMemory(2);
expect(actual).toEqual(expected);
});
});

describe('SHL', () => {
it('Should shift correctly 0 positions over Fr type', () => {
const a = new Fr(0b11111110010011100100n);
const b = new Fr(0n);

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

new Shl(0, 1, 2).execute(machineState, stateManager);

const expected = a;
const actual = machineState.readMemory(2);
expect(actual).toEqual(expected);
});

it('Should shift correctly 2 positions over Fr type', () => {
const a = new Fr(0b11111110010011100100n);
const b = new Fr(2n);

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

new Shl(0, 1, 2).execute(machineState, stateManager);

const expected = new Fr(0b1111111001001110010000n);
const actual = machineState.readMemory(2);
expect(actual).toEqual(expected);
});

// it('Should shift correctly over bit limit over Fr type', () => {
// const a = new Fr(0b11111110010011100100n);
// const b = new Fr(19n);

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

// new Shl(0, 1, 2).execute(machineState, stateManager);

// const expected = new Fr(0b01n);
// const actual = machineState.readMemory(2);
// expect(actual).toEqual(expected);
// });
});

// it('Should NOT correctly over Fr type', () => {
// const a = new Fr(0b11111110010011100100n);

// machineState.writeMemory(0, a);

// new Not(0, 1).execute(machineState, stateManager);

// const expected = new Fr(0b00000001101100011011n); // high bits!
// const actual = machineState.readMemory(1);
// expect(actual).toEqual(expected);
// });
});
3 changes: 3 additions & 0 deletions yarn-project/acir-simulator/src/avm/opcodes/bitwise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ export class Shr extends Instruction {
const a: Fr = machineState.readMemory(this.aOffset);
const b: Fr = machineState.readMemory(this.bOffset);

// Here we are assuming that the field element maps to a positive number.
// The >> operator is *signed* in JS (and it sign extends).
// E.g.: -1n >> 3n == -1n.
const dest = new Fr(a.toBigInt() >> b.toBigInt());
machineState.writeMemory(this.destOffset, dest);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ 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, InternalCallStackEmptyError, InternalReturn, Jump, JumpI } from './control_flow.js';
import { CalldataCopy, Cast, Mov, Set } from './memory.js';
import { CMov, CalldataCopy, Cast, Mov, Set } from './memory.js';

describe('Control Flow Opcodes', () => {
let stateManager = mock<AvmStateManager>();
Expand Down Expand Up @@ -132,6 +132,7 @@ describe('Control Flow Opcodes', () => {
new CalldataCopy(0, 1, 2),
new Set(0n, 1),
new Mov(0, 1),
new CMov(0, 1, 2, 3),
new Cast(0, 1),
];

Expand Down
27 changes: 12 additions & 15 deletions yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { Add, Div, Mul, Sub } from './arithmetic.js';
//import { And, Not, Or, Shl, Shr, Xor } from './bitwise.js';
import { And, Not, Or, Shl, Shr, Xor } from './bitwise.js';
//import { Eq, Lt, Lte } from './comparators.js';
import { InternalCall, InternalReturn, Jump, JumpI, Return } from './control_flow.js';
import { Instruction } from './instruction.js';
import {
CalldataCopy,
/*Cast, Mov*/
} from './memory.js';
import { CMov, CalldataCopy, Cast, Mov, Set } from './memory.js';
import { Opcode } from './opcodes.js';

/** - */
Expand All @@ -30,14 +27,14 @@ export const INSTRUCTION_SET: Map<Opcode, InstructionConstructorAndMembers> = ne
//[Opcode.LT, Lt],
//[Opcode.LTE, Lte],
//// Compute - Bitwise
//[Opcode.AND, And],
//[Opcode.OR, Or],
//[Opcode.XOR, Xor],
//[Opcode.NOT, Not],
//[Opcode.SHL, Shl],
//[Opcode.SHR, Shr],
[Opcode.AND, And],
[Opcode.OR, Or],
[Opcode.XOR, Xor],
[Opcode.NOT, Not],
[Opcode.SHL, Shl],
[Opcode.SHR, Shr],
//// Compute - Type Conversions
//[Opcode.CAST, Cast],
[Opcode.CAST, Cast],

//// Execution Environment
//[Opcode.ADDRESS, Address],
Expand Down Expand Up @@ -72,9 +69,9 @@ export const INSTRUCTION_SET: Map<Opcode, InstructionConstructorAndMembers> = ne
[Opcode.INTERNALCALL, InternalCall],
[Opcode.INTERNALRETURN, InternalReturn],
//// Machine State - Memory
//[Opcode.SET, Set],
//[Opcode.MOV, Mov],
//[Opcode.CMOV, CMov],
[Opcode.SET, Set],
[Opcode.MOV, Mov],
[Opcode.CMOV, CMov],

//// World State
//[Opcode.BLOCKHEADERBYNUMBER, Blockheaderbynumber],
Expand Down
Loading