Skip to content

Commit

Permalink
Add is_variable_length to the Rust poseidon_hash function
Browse files Browse the repository at this point in the history
  • Loading branch information
aakoshh committed Oct 10, 2024
1 parent 1ac5b3e commit 1cb7118
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 5 deletions.
14 changes: 12 additions & 2 deletions acvm-repo/bn254_blackbox_solver/src/poseidon2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,13 +544,23 @@ impl<'a> Poseidon2<'a> {
}

/// Performs a poseidon hash with a sponge construction equivalent to the one in poseidon2.nr
pub fn poseidon_hash(inputs: &[FieldElement]) -> Result<FieldElement, BlackBoxResolutionError> {
///
/// The `is_variable_length` parameter is there to so we can produce an equivalent hash with
/// the Barretenberg implementation which distinguishes between variable and fixed length inputs.
/// Set it to true if the input length matches the static size expected by the Noir function.
pub fn poseidon_hash(
inputs: &[FieldElement],
is_variable_length: bool,
) -> Result<FieldElement, BlackBoxResolutionError> {
let two_pow_64 = 18446744073709551616_u128.into();
let iv = FieldElement::from(inputs.len()) * two_pow_64;
let mut sponge = Poseidon2Sponge::new(iv, 3);
for input in inputs.iter() {
sponge.absorb(*input)?;
}
if is_variable_length {
sponge.absorb(FieldElement::from(1u32))?;
}
sponge.squeeze()
}

Expand Down Expand Up @@ -640,7 +650,7 @@ mod test {
FieldElement::from(3u128),
FieldElement::from(4u128),
];
let result = super::poseidon_hash(&fields).expect("should hash successfully");
let result = super::poseidon_hash(&fields, false).expect("should hash successfully");
assert_eq!(
result,
field_from_hex("130bf204a32cac1f0ace56c78b731aa3809f06df2731ebcf6b3464a15788b1b9"),
Expand Down
5 changes: 2 additions & 3 deletions tooling/nargo_cli/tests/stdlib-props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,13 @@ fn fuzz_sha512_equivalence() {
fn fuzz_poseidon2_equivalence() {
use bn254_blackbox_solver::poseidon_hash;

for max_len in [0, 1, 4, 511, 512] {
for max_len in [0, 1, 3, 4, 511, 512] {
let source = format!(
"fn main(input: [Field; {max_len}], message_size: u32) -> pub Field {{
std::hash::poseidon2::Poseidon2::hash(input, message_size)
}}"
);

// The actual input length can be up to the maximum.
let strategy = (0..=max_len)
.prop_flat_map(|len: usize| {
// Generate Field elements from random 32 byte vectors.
Expand All @@ -277,7 +276,7 @@ fn fuzz_poseidon2_equivalence() {
})
.prop_map(move |mut msg| {
// The output hash is a single field element.
let output = poseidon_hash(&msg).expect("failed to hash");
let output = poseidon_hash(&msg, msg.len() < max_len).expect("failed to hash");

// The input has to be padded to the maximum length.
let msg_size = msg.len();
Expand Down

0 comments on commit 1cb7118

Please sign in to comment.