Skip to content

Commit

Permalink
refactor: leveraging Bufferable in pedersenHash(...) and `sha256T…
Browse files Browse the repository at this point in the history
…oField(...)` (#5444)

We had a ton of manual conversions to buffer when computing hashes. A
few PRs ago I sneaked in a modification and pedersenHash(...) now
accepts `Bufferable[]` instead of `Buffer[]`. In this PR I leverage this
and remove the unnecessary conversions and do the same for
`sha256ToField(...)`.
  • Loading branch information
benesjan authored Mar 26, 2024
1 parent 16b0bdd commit 0e0748c
Show file tree
Hide file tree
Showing 42 changed files with 288 additions and 393 deletions.
10 changes: 2 additions & 8 deletions yarn-project/aztec.js/src/utils/authwit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ export const computeAuthWitMessageHash = (caller: AztecAddress, chainId: Fr, ver
* @returns The inner hash for the witness
*/
export const computeInnerAuthWitHash = (args: Fr[]) => {
return pedersenHash(
args.map(fr => fr.toBuffer()),
GeneratorIndex.AUTHWIT_INNER,
);
return pedersenHash(args, GeneratorIndex.AUTHWIT_INNER);
};

/**
Expand All @@ -61,8 +58,5 @@ export const computeInnerAuthWitHash = (args: Fr[]) => {
* @returns The outer hash for the witness
*/
export const computeOuterAuthWitHash = (consumer: AztecAddress, chainId: Fr, version: Fr, innerHash: Fr) => {
return pedersenHash(
[consumer.toField(), chainId, version, innerHash].map(fr => fr.toBuffer()),
GeneratorIndex.AUTHWIT_OUTER,
);
return pedersenHash([consumer.toField(), chainId, version, innerHash], GeneratorIndex.AUTHWIT_OUTER);
};
2 changes: 1 addition & 1 deletion yarn-project/aztec.js/src/utils/cheat_codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export class AztecCheatCodes {
public computeSlotInMap(baseSlot: Fr | bigint, key: Fr | bigint | AztecAddress): Fr {
// Based on `at` function in
// aztec3-packages/aztec-nr/aztec/src/state_vars/map.nr
return pedersenHash([new Fr(baseSlot), new Fr(key)].map(f => f.toBuffer()));
return pedersenHash([new Fr(baseSlot), new Fr(key)]);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions yarn-project/circuit-types/src/l2_block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export class L2Block {
*/
// TODO(#4844)
getPublicInputsHash(): Fr {
const buf = serializeToBuffer(
const preimage = [
this.header.globalVariables,
AppendOnlyTreeSnapshot.zero(), // this.startNoteHashTreeSnapshot / commitments,
AppendOnlyTreeSnapshot.zero(), // this.startNullifierTreeSnapshot,
Expand All @@ -158,9 +158,9 @@ export class L2Block {
this.header.state.l1ToL2MessageTree,
this.archive,
this.body.getTxsEffectsHash(),
);
];

return sha256ToField(buf);
return sha256ToField(preimage);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class L1ToL2Message {
}

hash(): Fr {
return sha256ToField(serializeToBuffer(...this.toFields()));
return sha256ToField(this.toFields());
}

static fromBuffer(buffer: Buffer | BufferReader): L1ToL2Message {
Expand Down
18 changes: 5 additions & 13 deletions yarn-project/circuits.js/src/contract/contract_address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ export function computePartialAddress(
? instance.saltedInitializationHash
: computeSaltedInitializationHash(instance);

return pedersenHash(
[instance.contractClassId, saltedInitializationHash].map(x => x.toBuffer()),
GeneratorIndex.PARTIAL_ADDRESS,
);
return pedersenHash([instance.contractClassId, saltedInitializationHash], GeneratorIndex.PARTIAL_ADDRESS);
}

/**
Expand All @@ -57,9 +54,7 @@ export function computeSaltedInitializationHash(
instance: Pick<ContractInstance, 'initializationHash' | 'salt' | 'portalContractAddress' | 'deployer'>,
): Fr {
return pedersenHash(
[instance.salt, instance.initializationHash, instance.deployer, instance.portalContractAddress].map(x =>
x.toBuffer(),
),
[instance.salt, instance.initializationHash, instance.deployer, instance.portalContractAddress],
GeneratorIndex.PARTIAL_ADDRESS,
);
}
Expand All @@ -73,10 +68,7 @@ export function computeContractAddressFromPartial(
args: ({ publicKeyHash: Fr } | { publicKey: PublicKey }) & { partialAddress: Fr },
): AztecAddress {
const publicKeyHash = 'publicKey' in args ? computePublicKeysHash(args.publicKey) : args.publicKeyHash;
const result = pedersenHash(
[publicKeyHash.toBuffer(), args.partialAddress.toBuffer()],
GeneratorIndex.CONTRACT_ADDRESS,
);
const result = pedersenHash([publicKeyHash, args.partialAddress], GeneratorIndex.CONTRACT_ADDRESS);
return AztecAddress.fromField(result);
}

Expand All @@ -89,7 +81,7 @@ export function computePublicKeysHash(publicKey: PublicKey | undefined): Fr {
if (!publicKey) {
return Fr.ZERO;
}
return pedersenHash([publicKey.x.toBuffer(), publicKey.y.toBuffer()], GeneratorIndex.PARTIAL_ADDRESS);
return pedersenHash([publicKey.x, publicKey.y], GeneratorIndex.PARTIAL_ADDRESS);
}

/**
Expand All @@ -115,5 +107,5 @@ export function computeInitializationHash(initFn: FunctionAbi | undefined, args:
*/
export function computeInitializationHashFromEncodedArgs(initFn: FunctionSelector, encodedArgs: Fr[]): Fr {
const argsHash = computeVarArgsHash(encodedArgs);
return pedersenHash([initFn.toBuffer(), argsHash.toBuffer()], GeneratorIndex.CONSTRUCTOR);
return pedersenHash([initFn, argsHash], GeneratorIndex.CONSTRUCTOR);
}
2 changes: 1 addition & 1 deletion yarn-project/circuits.js/src/contract/contract_class_id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function computeContractClassIdWithPreimage(
? contractClass.publicBytecodeCommitment
: computePublicBytecodeCommitment(contractClass.packedBytecode);
const id = pedersenHash(
[artifactHash.toBuffer(), privateFunctionsRoot.toBuffer(), publicBytecodeCommitment.toBuffer()],
[artifactHash, privateFunctionsRoot, publicBytecodeCommitment],
GeneratorIndex.CONTRACT_LEAF, // TODO(@spalladino): Review all generator indices in this file
);
return { id, artifactHash, privateFunctionsRoot, publicBytecodeCommitment };
Expand Down
5 changes: 1 addition & 4 deletions yarn-project/circuits.js/src/contract/private_function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ function computePrivateFunctionLeaves(fns: PrivateFunction[]): Buffer[] {

/** Returns the leaf for a given private function. */
export function computePrivateFunctionLeaf(fn: PrivateFunction): Buffer {
return pedersenHash(
[fn.selector, fn.vkHash].map(x => x.toBuffer()),
GeneratorIndex.FUNCTION_LEAF,
).toBuffer();
return pedersenHash([fn.selector, fn.vkHash], GeneratorIndex.FUNCTION_LEAF).toBuffer();
}

function getPrivateFunctionTreeCalculator(): MerkleTreeCalculator {
Expand Down
29 changes: 10 additions & 19 deletions yarn-project/circuits.js/src/hash/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function hashVK(vkBuf: Buffer) {
* @returns A commitment nonce.
*/
export function computeCommitmentNonce(nullifierZero: Fr, commitmentIndex: number): Fr {
return pedersenHash([nullifierZero.toBuffer(), numToUInt32BE(commitmentIndex, 32)], GeneratorIndex.NOTE_HASH_NONCE);
return pedersenHash([nullifierZero, numToUInt32BE(commitmentIndex, 32)], GeneratorIndex.NOTE_HASH_NONCE);
}

/**
Expand All @@ -72,7 +72,7 @@ export function computeCommitmentNonce(nullifierZero: Fr, commitmentIndex: numbe
* @returns A siloed commitment.
*/
export function siloNoteHash(contract: AztecAddress, innerNoteHash: Fr): Fr {
return pedersenHash([contract.toBuffer(), innerNoteHash.toBuffer()], GeneratorIndex.SILOED_NOTE_HASH);
return pedersenHash([contract, innerNoteHash], GeneratorIndex.SILOED_NOTE_HASH);
}

/**
Expand All @@ -82,7 +82,7 @@ export function siloNoteHash(contract: AztecAddress, innerNoteHash: Fr): Fr {
* @returns A unique commitment.
*/
export function computeUniqueCommitment(nonce: Fr, siloedCommitment: Fr): Fr {
return pedersenHash([nonce.toBuffer(), siloedCommitment.toBuffer()], GeneratorIndex.UNIQUE_NOTE_HASH);
return pedersenHash([nonce, siloedCommitment], GeneratorIndex.UNIQUE_NOTE_HASH);
}

/**
Expand All @@ -93,7 +93,7 @@ export function computeUniqueCommitment(nonce: Fr, siloedCommitment: Fr): Fr {
* @returns A siloed nullifier.
*/
export function siloNullifier(contract: AztecAddress, innerNullifier: Fr): Fr {
return pedersenHash([contract.toBuffer(), innerNullifier.toBuffer()], GeneratorIndex.OUTER_NULLIFIER);
return pedersenHash([contract, innerNullifier], GeneratorIndex.OUTER_NULLIFIER);
}

/**
Expand All @@ -114,7 +114,7 @@ export function computePublicDataTreeValue(value: Fr): Fr {
*/
export function computePublicDataTreeLeafSlot(contractAddress: AztecAddress, storageSlot: Fr): Fr {
return pedersenHash([contractAddress.toBuffer(), storageSlot.toBuffer()], GeneratorIndex.PUBLIC_LEAF_INDEX);
return pedersenHash([contractAddress, storageSlot], GeneratorIndex.PUBLIC_LEAF_INDEX);
}

/**
Expand All @@ -138,31 +138,22 @@ export function computeVarArgsHash(args: Fr[]) {
if (c.length < ARGS_HASH_CHUNK_LENGTH) {
c = padArrayEnd(c, Fr.ZERO, ARGS_HASH_CHUNK_LENGTH);
}
return pedersenHash(
c.map(a => a.toBuffer()),
GeneratorIndex.FUNCTION_ARGS,
);
return pedersenHash(c, GeneratorIndex.FUNCTION_ARGS);
});

if (chunksHashes.length < ARGS_HASH_CHUNK_COUNT) {
chunksHashes = padArrayEnd(chunksHashes, Fr.ZERO, ARGS_HASH_CHUNK_COUNT);
}

return pedersenHash(
chunksHashes.map(a => a.toBuffer()),
GeneratorIndex.FUNCTION_ARGS,
);
return pedersenHash(chunksHashes, GeneratorIndex.FUNCTION_ARGS);
}

export function computeCommitmentsHash(input: SideEffect) {
return pedersenHash([input.value.toBuffer(), input.counter.toBuffer()], GeneratorIndex.SIDE_EFFECT);
return pedersenHash([input.value, input.counter], GeneratorIndex.SIDE_EFFECT);
}

export function computeNullifierHash(input: SideEffectLinkedToNoteHash) {
return pedersenHash(
[input.value.toBuffer(), input.noteHash.toBuffer(), input.counter.toBuffer()],
GeneratorIndex.SIDE_EFFECT,
);
return pedersenHash([input.value, input.noteHash, input.counter], GeneratorIndex.SIDE_EFFECT);
}

/**
Expand All @@ -171,7 +162,7 @@ export function computeNullifierHash(input: SideEffectLinkedToNoteHash) {
* @returns the hash
*/
export function computeMessageSecretHash(secretMessage: Fr) {
return pedersenHash([secretMessage.toBuffer()], GeneratorIndex.L1_TO_L2_MESSAGE_SECRET);
return pedersenHash([secretMessage], GeneratorIndex.L1_TO_L2_MESSAGE_SECRET);
}

export function computeL1ToL2MessageNullifier(
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/circuits.js/src/keys/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function derivePublicKey(secretKey: GrumpkinPrivateKey) {
function deriveSecretKey(secretKey: GrumpkinPrivateKey, index: Fr): GrumpkinPrivateKey {
// TODO: Temporary hack. Should replace it with a secure way to derive the secret key.
// Match the way keys are derived in noir-protocol-circuits/crates/private_kernel_lib/src/common.nr
const hash = pedersenHash([secretKey.high, secretKey.low, index].map(v => v.toBuffer()));
const hash = pedersenHash([secretKey.high, secretKey.low, index]);
return new GrumpkinScalar(hash.toBuffer());
}

Expand Down
5 changes: 1 addition & 4 deletions yarn-project/circuits.js/src/structs/function_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,6 @@ export class FunctionData {
}

hash(): Fr {
return pedersenHash(
this.toFields().map(field => field.toBuffer()),
GeneratorIndex.FUNCTION_DATA,
);
return pedersenHash(this.toFields(), GeneratorIndex.FUNCTION_DATA);
}
}
5 changes: 1 addition & 4 deletions yarn-project/circuits.js/src/structs/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,6 @@ export class Header {
}

hash(): Fr {
return pedersenHash(
this.toFields().map(f => f.toBuffer()),
GeneratorIndex.BLOCK_HASH,
);
return pedersenHash(this.toFields(), GeneratorIndex.BLOCK_HASH);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,7 @@ export class PrivateCallStackItem {
* @returns Hash.
*/
public hash(): Fr {
return pedersenHash(
this.toFields().map(field => field.toBuffer()),
GeneratorIndex.CALL_STACK_ITEM,
);
return pedersenHash(this.toFields(), GeneratorIndex.CALL_STACK_ITEM);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,6 @@ export class PrivateCircuitPublicInputs {
}

hash(): Fr {
return pedersenHash(
this.toFields().map(field => field.toBuffer()),
GeneratorIndex.PRIVATE_CIRCUIT_PUBLIC_INPUTS,
);
return pedersenHash(this.toFields(), GeneratorIndex.PRIVATE_CIRCUIT_PUBLIC_INPUTS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class PublicCallStackItem {
}

return pedersenHash(
[this.contractAddress, this.functionData.hash(), this.publicInputs.hash()].map(f => f.toBuffer()),
[this.contractAddress, this.functionData.hash(), this.publicInputs.hash()],
GeneratorIndex.CALL_STACK_ITEM,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,6 @@ export class PublicCircuitPublicInputs {
}

hash(): Fr {
return pedersenHash(
this.toFields().map(field => field.toBuffer()),
GeneratorIndex.PUBLIC_CIRCUIT_PUBLIC_INPUTS,
);
return pedersenHash(this.toFields(), GeneratorIndex.PUBLIC_CIRCUIT_PUBLIC_INPUTS);
}
}
5 changes: 1 addition & 4 deletions yarn-project/circuits.js/src/structs/tx_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,6 @@ export class TxContext {
}

hash(): Fr {
return pedersenHash(
this.toFields().map(f => f.toBuffer()),
GeneratorIndex.TX_CONTEXT,
);
return pedersenHash(this.toFields(), GeneratorIndex.TX_CONTEXT);
}
}
5 changes: 1 addition & 4 deletions yarn-project/circuits.js/src/structs/tx_request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,7 @@ export class TxRequest {
}

hash() {
return pedersenHash(
this.toFields().map(field => field.toBuffer()),
GeneratorIndex.TX_REQUEST,
);
return pedersenHash(this.toFields(), GeneratorIndex.TX_REQUEST);
}

static empty() {
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/end-to-end/src/e2e_block_building.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ describe('e2e_block_building', () => {
it('drops tx with private nullifier already emitted from public on the same block', async () => {
const secret = Fr.random();
// See yarn-project/simulator/src/public/index.test.ts 'Should be able to create a nullifier from the public context'
const emittedPublicNullifier = pedersenHash([new Fr(140), secret].map(a => a.toBuffer()));
const emittedPublicNullifier = pedersenHash([new Fr(140), secret]);

const calls = [
contract.methods.create_nullifier_public(140n, secret),
Expand All @@ -172,7 +172,7 @@ describe('e2e_block_building', () => {
describe('across blocks', () => {
it('drops a tx that tries to spend a nullifier already emitted on a previous block', async () => {
const secret = Fr.random();
const emittedPublicNullifier = pedersenHash([new Fr(140), secret].map(a => a.toBuffer()));
const emittedPublicNullifier = pedersenHash([new Fr(140), secret]);

await expect(contract.methods.create_nullifier_public(140n, secret).send().wait()).resolves.toEqual(
expect.objectContaining({
Expand Down
23 changes: 10 additions & 13 deletions yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
computeAuthWitMessageHash,
} from '@aztec/aztec.js';
import { sha256ToField } from '@aztec/foundation/crypto';
import { serializeToBuffer } from '@aztec/foundation/serialize';
import { TokenBridgeContract, TokenContract } from '@aztec/noir-contracts.js';

import { toFunctionSelector } from 'viem/utils';
Expand Down Expand Up @@ -157,12 +156,11 @@ describe('e2e_cross_chain_messaging', () => {
await crossChainTestHarness.makeMessageConsumable(msgHash);

// 3. Consume L1 -> L2 message and mint private tokens on L2
const content = sha256ToField(
Buffer.concat([
Buffer.from(toFunctionSelector('mint_private(bytes32,uint256)').substring(2), 'hex'),
serializeToBuffer(...[secretHashForL2MessageConsumption, new Fr(bridgeAmount)]),
]),
);
const content = sha256ToField([
Buffer.from(toFunctionSelector('mint_private(bytes32,uint256)').substring(2), 'hex'),
secretHashForL2MessageConsumption,
new Fr(bridgeAmount),
]);
const wrongMessage = new L1ToL2Message(
new L1Actor(crossChainTestHarness.tokenPortalAddress, crossChainTestHarness.publicClient.chain.id),
new L2Actor(l2Bridge.address, 1),
Expand Down Expand Up @@ -235,12 +233,11 @@ describe('e2e_cross_chain_messaging', () => {
// Wait for the message to be available for consumption
await crossChainTestHarness.makeMessageConsumable(msgHash);

const content = sha256ToField(
Buffer.concat([
Buffer.from(toFunctionSelector('mint_public(bytes32,uint256)').substring(2), 'hex'),
serializeToBuffer(...[ownerAddress, new Fr(bridgeAmount)]),
]),
);
const content = sha256ToField([
Buffer.from(toFunctionSelector('mint_public(bytes32,uint256)').substring(2), 'hex'),
ownerAddress,
new Fr(bridgeAmount),
]);
const wrongMessage = new L1ToL2Message(
new L1Actor(crossChainTestHarness.tokenPortalAddress, crossChainTestHarness.publicClient.chain.id),
new L2Actor(l2Bridge.address, 1),
Expand Down
Loading

0 comments on commit 0e0748c

Please sign in to comment.