From 0a9b73da05ef07360de3c945f9a7ecf57c3ef0d9 Mon Sep 17 00:00:00 2001 From: fcarreiro Date: Wed, 7 Feb 2024 09:57:40 +0000 Subject: [PATCH 01/12] chore(avm): add SET serialize comments and simplify signature --- .../simulator/src/avm/opcodes/instruction.ts | 17 ++++++++++------- .../simulator/src/avm/opcodes/memory.ts | 7 +++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/yarn-project/simulator/src/avm/opcodes/instruction.ts b/yarn-project/simulator/src/avm/opcodes/instruction.ts index 3f4cf27f7de..f968ad88d2b 100644 --- a/yarn-project/simulator/src/avm/opcodes/instruction.ts +++ b/yarn-project/simulator/src/avm/opcodes/instruction.ts @@ -1,4 +1,4 @@ -import { assert } from 'console'; +import { strict as assert } from 'assert'; import type { AvmContext } from '../avm_context.js'; import { BufferCursor } from '../serialization/buffer_cursor.js'; @@ -39,7 +39,7 @@ export abstract class Instruction { * @returns The serialized instruction. */ public serialize(this: any): Buffer { - assert(this instanceof Instruction); + assert(!!this.constructor.wireFormat, 'wireFormat must be defined on the class'); return serialize(this.constructor.wireFormat, this); } @@ -50,12 +50,15 @@ export abstract class Instruction { * @param buf Buffer to read from. * @returns Constructed instance of Class. */ - public static deserialize; wireFormat: OperandType[] }>( - this: T, - buf: BufferCursor | Buffer, - ): InstanceType { + public static deserialize(this: InstructionConstructor, buf: BufferCursor | Buffer): Instruction { + assert(!!this.wireFormat, 'wireFormat must be defined on the instruction class'); const res = deserialize(buf, this.wireFormat); - const args = res.slice(1) as ConstructorParameters; // Remove opcode. + const args = res.slice(1); // Remove opcode. return new this(...args); } } + +type InstructionConstructor = { + new (...args: any[]): Instruction; + wireFormat?: OperandType[]; +}; diff --git a/yarn-project/simulator/src/avm/opcodes/memory.ts b/yarn-project/simulator/src/avm/opcodes/memory.ts index 06e7b615332..6f181e52f96 100644 --- a/yarn-project/simulator/src/avm/opcodes/memory.ts +++ b/yarn-project/simulator/src/avm/opcodes/memory.ts @@ -43,6 +43,7 @@ export class Set extends Instruction { super(); } + /** We need to use a custom serialize function because of the variable length of the value. */ public serialize(): Buffer { const format: OperandType[] = [ ...Set.wireFormatBeforeConst, @@ -52,10 +53,8 @@ export class Set extends Instruction { return serialize(format, this); } - public static deserialize }>( - this: T, - buf: BufferCursor | Buffer, - ): InstanceType { + /** We need to use a custom deserialize function because of the variable length of the value. */ + public static deserialize(this: typeof Set, buf: BufferCursor | Buffer): Set { if (buf instanceof Buffer) { buf = new BufferCursor(buf); } From 6648b29df0c6b0f6e9479f3421ed3cf712cae72e Mon Sep 17 00:00:00 2001 From: fcarreiro Date: Wed, 7 Feb 2024 15:19:08 +0000 Subject: [PATCH 02/12] chore(avm): add/improve tests for AvmContext, tagged memory, etc --- yarn-project/simulator/package.json | 2 + .../simulator/src/avm/avm_context.test.ts | 57 +++- .../src/avm/avm_execution_environment.test.ts | 53 ++-- .../src/avm/avm_memory_types.test.ts | 190 ++++++++++- .../simulator/src/avm/avm_memory_types.ts | 15 +- .../simulator/src/avm/fixtures/index.ts | 8 + .../src/avm/opcodes/arithmetic.test.ts | 10 +- .../avm/opcodes/environment_getters.test.ts | 298 ++++-------------- yarn-project/yarn.lock | 11 + 9 files changed, 348 insertions(+), 296 deletions(-) diff --git a/yarn-project/simulator/package.json b/yarn-project/simulator/package.json index 0f55f685910..0a84d51627b 100644 --- a/yarn-project/simulator/package.json +++ b/yarn-project/simulator/package.json @@ -45,10 +45,12 @@ "@jest/globals": "^29.5.0", "@types/jest": "^29.5.0", "@types/levelup": "^5.1.3", + "@types/lodash.merge": "^4.6.9", "@types/memdown": "^3.0.2", "@types/node": "^18.7.23", "jest": "^29.5.0", "jest-mock-extended": "^3.0.4", + "lodash.merge": "^4.6.2", "ts-jest": "^29.1.0", "ts-node": "^10.9.1", "typescript": "^5.0.4", diff --git a/yarn-project/simulator/src/avm/avm_context.test.ts b/yarn-project/simulator/src/avm/avm_context.test.ts index 6f198fa0bb8..f54fe99a358 100644 --- a/yarn-project/simulator/src/avm/avm_context.test.ts +++ b/yarn-project/simulator/src/avm/avm_context.test.ts @@ -1,18 +1,55 @@ -// import { AztecAddress, Fr } from '@aztec/circuits.js'; -// import { initContext } from './fixtures/index.js'; +import { AztecAddress, Fr } from '@aztec/circuits.js'; + +import { allSameExcept, initContext } from './fixtures/index.js'; describe('Avm Context', () => { it('New call should fork context correctly', () => { - // const context = initContext(); - // const newAddress = AztecAddress.random(); - // const newCalldata = [new Fr(1), new Fr(2)]; - // const newContext = context.createNestedContractCallContext(newAddress, newCalldata); + const context = initContext(); + context.machineState.pc = 20; + + const newAddress = AztecAddress.random(); + const newCalldata = [new Fr(1), new Fr(2)]; + const newContext = context.createNestedContractCallContext(newAddress, newCalldata); + + expect(newContext.environment).toEqual( + allSameExcept(context.environment, { + address: newAddress, + storageAddress: newAddress, + calldata: newCalldata, + isStaticCall: false, + }), + ); + expect(newContext.machineState).toEqual( + allSameExcept(context.machineState, { + pc: 0, + }), + ); + // FIXME: I can't get this to work. + // expect(newContext.worldState).toEqual(context.worldState.fork()); }); it('New static call should fork context correctly', () => { - // const context = initContext(); - // const newAddress = AztecAddress.random(); - // const newCalldata = [new Fr(1), new Fr(2)]; - // const newContext = context.createNestedContractStaticCallContext(newAddress, newCalldata); + const context = initContext(); + context.machineState.pc = 20; + + const newAddress = AztecAddress.random(); + const newCalldata = [new Fr(1), new Fr(2)]; + const newContext = context.createNestedContractStaticCallContext(newAddress, newCalldata); + + expect(newContext.environment).toEqual( + allSameExcept(context.environment, { + address: newAddress, + storageAddress: newAddress, + calldata: newCalldata, + isStaticCall: true, + }), + ); + expect(newContext.machineState).toEqual( + allSameExcept(context.machineState, { + pc: 0, + }), + ); + // FIXME: I can't get this to work. + // expect(newContext.worldState).toEqual(context.worldState.fork()); }); }); diff --git a/yarn-project/simulator/src/avm/avm_execution_environment.test.ts b/yarn-project/simulator/src/avm/avm_execution_environment.test.ts index 27043eb3660..e2104cbad59 100644 --- a/yarn-project/simulator/src/avm/avm_execution_environment.test.ts +++ b/yarn-project/simulator/src/avm/avm_execution_environment.test.ts @@ -1,6 +1,6 @@ import { Fr } from '@aztec/foundation/fields'; -import { initExecutionEnvironment } from './fixtures/index.js'; +import { allSameExcept, initExecutionEnvironment } from './fixtures/index.js'; describe('Execution Environment', () => { const newAddress = new Fr(123456n); @@ -10,46 +10,39 @@ describe('Execution Environment', () => { const executionEnvironment = initExecutionEnvironment(); const newExecutionEnvironment = executionEnvironment.deriveEnvironmentForNestedCall(newAddress, calldata); - allTheSameExcept(executionEnvironment, newExecutionEnvironment, { - address: newAddress, - storageAddress: newAddress, - calldata, - }); + expect(newExecutionEnvironment).toEqual( + allSameExcept(executionEnvironment, { + address: newAddress, + storageAddress: newAddress, + calldata, + }), + ); }); it('New delegate call should fork execution environment correctly', () => { const executionEnvironment = initExecutionEnvironment(); const newExecutionEnvironment = executionEnvironment.newDelegateCall(newAddress, calldata); - allTheSameExcept(executionEnvironment, newExecutionEnvironment, { - address: newAddress, - isDelegateCall: true, - calldata, - }); + expect(newExecutionEnvironment).toEqual( + allSameExcept(executionEnvironment, { + address: newAddress, + isDelegateCall: true, + calldata, + }), + ); }); it('New static call call should fork execution environment correctly', () => { const executionEnvironment = initExecutionEnvironment(); const newExecutionEnvironment = executionEnvironment.deriveEnvironmentForNestedStaticCall(newAddress, calldata); - allTheSameExcept(executionEnvironment, newExecutionEnvironment, { - address: newAddress, - storageAddress: newAddress, - isStaticCall: true, - calldata, - }); + expect(newExecutionEnvironment).toEqual( + allSameExcept(executionEnvironment, { + address: newAddress, + storageAddress: newAddress, + isStaticCall: true, + calldata, + }), + ); }); }); - -/** - * Check all properties of one object are the same, except for the specified differentProperties - */ -function allTheSameExcept(referenceObject: any, comparingObject: any, differentProperties: Record): void { - for (const key in referenceObject) { - if (Object.keys(differentProperties).includes(key)) { - expect(comparingObject[key]).toEqual(differentProperties[key]); - } else { - expect(comparingObject[key]).toEqual(referenceObject[key]); - } - } -} diff --git a/yarn-project/simulator/src/avm/avm_memory_types.test.ts b/yarn-project/simulator/src/avm/avm_memory_types.test.ts index 6df75930fe1..c5701c54d93 100644 --- a/yarn-project/simulator/src/avm/avm_memory_types.test.ts +++ b/yarn-project/simulator/src/avm/avm_memory_types.test.ts @@ -1,22 +1,190 @@ -import { Field, Uint8 } from './avm_memory_types.js'; +import { Field, TaggedMemory, Uint8, Uint16, Uint32, Uint64, Uint128 } from './avm_memory_types.js'; -// TODO: complete -describe('Uint8', () => { - it('Unsigned 8 max value', () => { - expect(new Uint8(255).toBigInt()).toEqual(255n); +describe('TaggedMemory', () => { + it('Elements should be undefined after construction', () => { + const mem = new TaggedMemory(); + expect(mem.get(10)).toBe(undefined); }); - it('Unsigned 8 bit add', () => { - expect(new Uint8(50).add(new Uint8(20))).toEqual(new Uint8(70)); + it(`Should set and get integral types`, () => { + const mem = new TaggedMemory(); + mem.set(10, new Uint8(5)); + expect(mem.get(10)).toStrictEqual(new Uint8(5)); }); - it('Unsigned 8 bit add wraps', () => { - expect(new Uint8(200).add(new Uint8(100))).toEqual(new Uint8(44)); + it(`Should set and get field elements`, () => { + const mem = new TaggedMemory(); + mem.set(10, new Field(5)); + expect(mem.get(10)).toStrictEqual(new Field(5)); + }); + + it(`Should getSlice beyond current size`, () => { + const mem = new TaggedMemory(); + const val = [new Field(5), new Field(6)]; + + mem.setSlice(10, val); + + expect(mem.getSlice(10, /*size=*/ 4)).toEqual([...val, undefined, undefined]); + }); + + it(`Should set and get slices`, () => { + const mem = new TaggedMemory(); + const val = [new Field(5), new Field(6)]; + + mem.setSlice(10, val); + + expect(mem.getSlice(10, /*size=*/ 2)).toStrictEqual(val); + }); +}); + +type IntegralClass = typeof Uint8 | typeof Uint16 | typeof Uint32 | typeof Uint64 | typeof Uint128; +describe.each([Uint8, Uint16, Uint32, Uint64, Uint128])('Integral Types', (clsValue: IntegralClass) => { + it(`Should construct a new ${clsValue.name} from a number`, () => { + const x = new clsValue(5); + expect(x.toBigInt()).toStrictEqual(5n); + }); + + it(`Should construct a new ${clsValue.name} from a bigint`, () => { + const x = new clsValue(5n); + expect(x.toBigInt()).toStrictEqual(5n); + }); + + it(`Should build a new ${clsValue.name}`, () => { + const x = new clsValue(5); + const newX = x.build(10n); + expect(newX).toStrictEqual(new clsValue(10n)); + }); + + it(`Should add two ${clsValue.name} correctly`, () => { + const a = new clsValue(5); + const b = new clsValue(10); + const result = a.add(b); + expect(result).toStrictEqual(new clsValue(15n)); + }); + + it(`Should subtract two ${clsValue.name} correctly`, () => { + const a = new clsValue(10); + const b = new clsValue(5); + const result = a.sub(b); + expect(result).toStrictEqual(new clsValue(5n)); + }); + + it(`Should multiply two ${clsValue.name} correctly`, () => { + const a = new clsValue(5); + const b = new clsValue(10); + const result = a.mul(b); + expect(result).toStrictEqual(new clsValue(50n)); + }); + + it(`Should divide two ${clsValue.name} correctly`, () => { + const a = new clsValue(10); + const b = new clsValue(5); + const result = a.div(b); + expect(result).toStrictEqual(new clsValue(2n)); + }); + + it('Should shift right ${clsValue.name} correctly', () => { + const uintA = new clsValue(10); + const result = uintA.shr(new clsValue(1n)); + expect(result).toEqual(new clsValue(5n)); + }); + + it('Should shift left ${clsValue.name} correctly', () => { + const uintA = new clsValue(10); + const result = uintA.shl(new clsValue(1n)); + expect(result).toEqual(new clsValue(20n)); + }); + + it('Should and two ${clsValue.name} correctly', () => { + const uintA = new clsValue(10); + const uintB = new clsValue(5); + const result = uintA.and(uintB); + expect(result).toEqual(new clsValue(0n)); + }); + + it('Should or two ${clsValue.name} correctly', () => { + const uintA = new clsValue(10); + const uintB = new clsValue(5); + const result = uintA.or(uintB); + expect(result).toEqual(new clsValue(15n)); + }); + + it('Should xor two ${clsValue.name} correctly', () => { + const uintA = new clsValue(10); + const uintB = new clsValue(5); + const result = uintA.xor(uintB); + expect(result).toEqual(new clsValue(15n)); + }); + + it(`Should check equality of two ${clsValue.name} correctly`, () => { + const a = new clsValue(5); + const b = new clsValue(5); + const c = new clsValue(10); + expect(a.equals(b)).toBe(true); + expect(a.equals(c)).toBe(false); + }); + + it(`Should check if one ${clsValue.name} is less than another correctly`, () => { + const a = new clsValue(5); + const b = new clsValue(10); + expect(a.lt(b)).toBe(true); + expect(b.lt(a)).toBe(false); }); }); describe('Field', () => { - it('Add correctly without wrapping', () => { - expect(new Field(27).add(new Field(48))).toEqual(new Field(75)); + it(`Should build a new Field`, () => { + const field = new Field(5); + const newField = field.build(10n); + expect(newField.toBigInt()).toStrictEqual(10n); + }); + + it(`Should add two Fields correctly`, () => { + const field1 = new Field(5); + const field2 = new Field(10); + const result = field1.add(field2); + expect(result).toStrictEqual(new Field(15n)); + }); + + it(`Should subtract two Fields correctly`, () => { + const field1 = new Field(10); + const field2 = new Field(5); + const result = field1.sub(field2); + expect(result).toStrictEqual(new Field(5n)); + }); + + it(`Should multiply two Fields correctly`, () => { + const field1 = new Field(5); + const field2 = new Field(10); + const result = field1.mul(field2); + expect(result).toStrictEqual(new Field(50n)); + }); + + // FIXME: field division is wrong + it.skip(`Should divide two Fields correctly`, () => { + const field1 = new Field(10); + const field2 = new Field(5); + const result = field1.div(field2); + expect(result).toStrictEqual(new Field(2n)); + }); + + it(`Should check equality of two Fields correctly`, () => { + const field1 = new Field(5); + const field2 = new Field(5); + const field3 = new Field(10); + expect(field1.equals(field2)).toBe(true); + expect(field1.equals(field3)).toBe(false); + }); + + it(`Should check if one Field is less than another correctly`, () => { + const field1 = new Field(5); + const field2 = new Field(10); + expect(field1.lt(field2)).toBe(true); + expect(field2.lt(field1)).toBe(false); + }); + + it(`Should convert Field to BigInt correctly`, () => { + const field = new Field(5); + expect(field.toBigInt()).toStrictEqual(5n); }); }); diff --git a/yarn-project/simulator/src/avm/avm_memory_types.ts b/yarn-project/simulator/src/avm/avm_memory_types.ts index e620263f059..12df18223c1 100644 --- a/yarn-project/simulator/src/avm/avm_memory_types.ts +++ b/yarn-project/simulator/src/avm/avm_memory_types.ts @@ -223,15 +223,16 @@ export enum TypeTag { // TODO: Consider automatic conversion when getting undefined values. export class TaggedMemory { // FIXME: memory should be 2^32, but TS doesn't allow for arrays that big. - static readonly MAX_MEMORY_SIZE = Number(1n << 31n); // 1n << 32n + static readonly MAX_MEMORY_SIZE = Number((1n << 32n) - 2n); private _mem: MemoryValue[]; constructor() { - // Initialize memory size, but leave all entries undefined. - this._mem = new Array(TaggedMemory.MAX_MEMORY_SIZE); + // We do not initialize memory size here because otherwise tests blow up when diffing. + this._mem = []; } public get(offset: number): MemoryValue { + assert(offset < TaggedMemory.MAX_MEMORY_SIZE); return this.getAs(offset); } @@ -243,16 +244,19 @@ export class TaggedMemory { public getSlice(offset: number, size: number): MemoryValue[] { assert(offset < TaggedMemory.MAX_MEMORY_SIZE); + assert(offset + size < TaggedMemory.MAX_MEMORY_SIZE); return this._mem.slice(offset, offset + size); } public getSliceAs(offset: number, size: number): T[] { assert(offset < TaggedMemory.MAX_MEMORY_SIZE); + assert(offset + size < TaggedMemory.MAX_MEMORY_SIZE); return this._mem.slice(offset, offset + size) as T[]; } public getSliceTags(offset: number, size: number): TypeTag[] { assert(offset < TaggedMemory.MAX_MEMORY_SIZE); + assert(offset + size < TaggedMemory.MAX_MEMORY_SIZE); return this._mem.slice(offset, offset + size).map(TaggedMemory.getTag); } @@ -263,6 +267,11 @@ export class TaggedMemory { public setSlice(offset: number, vs: MemoryValue[]) { assert(offset < TaggedMemory.MAX_MEMORY_SIZE); + assert(offset + vs.length < TaggedMemory.MAX_MEMORY_SIZE); + // We may need to extend the memory size, otherwise splice doesn't insert. + if (offset + vs.length > this._mem.length) { + this._mem.length = offset + vs.length; + } this._mem.splice(offset, vs.length, ...vs); } diff --git a/yarn-project/simulator/src/avm/fixtures/index.ts b/yarn-project/simulator/src/avm/fixtures/index.ts index bdbf5bed4bc..565622a40f3 100644 --- a/yarn-project/simulator/src/avm/fixtures/index.ts +++ b/yarn-project/simulator/src/avm/fixtures/index.ts @@ -4,6 +4,7 @@ import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { mock } from 'jest-mock-extended'; +import merge from 'lodash.merge'; import { CommitmentsDB, PublicContractsDB, PublicStateDB } from '../../index.js'; import { AvmContext } from '../avm_context.js'; @@ -76,3 +77,10 @@ export function initMachineState(overrides?: Partial): AvmMachi daGasLeft: overrides?.daGasLeft ?? 0, }); } + +/** + * Create a new object with all the same properties as the original, except for the ones in the overrides object. + */ +export function allSameExcept(original: any, overrides: any): any { + return merge({}, original, overrides); +} diff --git a/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts b/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts index a66201a9808..1475ef1a7c4 100644 --- a/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts @@ -201,9 +201,10 @@ describe('Arithmetic Instructions', () => { expect(inst.serialize()).toEqual(buf); }); - it('Should perform field division', async () => { - const a = new Field(2n); - const b = new Field(3n); + // FIXME: field division is wrong + it.skip('Should perform field division', async () => { + const a = new Field(10n); + const b = new Field(5n); context.machineState.memory.set(0, a); context.machineState.memory.set(1, b); @@ -217,8 +218,7 @@ describe('Arithmetic Instructions', () => { ).execute(context); const actual = context.machineState.memory.get(2); - const recovered = actual.mul(b); - expect(recovered).toEqual(a); + expect(actual).toEqual(new Field(2)); }); }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts index 0af20744a53..be9505d4e19 100644 --- a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts @@ -16,253 +16,77 @@ import { Version, } from './environment_getters.js'; -describe('Environment getters instructions', () => { - type EnvInstruction = Portal | FeePerL1Gas | FeePerL2Gas | FeePerDAGas | Origin | Sender | StorageAddress | Address; - const envGetterTest = async (key: string, value: Fr, instruction: EnvInstruction) => { +type EnvInstruction = + | typeof Portal + | typeof FeePerL1Gas + | typeof FeePerL2Gas + | typeof FeePerDAGas + | typeof Origin + | typeof Sender + | typeof StorageAddress + | typeof Address; +describe.each([ + [Portal, 'portal'], + [FeePerL1Gas, 'feePerL1Gas'], + [FeePerL2Gas, 'feePerL2Gas'], + [FeePerDAGas, 'feePerDaGas'], + [Origin, 'origin'], + [Sender, 'sender'], + [StorageAddress, 'storageAddress'], + [Address, 'address'], +])('Environment getters instructions', (clsValue: EnvInstruction, key: string) => { + it(`${clsValue.name} should (de)serialize correctly`, () => { + const buf = Buffer.from([ + clsValue.opcode, // opcode + 0x01, // indirect + ...Buffer.from('12345678', 'hex'), // dstOffset + ]); + const inst = new clsValue(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); + + expect(clsValue.deserialize(buf)).toEqual(inst); + expect(inst.serialize()).toEqual(buf); + }); + + it(`${clsValue.name} should read '${key}' correctly`, async () => { + const value = new Fr(123456n); + const instruction = new clsValue(/*indirect=*/ 0, /*dstOffset=*/ 0); const context = initContext({ env: initExecutionEnvironment({ [key]: value }) }); await instruction.execute(context); + const actual = context.machineState.memory.get(0).toFr(); expect(actual).toEqual(value); - }; - - describe('Address', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - Address.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new Address(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(Address.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read address correctly', async () => { - const address = new Fr(123456n); - await envGetterTest('address', address, new Address(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); - - describe('StorageAddress', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - StorageAddress.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new StorageAddress(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(StorageAddress.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read storage address correctly', async () => { - const address = new Fr(123456n); - await envGetterTest('storageAddress', address, new StorageAddress(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); - - describe('Portal', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - Portal.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new Portal(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(Portal.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read Portal correctly', async () => { - const portal = new Fr(123456n); - await envGetterTest('portal', portal, new Portal(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); - - describe('FeePerL1Gas', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - FeePerL1Gas.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new FeePerL1Gas(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(FeePerL1Gas.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read FeePerL1Gas correctly', async () => { - const feePerL1Gas = new Fr(123456n); - await envGetterTest('feePerL1Gas', feePerL1Gas, new FeePerL1Gas(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); }); +}); - describe('FeePerL2Gas', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - FeePerL2Gas.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new FeePerL2Gas(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(FeePerL2Gas.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read FeePerL2Gas correctly', async () => { - const feePerL2Gas = new Fr(123456n); - await envGetterTest('feePerL2Gas', feePerL2Gas, new FeePerL2Gas(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); - - describe('FeePerDAGas', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - FeePerDAGas.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new FeePerDAGas(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(FeePerDAGas.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read FeePerDAGas correctly', async () => { - const feePerDaGas = new Fr(123456n); - await envGetterTest('feePerDaGas', feePerDaGas, new FeePerDAGas(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); - - describe('Origin', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - Origin.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new Origin(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(Origin.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read Origin correctly', async () => { - const origin = new Fr(123456n); - await envGetterTest('origin', origin, new Origin(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); - - describe('Sender', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - Sender.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new Sender(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(Sender.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read Sender correctly', async () => { - const sender = new Fr(123456n); - await envGetterTest('sender', sender, new Sender(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); +type GlobalsInstruction = typeof ChainId | typeof Version | typeof BlockNumber | typeof Timestamp; +describe.each([ + [ChainId, 'chainId'], + [Version, 'version'], + [BlockNumber, 'blockNumber'], + [Timestamp, 'timestamp'], +])('Global Variables', (clsValue: GlobalsInstruction, key: string) => { + it(`${clsValue.name} should (de)serialize correctly`, () => { + const buf = Buffer.from([ + clsValue.opcode, // opcode + 0x01, // indirect + ...Buffer.from('12345678', 'hex'), // dstOffset + ]); + const inst = new clsValue(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); + + expect(clsValue.deserialize(buf)).toEqual(inst); + expect(inst.serialize()).toEqual(buf); }); - describe('Global Variables', () => { - type GlobalsInstruction = ChainId | Version | BlockNumber | Timestamp; - const readGlobalVariableTest = async (key: string, value: Fr, instruction: GlobalsInstruction) => { - const globals = initGlobalVariables({ [key]: value }); - const context = initContext({ env: initExecutionEnvironment({ globals }) }); - - await instruction.execute(context); - const actual = context.machineState.memory.get(0).toFr(); - expect(actual).toEqual(value); - }; - - describe('chainId', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - ChainId.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new ChainId(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(ChainId.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); + it(`${clsValue.name} should read '${key}' correctly`, async () => { + const value = new Fr(123456n); + const instruction = new clsValue(/*indirect=*/ 0, /*dstOffset=*/ 0); + const globals = initGlobalVariables({ [key]: value }); + const context = initContext({ env: initExecutionEnvironment({ globals }) }); - it('Should read chainId', async () => { - const chainId = new Fr(123456n); - await readGlobalVariableTest('chainId', chainId, new ChainId(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); - - describe('version', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - Version.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new Version(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(Version.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read version', async () => { - const version = new Fr(123456n); - await readGlobalVariableTest('version', version, new Version(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); - - describe('block', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - BlockNumber.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new BlockNumber(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(BlockNumber.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should read block number', async () => { - const blockNumber = new Fr(123456n); - await readGlobalVariableTest('blockNumber', blockNumber, new BlockNumber(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); - - describe('timestamp', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - Timestamp.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new Timestamp(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(Timestamp.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); + await instruction.execute(context); - it('Should read timestamp', async () => { - const timestamp = new Fr(123456n); - await readGlobalVariableTest('timestamp', timestamp, new Timestamp(/*indirect=*/ 0, /*dstOffset=*/ 0)); - }); - }); + const actual = context.machineState.memory.get(0).toFr(); + expect(actual).toEqual(value); }); }); diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 3555e8cfda0..dbd0d37b131 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -836,11 +836,13 @@ __metadata: "@noir-lang/acvm_js": "portal:../../noir/packages/acvm_js" "@types/jest": ^29.5.0 "@types/levelup": ^5.1.3 + "@types/lodash.merge": ^4.6.9 "@types/memdown": ^3.0.2 "@types/node": ^18.7.23 jest: ^29.5.0 jest-mock-extended: ^3.0.4 levelup: ^5.1.1 + lodash.merge: ^4.6.2 memdown: ^6.1.1 ts-jest: ^29.1.0 ts-node: ^10.9.1 @@ -3434,6 +3436,15 @@ __metadata: languageName: node linkType: hard +"@types/lodash.merge@npm:^4.6.9": + version: 4.6.9 + resolution: "@types/lodash.merge@npm:4.6.9" + dependencies: + "@types/lodash": "*" + checksum: d0dd6654547c9d8d905184d14aa5c2a37a1ed1c3204f5ab20b7d591a05f34859ef09d3b72c065e94ca1989abf9109eb8230f67c4d64a5768b1d65b9ed8baf8e7 + languageName: node + linkType: hard + "@types/lodash.omit@npm:^4.5.7": version: 4.5.9 resolution: "@types/lodash.omit@npm:4.5.9" From 824fb804f60ddf0a48eda51c852bf10d7dea83e3 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:30:18 +0000 Subject: [PATCH 03/12] journal compare --- .../simulator/src/avm/avm_context.test.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/yarn-project/simulator/src/avm/avm_context.test.ts b/yarn-project/simulator/src/avm/avm_context.test.ts index f54fe99a358..3eab56099d3 100644 --- a/yarn-project/simulator/src/avm/avm_context.test.ts +++ b/yarn-project/simulator/src/avm/avm_context.test.ts @@ -1,6 +1,7 @@ import { AztecAddress, Fr } from '@aztec/circuits.js'; import { allSameExcept, initContext } from './fixtures/index.js'; +import { AvmWorldStateJournal } from './journal/journal.js'; describe('Avm Context', () => { it('New call should fork context correctly', () => { @@ -24,10 +25,20 @@ describe('Avm Context', () => { pc: 0, }), ); - // FIXME: I can't get this to work. - // expect(newContext.worldState).toEqual(context.worldState.fork()); + + compareJournal(newContext.worldState, context.worldState); }); + function compareJournal(actual: AvmWorldStateJournal, expected: AvmWorldStateJournal) { + const removeParentReference = (journal: AvmWorldStateJournal) => { + const j = JSON.parse(JSON.stringify(journal)); + delete j.parentJournal; + return j; + } + + expect(removeParentReference(actual)).toEqual(removeParentReference(expected)); + } + it('New static call should fork context correctly', () => { const context = initContext(); context.machineState.pc = 20; From 781d2fdcb719c22e43182db0b73e1b8589e1ac59 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:33:04 +0000 Subject: [PATCH 04/12] add fork --- yarn-project/simulator/src/avm/avm_context.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/avm/avm_context.test.ts b/yarn-project/simulator/src/avm/avm_context.test.ts index 3eab56099d3..6a9f332715e 100644 --- a/yarn-project/simulator/src/avm/avm_context.test.ts +++ b/yarn-project/simulator/src/avm/avm_context.test.ts @@ -26,7 +26,7 @@ describe('Avm Context', () => { }), ); - compareJournal(newContext.worldState, context.worldState); + compareJournal(newContext.worldState, context.worldState.fork()); }); function compareJournal(actual: AvmWorldStateJournal, expected: AvmWorldStateJournal) { From 8e7deea6b8525ca48c6e0e390553d50ca12d8973 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:48:07 +0000 Subject: [PATCH 05/12] strinfigy does the job --- .../simulator/src/avm/avm_context.test.ts | 15 ++++----------- .../simulator/src/avm/opcodes/arithmetic.test.ts | 2 +- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/yarn-project/simulator/src/avm/avm_context.test.ts b/yarn-project/simulator/src/avm/avm_context.test.ts index 6a9f332715e..4201cb9bf3f 100644 --- a/yarn-project/simulator/src/avm/avm_context.test.ts +++ b/yarn-project/simulator/src/avm/avm_context.test.ts @@ -8,6 +8,8 @@ describe('Avm Context', () => { const context = initContext(); context.machineState.pc = 20; + + const newAddress = AztecAddress.random(); const newCalldata = [new Fr(1), new Fr(2)]; const newContext = context.createNestedContractCallContext(newAddress, newCalldata); @@ -26,19 +28,10 @@ describe('Avm Context', () => { }), ); - compareJournal(newContext.worldState, context.worldState.fork()); + // We stringify to remove circular references (parentJournal) + expect(JSON.stringify(newContext.worldState)).toEqual(JSON.stringify(context.worldState.fork())); }); - function compareJournal(actual: AvmWorldStateJournal, expected: AvmWorldStateJournal) { - const removeParentReference = (journal: AvmWorldStateJournal) => { - const j = JSON.parse(JSON.stringify(journal)); - delete j.parentJournal; - return j; - } - - expect(removeParentReference(actual)).toEqual(removeParentReference(expected)); - } - it('New static call should fork context correctly', () => { const context = initContext(); context.machineState.pc = 20; diff --git a/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts b/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts index 1475ef1a7c4..42680477fc3 100644 --- a/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts @@ -202,7 +202,7 @@ describe('Arithmetic Instructions', () => { }); // FIXME: field division is wrong - it.skip('Should perform field division', async () => { + it('Should perform field division', async () => { const a = new Field(10n); const b = new Field(5n); From 97bacf941983661ee3d7c804c09c43d9c8e9d849 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:54:48 +0000 Subject: [PATCH 06/12] fix: field division --- yarn-project/foundation/src/fields/fields.ts | 4 ++-- yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 0aebb8fa3cc..b4dc1229d5f 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -298,8 +298,8 @@ function modInverse(b: bigint) { if (gcd != 1n) { throw Error('Inverse does not exist'); } - // Add modulus to ensure positive - return new Fr(x + Fr.MODULUS); + // Add modulus if -ve to ensure positive + return new Fr(x > 0 ? x : x + Fr.MODULUS); } /** diff --git a/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts b/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts index 42680477fc3..e08fe4bcb8e 100644 --- a/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts @@ -201,7 +201,6 @@ describe('Arithmetic Instructions', () => { expect(inst.serialize()).toEqual(buf); }); - // FIXME: field division is wrong it('Should perform field division', async () => { const a = new Field(10n); const b = new Field(5n); From 600b3f16697a4c6d1132908d9779a5066ff2ba38 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:56:27 +0000 Subject: [PATCH 07/12] fmt --- yarn-project/simulator/src/avm/avm_context.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/yarn-project/simulator/src/avm/avm_context.test.ts b/yarn-project/simulator/src/avm/avm_context.test.ts index 4201cb9bf3f..50323b05f0e 100644 --- a/yarn-project/simulator/src/avm/avm_context.test.ts +++ b/yarn-project/simulator/src/avm/avm_context.test.ts @@ -1,15 +1,12 @@ import { AztecAddress, Fr } from '@aztec/circuits.js'; import { allSameExcept, initContext } from './fixtures/index.js'; -import { AvmWorldStateJournal } from './journal/journal.js'; describe('Avm Context', () => { it('New call should fork context correctly', () => { const context = initContext(); context.machineState.pc = 20; - - const newAddress = AztecAddress.random(); const newCalldata = [new Fr(1), new Fr(2)]; const newContext = context.createNestedContractCallContext(newAddress, newCalldata); From e4929b821dd5b3252434e4f8cd28e6d1c9ab180f Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:03:31 +0000 Subject: [PATCH 08/12] another context --- yarn-project/simulator/src/avm/avm_context.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yarn-project/simulator/src/avm/avm_context.test.ts b/yarn-project/simulator/src/avm/avm_context.test.ts index 50323b05f0e..240de5eb14f 100644 --- a/yarn-project/simulator/src/avm/avm_context.test.ts +++ b/yarn-project/simulator/src/avm/avm_context.test.ts @@ -50,7 +50,8 @@ describe('Avm Context', () => { pc: 0, }), ); - // FIXME: I can't get this to work. - // expect(newContext.worldState).toEqual(context.worldState.fork()); + + // We stringify to remove circular references (parentJournal) + expect(JSON.stringify(newContext.worldState)).toEqual(JSON.stringify(context.worldState.fork())); }); }); From 09ad78a93a8f5e9919b1590276881122f0b31c67 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:06:27 +0000 Subject: [PATCH 09/12] fix: one more field division --- yarn-project/simulator/src/avm/avm_memory_types.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/yarn-project/simulator/src/avm/avm_memory_types.test.ts b/yarn-project/simulator/src/avm/avm_memory_types.test.ts index c5701c54d93..9aeccaa73b9 100644 --- a/yarn-project/simulator/src/avm/avm_memory_types.test.ts +++ b/yarn-project/simulator/src/avm/avm_memory_types.test.ts @@ -160,8 +160,7 @@ describe('Field', () => { expect(result).toStrictEqual(new Field(50n)); }); - // FIXME: field division is wrong - it.skip(`Should divide two Fields correctly`, () => { + it(`Should divide two Fields correctly`, () => { const field1 = new Field(10); const field2 = new Field(5); const result = field1.div(field2); From a0fb6a9e4339260d602704de4de2cb1fb5b49b6c Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:35:57 +0000 Subject: [PATCH 10/12] feat: field division tests --- .../foundation/src/fields/fields.test.ts | 122 +++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/yarn-project/foundation/src/fields/fields.test.ts b/yarn-project/foundation/src/fields/fields.test.ts index 02f08f0e319..f8ad991a245 100644 --- a/yarn-project/foundation/src/fields/fields.test.ts +++ b/yarn-project/foundation/src/fields/fields.test.ts @@ -1,4 +1,4 @@ -import { GrumpkinScalar } from './fields.js'; +import { GrumpkinScalar, Fr } from './fields.js'; describe('GrumpkinScalar Serialization', () => { // Test case for GrumpkinScalar.fromHighLow @@ -53,3 +53,123 @@ describe('GrumpkinScalar Serialization', () => { expect(deserialized).toEqual(original); }); }); + +describe("Bn254 arithmetic", () => { + describe("Addition", () => { + it("Low Boundary", () => { + // 0 + -1 = -1 + const a = Fr.ZERO; + const b = new Fr(Fr.MODULUS - 1n); + const expected = new Fr(Fr.MODULUS - 1n); + + const actual = a.add(b); + expect(actual).toEqual(expected); + }) + + it("High Boundary", () => { + // -1 + 1 = 0 + const a = new Fr(Fr.MODULUS - 1n); + const b = new Fr(1); + const expected = Fr.ZERO; + + const actual = a.add(b); + expect(actual).toEqual(expected); + }); + + it("Performs addition correctly", () => { + const a = new Fr(2); + const b = new Fr(3); + const expected = new Fr(5); + + const actual = a.add(b); + expect(actual).toEqual(expected); + }) + }) + + describe("Subtraction", () => { + it("Low Boundary", () => { + // 0 - 1 = -1 + const a = new Fr(0); + const b = new Fr(1); + const expected = new Fr(Fr.MODULUS - 1n); + + const actual = a.sub(b); + expect(actual).toEqual(expected); + }) + + it("High Bonudary", () => { + // -1 - (-1) = 0 + const a = new Fr(Fr.MODULUS - 1n); + const b = new Fr(Fr.MODULUS - 1n); + + const actual = a.sub(b); + expect(actual).toEqual(Fr.ZERO); + }) + + it("Performs subtraction correctly", () => { + const a = new Fr(10); + const b = new Fr(5); + const expected = new Fr(5); + + const actual = a.sub(b); + expect(actual).toEqual(expected); + }); + }) + + describe("Multiplication", () => { + it("Identity", () => { + const a = new Fr(Fr.MODULUS - 1n); + const b = new Fr(1); + const expected = new Fr(Fr.MODULUS - 1n); + + const actual = a.mul(b); + expect(actual).toEqual(expected); + }); + + it("Performs multiplication correctly", () => { + const a = new Fr(2); + const b = new Fr(3); + const expected = new Fr(6); + + const actual = a.mul(b); + expect(actual).toEqual(expected); + }); + + it("High Boundary", () => { + const a = new Fr(Fr.MODULUS - 1n); + const b = new Fr(Fr.MODULUS / 2n); + const expected = new Fr(10944121435919637611123202872628637544274182200208017171849102093287904247809n); + + const actual = a.mul(b); + expect(actual).toEqual(expected); + }); + }) + + + describe("Division", () => { + it("Should succeed when mod inverse is -ve", () => { + const a = new Fr(2); + const b = new Fr(3); + + const actual = a.div(b); + expect(actual.mul(b)).toEqual(a); + }) + + it("Should succeed when mod inverse is +ve", () => { + const a = new Fr(10); + const b = new Fr(5); + const expected = new Fr(2); + + const actual = a.div(b); + expect(actual.mul(b)).toEqual(a); + expect(actual).toEqual(expected); + }) + + it("Should not allow a division by 0", () => { + const a = new Fr(10); + const b = Fr.ZERO; + + expect(() => a.div(b)).toThrowError(); + }) + }) +}) From f2f01176d70fd0b5e6c8d886b0867b4e79c607bd Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:36:12 +0000 Subject: [PATCH 11/12] fmt --- .../foundation/src/fields/fields.test.ts | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/yarn-project/foundation/src/fields/fields.test.ts b/yarn-project/foundation/src/fields/fields.test.ts index f8ad991a245..c2673ff86e9 100644 --- a/yarn-project/foundation/src/fields/fields.test.ts +++ b/yarn-project/foundation/src/fields/fields.test.ts @@ -1,4 +1,4 @@ -import { GrumpkinScalar, Fr } from './fields.js'; +import { Fr, GrumpkinScalar } from './fields.js'; describe('GrumpkinScalar Serialization', () => { // Test case for GrumpkinScalar.fromHighLow @@ -54,9 +54,9 @@ describe('GrumpkinScalar Serialization', () => { }); }); -describe("Bn254 arithmetic", () => { - describe("Addition", () => { - it("Low Boundary", () => { +describe('Bn254 arithmetic', () => { + describe('Addition', () => { + it('Low Boundary', () => { // 0 + -1 = -1 const a = Fr.ZERO; const b = new Fr(Fr.MODULUS - 1n); @@ -64,9 +64,9 @@ describe("Bn254 arithmetic", () => { const actual = a.add(b); expect(actual).toEqual(expected); - }) + }); - it("High Boundary", () => { + it('High Boundary', () => { // -1 + 1 = 0 const a = new Fr(Fr.MODULUS - 1n); const b = new Fr(1); @@ -76,18 +76,18 @@ describe("Bn254 arithmetic", () => { expect(actual).toEqual(expected); }); - it("Performs addition correctly", () => { + it('Performs addition correctly', () => { const a = new Fr(2); const b = new Fr(3); const expected = new Fr(5); const actual = a.add(b); expect(actual).toEqual(expected); - }) - }) + }); + }); - describe("Subtraction", () => { - it("Low Boundary", () => { + describe('Subtraction', () => { + it('Low Boundary', () => { // 0 - 1 = -1 const a = new Fr(0); const b = new Fr(1); @@ -95,18 +95,18 @@ describe("Bn254 arithmetic", () => { const actual = a.sub(b); expect(actual).toEqual(expected); - }) + }); - it("High Bonudary", () => { + it('High Bonudary', () => { // -1 - (-1) = 0 const a = new Fr(Fr.MODULUS - 1n); const b = new Fr(Fr.MODULUS - 1n); const actual = a.sub(b); expect(actual).toEqual(Fr.ZERO); - }) + }); - it("Performs subtraction correctly", () => { + it('Performs subtraction correctly', () => { const a = new Fr(10); const b = new Fr(5); const expected = new Fr(5); @@ -114,10 +114,10 @@ describe("Bn254 arithmetic", () => { const actual = a.sub(b); expect(actual).toEqual(expected); }); - }) + }); - describe("Multiplication", () => { - it("Identity", () => { + describe('Multiplication', () => { + it('Identity', () => { const a = new Fr(Fr.MODULUS - 1n); const b = new Fr(1); const expected = new Fr(Fr.MODULUS - 1n); @@ -126,7 +126,7 @@ describe("Bn254 arithmetic", () => { expect(actual).toEqual(expected); }); - it("Performs multiplication correctly", () => { + it('Performs multiplication correctly', () => { const a = new Fr(2); const b = new Fr(3); const expected = new Fr(6); @@ -135,7 +135,7 @@ describe("Bn254 arithmetic", () => { expect(actual).toEqual(expected); }); - it("High Boundary", () => { + it('High Boundary', () => { const a = new Fr(Fr.MODULUS - 1n); const b = new Fr(Fr.MODULUS / 2n); const expected = new Fr(10944121435919637611123202872628637544274182200208017171849102093287904247809n); @@ -143,19 +143,18 @@ describe("Bn254 arithmetic", () => { const actual = a.mul(b); expect(actual).toEqual(expected); }); - }) - + }); - describe("Division", () => { - it("Should succeed when mod inverse is -ve", () => { + describe('Division', () => { + it('Should succeed when mod inverse is -ve', () => { const a = new Fr(2); const b = new Fr(3); const actual = a.div(b); expect(actual.mul(b)).toEqual(a); - }) + }); - it("Should succeed when mod inverse is +ve", () => { + it('Should succeed when mod inverse is +ve', () => { const a = new Fr(10); const b = new Fr(5); const expected = new Fr(2); @@ -163,13 +162,13 @@ describe("Bn254 arithmetic", () => { const actual = a.div(b); expect(actual.mul(b)).toEqual(a); expect(actual).toEqual(expected); - }) + }); - it("Should not allow a division by 0", () => { + it('Should not allow a division by 0', () => { const a = new Fr(10); const b = Fr.ZERO; expect(() => a.div(b)).toThrowError(); - }) - }) -}) + }); + }); +}); From 059432bbbafa3df2ed047a103180b21f9eb0c4ef Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 7 Feb 2024 18:24:58 +0000 Subject: [PATCH 12/12] fix --- yarn-project/simulator/src/avm/opcodes/instruction.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/yarn-project/simulator/src/avm/opcodes/instruction.ts b/yarn-project/simulator/src/avm/opcodes/instruction.ts index 66396bed7d3..afe7f6e5209 100644 --- a/yarn-project/simulator/src/avm/opcodes/instruction.ts +++ b/yarn-project/simulator/src/avm/opcodes/instruction.ts @@ -62,8 +62,3 @@ export abstract class Instruction { return new this(...args); } } - -type InstructionConstructor = { - new (...args: any[]): Instruction; - wireFormat?: OperandType[]; -};