-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Poseidon2-based CRHF and available as Merkle hash (#716)
* add Poseidon2Sponge impl * fix CI attempt * fix ci * rename Sponge->SpongeState, Sponge=DuplexSponge<SpongeState> * add Fixed/VariableLenCRHF from P2-sponge * make P2Hash available in MT hash
- Loading branch information
Showing
9 changed files
with
179 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ resolver = "2" | |
authors = ["Espresso Systems <[email protected]>"] | ||
edition = "2021" | ||
license = "MIT" | ||
rust-version = "1.64.0" | ||
rust-version = "1.73.0" | ||
homepage = "https://github.com/EspressoSystems/jellyfish" | ||
documentation = "https://jellyfish.docs.espressosys.com" | ||
repository = "https://github.com/EspressoSystems/jellyfish" | ||
|
@@ -31,6 +31,6 @@ rand_chacha = { version = "0.3.1", default-features = false } | |
serde = { version = "1.0", default-features = false, features = [ "derive", "rc" ] } | ||
sha2 = { version = "0.10", default-features = false } | ||
sha3 = { version = "0.10", default-features = false } | ||
itertools = { version = "0.12", default-features = false } | ||
itertools = { version = "0.12", default-features = false } | ||
tagged-base64 = "0.4" | ||
zeroize = { version = "^1.8" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
//! Collision-resistant Hash Function (CRHF) based on Poseidon2 permutation | ||
use core::marker::PhantomData; | ||
|
||
use ark_ff::{Field, PrimeField}; | ||
use ark_std::{borrow::Borrow, string::ToString, vec::Vec}; | ||
use jf_crhf::CRHF; | ||
use nimue::{ | ||
hash::sponge::{DuplexSponge, Sponge}, | ||
DuplexHash, Unit, | ||
}; | ||
|
||
use crate::Poseidon2Error; | ||
|
||
/// Sponge-based CRHF where the Sponge uses Poseidon2 permutation | ||
/// Input length is fixed: the actual input can be shorter, but will internally | ||
/// be zero-padded to `INPUT_SIZE` | ||
/// | ||
/// Example: | ||
/// `FixedLenPoseidon2Hash<ark_bn254::Fr, Poseidon2SpongeStateBnN3R1, 6, 2>` | ||
#[derive(Clone)] | ||
pub struct FixedLenPoseidon2Hash<F, S, const INPUT_SIZE: usize, const OUTPUT_SIZE: usize> | ||
where | ||
F: PrimeField + Unit, | ||
S: Sponge<U = F>, | ||
{ | ||
_field: PhantomData<F>, | ||
_sponge: PhantomData<S>, | ||
} | ||
|
||
impl<F, S, const IN: usize, const OUT: usize> CRHF for FixedLenPoseidon2Hash<F, S, IN, OUT> | ||
where | ||
F: PrimeField + Unit, | ||
S: Sponge<U = F>, | ||
{ | ||
type Input = [F]; // length should be <= IN | ||
type Output = [F; OUT]; | ||
type Error = Poseidon2Error; | ||
|
||
fn evaluate<T: Borrow<Self::Input>>(input: T) -> Result<Self::Output, Self::Error> { | ||
let input = input.borrow(); | ||
if input.len() > IN { | ||
return Err(Poseidon2Error::ParamErr("hash input too long".to_string())); | ||
} | ||
|
||
let mut padded = Vec::from(input); | ||
zero_padding(&mut padded, IN); | ||
|
||
let mut sponge = DuplexSponge::<S>::default(); | ||
sponge.absorb_unchecked(&padded); | ||
let mut output = [F::default(); OUT]; | ||
sponge.squeeze_unchecked(&mut output); | ||
Ok(output) | ||
} | ||
} | ||
|
||
/// Sponge-based CRHF where the Sponge uses Poseidon2 permutation, with | ||
/// variable-length input | ||
#[derive(Debug, Clone)] | ||
pub struct VariableLenPoseidon2Hash<F, S, const OUTPUT_SIZE: usize> | ||
where | ||
F: PrimeField + Unit, | ||
S: Sponge<U = F>, | ||
{ | ||
_field: PhantomData<F>, | ||
_sponge: PhantomData<S>, | ||
} | ||
|
||
impl<F, S, const OUT: usize> CRHF for VariableLenPoseidon2Hash<F, S, OUT> | ||
where | ||
F: PrimeField + Unit, | ||
S: Sponge<U = F>, | ||
{ | ||
type Input = [F]; | ||
type Output = [F; OUT]; | ||
type Error = Poseidon2Error; | ||
|
||
fn evaluate<T: Borrow<Self::Input>>(input: T) -> Result<Self::Output, Self::Error> { | ||
let mut padded = Vec::from(input.borrow()); | ||
bit_padding(&mut padded, S::R); | ||
|
||
let mut sponge = DuplexSponge::<S>::default(); | ||
sponge.absorb_unchecked(&padded); | ||
let mut output = [F::default(); OUT]; | ||
sponge.squeeze_unchecked(&mut output); | ||
Ok(output) | ||
} | ||
} | ||
|
||
// pad `data` with zeros until the length is the next multiple of `multiple` | ||
#[inline(always)] | ||
fn zero_padding<F: Field>(data: &mut Vec<F>, multiple: usize) { | ||
data.resize(data.len().next_multiple_of(multiple), F::zero()); | ||
} | ||
|
||
// pad `data` with "10..0" (always pad "1"), until the length is the next | ||
// multiple of `multiple` | ||
#[inline(always)] | ||
fn bit_padding<F: Field>(data: &mut Vec<F>, multiple: usize) { | ||
data.push(F::one()); | ||
zero_padding(data, multiple); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters