From 9701a675fcbb84bb1d31ef3fb64b5b7c6ed86376 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 1 Feb 2024 15:18:14 +0000 Subject: [PATCH] feat: hashing output of serialize() in noir --- .../src/core/libraries/ConstantsGen.sol | 1 - .../src/abis/__snapshots__/abis.test.ts.snap | 64 +++++++++---------- .../circuits.js/src/abis/abis.test.ts | 11 +--- yarn-project/circuits.js/src/abis/abis.ts | 44 ++----------- yarn-project/circuits.js/src/constants.gen.ts | 1 - .../public_circuit_public_inputs.test.ts.snap | 44 +++++++++++++ .../public_circuit_public_inputs.test.ts | 6 ++ .../structs/public_circuit_public_inputs.ts | 11 ++++ .../end-to-end/src/e2e_token_contract.test.ts | 2 +- .../src/abis/public_circuit_public_inputs.nr | 37 ++--------- .../src/crates/types/src/constants.nr | 1 - 11 files changed, 103 insertions(+), 119 deletions(-) create mode 100644 yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index d367cd2206c4..4e9d03808528 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -79,7 +79,6 @@ library Constants { uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 201; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant CALL_PRIVATE_FUNCTION_RETURN_SIZE = 210; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 98; uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 188; uint256 internal constant COMMITMENTS_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap b/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap index a04642f359b3..1497235e4efc 100644 --- a/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap +++ b/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap @@ -1,13 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`abis Computes a callstack item hash 1`] = `"0x06dc9c35290e1868f41fc9f45bca49482bf5d5c000c789d6c74e53bce0f686f8"`; +exports[`abis Computes a callstack item hash 1`] = `"0x037cb5ba672a7c461e23cf22ae618757ab4f1a912f3fdc93b2b2800cfe57bb91"`; -exports[`abis Computes a callstack item request hash 1`] = `"0x05c5d32c38f3de19dbfa92e25746e1db1a887d5b02b79dd915c0f50e9fc51dcd"`; +exports[`abis Computes a callstack item request hash 1`] = `"0x2c36008a759d932a3a1986429aa295e2c2d4e62c33197a7d259750d29347bf30"`; exports[`abis Computes an empty nullifier hash 1`] = `"0x066e6cdc4a6ba5e4781deda650b0be6c12f975f064fc38df72c1060716759b17"`; -exports[`abis Computes an empty public inputs hash 1`] = `"0x2e2b79cee62cb99e9163a58daa37da8099a9eef49353d0cbbf85093dca66eca7"`; - exports[`abis Computes an empty sideeffect hash 1`] = `"0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed"`; exports[`abis compute private call stack item hash 1`] = ` @@ -55,41 +53,41 @@ Fr { exports[`abis compute public call stack item hash 1`] = ` Fr { - "asBigInt": 13521975876243055846900626787876592989336331137171592962170740576377717759471n, + "asBigInt": 4942803204430729321299247114280769628204291639882373728884145897482860239103n, "asBuffer": { "data": [ - 29, - 229, - 42, - 200, - 229, - 101, - 73, + 10, + 237, 135, + 8, + 121, + 161, 111, - 135, - 149, - 117, - 252, - 244, - 207, - 1, - 155, - 22, - 194, - 235, - 62, - 7, - 199, + 170, + 23, + 173, + 20, + 73, + 240, + 78, + 59, + 30, 113, - 209, - 176, - 171, + 136, + 151, + 117, + 250, + 42, 35, - 248, - 145, - 157, - 239, + 186, + 162, + 159, + 250, + 242, + 152, + 210, + 24, + 255, ], "type": "Buffer", }, diff --git a/yarn-project/circuits.js/src/abis/abis.test.ts b/yarn-project/circuits.js/src/abis/abis.test.ts index 99b718e52a93..614541216a85 100644 --- a/yarn-project/circuits.js/src/abis/abis.test.ts +++ b/yarn-project/circuits.js/src/abis/abis.test.ts @@ -8,9 +8,8 @@ import { FunctionSelector, NewContractData, PublicCallStackItem, - PublicCircuitPublicInputs, SideEffect, - SideEffectLinkedToNoteHash, + SideEffectLinkedToNoteHash } from '../index.js'; import { makeAztecAddress, @@ -32,7 +31,6 @@ import { computePublicCallStackItemHash, computePublicDataTreeLeafSlot, computePublicDataTreeValue, - computePublicInputsHash, computeSecretMessageHash, computeTxHash, computeUniqueCommitment, @@ -190,13 +188,6 @@ describe('abis', () => { expect(emptyHash).toMatchSnapshot(); }); - it('Computes an empty public inputs hash ', () => { - const publicInputs = PublicCircuitPublicInputs.empty(); - const emptyHash = computePublicInputsHash(publicInputs); - - expect(Fr.fromBuffer(emptyHash).toString()).toMatchSnapshot(); - }); - it('Computes a callstack item request hash', () => { const callStack = PublicCallStackItem.empty(); diff --git a/yarn-project/circuits.js/src/abis/abis.ts b/yarn-project/circuits.js/src/abis/abis.ts index 003829def1b9..ad99c3d03bd1 100644 --- a/yarn-project/circuits.js/src/abis/abis.ts +++ b/yarn-project/circuits.js/src/abis/abis.ts @@ -2,7 +2,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { padArrayEnd } from '@aztec/foundation/collection'; import { keccak, pedersenHash, pedersenHashBuffer } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; -import { boolToBuffer, numToUInt8, numToUInt16BE, numToUInt32BE } from '@aztec/foundation/serialize'; +import { boolToBuffer, numToUInt16BE, numToUInt32BE, numToUInt8 } from '@aztec/foundation/serialize'; import { Buffer } from 'buffer'; import chunk from 'lodash.chunk'; @@ -11,15 +11,12 @@ import { FUNCTION_SELECTOR_NUM_BYTES, FUNCTION_TREE_HEIGHT, GeneratorIndex, - PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH, - PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH, + PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH } from '../constants.gen.js'; import { MerkleTreeCalculator } from '../merkle/merkle_tree_calculator.js'; import { CallContext, ContractDeploymentData, - ContractStorageRead, - ContractStorageUpdateRequest, FunctionData, FunctionLeafPreimage, NewContractData, @@ -31,7 +28,7 @@ import { SideEffectLinkedToNoteHash, TxContext, TxRequest, - VerificationKey, + VerificationKey } from '../structs/index.js'; /** @@ -428,17 +425,6 @@ export function computePrivateCallStackItemHash(callStackItem: PrivateCallStackI ); } -function computeContractStorageUpdateRequestHash(input: ContractStorageUpdateRequest) { - return pedersenHash( - [input.storageSlot.toBuffer(), input.oldValue.toBuffer(), input.newValue.toBuffer()], - GeneratorIndex.PUBLIC_DATA_UPDATE_REQUEST, - ); -} - -function computeContractStorageReadsHash(input: ContractStorageRead) { - return pedersenHash([input.storageSlot.toBuffer(), input.currentValue.toBuffer()], GeneratorIndex.PUBLIC_DATA_READ); -} - export function computeCommitmentsHash(input: SideEffect) { return pedersenHash([input.value.toBuffer(), input.counter.toBuffer()], GeneratorIndex.SIDE_EFFECT); } @@ -450,28 +436,6 @@ export function computeNullifierHash(input: SideEffectLinkedToNoteHash) { ); } -export function computePublicInputsHash(input: PublicCircuitPublicInputs) { - const toHash = [ - computeCallContextHash(input.callContext), - input.argsHash.toBuffer(), - ...input.returnValues.map(fr => fr.toBuffer()), - ...input.contractStorageUpdateRequests.map(computeContractStorageUpdateRequestHash), - ...input.contractStorageReads.map(computeContractStorageReadsHash), - ...input.publicCallStackHashes.map(fr => fr.toBuffer()), - ...input.newCommitments.map(computeCommitmentsHash), - ...input.newNullifiers.map(computeNullifierHash), - ...input.newL2ToL1Msgs.map(fr => fr.toBuffer()), - ...input.unencryptedLogsHash.map(fr => fr.toBuffer()), - input.unencryptedLogPreimagesLength.toBuffer(), - ...input.historicalHeader.toFields().map(fr => fr.toBuffer()), - input.proverAddress.toBuffer(), - ]; - if (toHash.length != PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH) { - throw new Error('Incorrect number of input fields when hashing PublicCircuitPublicInputs'); - } - return pedersenHash(toHash, GeneratorIndex.PUBLIC_CIRCUIT_PUBLIC_INPUTS); -} - /** * Computes a call stack item hash. * @param callStackItem - The call stack item. @@ -495,7 +459,7 @@ export function computePublicCallStackItemHash({ [ contractAddress.toBuffer(), computeFunctionDataHash(functionData).toBuffer(), - computePublicInputsHash(publicInputs), + publicInputs.hash().toBuffer(), ], GeneratorIndex.CALL_STACK_ITEM, ), diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 6fcfc964d857..6d4e1f535902 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -65,7 +65,6 @@ export const CONTRACT_STORAGE_READ_LENGTH = 2; export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 201; export const GET_NOTES_ORACLE_RETURN_LENGTH = 674; export const CALL_PRIVATE_FUNCTION_RETURN_SIZE = 210; -export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 98; export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 188; export const COMMITMENTS_NUM_BYTES_PER_BASE_ROLLUP = 2048; export const NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap new file mode 100644 index 000000000000..574d36a80416 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = ` +Fr { + "asBigInt": 10987106036606499987406426170447920941391129891158672246363150499235953526428n, + "asBuffer": { + "data": [ + 24, + 74, + 123, + 76, + 228, + 113, + 134, + 151, + 63, + 27, + 17, + 70, + 189, + 227, + 135, + 146, + 250, + 51, + 192, + 79, + 251, + 233, + 86, + 238, + 0, + 176, + 100, + 200, + 210, + 134, + 70, + 156, + ], + "type": "Buffer", + }, +} +`; diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts index 29ff45138010..c72c462f8f0b 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts @@ -22,4 +22,10 @@ describe('PublicCircuitPublicInputs', () => { const fields = target.toFields(); expect(fields.length).toBe(PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH); }); + + it('hash matches snapshot', () => { + const target = makePublicCircuitPublicInputs(327); + const hash = target.hash(); + expect(hash).toMatchSnapshot(); + }); }); diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts index d0d7961f538a..bd854e3e56d8 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts @@ -1,11 +1,13 @@ import { makeTuple } from '@aztec/foundation/array'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { isArrayEmpty } from '@aztec/foundation/collection'; +import { pedersenHash } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { FieldReader, Tuple, serializeToBuffer, serializeToFieldArray } from '@aztec/foundation/serialize'; import { FieldsOf } from '@aztec/foundation/types'; import { + GeneratorIndex, MAX_NEW_COMMITMENTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, @@ -212,4 +214,13 @@ export class PublicCircuitPublicInputs { proverAddress, ); } + + hash(): Fr { + return Fr.fromBuffer( + pedersenHash( + this.toFields().map(field => field.toBuffer()), + GeneratorIndex.PUBLIC_CIRCUIT_PUBLIC_INPUTS, + ), + ); + } } diff --git a/yarn-project/end-to-end/src/e2e_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_token_contract.test.ts index bd40ce3faacb..0bb1b2da8ce6 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract.test.ts @@ -209,7 +209,7 @@ describe('e2e_token_contract', () => { describe('Minting', () => { describe('Public', () => { - it('as minter', async () => { + it.only('as minter', async () => { const amount = 10000n; const tx = asset.methods.mint_public(accounts[0].address, amount).send(); const receipt = await tx.wait(); diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr index 6c130e5e65db..17acd93180d0 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr @@ -8,7 +8,6 @@ use crate::constants::{ NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS, - PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH, PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, }; use crate::{ @@ -21,6 +20,7 @@ use crate::{ storage_read::StorageRead, storage_update_request::StorageUpdateRequest, }, + hash::pedersen_hash, header::Header, }; @@ -53,37 +53,6 @@ struct PublicCircuitPublicInputs{ } impl PublicCircuitPublicInputs{ - fn hash(self) -> Field { - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3595) have mercy por favor - let mut inputs: BoundedVec = BoundedVec::new(0); - inputs.push(self.call_context.hash()); - inputs.push(self.args_hash); - inputs.extend_from_array(self.return_values); - for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL { - inputs.push(self.contract_storage_update_requests[i].hash()); - } - for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { - inputs.push(self.contract_storage_reads[i].hash()); - } - inputs.extend_from_array(self.public_call_stack_hashes); - - for i in 0..MAX_NEW_COMMITMENTS_PER_CALL{ - inputs.push(self.new_commitments[i].hash()); - } - for i in 0..MAX_NEW_NULLIFIERS_PER_CALL{ - inputs.push(self.new_nullifiers[i].hash()); - } - inputs.extend_from_array(self.new_l2_to_l1_msgs); - inputs.extend_from_array(self.unencrypted_logs_hash); - inputs.push(self.unencrypted_log_preimages_length); - inputs.extend_from_array(self.historical_header.serialize()); - inputs.push(self.prover_address.to_field()); - - assert_eq(inputs.len(), PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH, "Incorrect number of input fields when hashing PublicCircuitPublicInputs"); - - dep::std::hash::pedersen_hash_with_separator(inputs.storage, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS) - } - pub fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(0); fields.extend_from_array(self.call_context.serialize()); @@ -110,4 +79,8 @@ impl PublicCircuitPublicInputs{ fields.push(self.prover_address.to_field()); fields.storage } + + fn hash(self) -> Field { + pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS) + } } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/constants.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/constants.nr index 40a15506cdf1..b2d842bb03ac 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/constants.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/constants.nr @@ -111,7 +111,6 @@ global CONTRACT_STORAGE_READ_LENGTH: Field = 2; global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: Field = 201; global GET_NOTES_ORACLE_RETURN_LENGTH: Field = 674; global CALL_PRIVATE_FUNCTION_RETURN_SIZE: Field = 210; -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH: Field = 98; global PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH: Field = 188; global COMMITMENTS_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048;