Skip to content

Commit

Permalink
Rework API based on split-sponge refactor in our fork.
Browse files Browse the repository at this point in the history
This uses the API changes from:
- https://github.com/arkworks-rs/sponge/issues/29
- arkworks-rs/sponge#30
to avoid working through the Arkworks sponge interface, and do hashing using
the permutation directly.
  • Loading branch information
hdevalence committed Oct 20, 2021
1 parent 481dcea commit 0609add
Show file tree
Hide file tree
Showing 6 changed files with 1,295 additions and 110 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license = "MIT OR Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
once_cell = "1.8"
ark-ff = "0.3"
ark-sponge = { git = "https://github.com/arkworks-rs/sponge", rev = "51d6fc9aac1fa69f44a04839202b5de828584ed8" }
ark-sponge = { git = "https://github.com/penumbra-zone/sponge", branch = "split-sponge" }
ark-ed-on-bls12-377 = "0.3"
57 changes: 57 additions & 0 deletions src/hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use crate::{Fq, State};

/// Hash a single [`Fq`] element with the provided `domain_separator`.
pub fn hash_1(domain_separator: &Fq, value: Fq) -> Fq {
let mut state = State::from(crate::RATE_1_PARAMS.clone());

// Use the domain separator as the sponge's capacity element
state[0] = domain_separator.clone();
state[1] = value;

state.permute();
state[1]
}

/// Hash two [`Fq`] elements with the provided `domain_separator`.
pub fn hash_2(domain_separator: &Fq, value: (Fq, Fq)) -> Fq {
let mut state = State::from(crate::RATE_2_PARAMS.clone());

// Use the domain separator as the sponge's capacity element
state[0] = domain_separator.clone();
state[1] = value.0;
state[2] = value.1;

state.permute();
state[1]
}

/// Hash four [`Fq`] elements with the provided `domain_separator`.
pub fn hash_4(domain_separator: &Fq, value: (Fq, Fq, Fq, Fq)) -> Fq {
let mut state = State::from(crate::RATE_4_PARAMS.clone());

// Use the domain separator as the sponge's capacity element
state[0] = domain_separator.clone();
state[1] = value.0;
state[2] = value.1;
state[3] = value.2;
state[4] = value.3;

state.permute();
state[1]
}

/// Hash five [`Fq`] elements with the provided `domain_separator`.
pub fn hash_5(domain_separator: &Fq, value: (Fq, Fq, Fq, Fq, Fq)) -> Fq {
let mut state = State::from(crate::RATE_5_PARAMS.clone());

// Use the domain separator as the sponge's capacity element
state[0] = domain_separator.clone();
state[1] = value.0;
state[2] = value.1;
state[3] = value.2;
state[4] = value.3;
state[5] = value.4;

state.permute();
state[1]
}
55 changes: 15 additions & 40 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,45 +1,20 @@
mod sponge;
//! An instantiation of Poseidon for the BLS12-377 scalar field.

pub mod params;
use once_cell::sync::Lazy;

// Since we depend on a git version of ark-sponge, re-exporting it here means
// our deps can access it without having to keep git revisions in sync.
//
// Going forward, this re-export should be removed and the functionality our
// deps need from direct use of ark-sponge should be folded into this crate.
// However, it's faster to iterate on required functionality without imposing
// hard compartmentalization boundaries from the start.
pub use ark_sponge;
mod hash;
mod params;

#[cfg(test)]
mod tests {
use super::*;
pub use hash::{hash_1, hash_2, hash_4, hash_5};

#[test]
fn it_works() {
use ark_ed_on_bls12_377::Fq; // lazy import, fix
use ark_ff::{One, Zero};
use ark_sponge::{
poseidon::PoseidonSponge, CryptographicSponge, DuplexSpongeMode,
FieldBasedCryptographicSponge,
};
/// Parameters for the rate-1 instance of Poseidon.
pub const RATE_1_PARAMS: Lazy<Parameters<Fq>> = Lazy::new(params::rate_1);
/// Parameters for the rate-2 instance of Poseidon.
pub const RATE_2_PARAMS: Lazy<Parameters<Fq>> = Lazy::new(params::rate_2);
/// Parameters for the rate-4 instance of Poseidon.
pub const RATE_4_PARAMS: Lazy<Parameters<Fq>> = Lazy::new(params::rate_4);
/// Parameters for the rate-5 instance of Poseidon.
pub const RATE_5_PARAMS: Lazy<Parameters<Fq>> = Lazy::new(params::rate_5);

// Current API has a `new()` method as part of the `CryptographicSponge`
// trait, but this method doesn't allow setting the initial state
// manually. Instead, the fields can be set manually.
// Slightly inconvenient that we have to initialize the mode.
let mut sponge = PoseidonSponge {
parameters: params::rate_2(),
state: vec![Fq::zero(); 3],
mode: DuplexSpongeMode::Absorbing {
next_absorb_index: 0,
},
};

sponge.absorb(&Fq::one());
sponge.absorb(&Fq::one());

let output = sponge.squeeze_native_field_elements(1);
dbg!(output);
}
}
pub use ark_ed_on_bls12_377::Fq;
pub use ark_sponge::poseidon::{Parameters, State};
Loading

0 comments on commit 0609add

Please sign in to comment.