From 8d06d9e7a0365dadad4a1cd7ca8049c2140f1cdd Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 18 Jan 2024 19:24:32 +0000 Subject: [PATCH 1/8] feat(avm): better field arithmetic --- barretenberg/ts/src/types/fields.ts | 1 + yarn-project/foundation/src/fields/fields.ts | 44 ++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/barretenberg/ts/src/types/fields.ts b/barretenberg/ts/src/types/fields.ts index a54cbe5a3289..52c61c99ad10 100644 --- a/barretenberg/ts/src/types/fields.ts +++ b/barretenberg/ts/src/types/fields.ts @@ -54,6 +54,7 @@ export class Fr { isZero() { return this.value.every(v => v === 0); } + } export class Fq { diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 90600643cfe5..1a51c64d041e 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -192,8 +192,31 @@ export class Fr extends BaseField { static fromString(buf: string) { return fromString(buf, Fr); } + + add(rhs: Fr) { + return new Fr((this.toBigInt() + rhs.toBigInt()) % Fr.MODULUS); + } + + sub(rhs: Fr) { + const result = this.toBigInt() - rhs.toBigInt(); + return new Fr((result < 0) ? result + Fr.MODULUS : result); + } + + mul(rhs: Fr) { + return new Fr((this.toBigInt() * rhs.toBigInt()) % Fr.MODULUS); + } + + div(rhs: Fr) { + if (rhs.isZero()) { + throw new Error('Division by zero'); + } + + const bInv = modInverse(rhs.toBigInt()); + return new Fr((this.toBigInt() * bInv) % Fr.MODULUS); + } } + /** * Branding to ensure fields are not interchangeable types. */ @@ -252,6 +275,26 @@ export class Fq extends BaseField { } } +// Performance bottleneck +// TODO: add documentation +function extendedEuclidean(a: bigint, modulus: bigint): [bigint, bigint, bigint] { + if (a == 0n){ + return [modulus, 0n, 1n] + } + else{ + const [gcd, x, y]: [bigint, bigint, bigint] = extendedEuclidean(modulus % a, a) + return [gcd, y - (modulus / a) * x, x] + } +} + +function modInverse(b: bigint){ + const [gcd, x, _] = extendedEuclidean(b, Fr.MODULUS); + if (gcd != 1n){ + throw Error("Inverse does not exist"); + } + return x % Fr.MODULUS; +} + /** * GrumpkinScalar is an Fq. * @remarks Called GrumpkinScalar because it is used to represent elements in Grumpkin's scalar field as defined in @@ -259,3 +302,4 @@ export class Fq extends BaseField { */ export type GrumpkinScalar = Fq; export const GrumpkinScalar = Fq; + From 2c471d39468c9e108b289f438f7ec9dbb3dc74c4 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 18 Jan 2024 20:14:18 +0000 Subject: [PATCH 2/8] chore: test field division --- barretenberg/ts/src/types/fields.ts | 2 + .../src/avm/opcodes/arithmetic.test.ts | 110 ++++++++++++++++++ .../src/avm/opcodes/arithmetic.ts | 9 +- .../acir-simulator/src/avm/opcodes/bitwise.ts | 4 +- yarn-project/foundation/src/fields/fields.ts | 11 +- 5 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts diff --git a/barretenberg/ts/src/types/fields.ts b/barretenberg/ts/src/types/fields.ts index 52c61c99ad10..a17b8e0b2ef6 100644 --- a/barretenberg/ts/src/types/fields.ts +++ b/barretenberg/ts/src/types/fields.ts @@ -55,6 +55,8 @@ export class Fr { return this.value.every(v => v === 0); } + + } export class Fq { diff --git a/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts new file mode 100644 index 000000000000..9cda39873bef --- /dev/null +++ b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts @@ -0,0 +1,110 @@ +import { AvmMachineState } from "../avm_machine_state.js"; +import { Add, Div, Mul, Sub } from "./arithmetic.js"; +import { AvmStateManager } from "../avm_state_manager.js"; +import { mock } from "jest-mock-extended"; +import { Fr } from "@aztec/foundation/fields"; + +describe("Arithmetic Instructions", () => { + let machineState: AvmMachineState; + let stateManager = mock(); + + beforeEach(() => { + machineState = new AvmMachineState([]); + stateManager = mock(); + }) + + describe("Add", () => { + it("Should add correctly over Fr type", () => { + const a = new Fr(1n); + const b = new Fr(2n); + + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); + + new Add(0, 1, 2).execute(machineState, stateManager); + + const expected = new Fr(3n); + const actual = machineState.readMemory(2); + expect(actual).toEqual(expected); + }) + + it("Should wrap around on addition", () => { + const a = new Fr(1n); + const b = new Fr(Fr.MODULUS - 1n); + + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); + + new Add(0, 1, 2).execute(machineState, stateManager); + + const expected = new Fr(0n); + const actual = machineState.readMemory(3); + expect(actual).toEqual(expected); + }) + }) + + describe("Sub", () => { + it("Should subtract correctly over Fr type", () => { + const a = new Fr(1n); + const b = new Fr(2n); + + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); + + new Sub(0, 1, 2).execute(machineState, stateManager); + + const expected = new Fr(Fr.MODULUS - 1n); + const actual = machineState.readMemory(2); + expect(actual).toEqual(expected); + }); + }); + + describe("Mul", () => { + it("Should multiply correctly over Fr type", () => { + const a = new Fr(2n); + const b = new Fr(3n); + + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); + + new Mul(0, 1, 2).execute(machineState, stateManager); + + const expected = new Fr(6n); + const actual = machineState.readMemory(2); + expect(actual).toEqual(expected); + }); + + it("Should wrap around on multiplication", () => { + const a = new Fr(2n); + const b = new Fr((Fr.MODULUS / 2n) - 1n); + + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); + + new Mul(0, 1, 2).execute(machineState, stateManager); + + const expected = new Fr(Fr.MODULUS - 3n); + const actual = machineState.readMemory(2); + expect(actual).toEqual(expected); + }); + }); + + describe("Div", () => { + it("Should perform field division", () => { + const a = new Fr(2n); + const b = new Fr(3n); + + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); + + new Div(0, 1, 2).execute(machineState, stateManager); + + // Note + const actual = machineState.readMemory(2); + const recovered = actual.mul(b); + expect(recovered).toEqual(a); + }) + + }); + +}) \ No newline at end of file diff --git a/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.ts b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.ts index 7f2fb3db052c..4f9649624c8f 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.ts @@ -17,7 +17,7 @@ export class Add extends Instruction { const a = machineState.readMemory(this.aOffset); const b = machineState.readMemory(this.bOffset); - const dest = new Fr((a.toBigInt() + b.toBigInt()) % Fr.MODULUS); + const dest = a.add(b); machineState.writeMemory(this.destOffset, dest); this.incrementPc(machineState); @@ -37,7 +37,7 @@ export class Sub extends Instruction { const a = machineState.readMemory(this.aOffset); const b = machineState.readMemory(this.bOffset); - const dest = new Fr((a.toBigInt() - b.toBigInt()) % Fr.MODULUS); + const dest = a.sub(b); machineState.writeMemory(this.destOffset, dest); this.incrementPc(machineState); @@ -57,7 +57,7 @@ export class Mul extends Instruction { const a: Fr = machineState.readMemory(this.aOffset); const b: Fr = machineState.readMemory(this.bOffset); - const dest = new Fr((a.toBigInt() * b.toBigInt()) % Fr.MODULUS); + const dest = a.mul(b); machineState.writeMemory(this.destOffset, dest); this.incrementPc(machineState); @@ -77,8 +77,7 @@ export class Div extends Instruction { const a: Fr = machineState.readMemory(this.aOffset); const b: Fr = machineState.readMemory(this.bOffset); - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3993): proper field division - const dest = new Fr(a.toBigInt() / b.toBigInt()); + const dest = a.div(b) machineState.writeMemory(this.destOffset, dest); this.incrementPc(machineState); diff --git a/yarn-project/acir-simulator/src/avm/opcodes/bitwise.ts b/yarn-project/acir-simulator/src/avm/opcodes/bitwise.ts index bc5c3a211cb6..4950c771f7c6 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/bitwise.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/bitwise.ts @@ -76,8 +76,10 @@ export class Not extends Instruction { execute(machineState: AvmMachineState, _stateManager: AvmStateManager): void { const a: Fr = machineState.readMemory(this.aOffset); - // TODO: hack -> until proper field arithmetic is implemented + // TODO: hack -> Bitwise operations should not occur over field elements + // It should only work over integers const result = ~a.toBigInt(); + const dest = new Fr(result < 0 ? Fr.MODULUS + /* using a + as result is -ve*/ result : result); machineState.writeMemory(this.destOffset, dest); diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 1a51c64d041e..d7a919e89c23 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -193,6 +193,8 @@ export class Fr extends BaseField { return fromString(buf, Fr); } + /** Arithmetic */ + add(rhs: Fr) { return new Fr((this.toBigInt() + rhs.toBigInt()) % Fr.MODULUS); } @@ -212,7 +214,7 @@ export class Fr extends BaseField { } const bInv = modInverse(rhs.toBigInt()); - return new Fr((this.toBigInt() * bInv) % Fr.MODULUS); + return this.mul(bInv); } } @@ -282,8 +284,8 @@ function extendedEuclidean(a: bigint, modulus: bigint): [bigint, bigint, bigint] return [modulus, 0n, 1n] } else{ - const [gcd, x, y]: [bigint, bigint, bigint] = extendedEuclidean(modulus % a, a) - return [gcd, y - (modulus / a) * x, x] + const [gcd, x, y] = extendedEuclidean(modulus % a, a) + return [gcd, y - ((modulus / a) * x), x] } } @@ -292,7 +294,8 @@ function modInverse(b: bigint){ if (gcd != 1n){ throw Error("Inverse does not exist"); } - return x % Fr.MODULUS; + // Add modulus to ensure positive + return new Fr(x + Fr.MODULUS); } /** From 688530a6112d5e32625683730d4ddb643c2b500c Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 18 Jan 2024 20:16:13 +0000 Subject: [PATCH 3/8] chore: add div to opcodes list --- .../src/avm/opcodes/arithmetic.test.ts | 162 +++++++++--------- .../src/avm/opcodes/arithmetic.ts | 2 +- .../src/avm/opcodes/instruction_set.ts | 3 +- yarn-project/foundation/src/fields/fields.ts | 31 ++-- 4 files changed, 98 insertions(+), 100 deletions(-) diff --git a/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts index 9cda39873bef..76a802231a3b 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.test.ts @@ -1,110 +1,110 @@ -import { AvmMachineState } from "../avm_machine_state.js"; -import { Add, Div, Mul, Sub } from "./arithmetic.js"; -import { AvmStateManager } from "../avm_state_manager.js"; -import { mock } from "jest-mock-extended"; -import { Fr } from "@aztec/foundation/fields"; +import { Fr } from '@aztec/foundation/fields'; -describe("Arithmetic Instructions", () => { - let machineState: AvmMachineState; - let stateManager = mock(); +import { mock } from 'jest-mock-extended'; - beforeEach(() => { - machineState = new AvmMachineState([]); - stateManager = mock(); - }) +import { AvmMachineState } from '../avm_machine_state.js'; +import { AvmStateManager } from '../avm_state_manager.js'; +import { Add, Div, Mul, Sub } from './arithmetic.js'; - describe("Add", () => { - it("Should add correctly over Fr type", () => { - const a = new Fr(1n); - const b = new Fr(2n); +describe('Arithmetic Instructions', () => { + let machineState: AvmMachineState; + let stateManager = mock(); - machineState.writeMemory(0, a); - machineState.writeMemory(1, b); + beforeEach(() => { + machineState = new AvmMachineState([]); + stateManager = mock(); + }); - new Add(0, 1, 2).execute(machineState, stateManager); + describe('Add', () => { + it('Should add correctly over Fr type', () => { + const a = new Fr(1n); + const b = new Fr(2n); - const expected = new Fr(3n); - const actual = machineState.readMemory(2); - expect(actual).toEqual(expected); - }) + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); - it("Should wrap around on addition", () => { - const a = new Fr(1n); - const b = new Fr(Fr.MODULUS - 1n); + new Add(0, 1, 2).execute(machineState, stateManager); - machineState.writeMemory(0, a); - machineState.writeMemory(1, b); + const expected = new Fr(3n); + const actual = machineState.readMemory(2); + expect(actual).toEqual(expected); + }); + + it('Should wrap around on addition', () => { + const a = new Fr(1n); + const b = new Fr(Fr.MODULUS - 1n); + + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); - new Add(0, 1, 2).execute(machineState, stateManager); + new Add(0, 1, 2).execute(machineState, stateManager); - const expected = new Fr(0n); - const actual = machineState.readMemory(3); - expect(actual).toEqual(expected); - }) - }) + const expected = new Fr(0n); + const actual = machineState.readMemory(3); + expect(actual).toEqual(expected); + }); + }); - describe("Sub", () => { - it("Should subtract correctly over Fr type", () => { - const a = new Fr(1n); - const b = new Fr(2n); + describe('Sub', () => { + it('Should subtract correctly over Fr type', () => { + const a = new Fr(1n); + const b = new Fr(2n); - machineState.writeMemory(0, a); - machineState.writeMemory(1, b); + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); - new Sub(0, 1, 2).execute(machineState, stateManager); + new Sub(0, 1, 2).execute(machineState, stateManager); - const expected = new Fr(Fr.MODULUS - 1n); - const actual = machineState.readMemory(2); - expect(actual).toEqual(expected); - }); + const expected = new Fr(Fr.MODULUS - 1n); + const actual = machineState.readMemory(2); + expect(actual).toEqual(expected); }); + }); - describe("Mul", () => { - it("Should multiply correctly over Fr type", () => { - const a = new Fr(2n); - const b = new Fr(3n); + describe('Mul', () => { + it('Should multiply correctly over Fr type', () => { + const a = new Fr(2n); + const b = new Fr(3n); - machineState.writeMemory(0, a); - machineState.writeMemory(1, b); + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); - new Mul(0, 1, 2).execute(machineState, stateManager); + new Mul(0, 1, 2).execute(machineState, stateManager); - const expected = new Fr(6n); - const actual = machineState.readMemory(2); - expect(actual).toEqual(expected); - }); + const expected = new Fr(6n); + const actual = machineState.readMemory(2); + expect(actual).toEqual(expected); + }); - it("Should wrap around on multiplication", () => { - const a = new Fr(2n); - const b = new Fr((Fr.MODULUS / 2n) - 1n); + it('Should wrap around on multiplication', () => { + const a = new Fr(2n); + const b = new Fr(Fr.MODULUS / 2n - 1n); - machineState.writeMemory(0, a); - machineState.writeMemory(1, b); + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); - new Mul(0, 1, 2).execute(machineState, stateManager); + new Mul(0, 1, 2).execute(machineState, stateManager); - const expected = new Fr(Fr.MODULUS - 3n); - const actual = machineState.readMemory(2); - expect(actual).toEqual(expected); - }); + const expected = new Fr(Fr.MODULUS - 3n); + const actual = machineState.readMemory(2); + expect(actual).toEqual(expected); }); + }); - describe("Div", () => { - it("Should perform field division", () => { - const a = new Fr(2n); - const b = new Fr(3n); - - machineState.writeMemory(0, a); - machineState.writeMemory(1, b); + describe('Div', () => { + it('Should perform field division', () => { + const a = new Fr(2n); + const b = new Fr(3n); - new Div(0, 1, 2).execute(machineState, stateManager); + machineState.writeMemory(0, a); + machineState.writeMemory(1, b); - // Note - const actual = machineState.readMemory(2); - const recovered = actual.mul(b); - expect(recovered).toEqual(a); - }) + new Div(0, 1, 2).execute(machineState, stateManager); + // Note + const actual = machineState.readMemory(2); + const recovered = actual.mul(b); + expect(recovered).toEqual(a); }); - -}) \ No newline at end of file + }); +}); diff --git a/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.ts b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.ts index 4f9649624c8f..94df9713c83c 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/arithmetic.ts @@ -77,7 +77,7 @@ export class Div extends Instruction { const a: Fr = machineState.readMemory(this.aOffset); const b: Fr = machineState.readMemory(this.bOffset); - const dest = a.div(b) + const dest = a.div(b); machineState.writeMemory(this.destOffset, dest); this.incrementPc(machineState); diff --git a/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts b/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts index 1211205b979d..b36c5d34d297 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts @@ -1,5 +1,6 @@ import { Add, + Div, /*Div,*/ Mul, Sub, @@ -29,7 +30,7 @@ export const INSTRUCTION_SET: Map = ne [Opcode.ADD, Add], [Opcode.SUB, Sub], [Opcode.MUL, Mul], - //[Opcode.DIV, Div], + [Opcode.DIV, Div], //// Compute - Comparators //[Opcode.EQ, Eq], //[Opcode.LT, Lt], diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index d7a919e89c23..899ff03002b3 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -201,7 +201,7 @@ export class Fr extends BaseField { sub(rhs: Fr) { const result = this.toBigInt() - rhs.toBigInt(); - return new Fr((result < 0) ? result + Fr.MODULUS : result); + return new Fr(result < 0 ? result + Fr.MODULUS : result); } mul(rhs: Fr) { @@ -218,7 +218,6 @@ export class Fr extends BaseField { } } - /** * Branding to ensure fields are not interchangeable types. */ @@ -280,22 +279,21 @@ export class Fq extends BaseField { // Performance bottleneck // TODO: add documentation function extendedEuclidean(a: bigint, modulus: bigint): [bigint, bigint, bigint] { - if (a == 0n){ - return [modulus, 0n, 1n] - } - else{ - const [gcd, x, y] = extendedEuclidean(modulus % a, a) - return [gcd, y - ((modulus / a) * x), x] - } + if (a == 0n) { + return [modulus, 0n, 1n]; + } else { + const [gcd, x, y] = extendedEuclidean(modulus % a, a); + return [gcd, y - (modulus / a) * x, x]; + } } -function modInverse(b: bigint){ - const [gcd, x, _] = extendedEuclidean(b, Fr.MODULUS); - if (gcd != 1n){ - throw Error("Inverse does not exist"); - } - // Add modulus to ensure positive - return new Fr(x + Fr.MODULUS); +function modInverse(b: bigint) { + const [gcd, x, _] = extendedEuclidean(b, Fr.MODULUS); + if (gcd != 1n) { + throw Error('Inverse does not exist'); + } + // Add modulus to ensure positive + return new Fr(x + Fr.MODULUS); } /** @@ -305,4 +303,3 @@ function modInverse(b: bigint){ */ export type GrumpkinScalar = Fq; export const GrumpkinScalar = Fq; - From 8eb1ad7c62e18a679f2104ddc19e61ba9c8ac9a2 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 18 Jan 2024 20:20:39 +0000 Subject: [PATCH 4/8] fix: lint bb --- barretenberg/ts/src/types/fields.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/barretenberg/ts/src/types/fields.ts b/barretenberg/ts/src/types/fields.ts index a17b8e0b2ef6..a54cbe5a3289 100644 --- a/barretenberg/ts/src/types/fields.ts +++ b/barretenberg/ts/src/types/fields.ts @@ -54,9 +54,6 @@ export class Fr { isZero() { return this.value.every(v => v === 0); } - - - } export class Fq { From d9b77475b4de9967138b82cbeffa23357ac51d26 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 18 Jan 2024 20:23:12 +0000 Subject: [PATCH 5/8] chore: Add comments to mod inverse method --- yarn-project/foundation/src/fields/fields.ts | 28 +++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 899ff03002b3..4435366d80bd 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -276,17 +276,11 @@ export class Fq extends BaseField { } } -// Performance bottleneck -// TODO: add documentation -function extendedEuclidean(a: bigint, modulus: bigint): [bigint, bigint, bigint] { - if (a == 0n) { - return [modulus, 0n, 1n]; - } else { - const [gcd, x, y] = extendedEuclidean(modulus % a, a); - return [gcd, y - (modulus / a) * x, x]; - } -} +// Beware: Performance bottleneck below +/** + * Find the modular inverse of a given element, for BN254 Fr. + */ function modInverse(b: bigint) { const [gcd, x, _] = extendedEuclidean(b, Fr.MODULUS); if (gcd != 1n) { @@ -296,6 +290,20 @@ function modInverse(b: bigint) { return new Fr(x + Fr.MODULUS); } +/** + * The extended Euclidean algorithm can be used to find the multiplicative inverse of a field element + * This is used to perform field division. + */ +function extendedEuclidean(a: bigint, modulus: bigint): [bigint, bigint, bigint] { + if (a == 0n) { + return [modulus, 0n, 1n]; + } else { + const [gcd, x, y] = extendedEuclidean(modulus % a, a); + return [gcd, y - (modulus / a) * x, x]; + } +} + + /** * GrumpkinScalar is an Fq. * @remarks Called GrumpkinScalar because it is used to represent elements in Grumpkin's scalar field as defined in From 8550753aa615f7b112fd0eba5b850d617977f729 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 18 Jan 2024 20:24:42 +0000 Subject: [PATCH 6/8] chore: remove commented import --- yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts b/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts index b36c5d34d297..102fc24b96b4 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts @@ -1,7 +1,6 @@ import { Add, Div, - /*Div,*/ Mul, Sub, } from './arithmetic.js'; From e66d6495423c009b665717893e0581ca0c3db1e8 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 18 Jan 2024 21:05:41 +0000 Subject: [PATCH 7/8] fix: fmr --- .../acir-simulator/src/avm/opcodes/instruction_set.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts b/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts index 102fc24b96b4..4395ba46d534 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/instruction_set.ts @@ -1,9 +1,4 @@ -import { - Add, - Div, - Mul, - Sub, -} from './arithmetic.js'; +import { Add, Div, 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, Return } from './control_flow.js'; From b40f42c5d3235cd3fede2665d31d27515fe6fed6 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Fri, 19 Jan 2024 09:40:45 +0000 Subject: [PATCH 8/8] fix: fmt --- yarn-project/foundation/src/fields/fields.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 4435366d80bd..bbf2f3b9a20c 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -278,7 +278,7 @@ export class Fq extends BaseField { // Beware: Performance bottleneck below -/** +/** * Find the modular inverse of a given element, for BN254 Fr. */ function modInverse(b: bigint) { @@ -303,7 +303,6 @@ function extendedEuclidean(a: bigint, modulus: bigint): [bigint, bigint, bigint] } } - /** * GrumpkinScalar is an Fq. * @remarks Called GrumpkinScalar because it is used to represent elements in Grumpkin's scalar field as defined in