Skip to content

Commit

Permalink
Reorganize poseidon (#355)
Browse files Browse the repository at this point in the history
* migrate sponge code from provider to gadgets

* fix hashchain example
  • Loading branch information
srinathsetty authored Jan 17, 2025
1 parent ae6be2d commit 435665b
Show file tree
Hide file tree
Showing 20 changed files with 114 additions and 102 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ rand_core = { version = "0.6", default-features = false }
rand_chacha = "0.3"
subtle = "2.6.1"
halo2curves = { version = "0.8.0", features = ["bits", "derive_serde"] }
generic-array = "1.1"
generic-array = "1.2.0"
num-bigint = { version = "0.4.6", features = ["serde", "rand"] }
num-traits = "0.2.19"
num-integer = "0.1.46"
serde = { version = "1.0.217", features = ["derive"] }
bincode = "1.3"
bitvec = "1.0"
byteorder = "1.4.3"
thiserror = "2.0.9"
thiserror = "2.0.11"
once_cell = "1.18.0"
itertools = "0.13.0"
itertools = "0.14.0"

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2.15", default-features = false, features = ["js"] }
Expand Down
9 changes: 5 additions & 4 deletions examples/hashchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use ff::Field;
use flate2::{write::ZlibEncoder, Compression};
use generic_array::typenum::U24;
use nova_snark::{
frontend::{num::AllocatedNum, ConstraintSystem, SynthesisError},
provider::{
poseidon::{
frontend::{
gadgets::poseidon::{
Elt, IOPattern, Simplex, Sponge, SpongeAPI, SpongeCircuit, SpongeOp, SpongeTrait, Strength,
},
Bn256EngineKZG, GrumpkinEngine,
num::AllocatedNum,
ConstraintSystem, SynthesisError,
},
provider::{Bn256EngineKZG, GrumpkinEngine},
traits::{
circuit::{StepCircuit, TrivialCircuit},
snark::RelaxedR1CSSNARKTrait,
Expand Down
7 changes: 5 additions & 2 deletions src/frontend/gadgets/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//! Self-contained sub-circuit implementations for various primitives.
use super::SynthesisError;
pub mod boolean;

mod multieq;
mod uint32;

pub mod boolean;
pub mod num;
pub mod poseidon;
pub mod sha256;
mod uint32;

/// A trait for representing an assignment to a variable.
pub trait Assignment<T> {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
82 changes: 82 additions & 0 deletions src/frontend/gadgets/poseidon/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//! The underlying Poseidon sponge code is ported from https://github.com/argumentcomputer/neptune.
use ff::PrimeField;
use serde::{Deserialize, Serialize};

mod circuit2;
mod circuit2_witness;
mod hash_type;
mod matrix;
mod mds;
mod poseidon_inner;
mod preprocessing;
mod round_constants;
mod round_numbers;
mod serde_impl;
mod sponge;

pub use circuit2::Elt;
pub use poseidon_inner::PoseidonConstants;
use round_constants::generate_constants;
use round_numbers::{round_numbers_base, round_numbers_strengthened};
pub use sponge::{
api::{IOPattern, SpongeAPI, SpongeOp},
circuit::SpongeCircuit,
vanilla::{Mode::Simplex, Sponge, SpongeTrait},
};

/// The strength of the Poseidon hash function
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum Strength {
/// Standard strength
Standard,
/// Strengthened strength
Strengthened,
}

const DEFAULT_STRENGTH: Strength = Strength::Standard;

fn round_numbers(arity: usize, strength: &Strength) -> (usize, usize) {
match strength {
Strength::Standard => round_numbers_base(arity),
Strength::Strengthened => round_numbers_strengthened(arity),
}
}

const SBOX: u8 = 1; // x^5
const FIELD: u8 = 1; // Gf(p)

fn round_constants<F: PrimeField>(arity: usize, strength: &Strength) -> Vec<F> {
let t = arity + 1;

let (full_rounds, partial_rounds) = round_numbers(arity, strength);

let r_f = full_rounds as u16;
let r_p = partial_rounds as u16;

let fr_num_bits = F::NUM_BITS;
let field_size = {
assert!(fr_num_bits <= u32::from(u16::MAX));
// It's safe to convert to u16 for compatibility with other types.
fr_num_bits as u16
};

generate_constants::<F>(FIELD, SBOX, field_size, t as u16, r_f, r_p)
}

/// Apply the quintic S-Box (s^5) to a given item
pub(crate) fn quintic_s_box<F: PrimeField>(l: &mut F, pre_add: Option<&F>, post_add: Option<&F>) {
if let Some(x) = pre_add {
l.add_assign(x);
}
let mut tmp = *l;
tmp = tmp.square(); // l^2
tmp = tmp.square(); // l^4
l.mul_assign(&tmp); // l^5
if let Some(x) = post_add {
l.add_assign(x);
}
}

#[derive(Debug, Clone)]
/// Possible error states for the hashing.
pub enum PoseidonError {}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
///
/// The API is defined by the `SpongeAPI` trait, which is implemented in terms of the `InnerSpongeAPI` trait.
/// `Neptune` provides implementations of `InnerSpongeAPI` for both `sponge::Sponge` and `sponge_circuit::SpongeCircuit`.
use crate::provider::poseidon::poseidon_inner::Arity;
use crate::frontend::gadgets::poseidon::poseidon_inner::Arity;
use ff::PrimeField;

#[derive(Debug)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use crate::{
frontend::{util_cs::witness_cs::SizedWitness, ConstraintSystem, Namespace, SynthesisError},
provider::poseidon::{
use crate::frontend::{
gadgets::poseidon::{
circuit2::{Elt, PoseidonCircuit2},
poseidon_inner::{Arity, Poseidon, PoseidonConstants},
sponge::{
api::{IOPattern, InnerSpongeAPI},
vanilla::{Direction, Mode, SpongeTrait},
},
},
util_cs::witness_cs::SizedWitness,
ConstraintSystem, Namespace, SynthesisError,
};

use ff::PrimeField;
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::provider::poseidon::{
use crate::frontend::gadgets::poseidon::{
hash_type::HashType,
poseidon_inner::{Arity, Poseidon, PoseidonConstants},
sponge::api::{IOPattern, InnerSpongeAPI},
Expand Down
4 changes: 3 additions & 1 deletion src/frontend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
//!
//! Most of the code is ported from https://github.com/argumentcomputer/bellpepper.
pub mod gadgets;

mod constraint_system;
mod gadgets;
mod lc;

pub use constraint_system::{Circuit, ConstraintSystem, Namespace, SynthesisError};
pub use gadgets::{
boolean::{AllocatedBit, Boolean},
num,
poseidon::{Elt, PoseidonConstants, SpongeCircuit},
sha256::sha256,
Assignment,
};
Expand Down
97 changes: 10 additions & 87 deletions src/provider/poseidon/mod.rs → src/provider/poseidon.rs
Original file line number Diff line number Diff line change
@@ -1,96 +1,19 @@
//! Poseidon Constants and Poseidon-based RO used in Nova
//!
//! The underlying Poseidon sponge code is ported from https://github.com/argumentcomputer/neptune.
use ff::PrimeField;
use round_constants::generate_constants;
use round_numbers::{round_numbers_base, round_numbers_strengthened};
use serde::{Deserialize, Serialize};
mod circuit2;
mod circuit2_witness;
mod hash_type;
mod matrix;
mod mds;
mod poseidon_inner;
mod preprocessing;
mod round_constants;
mod round_numbers;
mod serde_impl;
mod sponge;

pub use circuit2::Elt;

pub use sponge::{
api::{IOPattern, SpongeAPI, SpongeOp},
circuit::SpongeCircuit,
vanilla::{Mode::Simplex, Sponge, SpongeTrait},
};

use crate::{
frontend::{num::AllocatedNum, AllocatedBit, Boolean, ConstraintSystem, SynthesisError},
provider::poseidon::poseidon_inner::PoseidonConstants,
frontend::{
gadgets::poseidon::{
Elt, IOPattern, PoseidonConstants, Simplex, Sponge, SpongeAPI, SpongeCircuit, SpongeOp,
SpongeTrait, Strength,
},
num::AllocatedNum,
AllocatedBit, Boolean, ConstraintSystem, SynthesisError,
},
traits::{ROCircuitTrait, ROTrait},
};
use core::marker::PhantomData;
use ff::PrimeFieldBits;
use ff::{PrimeField, PrimeFieldBits};
use generic_array::typenum::U24;

/// The strength of the Poseidon hash function
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum Strength {
/// Standard strength
Standard,
/// Strengthened strength
Strengthened,
}

const DEFAULT_STRENGTH: Strength = Strength::Standard;

fn round_numbers(arity: usize, strength: &Strength) -> (usize, usize) {
match strength {
Strength::Standard => round_numbers_base(arity),
Strength::Strengthened => round_numbers_strengthened(arity),
}
}

const SBOX: u8 = 1; // x^5
const FIELD: u8 = 1; // Gf(p)

fn round_constants<F: PrimeField>(arity: usize, strength: &Strength) -> Vec<F> {
let t = arity + 1;

let (full_rounds, partial_rounds) = round_numbers(arity, strength);

let r_f = full_rounds as u16;
let r_p = partial_rounds as u16;

let fr_num_bits = F::NUM_BITS;
let field_size = {
assert!(fr_num_bits <= u32::from(u16::MAX));
// It's safe to convert to u16 for compatibility with other types.
fr_num_bits as u16
};

generate_constants::<F>(FIELD, SBOX, field_size, t as u16, r_f, r_p)
}

/// Apply the quintic S-Box (s^5) to a given item
pub(crate) fn quintic_s_box<F: PrimeField>(l: &mut F, pre_add: Option<&F>, post_add: Option<&F>) {
if let Some(x) = pre_add {
l.add_assign(x);
}
let mut tmp = *l;
tmp = tmp.square(); // l^2
tmp = tmp.square(); // l^4
l.mul_assign(&tmp); // l^5
if let Some(x) = post_add {
l.add_assign(x);
}
}

#[derive(Debug, Clone)]
/// Possible error states for the hashing.
pub enum PoseidonError {}
use serde::{Deserialize, Serialize};

/// All Poseidon Constants that are used in Nova
#[derive(Clone, PartialEq, Serialize, Deserialize)]
Expand Down

0 comments on commit 435665b

Please sign in to comment.