Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update args hash to be a flat poseidon #8571

Merged
merged 2 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ library Constants {
uint256 internal constant BLOCK_MERGE_ROLLUP_INDEX = 23;
uint256 internal constant ROOT_ROLLUP_INDEX = 24;
uint256 internal constant FUNCTION_SELECTOR_NUM_BYTES = 4;
uint256 internal constant ARGS_HASH_CHUNK_LENGTH = 16;
uint256 internal constant ARGS_HASH_CHUNK_COUNT = 16;
uint256 internal constant MAX_ARGS_LENGTH = 256;
uint256 internal constant INITIALIZATION_SLOT_SEPARATOR = 1000000000;
uint256 internal constant INITIAL_L2_BLOCK_NUM = 1;
uint256 internal constant BLOB_SIZE_IN_BYTES = 126976;
Expand Down
40 changes: 12 additions & 28 deletions noir-projects/aztec-nr/aztec/src/hash.nr
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use dep::protocol_types::{
address::{AztecAddress, EthAddress},
constants::{
GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,
GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH, MAX_ARGS_LENGTH
},
point::Point, traits::Hash, hash::{sha256_to_field, poseidon2_hash_with_separator}
constants::{GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, GENERATOR_INDEX__FUNCTION_ARGS},
point::Point, traits::Hash,
hash::{sha256_to_field, poseidon2_hash_with_separator, poseidon2_hash_with_separator_slice}
};
use crate::oracle::logs_traits::ToBytesForUnencryptedLog;

Expand Down Expand Up @@ -106,44 +104,30 @@ impl ArgsHasher {
}

pub fn hash_args_array<let N: u32>(args: [Field; N]) -> Field {
hash_args(args.as_slice())
if args.len() == 0 {
0
} else {
poseidon2_hash_with_separator(args, GENERATOR_INDEX__FUNCTION_ARGS)
}
}

pub fn hash_args(args: [Field]) -> Field {
if args.len() == 0 {
0
} else {
assert(args.len() <= MAX_ARGS_LENGTH, "Args length exceeds maximum");
let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];
let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];

let mut current_chunk_index = 0;
let mut index_inside_current_chunk = 0;
for i in 0..args.len() {
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] = 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] = poseidon2_hash_with_separator(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);
}
poseidon2_hash_with_separator(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)
poseidon2_hash_with_separator_slice(args, GENERATOR_INDEX__FUNCTION_ARGS)
}
}

#[test]
fn compute_var_args_hash() {
let mut input = ArgsHasher::new();
for i in 0..MAX_ARGS_LENGTH {
for i in 0..100 {
input.add(i as Field);
}
let hash = input.hash();
assert(hash == 0x1cce4dbf69f14c44865919991ee1057922e34d7310ba237d71759aa422621ca9);
dep::std::println(hash);
assert(hash == 0x19b0d74feb06ebde19edd85a28986c97063e84b3b351a8b666c7cac963ce655f);
}

#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,6 @@ global ROOT_ROLLUP_INDEX: u32 = 24;

// MISC CONSTANTS
global FUNCTION_SELECTOR_NUM_BYTES: Field = 4;
global ARGS_HASH_CHUNK_LENGTH: u32 = 16;
global ARGS_HASH_CHUNK_COUNT: u32 = 16;
global MAX_ARGS_LENGTH: u32 = ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH;
// The following is used in immutable state variables to compute an initialization slot whose value is used to
// determine whether a given variable has been initialized (by asserting that the value in the slot is 0).
// The initialization slot is computed by adding the constant below to the variable's storage slot. This constant has
Expand Down
14 changes: 14 additions & 0 deletions noir-projects/noir-protocol-circuits/crates/types/src/hash.nr
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,20 @@ pub fn poseidon2_hash_with_separator<let N: u32, T>(
sponge.squeeze()
}

pub fn poseidon2_hash_with_separator_slice<T>(inputs: [Field], separator: T) -> Field where T: ToField {
let in_len = inputs.len() + 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()
}

#[no_predicates]
pub fn poseidon2_hash_bytes<let N: u32>(inputs: [u8; N]) -> Field {
// We manually hash the inputs here, since we cannot express with the type system a constant size inputs array of Math.ceil(N/31)
Expand Down
3 changes: 0 additions & 3 deletions yarn-project/circuits.js/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ export const BLOCK_ROOT_ROLLUP_INDEX = 22;
export const BLOCK_MERGE_ROLLUP_INDEX = 23;
export const ROOT_ROLLUP_INDEX = 24;
export const FUNCTION_SELECTOR_NUM_BYTES = 4;
export const ARGS_HASH_CHUNK_LENGTH = 16;
export const ARGS_HASH_CHUNK_COUNT = 16;
export const MAX_ARGS_LENGTH = 256;
export const INITIALIZATION_SLOT_SEPARATOR = 1000000000;
export const INITIAL_L2_BLOCK_NUM = 1;
export const BLOB_SIZE_IN_BYTES = 126976;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

exports[`ContractAddress computeInitializationHash 1`] = `Fr<0x0a79e35b159f2755e79e7ac21aed31964a6446d279670b499595da24c66144ff>`;
exports[`ContractAddress computeInitializationHash 1`] = `Fr<0x153329c6098512a53cb449057bb5adade93e360575b71192b7b304ace35b2b6b>`;

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

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<0x1cce4dbf69f14c44865919991ee1057922e34d7310ba237d71759aa422621ca9>`;
exports[`hash Var args hash matches noir 1`] = `Fr<0x19b0d74feb06ebde19edd85a28986c97063e84b3b351a8b666c7cac963ce655f>`;

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

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

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

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

exports[`hash hashes many function args 1`] = `Fr<0x0f987cfa046685fd829f2cab0cc5e078941719d229df8292924178c77a6f886e>`;
exports[`hash hashes many function args 1`] = `Fr<0x03933d5a59efde5af91c47a93e6c4965f0506d160f76c701b2de1503d74c7775>`;
4 changes: 2 additions & 2 deletions yarn-project/circuits.js/src/hash/hash.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { times } from '@aztec/foundation/collection';
import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing';

import { AztecAddress, EthAddress, Fr, L2ToL1Message, MAX_ARGS_LENGTH, ScopedL2ToL1Message } from '../index.js';
import { AztecAddress, EthAddress, Fr, L2ToL1Message, ScopedL2ToL1Message } from '../index.js';
import { makeAztecAddress } from '../tests/factories.js';
import {
computeNoteHashNonce,
Expand Down Expand Up @@ -83,7 +83,7 @@ describe('hash', () => {
});

it('Var args hash matches noir', () => {
const args = times(MAX_ARGS_LENGTH, i => new Fr(i));
const args = times(100, i => new Fr(i));
const res = computeVarArgsHash(args);
expect(res).toMatchSnapshot();

Expand Down
21 changes: 2 additions & 19 deletions yarn-project/circuits.js/src/hash/hash.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { type AztecAddress } from '@aztec/foundation/aztec-address';
import { padArrayEnd } from '@aztec/foundation/collection';
import { pedersenHashBuffer, poseidon2HashWithSeparator, sha256Trunc } from '@aztec/foundation/crypto';
import { Fr } from '@aztec/foundation/fields';
import { numToUInt8, numToUInt16BE, numToUInt32BE } from '@aztec/foundation/serialize';

import chunk from 'lodash.chunk';

import { ARGS_HASH_CHUNK_COUNT, ARGS_HASH_CHUNK_LENGTH, GeneratorIndex, MAX_ARGS_LENGTH } from '../constants.gen.js';
import { GeneratorIndex } from '../constants.gen.js';
import { type ScopedL2ToL1Message, VerificationKey } from '../structs/index.js';

/**
Expand Down Expand Up @@ -103,22 +100,8 @@ export function computeVarArgsHash(args: Fr[]) {
if (args.length === 0) {
return Fr.ZERO;
}
if (args.length > MAX_ARGS_LENGTH) {
throw new Error(`Hashing ${args.length} args exceeds max of ${MAX_ARGS_LENGTH}`);
}

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 poseidon2HashWithSeparator(c, GeneratorIndex.FUNCTION_ARGS);
});

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

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

/**
Expand Down
Loading