From 055d288727888e298a2a9815ecebb628db9ebfbf Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Mon, 23 Oct 2023 12:33:43 -0700 Subject: [PATCH 1/8] feat(finite_field.ts): add leftShift and rightShift methods to support bitwise operations on big integers --- crypto/finite_field.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crypto/finite_field.ts b/crypto/finite_field.ts index 99763703..40540fe5 100644 --- a/crypto/finite_field.ts +++ b/crypto/finite_field.ts @@ -195,5 +195,11 @@ function createField(p: bigint, t: bigint, twoadicRoot: bigint) { } return BigInt('0b' + binary.reverse().join('')); }, + leftShift(x: bigint, bits: number) { + return this.rot(x, bits, 'left'); + }, + rightShift(x: bigint, bits: number) { + return this.rot(x, bits, 'right'); + }, }; } From 3cd5ee9f666ca81a599f0e75da8e0983f170a728 Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Mon, 23 Oct 2023 17:29:36 -0700 Subject: [PATCH 2/8] fix(finite_field.ts): replace rot function with bitwise shift operations in leftShift and rightShift --- crypto/finite_field.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/finite_field.ts b/crypto/finite_field.ts index 40540fe5..296db08c 100644 --- a/crypto/finite_field.ts +++ b/crypto/finite_field.ts @@ -196,10 +196,10 @@ function createField(p: bigint, t: bigint, twoadicRoot: bigint) { return BigInt('0b' + binary.reverse().join('')); }, leftShift(x: bigint, bits: number) { - return this.rot(x, bits, 'left'); + return mod(x << BigInt(bits), p); }, rightShift(x: bigint, bits: number) { - return this.rot(x, bits, 'right'); + return mod(x >> BigInt(bits), p); }, }; } From fd87c4ece761d35e05bf679165d49c577f4326ce Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Tue, 24 Oct 2023 10:03:19 -0700 Subject: [PATCH 3/8] fix(finite_field.ts): replace bitwise shift operations with manual shift implementation --- crypto/finite_field.ts | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/crypto/finite_field.ts b/crypto/finite_field.ts index 296db08c..71475a13 100644 --- a/crypto/finite_field.ts +++ b/crypto/finite_field.ts @@ -196,10 +196,28 @@ function createField(p: bigint, t: bigint, twoadicRoot: bigint) { return BigInt('0b' + binary.reverse().join('')); }, leftShift(x: bigint, bits: number) { - return mod(x << BigInt(bits), p); + let bitArray = x.toString(2).split('').reverse().map(Number); + let binary: number[] = + bitArray.length >= 64 + ? bitArray.splice(0, 64) + : [...bitArray, ...Array(64 - bitArray.length).fill(0)]; + for (let j = 0; j < bits; j++) { + binary.pop(); + binary.unshift(0); + } + return BigInt('0b' + binary.reverse().join('')); }, rightShift(x: bigint, bits: number) { - return mod(x >> BigInt(bits), p); + let bitArray = x.toString(2).split('').reverse().map(Number); + let binary: number[] = + bitArray.length >= 64 + ? bitArray.splice(0, 64) + : [...bitArray, ...Array(64 - bitArray.length).fill(0)]; + for (let j = 0; j < bits; j++) { + binary.shift(); + binary.push(0); + } + return BigInt('0b' + binary.reverse().join('')); }, }; } From f4514310b40974f2ea4fc434792023019252d434 Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Thu, 26 Oct 2023 14:54:23 -0700 Subject: [PATCH 4/8] Revert "fix(finite_field.ts): replace bitwise shift operations with manual shift implementation" This reverts commit fd87c4ece761d35e05bf679165d49c577f4326ce. --- crypto/finite_field.ts | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/crypto/finite_field.ts b/crypto/finite_field.ts index 507b6bf6..ed2b5189 100644 --- a/crypto/finite_field.ts +++ b/crypto/finite_field.ts @@ -199,28 +199,10 @@ function createField(p: bigint, t: bigint, twoadicRoot: bigint) { return BigInt('0b' + binary.reverse().join('')); }, leftShift(x: bigint, bits: number) { - let bitArray = x.toString(2).split('').reverse().map(Number); - let binary: number[] = - bitArray.length >= 64 - ? bitArray.splice(0, 64) - : [...bitArray, ...Array(64 - bitArray.length).fill(0)]; - for (let j = 0; j < bits; j++) { - binary.pop(); - binary.unshift(0); - } - return BigInt('0b' + binary.reverse().join('')); + return mod(x << BigInt(bits), p); }, rightShift(x: bigint, bits: number) { - let bitArray = x.toString(2).split('').reverse().map(Number); - let binary: number[] = - bitArray.length >= 64 - ? bitArray.splice(0, 64) - : [...bitArray, ...Array(64 - bitArray.length).fill(0)]; - for (let j = 0; j < bits; j++) { - binary.shift(); - binary.push(0); - } - return BigInt('0b' + binary.reverse().join('')); + return mod(x >> BigInt(bits), p); }, }; } From 169c97fa2ab1ef1ee345496795a067756fd8eab2 Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Thu, 26 Oct 2023 14:58:44 -0700 Subject: [PATCH 5/8] fix(finite_field.ts): modify leftShift function to limit bit size The leftShift function in finite_field.ts is updated to limit the bit size to a maximum value. This change is necessary to prevent potential overflow issues when shifting large BigInt values. The default maxBitSize is set to 64, but can be configured as needed. --- crypto/finite_field.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crypto/finite_field.ts b/crypto/finite_field.ts index ed2b5189..b5242f70 100644 --- a/crypto/finite_field.ts +++ b/crypto/finite_field.ts @@ -198,8 +198,9 @@ function createField(p: bigint, t: bigint, twoadicRoot: bigint) { } return BigInt('0b' + binary.reverse().join('')); }, - leftShift(x: bigint, bits: number) { - return mod(x << BigInt(bits), p); + leftShift(x: bigint, bits: number, maxBitSize: number = 64) { + let shifted = x << BigInt(bits); + return mod(BigInt('0b' + shifted.toString(2).slice(-maxBitSize)), p); }, rightShift(x: bigint, bits: number) { return mod(x >> BigInt(bits), p); From 03e8047966da86073d0dc3a06067f5568c8e873c Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Thu, 2 Nov 2023 10:58:40 -0700 Subject: [PATCH 6/8] fix(finite_field.ts): remove mod function from leftShift and rightShift methods to correct bit shifting operations --- crypto/finite_field.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/finite_field.ts b/crypto/finite_field.ts index f9cd8073..f806a942 100644 --- a/crypto/finite_field.ts +++ b/crypto/finite_field.ts @@ -197,10 +197,10 @@ function createField(p: bigint, t: bigint, twoadicRoot: bigint) { }, leftShift(x: bigint, bits: number, maxBitSize: number = 64) { let shifted = x << BigInt(bits); - return mod(BigInt('0b' + shifted.toString(2).slice(-maxBitSize)), p); + return BigInt('0b' + shifted.toString(2).slice(-maxBitSize)); }, rightShift(x: bigint, bits: number) { - return mod(x >> BigInt(bits), p); + return x >> BigInt(bits); }, }; } From e17660291a884877639fdbdd66c6537b75855661 Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Thu, 2 Nov 2023 13:24:58 -0700 Subject: [PATCH 7/8] feat(finite_field.ts): faster left shift implementation Co-authored-by: Gregor Mitscha-Baude --- crypto/finite_field.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/finite_field.ts b/crypto/finite_field.ts index f806a942..1c8c88b8 100644 --- a/crypto/finite_field.ts +++ b/crypto/finite_field.ts @@ -197,7 +197,7 @@ function createField(p: bigint, t: bigint, twoadicRoot: bigint) { }, leftShift(x: bigint, bits: number, maxBitSize: number = 64) { let shifted = x << BigInt(bits); - return BigInt('0b' + shifted.toString(2).slice(-maxBitSize)); + return shifted & ((1n << BigInt(maxBitSize)) - 1n); }, rightShift(x: bigint, bits: number) { return x >> BigInt(bits); From af48d4e80f51c2dff284bb7da23d91fb3f8fd3e9 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 3 Nov 2023 17:12:22 +0100 Subject: [PATCH 8/8] fix encoding --- lib/encoding.ts | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/lib/encoding.ts b/lib/encoding.ts index 4ecc5861..9d647c24 100644 --- a/lib/encoding.ts +++ b/lib/encoding.ts @@ -123,7 +123,7 @@ const Bijective = { }; function toBytesBijective(fields: Field[], p: bigint) { - let fieldsBigInts = fields.map(fieldToBigInt); + let fieldsBigInts = fields.map((x) => x.toBigInt()); let bytesBig = changeBase(fieldsBigInts, p, bytesBase); let bytes = bigIntArrayToBytes(bytesBig, bytesPerBigInt); return bytes; @@ -132,26 +132,12 @@ function toBytesBijective(fields: Field[], p: bigint) { function toFieldsBijective(bytes: Uint8Array, p: bigint) { let bytesBig = bytesToBigIntArray(bytes, bytesPerBigInt); let fieldsBigInts = changeBase(bytesBig, bytesBase, p); - let fields = fieldsBigInts.map(bigIntToField); + let fields = fieldsBigInts.map(Field); return fields; } -// a constant field is internally represented as {value: [0, Uint8Array(32)]} function bytesOfConstantField(field: Field): Uint8Array { - let value = (field as any).value; - if (value[0] !== 0) throw Error('Field is not constant'); - return value[1]; -} - -function fieldToBigInt(field: Field) { - let bytes = bytesOfConstantField(field); - return bytesToBigInt(bytes); -} - -function bigIntToField(x: bigint) { - let field = Field(1); - (field as any).value = [0, bigIntToBytes(x, 32)]; - return field; + return Uint8Array.from(Field.toBytes(field)); } function bigIntToBytes(x: bigint, length: number) {