From 83123e1d04671ec460ff37a24c26605353ca2952 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 15 Jan 2025 16:29:05 +0000 Subject: [PATCH] endianness fix --- yarn-project/foundation/src/abi/decoder.ts | 4 +-- yarn-project/foundation/src/abi/encoder.ts | 7 ++-- yarn-project/foundation/src/abi/u128.test.ts | 34 ++++++++++---------- yarn-project/foundation/src/abi/u128.ts | 8 ++--- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/yarn-project/foundation/src/abi/decoder.ts b/yarn-project/foundation/src/abi/decoder.ts index 2d1ec6a4637..1f4b0499d28 100644 --- a/yarn-project/foundation/src/abi/decoder.ts +++ b/yarn-project/foundation/src/abi/decoder.ts @@ -45,9 +45,9 @@ class AbiDecoder { } case 'struct': { if (isU128Struct(abiType)) { - const lo = this.decodeNext({ kind: 'field' }) as bigint; const hi = this.decodeNext({ kind: 'field' }) as bigint; - return U128.fromU64sLE(lo, hi).toInteger(); + const lo = this.decodeNext({ kind: 'field' }) as bigint; + return U128.fromU64sBE(hi, lo).toInteger(); } const struct: { [key: string]: AbiDecoded } = {}; diff --git a/yarn-project/foundation/src/abi/encoder.ts b/yarn-project/foundation/src/abi/encoder.ts index 6173663f622..b3fdb81c41a 100644 --- a/yarn-project/foundation/src/abi/encoder.ts +++ b/yarn-project/foundation/src/abi/encoder.ts @@ -107,11 +107,12 @@ class ArgumentEncoder { break; } if (isU128Struct(abiType)) { - // U128 struct has low and high limbs - so we first convert the value to the 2 limbs and then we encode them - // --> this results in the limbs being added to the final flat array as [..., lo, hi, ...]. + // U128 struct has high and low limbs - so we first convert the value to the 2 limbs and then we encode them + // --> this results in the limbs being added to the final flat array as [..., hi, lo, ...] (we stick to big + // endian!). const value = new U128(arg); - this.encodeArgument({ kind: 'field' }, value.lo, `${name}.lo`); this.encodeArgument({ kind: 'field' }, value.hi, `${name}.hi`); + this.encodeArgument({ kind: 'field' }, value.lo, `${name}.lo`); break; } if (isWrappedFieldStruct(abiType)) { diff --git a/yarn-project/foundation/src/abi/u128.test.ts b/yarn-project/foundation/src/abi/u128.test.ts index 0c18baba722..fb76bdb9729 100644 --- a/yarn-project/foundation/src/abi/u128.test.ts +++ b/yarn-project/foundation/src/abi/u128.test.ts @@ -29,11 +29,11 @@ describe('U128', () => { }); }); - describe('fromU64sLE', () => { + describe('fromU64sBE', () => { it('correctly combines valid limbs', () => { - const lo = 0xdeadbeefn; const hi = 0xcafebaben; - const combined = U128.fromU64sLE(lo, hi); + const lo = 0xdeadbeefn; + const combined = U128.fromU64sBE(hi, lo); expect(combined.lo).toBe(lo); expect(combined.hi).toBe(hi); @@ -42,41 +42,41 @@ describe('U128', () => { it('accepts maximum valid limb values', () => { const maxLimb = 2n ** 64n - 1n; - const value = U128.fromU64sLE(maxLimb, maxLimb); + const value = U128.fromU64sBE(maxLimb, maxLimb); - expect(value.lo).toBe(maxLimb); expect(value.hi).toBe(maxLimb); + expect(value.lo).toBe(maxLimb); expect(value.toInteger()).toBe(2n ** 128n - 1n); }); it('throws for invalid lower limb', () => { const invalid = 2n ** 64n; - expect(() => U128.fromU64sLE(invalid, 0n)).toThrow(`Lower limb ${invalid} is not within valid range`); + expect(() => U128.fromU64sBE(0n, invalid)).toThrow(`Lower limb ${invalid} is not within valid range`); - expect(() => U128.fromU64sLE(-1n, 0n)).toThrow('Lower limb -1 is not within valid range'); + expect(() => U128.fromU64sBE(0n, -1n)).toThrow('Lower limb -1 is not within valid range'); }); it('throws for invalid higher limb', () => { const invalid = 2n ** 64n; - expect(() => U128.fromU64sLE(0n, invalid)).toThrow(`Higher limb ${invalid} is not within valid range`); + expect(() => U128.fromU64sBE(invalid, 0n)).toThrow(`Higher limb ${invalid} is not within valid range`); - expect(() => U128.fromU64sLE(0n, -1n)).toThrow('Higher limb -1 is not within valid range'); + expect(() => U128.fromU64sBE(-1n, 0n)).toThrow('Higher limb -1 is not within valid range'); }); }); describe('getters', () => { - it('correctly extracts lo and hi components', () => { + it('correctly extracts hi and lo components', () => { const testCases = [ - { lo: 0xdeadbeefn, hi: 0xcafebaben }, - { lo: 0n, hi: 1n }, - { lo: 1n, hi: 0n }, - { lo: 2n ** 64n - 1n, hi: 2n ** 64n - 1n }, + { hi: 0xcafebaben, lo: 0xdeadbeefn }, + { hi: 1n, lo: 0n }, + { hi: 0n, lo: 1n }, + { hi: 2n ** 64n - 1n, lo: 2n ** 64n - 1n }, ]; - for (const { lo, hi } of testCases) { - const value = U128.fromU64sLE(lo, hi); - expect(value.lo).toBe(lo); + for (const { hi, lo } of testCases) { + const value = U128.fromU64sBE(hi, lo); expect(value.hi).toBe(hi); + expect(value.lo).toBe(lo); } }); }); diff --git a/yarn-project/foundation/src/abi/u128.ts b/yarn-project/foundation/src/abi/u128.ts index 4a0431bac07..25a34079e41 100644 --- a/yarn-project/foundation/src/abi/u128.ts +++ b/yarn-project/foundation/src/abi/u128.ts @@ -15,14 +15,14 @@ export class U128 { this.value = value; } - static fromU64sLE(lo: bigint, hi: bigint): U128 { + static fromU64sBE(hi: bigint, lo: bigint): U128 { // Validate limbs are within valid ranges - if (lo < 0n || lo >= 2n ** 64n) { - throw new Error(`Lower limb ${lo} is not within valid range (0 to 2^64-1)`); - } if (hi < 0n || hi >= 2n ** 64n) { throw new Error(`Higher limb ${hi} is not within valid range (0 to 2^64-1)`); } + if (lo < 0n || lo >= 2n ** 64n) { + throw new Error(`Lower limb ${lo} is not within valid range (0 to 2^64-1)`); + } // Combine limbs into full value and create new instance const value = (hi << 64n) | lo;