Skip to content

Commit

Permalink
feat: Use poseidon for var args hash (#7363)
Browse files Browse the repository at this point in the history
  • Loading branch information
sirasistant authored Aug 2, 2024
1 parent 6e8eecd commit 832b86e
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 18 deletions.
14 changes: 9 additions & 5 deletions noir-projects/aztec-nr/aztec/src/hash.nr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ use dep::protocol_types::{
GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,
GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH, MAX_ARGS_LENGTH
},
traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field, pedersen_commitment}
traits::Hash,
hash::{
pedersen_hash, compute_siloed_nullifier, sha256_to_field, pedersen_commitment,
poseidon2_hash_with_separator
}
};
// Note: pedersen_commitment is used only as a re-export here
use crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};
Expand Down Expand Up @@ -118,16 +122,16 @@ pub fn hash_args(args: [Field]) -> Field {
current_chunk_values[index_inside_current_chunk] = args[i];
index_inside_current_chunk+=1;
if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {
chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);
chunks_hashes[current_chunk_index] = poseidon2_hash_with_separator(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);
current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];
current_chunk_index+=1;
index_inside_current_chunk = 0;
}
}
if index_inside_current_chunk > 0 {
chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);
chunks_hashes[current_chunk_index] = poseidon2_hash_with_separator(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);
}
pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)
poseidon2_hash_with_separator(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)
}
}

Expand All @@ -138,7 +142,7 @@ fn compute_var_args_hash() {
input.add(i as Field);
}
let hash = input.hash();
assert(hash == 0x11e40f2a780822f7971803048c9a2100579de352e7dadd99981760964da65b57);
assert(hash == 0x1cce4dbf69f14c44865919991ee1057922e34d7310ba237d71759aa422621ca9);
}

#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ impl AztecAddress {

pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {
AztecAddress::from_field(
poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])
poseidon2_hash(
[
pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1 as Field
]
)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,13 @@ global GENERATOR_INDEX__FUNCTION_LEAF: u32 = 11;
global GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA: u32 = 12;
global GENERATOR_INDEX__CONSTRUCTOR: u32 = 13;
global GENERATOR_INDEX__CONSTRUCTOR_ARGS: u32 = 14;
global GENERATOR_INDEX__CONTRACT_ADDRESS_V1 = 15;
global GENERATOR_INDEX__CONTRACT_ADDRESS_V1: u32 = 15;
global GENERATOR_INDEX__CONTRACT_LEAF: u32 = 16;
global GENERATOR_INDEX__CALL_CONTEXT: u32 = 17;
global GENERATOR_INDEX__CALL_STACK_ITEM: u32 = 18;
global GENERATOR_INDEX__CALL_STACK_ITEM_2 = 19;
global GENERATOR_INDEX__CALL_STACK_ITEM_2: u32 = 19;
global GENERATOR_INDEX__SECRET_HASH: u32 = 20;
global GENERATOR_INDEX__L2_TO_L1_MSG = 21;
global GENERATOR_INDEX__L2_TO_L1_MSG: u32 = 21;
global GENERATOR_INDEX__TX_CONTEXT: u32 = 22;
global GENERATOR_INDEX__PUBLIC_LEAF_INDEX: u32 = 23;
global GENERATOR_INDEX__PUBLIC_DATA_LEAF: u32 = 24;
Expand Down
18 changes: 17 additions & 1 deletion noir-projects/noir-protocol-circuits/crates/types/src/hash.nr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX
},
merkle_tree::root::root_from_sibling_path, messaging::l2_to_l1_message::ScopedL2ToL1Message,
recursion::verification_key::VerificationKey, traits::is_empty,
recursion::verification_key::VerificationKey, traits::{is_empty, ToField},
utils::field::field_from_bytes_32_trunc, point::Point
};

Expand Down Expand Up @@ -255,6 +255,22 @@ pub fn poseidon2_hash<let N: u32>(inputs: [Field; N]) -> Field {
std::hash::poseidon2::Poseidon2::hash(inputs, N)
}

#[no_predicates]
pub fn poseidon2_hash_with_separator<N, T>(inputs: [Field; N], separator: T) -> Field where T: ToField {
// We manually hash the inputs here, since we cannot express with the type system a constant size inputs array of N + 1
let in_len = N + 1;
let two_pow_64 = 18446744073709551616;
let iv : Field = (in_len as Field) * two_pow_64;
let mut sponge = std::hash::poseidon2::Poseidon2::new(iv);
sponge.absorb(separator.to_field());

for i in 0..inputs.len() {
sponge.absorb(inputs[i]);
}

sponge.squeeze()
}

pub fn pedersen_commitment<let N: u32>(inputs: [Field; N], hash_index: u32) -> Point {
std::hash::pedersen_commitment_with_separator(inputs, hash_index)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x1e7ab8ea46fac7865205e7b5f13761e96a789fda67cdd17c46fb1d259c706902"`;

exports[`ContractAddress computeInitializationHash 1`] = `Fr<0x06fdfa55764301f37a1e8f2f7aef196245747858bf8cba8806c30f53ea6c07df>`;
exports[`ContractAddress computeInitializationHash 1`] = `Fr<0x2993633b581934f500950764c5be63dde8888791cdaf6b02dbc0f5c31460ca57>`;

exports[`ContractAddress computePartialAddress 1`] = `Fr<0x1923a6246e305720b6aaf751fde0342613e93c82e455c3831e28375c16dd40d8>`;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`hash Var args hash matches noir 1`] = `Fr<0x11e40f2a780822f7971803048c9a2100579de352e7dadd99981760964da65b57>`;
exports[`hash Var args hash matches noir 1`] = `Fr<0x1cce4dbf69f14c44865919991ee1057922e34d7310ba237d71759aa422621ca9>`;

exports[`hash compute secret message hash 1`] = `Fr<0x0dc06f2167e2cd19adf738d1f38469d7f8bff1e26b029816e8230bcd6ab6332e>`;

Expand All @@ -18,6 +18,6 @@ exports[`hash computes unique note hash 1`] = `Fr<0x1cbdcecec4fe92f6638eb6a8dade

exports[`hash hashes empty function args 1`] = `Fr<0x0000000000000000000000000000000000000000000000000000000000000000>`;

exports[`hash hashes function args 1`] = `Fr<0x0f4da5b77d47f61ea495c0ae504c300bfe608d1f233013c20f34ac7c030d8c14>`;
exports[`hash hashes function args 1`] = `Fr<0x2cb19d7f1c57660c695e279c0163042f20dc89e4ae7bed9ada08b74790df3204>`;

exports[`hash hashes many function args 1`] = `Fr<0x21fe126bab6cf132a34ef16f23bb6e6a97551d91a2408cd186443e465dc66606>`;
exports[`hash hashes many function args 1`] = `Fr<0x0f987cfa046685fd829f2cab0cc5e078941719d229df8292924178c77a6f886e>`;
8 changes: 4 additions & 4 deletions yarn-project/circuits.js/src/hash/hash.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type AztecAddress } from '@aztec/foundation/aztec-address';
import { padArrayEnd } from '@aztec/foundation/collection';
import { pedersenHash, pedersenHashBuffer } from '@aztec/foundation/crypto';
import { pedersenHash, pedersenHashBuffer, poseidon2HashWithSeparator } from '@aztec/foundation/crypto';
import { Fr } from '@aztec/foundation/fields';
import { numToUInt8, numToUInt16BE, numToUInt32BE } from '@aztec/foundation/serialize';

Expand Down Expand Up @@ -107,18 +107,18 @@ export function computeVarArgsHash(args: Fr[]) {
throw new Error(`Hashing ${args.length} args exceeds max of ${MAX_ARGS_LENGTH}`);
}

let chunksHashes = chunk(args, ARGS_HASH_CHUNK_LENGTH).map(c => {
let chunksHashes = chunk(args, ARGS_HASH_CHUNK_LENGTH).map((c: Fr[]) => {
if (c.length < ARGS_HASH_CHUNK_LENGTH) {
c = padArrayEnd(c, Fr.ZERO, ARGS_HASH_CHUNK_LENGTH);
}
return pedersenHash(c, GeneratorIndex.FUNCTION_ARGS);
return poseidon2HashWithSeparator(c, GeneratorIndex.FUNCTION_ARGS);
});

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

return pedersenHash(chunksHashes, GeneratorIndex.FUNCTION_ARGS);
return poseidon2HashWithSeparator(chunksHashes, GeneratorIndex.FUNCTION_ARGS);
}

/**
Expand Down
20 changes: 20 additions & 0 deletions yarn-project/foundation/src/crypto/poseidon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,26 @@ export function poseidon2Hash(input: Fieldable[]): Fr {
);
}

/**
* Create a poseidon hash (field) from an array of input fields and a domain separator.
* @param input - The input fields to hash.
* @param separator - The domain separator.
* @returns The poseidon hash.
*/
export function poseidon2HashWithSeparator(input: Fieldable[], separator: number): Fr {
const inputFields = serializeToFields(input);
inputFields.unshift(new Fr(separator));
return Fr.fromBuffer(
Buffer.from(
BarretenbergSync.getSingleton()
.poseidon2Hash(
inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
)
.toBuffer(),
),
);
}

/**
* Runs a Poseidon2 permutation.
* @param input the input state. Expected to be of size 4.
Expand Down

0 comments on commit 832b86e

Please sign in to comment.