From 8c8d078896dda3024298adeb25ac1aae16155f08 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 11 Apr 2024 13:39:39 +0000 Subject: [PATCH 01/17] refactor: TS hash wrappers cleanup --- .../ts/src/barretenberg/poseidon.test.ts | 6 +++--- barretenberg/ts/src/barretenberg_api/index.ts | 4 ++-- yarn-project/circuits.js/src/hash/hash.ts | 2 +- .../src/merkle/merkle_tree_calculator.ts | 3 ++- .../circuits.js/src/merkle/sibling_path.ts | 3 ++- .../foundation/src/crypto/pedersen/index.test.ts | 4 ++-- .../src/crypto/pedersen/pedersen.wasm.ts | 16 +++++++--------- .../foundation/src/crypto/poseidon/index.ts | 13 ++++++++++--- .../foundation/src/serialize/serialize.ts | 6 ++++++ yarn-project/merkle-tree/src/pedersen.ts | 6 ++++-- .../simulator/src/avm/avm_simulator.test.ts | 7 ++++--- .../simulator/src/avm/opcodes/hashing.test.ts | 4 ++-- .../simulator/src/avm/opcodes/hashing.ts | 2 +- 13 files changed, 46 insertions(+), 30 deletions(-) diff --git a/barretenberg/ts/src/barretenberg/poseidon.test.ts b/barretenberg/ts/src/barretenberg/poseidon.test.ts index 2647e4778ddc..0170a225a263 100644 --- a/barretenberg/ts/src/barretenberg/poseidon.test.ts +++ b/barretenberg/ts/src/barretenberg/poseidon.test.ts @@ -10,7 +10,7 @@ describe('poseidon sync', () => { }); it('poseidonHash', () => { - const result = api.poseidonHash([new Fr(4n), new Fr(8n)]); + const result = api.poseidonHash([new Fr(4n), new Fr(8n)], 7); expect(result).toMatchSnapshot(); }); @@ -19,7 +19,7 @@ describe('poseidon sync', () => { const fields = Array.from({ length: loops * 2 }).map(() => Fr.random()); const t = new Timer(); for (let i = 0; i < loops; ++i) { - api.poseidonHash([fields[i * 2], fields[i * 2 + 1]]); + api.poseidonHash([fields[i * 2], fields[i * 2 + 1]], 0); } const us = t.us() / loops; console.log(`Executed ${loops} hashes at an average ${us}us / hash`); @@ -36,4 +36,4 @@ describe('poseidon sync', () => { const us = t.us() / (numHashesPerLoop * loops); console.log(`Executed ${numHashesPerLoop * loops} hashes at an average ${us}us / hash`); }); -}); +}); \ No newline at end of file diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index 05d6568cdb7d..5cba649eaac8 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -607,8 +607,8 @@ export class BarretenbergApiSync { return out[0]; } - poseidonHash(inputsBuffer: Fr[]): Fr { - const inArgs = [inputsBuffer].map(serializeBufferable); + poseidonHash(inputsBuffer: Fr[], hashIndex: number): Fr { + const inArgs = [inputsBuffer, hashIndex].map(serializeBufferable); const outTypes: OutputType[] = [Fr]; const result = this.wasm.callWasmExport( 'poseidon_hash', diff --git a/yarn-project/circuits.js/src/hash/hash.ts b/yarn-project/circuits.js/src/hash/hash.ts index b5f4f1c0a633..b5496f757139 100644 --- a/yarn-project/circuits.js/src/hash/hash.ts +++ b/yarn-project/circuits.js/src/hash/hash.ts @@ -61,7 +61,7 @@ export function hashVK(vkBuf: Buffer) { * @returns A commitment nonce. */ export function computeCommitmentNonce(nullifierZero: Fr, commitmentIndex: number): Fr { - return pedersenHash([nullifierZero, numToUInt32BE(commitmentIndex, 32)], GeneratorIndex.NOTE_HASH_NONCE); + return pedersenHash([nullifierZero, commitmentIndex], GeneratorIndex.NOTE_HASH_NONCE); } /** diff --git a/yarn-project/circuits.js/src/merkle/merkle_tree_calculator.ts b/yarn-project/circuits.js/src/merkle/merkle_tree_calculator.ts index c8d4870039c0..471c0f776bd2 100644 --- a/yarn-project/circuits.js/src/merkle/merkle_tree_calculator.ts +++ b/yarn-project/circuits.js/src/merkle/merkle_tree_calculator.ts @@ -1,4 +1,5 @@ import { pedersenHash } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; import { MerkleTree } from './merkle_tree.js'; @@ -12,7 +13,7 @@ export class MerkleTreeCalculator { constructor( private height: number, zeroLeaf = Buffer.alloc(32), - hasher = (left: Buffer, right: Buffer) => pedersenHash([left, right]).toBuffer(), + hasher = (left: Buffer, right: Buffer) => pedersenHash([Fr.fromBuffer(left), Fr.fromBuffer(right)]).toBuffer(), ) { this.hasher = hasher; this.zeroHashes = Array.from({ length: height }).reduce( diff --git a/yarn-project/circuits.js/src/merkle/sibling_path.ts b/yarn-project/circuits.js/src/merkle/sibling_path.ts index 52383dae87c7..4a31d3a7a233 100644 --- a/yarn-project/circuits.js/src/merkle/sibling_path.ts +++ b/yarn-project/circuits.js/src/merkle/sibling_path.ts @@ -1,11 +1,12 @@ import { pedersenHash } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; /** Computes the expected root of a merkle tree given a leaf and its sibling path. */ export function computeRootFromSiblingPath( leaf: Buffer, siblingPath: Buffer[], index: number, - hasher = (left: Buffer, right: Buffer) => pedersenHash([left, right]).toBuffer(), + hasher = (left: Buffer, right: Buffer) => pedersenHash([Fr.fromBuffer(left), Fr.fromBuffer(right)]).toBuffer(), ) { let result = leaf; for (const sibling of siblingPath) { diff --git a/yarn-project/foundation/src/crypto/pedersen/index.test.ts b/yarn-project/foundation/src/crypto/pedersen/index.test.ts index 0e9e1c1c92a0..5b2f1b435a2f 100644 --- a/yarn-project/foundation/src/crypto/pedersen/index.test.ts +++ b/yarn-project/foundation/src/crypto/pedersen/index.test.ts @@ -27,12 +27,12 @@ describe('pedersen', () => { }); it('pedersen hash', () => { - const r = pedersenHash([toBufferBE(1n, 32), toBufferBE(1n, 32)]); + const r = pedersenHash([1n, 1n]); expect(r.toString()).toEqual('0x07ebfbf4df29888c6cd6dca13d4bb9d1a923013ddbbcbdc3378ab8845463297b'); }); it('pedersen hash with index', () => { - const r = pedersenHash([toBufferBE(1n, 32), toBufferBE(1n, 32)], 5); + const r = pedersenHash([1n, 1n], 5); expect(r.toString()).toEqual('0x1c446df60816b897cda124524e6b03f36df0cec333fad87617aab70d7861daa6'); }); diff --git a/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts b/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts index 29fc82dcac3e..57df5fc9ff3b 100644 --- a/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts +++ b/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts @@ -1,7 +1,7 @@ import { BarretenbergSync, Fr as FrBarretenberg } from '@aztec/bb.js'; import { Fr } from '../../fields/fields.js'; -import { type Bufferable, serializeToBufferArray } from '../../serialize/serialize.js'; +import { type Fieldeable, serializeToFields } from '../../serialize/serialize.js'; /** * Create a pedersen commitment (point) from an array of input fields. @@ -20,19 +20,17 @@ export function pedersenCommit(input: Buffer[]) { /** * Create a pedersen hash (field) from an array of input fields. - * Left pads any inputs less than 32 bytes. + * @param input - The input fieldeables to hash. + * @param index - The separator index to use for the hash. + * @returns The pedersen hash. */ -export function pedersenHash(input: Bufferable[], index = 0): Fr { - let bufferredInput = serializeToBufferArray(input); - if (!bufferredInput.every(i => i.length <= 32)) { - throw new Error('All Pedersen Hash input buffers must be <= 32 bytes.'); - } - bufferredInput = bufferredInput.map(i => (i.length < 32 ? Buffer.concat([Buffer.alloc(32 - i.length, 0), i]) : i)); +export function pedersenHash(input: Fieldeable[], index = 0): Fr { + const inputFields = serializeToFields(input); return Fr.fromBuffer( Buffer.from( BarretenbergSync.getSingleton() .pedersenHash( - bufferredInput.map(i => new FrBarretenberg(i)), + inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion index, ) .toBuffer(), diff --git a/yarn-project/foundation/src/crypto/poseidon/index.ts b/yarn-project/foundation/src/crypto/poseidon/index.ts index 8f77b5802115..410ae8d91c1f 100644 --- a/yarn-project/foundation/src/crypto/poseidon/index.ts +++ b/yarn-project/foundation/src/crypto/poseidon/index.ts @@ -1,16 +1,23 @@ import { BarretenbergSync, Fr as FrBarretenberg } from '@aztec/bb.js'; import { Fr } from '../../fields/fields.js'; +import { type Fieldeable, serializeToFields } from '../../serialize/serialize.js'; /** * Create a poseidon hash (field) from an array of input fields. - * Left pads any inputs less than 32 bytes. + * @param input - The input fields to hash. + * @param index - The separator index to use for the hash. + * @returns The poseidon hash. */ -export function poseidonHash(input: Buffer[]): Fr { +export function poseidonHash(input: Fieldeable[], index = 0): Fr { + const inputFields = serializeToFields(input); return Fr.fromBuffer( Buffer.from( BarretenbergSync.getSingleton() - .poseidonHash(input.map(i => new FrBarretenberg(i))) + .poseidonHash( + inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion + index, + ) .toBuffer(), ), ); diff --git a/yarn-project/foundation/src/serialize/serialize.ts b/yarn-project/foundation/src/serialize/serialize.ts index c610b5fea643..44ef75534ac9 100644 --- a/yarn-project/foundation/src/serialize/serialize.ts +++ b/yarn-project/foundation/src/serialize/serialize.ts @@ -126,6 +126,10 @@ export type Fieldeable = | boolean | number | bigint + | { + /** Serialize to a field. */ + toFr: () => Fr; + } | { /** Serialize to a field. */ toField: () => Fr; @@ -187,6 +191,8 @@ export function serializeToFields(...objs: Fieldeable[]): Fr[] { ret.push(new Fr(obj)); } else if ('toFields' in obj) { ret = [...ret, ...obj.toFields()]; + } else if ('toFr' in obj) { + ret.push(obj.toFr()); } else { ret.push(obj.toField()); } diff --git a/yarn-project/merkle-tree/src/pedersen.ts b/yarn-project/merkle-tree/src/pedersen.ts index b49c34c527e7..8ddfa6365492 100644 --- a/yarn-project/merkle-tree/src/pedersen.ts +++ b/yarn-project/merkle-tree/src/pedersen.ts @@ -1,4 +1,5 @@ import { pedersenHash } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; import { type Hasher } from '@aztec/types/interfaces'; /** @@ -12,7 +13,7 @@ export class Pedersen implements Hasher { * purposes. */ public hash(lhs: Uint8Array, rhs: Uint8Array): Buffer { - return pedersenHash([Buffer.from(lhs), Buffer.from(rhs)]).toBuffer(); + return pedersenHash([Fr.fromBuffer(Buffer.from(lhs)), Fr.fromBuffer(Buffer.from(rhs))]).toBuffer(); } /* @@ -20,6 +21,7 @@ export class Pedersen implements Hasher { * purposes. */ public hashInputs(inputs: Buffer[]): Buffer { - return pedersenHash(inputs).toBuffer(); + const inputFields = inputs.map(i => Fr.fromBuffer(i)); + return pedersenHash(inputFields).toBuffer(); } } diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 78d0aa01011c..d10a1df3c0db 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -24,6 +24,7 @@ import { } from './fixtures/index.js'; import { Add, CalldataCopy, Return } from './opcodes/index.js'; import { encodeToBytecode } from './serialization/bytecode_serialization.js'; +import { Fieldeable } from '@aztec/foundation/serialize'; describe('AVM simulator: injected bytecode', () => { let calldata: Fr[]; @@ -140,11 +141,11 @@ describe('AVM simulator: transpiled Noir contracts', () => { describe.each([ ['poseidon_hash', poseidonHash], ['pedersen_hash', pedersenHash], - ['pedersen_hash_with_index', (m: Buffer[]) => pedersenHash(m, 20)], - ])('Hashes with field returned in noir contracts', (name: string, hashFunction: (data: Buffer[]) => Fr) => { + ['pedersen_hash_with_index', (m: Fieldeable[]) => pedersenHash(m, 20)], + ])('Hashes with field returned in noir contracts', (name: string, hashFunction: (data: Fieldeable[]) => Fr) => { it(`Should execute contract function that performs ${name} hash`, async () => { const calldata = [new Fr(1), new Fr(2), new Fr(3)]; - const hash = hashFunction(calldata.map(f => f.toBuffer())); + const hash = hashFunction(calldata); const context = initContext({ env: initExecutionEnvironment({ calldata }) }); const bytecode = getAvmTestContractBytecode(name); diff --git a/yarn-project/simulator/src/avm/opcodes/hashing.test.ts b/yarn-project/simulator/src/avm/opcodes/hashing.test.ts index 42e6d690e48b..3986bd73b2b8 100644 --- a/yarn-project/simulator/src/avm/opcodes/hashing.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/hashing.test.ts @@ -41,7 +41,7 @@ describe('Hashing Opcodes', () => { const dstOffset = 3; - const expectedHash = poseidonHash(args.map(field => field.toBuffer())); + const expectedHash = poseidonHash(args); await new Poseidon2(indirect, dstOffset, messageOffset, args.length).execute(context); const result = context.machineState.memory.get(dstOffset); @@ -62,7 +62,7 @@ describe('Hashing Opcodes', () => { const dstOffset = 3; - const expectedHash = poseidonHash(args.map(field => field.toBuffer())); + const expectedHash = poseidonHash(args); await new Poseidon2(indirect, dstOffset, messageOffset, args.length).execute(context); const result = context.machineState.memory.get(dstOffset); diff --git a/yarn-project/simulator/src/avm/opcodes/hashing.ts b/yarn-project/simulator/src/avm/opcodes/hashing.ts index 31c5f7ac54cb..500bbf46cbdd 100644 --- a/yarn-project/simulator/src/avm/opcodes/hashing.ts +++ b/yarn-project/simulator/src/avm/opcodes/hashing.ts @@ -41,7 +41,7 @@ export class Poseidon2 extends Instruction { ); // Memory pointer will be indirect - const hashData = memory.getSlice(messageOffset, this.messageSize).map(word => word.toBuffer()); + const hashData = memory.getSlice(messageOffset, this.messageSize); const hash = poseidonHash(hashData); memory.set(dstOffset, new Field(hash)); From 38df5b35cb9ae680bf3e82c07adfceb5e9c02fb4 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 11 Apr 2024 13:50:53 +0000 Subject: [PATCH 02/17] less retarded spelling --- cspell.json | 2 +- .../foundation/src/crypto/pedersen/pedersen.wasm.ts | 6 +++--- yarn-project/foundation/src/crypto/poseidon/index.ts | 4 ++-- yarn-project/foundation/src/serialize/serialize.ts | 6 +++--- yarn-project/simulator/src/avm/avm_simulator.test.ts | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cspell.json b/cspell.json index 9180d507c568..b66546c31b17 100644 --- a/cspell.json +++ b/cspell.json @@ -79,7 +79,7 @@ "erc", "falsey", "fargate", - "Fieldeable", + "Fieldable", "filestat", "finalise", "finalised", diff --git a/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts b/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts index 57df5fc9ff3b..bb07994bb955 100644 --- a/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts +++ b/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts @@ -1,7 +1,7 @@ import { BarretenbergSync, Fr as FrBarretenberg } from '@aztec/bb.js'; import { Fr } from '../../fields/fields.js'; -import { type Fieldeable, serializeToFields } from '../../serialize/serialize.js'; +import { type Fieldable, serializeToFields } from '../../serialize/serialize.js'; /** * Create a pedersen commitment (point) from an array of input fields. @@ -20,11 +20,11 @@ export function pedersenCommit(input: Buffer[]) { /** * Create a pedersen hash (field) from an array of input fields. - * @param input - The input fieldeables to hash. + * @param input - The input fieldables to hash. * @param index - The separator index to use for the hash. * @returns The pedersen hash. */ -export function pedersenHash(input: Fieldeable[], index = 0): Fr { +export function pedersenHash(input: Fieldable[], index = 0): Fr { const inputFields = serializeToFields(input); return Fr.fromBuffer( Buffer.from( diff --git a/yarn-project/foundation/src/crypto/poseidon/index.ts b/yarn-project/foundation/src/crypto/poseidon/index.ts index 410ae8d91c1f..1a4bd104e476 100644 --- a/yarn-project/foundation/src/crypto/poseidon/index.ts +++ b/yarn-project/foundation/src/crypto/poseidon/index.ts @@ -1,7 +1,7 @@ import { BarretenbergSync, Fr as FrBarretenberg } from '@aztec/bb.js'; import { Fr } from '../../fields/fields.js'; -import { type Fieldeable, serializeToFields } from '../../serialize/serialize.js'; +import { type Fieldable, serializeToFields } from '../../serialize/serialize.js'; /** * Create a poseidon hash (field) from an array of input fields. @@ -9,7 +9,7 @@ import { type Fieldeable, serializeToFields } from '../../serialize/serialize.js * @param index - The separator index to use for the hash. * @returns The poseidon hash. */ -export function poseidonHash(input: Fieldeable[], index = 0): Fr { +export function poseidonHash(input: Fieldable[], index = 0): Fr { const inputFields = serializeToFields(input); return Fr.fromBuffer( Buffer.from( diff --git a/yarn-project/foundation/src/serialize/serialize.ts b/yarn-project/foundation/src/serialize/serialize.ts index 44ef75534ac9..b06c0dbfa6af 100644 --- a/yarn-project/foundation/src/serialize/serialize.ts +++ b/yarn-project/foundation/src/serialize/serialize.ts @@ -121,7 +121,7 @@ export type Bufferable = | Bufferable[]; /** A type that can be converted to a Field or a Field array. */ -export type Fieldeable = +export type Fieldable = | Fr | boolean | number @@ -138,7 +138,7 @@ export type Fieldeable = /** Serialize to an array of fields. */ toFields: () => Fr[]; } - | Fieldeable[]; + | Fieldable[]; /** * Serializes a list of objects contiguously. @@ -180,7 +180,7 @@ export function serializeToBufferArray(...objs: Bufferable[]): Buffer[] { * @param objs - Objects to serialize. * @returns An array of fields with the concatenation of all fields. */ -export function serializeToFields(...objs: Fieldeable[]): Fr[] { +export function serializeToFields(...objs: Fieldable[]): Fr[] { let ret: Fr[] = []; for (const obj of objs) { if (Array.isArray(obj)) { diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index d10a1df3c0db..ddad28738b70 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -24,7 +24,7 @@ import { } from './fixtures/index.js'; import { Add, CalldataCopy, Return } from './opcodes/index.js'; import { encodeToBytecode } from './serialization/bytecode_serialization.js'; -import { Fieldeable } from '@aztec/foundation/serialize'; +import { Fieldable } from '@aztec/foundation/serialize'; describe('AVM simulator: injected bytecode', () => { let calldata: Fr[]; @@ -141,8 +141,8 @@ describe('AVM simulator: transpiled Noir contracts', () => { describe.each([ ['poseidon_hash', poseidonHash], ['pedersen_hash', pedersenHash], - ['pedersen_hash_with_index', (m: Fieldeable[]) => pedersenHash(m, 20)], - ])('Hashes with field returned in noir contracts', (name: string, hashFunction: (data: Fieldeable[]) => Fr) => { + ['pedersen_hash_with_index', (m: Fieldable[]) => pedersenHash(m, 20)], + ])('Hashes with field returned in noir contracts', (name: string, hashFunction: (data: Fieldable[]) => Fr) => { it(`Should execute contract function that performs ${name} hash`, async () => { const calldata = [new Fr(1), new Fr(2), new Fr(3)]; const hash = hashFunction(calldata); From f05a671ab50c2b6448593c2aef1e11917e2fda4b Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 11 Apr 2024 13:53:53 +0000 Subject: [PATCH 03/17] comment --- yarn-project/foundation/src/serialize/serialize.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/yarn-project/foundation/src/serialize/serialize.ts b/yarn-project/foundation/src/serialize/serialize.ts index b06c0dbfa6af..c255ec279412 100644 --- a/yarn-project/foundation/src/serialize/serialize.ts +++ b/yarn-project/foundation/src/serialize/serialize.ts @@ -127,7 +127,10 @@ export type Fieldable = | number | bigint | { - /** Serialize to a field. */ + /** + * Serialize to a field. + * @dev Duplicate to `toField` but left as is as it is used in AVM codebase. + */ toFr: () => Fr; } | { From cf2466e72b7fac44fea8eb327c02333dd75a7408 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 11 Apr 2024 13:57:07 +0000 Subject: [PATCH 04/17] fmt --- barretenberg/ts/src/barretenberg/poseidon.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/ts/src/barretenberg/poseidon.test.ts b/barretenberg/ts/src/barretenberg/poseidon.test.ts index 0170a225a263..8086e16177c4 100644 --- a/barretenberg/ts/src/barretenberg/poseidon.test.ts +++ b/barretenberg/ts/src/barretenberg/poseidon.test.ts @@ -36,4 +36,4 @@ describe('poseidon sync', () => { const us = t.us() / (numHashesPerLoop * loops); console.log(`Executed ${numHashesPerLoop * loops} hashes at an average ${us}us / hash`); }); -}); \ No newline at end of file +}); From 5a7141773811a81556811b762a80d0b676deb683 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 11 Apr 2024 14:01:57 +0000 Subject: [PATCH 05/17] random fixes --- barretenberg/sol/README.md | 2 +- noir-projects/aztec-nr/aztec/src/note/utils.nr | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/barretenberg/sol/README.md b/barretenberg/sol/README.md index 30572db0b3c4..54506fd4fea3 100644 --- a/barretenberg/sol/README.md +++ b/barretenberg/sol/README.md @@ -18,7 +18,7 @@ The verification key is currently generated via [Barretenberg](https://github.co ## Generating Verification Keys and Proofs -Run `bootstrap.sh` to clone git submodules, download SRS and generate verification keys, relies on barretenberg already being compiled (run `./bootstrap` in `cpp`). The bootstrap will also install foundry to `./.foundry` so you can use `./.foundry/bin/forge` if you don't already have foundry installed. +Run `bootstrap.sh` to clone git submodules, download SRS and generate verification keys, relies on barretenberg already being compiled (run `./bootstrap` in `cpp`). The bootstrap will also install foundry to `./.foundry` so you can use `$PROJECT_ROOT/foundry/bin/forge` if you don't already have foundry installed. # Tests diff --git a/noir-projects/aztec-nr/aztec/src/note/utils.nr b/noir-projects/aztec-nr/aztec/src/note/utils.nr index 8732ca6be61f..49311d794af5 100644 --- a/noir-projects/aztec-nr/aztec/src/note/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/note/utils.nr @@ -71,8 +71,8 @@ pub fn compute_note_hash_for_consumption(note: Note) -> Field where Not } else { // When nonce is nonzero, that means we are reading a settled note (from tree) created in a // previous TX. So we need the unique_siloed_note_hash which has already been hashed with - // contract address and then nonce. This hash will match the existing leaf in the private - // data tree, so the kernel can just perform a membership check directly on this hash/leaf. + // contract address and then nonce. This hash will match the existing leaf in the note hash + // tree, so the kernel can just perform a membership check directly on this hash/leaf. compute_unique_siloed_note_hash(note) // IMPORTANT NOTE ON REDUNDANT SILOING BY CONTRACT ADDRESS: The note hash computed above is // "siloed" by contract address. When a note hash is computed solely for the purpose of @@ -81,7 +81,7 @@ pub fn compute_note_hash_for_consumption(note: Note) -> Field where Not // be computed from a siloed note hash. After all, persistable note hashes and nullifiers are // siloed by the kernel circuit. That being said, the siloed note hash computed above CAN be // used for nullifier computation, and this achieves the (arguably unnecessary) property that - // nullifiers are computed from a note hash's fully-computed private data tree leaf. + // nullifiers are computed from a note hash's fully-computed note hash tree leaf. } } From d49d4098e4499278a2c53753f37484318ee639c1 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 11 Apr 2024 15:26:51 +0000 Subject: [PATCH 06/17] fix --- yarn-project/circuits.js/src/contract/private_function.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/circuits.js/src/contract/private_function.ts b/yarn-project/circuits.js/src/contract/private_function.ts index ea244b9d94ac..b0395155e1cd 100644 --- a/yarn-project/circuits.js/src/contract/private_function.ts +++ b/yarn-project/circuits.js/src/contract/private_function.ts @@ -32,7 +32,7 @@ export function computePrivateFunctionLeaf(fn: PrivateFunction): Buffer { function getPrivateFunctionTreeCalculator(): MerkleTreeCalculator { if (!privateFunctionTreeCalculator) { - const functionTreeZeroLeaf = pedersenHash(new Array(PRIVATE_FUNCTION_SIZE).fill(Buffer.alloc(32))).toBuffer(); + const functionTreeZeroLeaf = pedersenHash(new Array(PRIVATE_FUNCTION_SIZE).fill(0)).toBuffer(); privateFunctionTreeCalculator = new MerkleTreeCalculator(FUNCTION_TREE_HEIGHT, functionTreeZeroLeaf); } return privateFunctionTreeCalculator; From 3712c5a15a13496cb214f9e480b329af12e642a0 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 11 Apr 2024 18:11:49 +0000 Subject: [PATCH 07/17] fix --- .../foundation/src/serialize/serialize.ts | 4 +++- .../snapshots/append_only_snapshot.test.ts | 4 ++-- .../src/snapshots/full_snapshot.test.ts | 4 ++-- .../src/sparse_tree/sparse_tree.test.ts | 19 ++++++++++--------- .../src/standard_tree/standard_tree.test.ts | 4 ++-- .../src/test/standard_based_test_suite.ts | 4 ++-- 6 files changed, 21 insertions(+), 18 deletions(-) diff --git a/yarn-project/foundation/src/serialize/serialize.ts b/yarn-project/foundation/src/serialize/serialize.ts index c255ec279412..9189fd39105a 100644 --- a/yarn-project/foundation/src/serialize/serialize.ts +++ b/yarn-project/foundation/src/serialize/serialize.ts @@ -196,8 +196,10 @@ export function serializeToFields(...objs: Fieldable[]): Fr[] { ret = [...ret, ...obj.toFields()]; } else if ('toFr' in obj) { ret.push(obj.toFr()); - } else { + } else if ('toField' in obj) { ret.push(obj.toField()); + } else { + throw new Error(`Cannot serialize input to field: ${typeof obj} ${(obj as any).constructor?.name}`); } } return ret; diff --git a/yarn-project/merkle-tree/src/snapshots/append_only_snapshot.test.ts b/yarn-project/merkle-tree/src/snapshots/append_only_snapshot.test.ts index 111f6de0439b..e68bde0ee71e 100644 --- a/yarn-project/merkle-tree/src/snapshots/append_only_snapshot.test.ts +++ b/yarn-project/merkle-tree/src/snapshots/append_only_snapshot.test.ts @@ -1,4 +1,4 @@ -import { randomBytes } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; import { type FromBuffer } from '@aztec/foundation/serialize'; import { type AztecKVStore } from '@aztec/kv-store'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -24,7 +24,7 @@ describe('AppendOnlySnapshot', () => { () => tree, () => snapshotBuilder, async tree => { - const newLeaves = Array.from({ length: 2 }).map(() => randomBytes(32)); + const newLeaves = Array.from({ length: 2 }).map(() => Fr.random().toBuffer()); await tree.appendLeaves(newLeaves); }, ); diff --git a/yarn-project/merkle-tree/src/snapshots/full_snapshot.test.ts b/yarn-project/merkle-tree/src/snapshots/full_snapshot.test.ts index 486f633262a7..be8a8572f6c1 100644 --- a/yarn-project/merkle-tree/src/snapshots/full_snapshot.test.ts +++ b/yarn-project/merkle-tree/src/snapshots/full_snapshot.test.ts @@ -1,4 +1,4 @@ -import { randomBytes } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; import { type FromBuffer } from '@aztec/foundation/serialize'; import { type AztecKVStore } from '@aztec/kv-store'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -23,7 +23,7 @@ describe('FullSnapshotBuilder', () => { () => tree, () => snapshotBuilder, async () => { - const newLeaves = Array.from({ length: 2 }).map(() => randomBytes(32)); + const newLeaves = Array.from({ length: 2 }).map(() => Fr.random().toBuffer()); await tree.appendLeaves(newLeaves); }, ); diff --git a/yarn-project/merkle-tree/src/sparse_tree/sparse_tree.test.ts b/yarn-project/merkle-tree/src/sparse_tree/sparse_tree.test.ts index e949192e9003..56cbaee0a58c 100644 --- a/yarn-project/merkle-tree/src/sparse_tree/sparse_tree.test.ts +++ b/yarn-project/merkle-tree/src/sparse_tree/sparse_tree.test.ts @@ -1,5 +1,6 @@ import { SiblingPath } from '@aztec/circuit-types'; -import { randomBigInt, randomBytes } from '@aztec/foundation/crypto'; +import { randomBigInt } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { type AztecKVStore } from '@aztec/kv-store'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -71,11 +72,11 @@ describe('SparseTreeSpecific', () => { expect(tree.getNumLeaves(false)).toEqual(0n); // Insert a leaf - await tree.updateLeaf(randomBytes(32), randomIndex); + await tree.updateLeaf(Fr.random().toBuffer(), randomIndex); expect(tree.getNumLeaves(true)).toEqual(1n); // Update a leaf - await tree.updateLeaf(randomBytes(32), randomIndex); + await tree.updateLeaf(Fr.random().toBuffer(), randomIndex); expect(tree.getNumLeaves(true)).toEqual(1n); }); @@ -90,7 +91,7 @@ describe('SparseTreeSpecific', () => { expect(tree.getNumLeaves(false)).toEqual(0n); // Insert a leaf - await tree.updateLeaf(randomBytes(32), randomIndex); + await tree.updateLeaf(Fr.random().toBuffer(), randomIndex); expect(tree.getNumLeaves(true)).toEqual(1n); // Delete a leaf @@ -110,7 +111,7 @@ describe('SparseTreeSpecific', () => { // Insert leaf at index 3 let level1LeftHash: Buffer; - const leafAtIndex3 = randomBytes(32); + const leafAtIndex3 = Fr.random().toBuffer(); { await tree.updateLeaf(leafAtIndex3, 3n); expect(tree.getNumLeaves(true)).toEqual(1n); @@ -126,7 +127,7 @@ describe('SparseTreeSpecific', () => { // Insert leaf at index 6 let level1RightHash: Buffer; { - const leafAtIndex6 = randomBytes(32); + const leafAtIndex6 = Fr.random().toBuffer(); await tree.updateLeaf(leafAtIndex6, 6n); expect(tree.getNumLeaves(true)).toEqual(2n); const level2Hash = pedersen.hash(leafAtIndex6, INITIAL_LEAF); @@ -139,7 +140,7 @@ describe('SparseTreeSpecific', () => { } // Insert leaf at index 2 - const leafAtIndex2 = randomBytes(32); + const leafAtIndex2 = Fr.random().toBuffer(); { await tree.updateLeaf(leafAtIndex2, 2n); expect(tree.getNumLeaves(true)).toEqual(3n); @@ -154,7 +155,7 @@ describe('SparseTreeSpecific', () => { // Updating leaf at index 3 { - const updatedLeafAtIndex3 = randomBytes(32); + const updatedLeafAtIndex3 = Fr.random().toBuffer(); await tree.updateLeaf(updatedLeafAtIndex3, 3n); expect(tree.getNumLeaves(true)).toEqual(3n); const level2Hash = pedersen.hash(leafAtIndex2, updatedLeafAtIndex3); @@ -175,7 +176,7 @@ describe('SparseTreeSpecific', () => { const db = openTmpStore(); const tree = await createDb(db, pedersen, 'test', depth); - const leaves = Array.from({ length: 1000 }).map(() => randomBytes(32)); + const leaves = Array.from({ length: 1000 }).map(() => Fr.random().toBuffer()); const indices = Array.from({ length: 1000 }).map(() => randomBigInt(BigInt(maxIndex))); const start = Date.now(); diff --git a/yarn-project/merkle-tree/src/standard_tree/standard_tree.test.ts b/yarn-project/merkle-tree/src/standard_tree/standard_tree.test.ts index cd946ac771a7..b01409eb14c5 100644 --- a/yarn-project/merkle-tree/src/standard_tree/standard_tree.test.ts +++ b/yarn-project/merkle-tree/src/standard_tree/standard_tree.test.ts @@ -1,4 +1,4 @@ -import { randomBytes } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; import { type FromBuffer } from '@aztec/foundation/serialize'; import { type AztecKVStore } from '@aztec/kv-store'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -41,7 +41,7 @@ describe('StandardTree_batchAppend', () => { it('correctly computes root when batch appending and calls hash function expected num times', async () => { const db = openTmpStore(); const tree = await createDb(db, pedersen, 'test', 3); - const leaves = Array.from({ length: 5 }, _ => randomBytes(32)); + const leaves = Array.from({ length: 5 }, _ => Fr.random().toBuffer()); pedersen.resetCounter(); await tree.appendLeaves(leaves); diff --git a/yarn-project/merkle-tree/src/test/standard_based_test_suite.ts b/yarn-project/merkle-tree/src/test/standard_based_test_suite.ts index a2533ad9e6df..6f8fc6d09873 100644 --- a/yarn-project/merkle-tree/src/test/standard_based_test_suite.ts +++ b/yarn-project/merkle-tree/src/test/standard_based_test_suite.ts @@ -1,5 +1,5 @@ import { SiblingPath } from '@aztec/circuit-types'; -import { randomBytes } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; import { type AztecKVStore } from '@aztec/kv-store'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type Hasher } from '@aztec/types/interfaces'; @@ -44,7 +44,7 @@ export const standardBasedTreeTestSuite = ( it('should throw when appending beyond max index', async () => { const db = openTmpStore(); const tree = await createDb(db, pedersen, 'test', 2); - const leaves = Array.from({ length: 5 }, _ => randomBytes(32)); + const leaves = Array.from({ length: 5 }, _ => Fr.random().toBuffer()); await expect(appendLeaves(tree, leaves)).rejects.toThrow(); }); From a70c29de0f249474c03f7334e10a7af806e08c59 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 11 Apr 2024 18:14:40 +0000 Subject: [PATCH 08/17] fix --- yarn-project/foundation/src/serialize/serialize.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yarn-project/foundation/src/serialize/serialize.ts b/yarn-project/foundation/src/serialize/serialize.ts index 9189fd39105a..a6886716ecc1 100644 --- a/yarn-project/foundation/src/serialize/serialize.ts +++ b/yarn-project/foundation/src/serialize/serialize.ts @@ -198,6 +198,8 @@ export function serializeToFields(...objs: Fieldable[]): Fr[] { ret.push(obj.toFr()); } else if ('toField' in obj) { ret.push(obj.toField()); + } else if (Buffer.isBuffer(obj)) { + ret.push(Fr.fromBuffer(obj)); } else { throw new Error(`Cannot serialize input to field: ${typeof obj} ${(obj as any).constructor?.name}`); } From 29fb9a79bcdf80a968749b90d33db00fa9b4a6d0 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 12 Apr 2024 06:56:29 +0000 Subject: [PATCH 09/17] fmt --- yarn-project/simulator/src/avm/avm_simulator.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index ddad28738b70..3e932af1294a 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -5,6 +5,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { keccak, pedersenHash, poseidonHash, sha256 } from '@aztec/foundation/crypto'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; +import { type Fieldable } from '@aztec/foundation/serialize'; import { AvmNestedCallsTestContractArtifact, AvmTestContractArtifact } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -24,7 +25,6 @@ import { } from './fixtures/index.js'; import { Add, CalldataCopy, Return } from './opcodes/index.js'; import { encodeToBytecode } from './serialization/bytecode_serialization.js'; -import { Fieldable } from '@aztec/foundation/serialize'; describe('AVM simulator: injected bytecode', () => { let calldata: Fr[]; From 47cc247fe7da8a5abe42da76c65fb1a0defb492d Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 12 Apr 2024 07:25:59 +0000 Subject: [PATCH 10/17] check in bb field --- barretenberg/ts/src/types/fields.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/barretenberg/ts/src/types/fields.ts b/barretenberg/ts/src/types/fields.ts index a54cbe5a3289..9305f0d6142d 100644 --- a/barretenberg/ts/src/types/fields.ts +++ b/barretenberg/ts/src/types/fields.ts @@ -2,6 +2,7 @@ import { randomBytes } from '../random/index.js'; import { toBigIntBE, toBufferBE } from '../bigint-array/index.js'; import { BufferReader, uint8ArrayToHexString } from '../serialize/index.js'; +// TODO(#4189): Replace with implementation in yarn-project/foundation/src/fields/fields.ts export class Fr { static ZERO = new Fr(0n); static MODULUS = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n; @@ -10,14 +11,14 @@ export class Fr { value: Uint8Array; constructor(value: Uint8Array | bigint) { - if (typeof value === 'bigint') { - if (value > Fr.MAX_VALUE) { - throw new Error(`Fr out of range ${value}.`); - } - this.value = toBufferBE(value); - } else { - this.value = value; + // We convert buffer value to bigint to be able to check it fits within modulus + const valueBigInt = typeof value === 'bigint' ? value : toBigIntBE(value); + + if (valueBigInt > Fr.MAX_VALUE) { + throw new Error(`Fr out of range: ${valueBigInt}`); } + + this.value = typeof value === 'bigint' ? toBufferBE(value) : value; } static random() { From 7bd9fcd3abd0c12b2af705c148af662bb99ce728 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 12 Apr 2024 07:26:04 +0000 Subject: [PATCH 11/17] fix --- yarn-project/foundation/src/serialize/serialize.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn-project/foundation/src/serialize/serialize.ts b/yarn-project/foundation/src/serialize/serialize.ts index a6886716ecc1..286df5306018 100644 --- a/yarn-project/foundation/src/serialize/serialize.ts +++ b/yarn-project/foundation/src/serialize/serialize.ts @@ -126,6 +126,7 @@ export type Fieldable = | boolean | number | bigint + | Buffer | { /** * Serialize to a field. From 12587acecbbc225bd965a9d23f23716706a7f361 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 12 Apr 2024 07:30:00 +0000 Subject: [PATCH 12/17] reverting incorrect change --- barretenberg/sol/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/sol/README.md b/barretenberg/sol/README.md index 54506fd4fea3..30572db0b3c4 100644 --- a/barretenberg/sol/README.md +++ b/barretenberg/sol/README.md @@ -18,7 +18,7 @@ The verification key is currently generated via [Barretenberg](https://github.co ## Generating Verification Keys and Proofs -Run `bootstrap.sh` to clone git submodules, download SRS and generate verification keys, relies on barretenberg already being compiled (run `./bootstrap` in `cpp`). The bootstrap will also install foundry to `./.foundry` so you can use `$PROJECT_ROOT/foundry/bin/forge` if you don't already have foundry installed. +Run `bootstrap.sh` to clone git submodules, download SRS and generate verification keys, relies on barretenberg already being compiled (run `./bootstrap` in `cpp`). The bootstrap will also install foundry to `./.foundry` so you can use `./.foundry/bin/forge` if you don't already have foundry installed. # Tests From 20a0ede0a7f49a0a39b0b4b85fe93548f4340fec Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 12 Apr 2024 08:03:57 +0000 Subject: [PATCH 13/17] WIP --- barretenberg/ts/src/barretenberg/poseidon.test.ts | 4 ++-- barretenberg/ts/src/barretenberg_api/index.ts | 4 ++-- yarn-project/foundation/src/crypto/poseidon/index.ts | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/barretenberg/ts/src/barretenberg/poseidon.test.ts b/barretenberg/ts/src/barretenberg/poseidon.test.ts index 8086e16177c4..2647e4778ddc 100644 --- a/barretenberg/ts/src/barretenberg/poseidon.test.ts +++ b/barretenberg/ts/src/barretenberg/poseidon.test.ts @@ -10,7 +10,7 @@ describe('poseidon sync', () => { }); it('poseidonHash', () => { - const result = api.poseidonHash([new Fr(4n), new Fr(8n)], 7); + const result = api.poseidonHash([new Fr(4n), new Fr(8n)]); expect(result).toMatchSnapshot(); }); @@ -19,7 +19,7 @@ describe('poseidon sync', () => { const fields = Array.from({ length: loops * 2 }).map(() => Fr.random()); const t = new Timer(); for (let i = 0; i < loops; ++i) { - api.poseidonHash([fields[i * 2], fields[i * 2 + 1]], 0); + api.poseidonHash([fields[i * 2], fields[i * 2 + 1]]); } const us = t.us() / loops; console.log(`Executed ${loops} hashes at an average ${us}us / hash`); diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index 5cba649eaac8..05d6568cdb7d 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -607,8 +607,8 @@ export class BarretenbergApiSync { return out[0]; } - poseidonHash(inputsBuffer: Fr[], hashIndex: number): Fr { - const inArgs = [inputsBuffer, hashIndex].map(serializeBufferable); + poseidonHash(inputsBuffer: Fr[]): Fr { + const inArgs = [inputsBuffer].map(serializeBufferable); const outTypes: OutputType[] = [Fr]; const result = this.wasm.callWasmExport( 'poseidon_hash', diff --git a/yarn-project/foundation/src/crypto/poseidon/index.ts b/yarn-project/foundation/src/crypto/poseidon/index.ts index 1a4bd104e476..4ba4e05aa30a 100644 --- a/yarn-project/foundation/src/crypto/poseidon/index.ts +++ b/yarn-project/foundation/src/crypto/poseidon/index.ts @@ -8,15 +8,16 @@ import { type Fieldable, serializeToFields } from '../../serialize/serialize.js' * @param input - The input fields to hash. * @param index - The separator index to use for the hash. * @returns The poseidon hash. + * TODO: enable index once the barretenberg API supports it */ -export function poseidonHash(input: Fieldable[], index = 0): Fr { +export function poseidonHash(input: Fieldable[], _index = 0): Fr { const inputFields = serializeToFields(input); return Fr.fromBuffer( Buffer.from( BarretenbergSync.getSingleton() .poseidonHash( inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion - index, + // index, // TODO: enable once the barretenberg API supports it ) .toBuffer(), ), From 409143fa53a5a9413d8b6fea12fa2f776e76f065 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 12 Apr 2024 08:26:28 +0000 Subject: [PATCH 14/17] cleanup --- yarn-project/circuits.js/src/merkle/merkle_tree_calculator.ts | 3 +-- yarn-project/circuits.js/src/merkle/sibling_path.ts | 3 +-- yarn-project/foundation/src/crypto/pedersen/index.test.ts | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/yarn-project/circuits.js/src/merkle/merkle_tree_calculator.ts b/yarn-project/circuits.js/src/merkle/merkle_tree_calculator.ts index 471c0f776bd2..c8d4870039c0 100644 --- a/yarn-project/circuits.js/src/merkle/merkle_tree_calculator.ts +++ b/yarn-project/circuits.js/src/merkle/merkle_tree_calculator.ts @@ -1,5 +1,4 @@ import { pedersenHash } from '@aztec/foundation/crypto'; -import { Fr } from '@aztec/foundation/fields'; import { MerkleTree } from './merkle_tree.js'; @@ -13,7 +12,7 @@ export class MerkleTreeCalculator { constructor( private height: number, zeroLeaf = Buffer.alloc(32), - hasher = (left: Buffer, right: Buffer) => pedersenHash([Fr.fromBuffer(left), Fr.fromBuffer(right)]).toBuffer(), + hasher = (left: Buffer, right: Buffer) => pedersenHash([left, right]).toBuffer(), ) { this.hasher = hasher; this.zeroHashes = Array.from({ length: height }).reduce( diff --git a/yarn-project/circuits.js/src/merkle/sibling_path.ts b/yarn-project/circuits.js/src/merkle/sibling_path.ts index 4a31d3a7a233..52383dae87c7 100644 --- a/yarn-project/circuits.js/src/merkle/sibling_path.ts +++ b/yarn-project/circuits.js/src/merkle/sibling_path.ts @@ -1,12 +1,11 @@ import { pedersenHash } from '@aztec/foundation/crypto'; -import { Fr } from '@aztec/foundation/fields'; /** Computes the expected root of a merkle tree given a leaf and its sibling path. */ export function computeRootFromSiblingPath( leaf: Buffer, siblingPath: Buffer[], index: number, - hasher = (left: Buffer, right: Buffer) => pedersenHash([Fr.fromBuffer(left), Fr.fromBuffer(right)]).toBuffer(), + hasher = (left: Buffer, right: Buffer) => pedersenHash([left, right]).toBuffer(), ) { let result = leaf; for (const sibling of siblingPath) { diff --git a/yarn-project/foundation/src/crypto/pedersen/index.test.ts b/yarn-project/foundation/src/crypto/pedersen/index.test.ts index 5b2f1b435a2f..0e9e1c1c92a0 100644 --- a/yarn-project/foundation/src/crypto/pedersen/index.test.ts +++ b/yarn-project/foundation/src/crypto/pedersen/index.test.ts @@ -27,12 +27,12 @@ describe('pedersen', () => { }); it('pedersen hash', () => { - const r = pedersenHash([1n, 1n]); + const r = pedersenHash([toBufferBE(1n, 32), toBufferBE(1n, 32)]); expect(r.toString()).toEqual('0x07ebfbf4df29888c6cd6dca13d4bb9d1a923013ddbbcbdc3378ab8845463297b'); }); it('pedersen hash with index', () => { - const r = pedersenHash([1n, 1n], 5); + const r = pedersenHash([toBufferBE(1n, 32), toBufferBE(1n, 32)], 5); expect(r.toString()).toEqual('0x1c446df60816b897cda124524e6b03f36df0cec333fad87617aab70d7861daa6'); }); From fd561a5816fa57b98ddeaba5921e9242e9175436 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 12 Apr 2024 09:08:46 +0000 Subject: [PATCH 15/17] linking issue --- yarn-project/foundation/src/crypto/poseidon/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/foundation/src/crypto/poseidon/index.ts b/yarn-project/foundation/src/crypto/poseidon/index.ts index 4ba4e05aa30a..7ccfdad8aeac 100644 --- a/yarn-project/foundation/src/crypto/poseidon/index.ts +++ b/yarn-project/foundation/src/crypto/poseidon/index.ts @@ -8,7 +8,7 @@ import { type Fieldable, serializeToFields } from '../../serialize/serialize.js' * @param input - The input fields to hash. * @param index - The separator index to use for the hash. * @returns The poseidon hash. - * TODO: enable index once the barretenberg API supports it + * TODO(#5714): enable index once the barretenberg API supports it */ export function poseidonHash(input: Fieldable[], _index = 0): Fr { const inputFields = serializeToFields(input); From b302b4e2f52c43f8dd57691bf33d61a20ed13e5e Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 12 Apr 2024 09:09:44 +0000 Subject: [PATCH 16/17] WIP --- yarn-project/foundation/src/crypto/poseidon/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/foundation/src/crypto/poseidon/index.ts b/yarn-project/foundation/src/crypto/poseidon/index.ts index 7ccfdad8aeac..b02b09e16eda 100644 --- a/yarn-project/foundation/src/crypto/poseidon/index.ts +++ b/yarn-project/foundation/src/crypto/poseidon/index.ts @@ -8,7 +8,7 @@ import { type Fieldable, serializeToFields } from '../../serialize/serialize.js' * @param input - The input fields to hash. * @param index - The separator index to use for the hash. * @returns The poseidon hash. - * TODO(#5714): enable index once the barretenberg API supports it + * TODO(#5714): enable index once barretenberg API supports it */ export function poseidonHash(input: Fieldable[], _index = 0): Fr { const inputFields = serializeToFields(input); From 353ce82cf501c597270aff9cd362eca4858e82fe Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 12 Apr 2024 10:47:06 +0000 Subject: [PATCH 17/17] less ugly code --- yarn-project/foundation/src/serialize/serialize.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn-project/foundation/src/serialize/serialize.ts b/yarn-project/foundation/src/serialize/serialize.ts index 286df5306018..eaa81c27c7fc 100644 --- a/yarn-project/foundation/src/serialize/serialize.ts +++ b/yarn-project/foundation/src/serialize/serialize.ts @@ -150,10 +150,10 @@ export type Fieldable = * @returns A buffer list with the concatenation of all fields. */ export function serializeToBufferArray(...objs: Bufferable[]): Buffer[] { - let ret: Buffer[] = []; + const ret: Buffer[] = []; for (const obj of objs) { if (Array.isArray(obj)) { - ret = [...ret, ...serializeToBufferArray(...obj)]; + ret.push(...serializeToBufferArray(...obj)); } else if (Buffer.isBuffer(obj)) { ret.push(obj); } else if (typeof obj === 'boolean') { @@ -185,16 +185,16 @@ export function serializeToBufferArray(...objs: Bufferable[]): Buffer[] { * @returns An array of fields with the concatenation of all fields. */ export function serializeToFields(...objs: Fieldable[]): Fr[] { - let ret: Fr[] = []; + const ret: Fr[] = []; for (const obj of objs) { if (Array.isArray(obj)) { - ret = [...ret, ...serializeToFields(...obj)]; + ret.push(...serializeToFields(...obj)); } else if (obj instanceof Fr) { ret.push(obj); } else if (typeof obj === 'boolean' || typeof obj === 'number' || typeof obj === 'bigint') { ret.push(new Fr(obj)); } else if ('toFields' in obj) { - ret = [...ret, ...obj.toFields()]; + ret.push(...obj.toFields()); } else if ('toFr' in obj) { ret.push(obj.toFr()); } else if ('toField' in obj) {