From 435665bab14356f96466eb72accc1308489f1170 Mon Sep 17 00:00:00 2001 From: Srinath Setty Date: Thu, 16 Jan 2025 18:06:17 -0800 Subject: [PATCH] Reorganize poseidon (#355) * migrate sponge code from provider to gadgets * fix hashchain example --- Cargo.toml | 6 +- examples/hashchain.rs | 9 +- src/frontend/gadgets/mod.rs | 7 +- .../gadgets}/poseidon/circuit2.rs | 0 .../gadgets}/poseidon/circuit2_witness.rs | 0 .../gadgets}/poseidon/hash_type.rs | 0 .../gadgets}/poseidon/matrix.rs | 0 .../gadgets}/poseidon/mds.rs | 0 src/frontend/gadgets/poseidon/mod.rs | 82 ++++++++++++++++ .../gadgets}/poseidon/poseidon_inner.rs | 0 .../gadgets}/poseidon/preprocessing.rs | 0 .../gadgets}/poseidon/round_constants.rs | 0 .../gadgets}/poseidon/round_numbers.rs | 0 .../gadgets}/poseidon/serde_impl.rs | 0 .../gadgets}/poseidon/sponge/api.rs | 2 +- .../gadgets}/poseidon/sponge/circuit.rs | 7 +- .../gadgets}/poseidon/sponge/mod.rs | 0 .../gadgets}/poseidon/sponge/vanilla.rs | 2 +- src/frontend/mod.rs | 4 +- src/provider/{poseidon/mod.rs => poseidon.rs} | 97 ++----------------- 20 files changed, 114 insertions(+), 102 deletions(-) rename src/{provider => frontend/gadgets}/poseidon/circuit2.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/circuit2_witness.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/hash_type.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/matrix.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/mds.rs (100%) create mode 100644 src/frontend/gadgets/poseidon/mod.rs rename src/{provider => frontend/gadgets}/poseidon/poseidon_inner.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/preprocessing.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/round_constants.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/round_numbers.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/serde_impl.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/sponge/api.rs (99%) rename src/{provider => frontend/gadgets}/poseidon/sponge/circuit.rs (97%) rename src/{provider => frontend/gadgets}/poseidon/sponge/mod.rs (100%) rename src/{provider => frontend/gadgets}/poseidon/sponge/vanilla.rs (99%) rename src/provider/{poseidon/mod.rs => poseidon.rs} (75%) diff --git a/Cargo.toml b/Cargo.toml index 0a1e576c..b227ff2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ 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" @@ -28,9 +28,9 @@ 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"] } diff --git a/examples/hashchain.rs b/examples/hashchain.rs index da5bee5f..f3e3ba9d 100644 --- a/examples/hashchain.rs +++ b/examples/hashchain.rs @@ -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, diff --git a/src/frontend/gadgets/mod.rs b/src/frontend/gadgets/mod.rs index bb751231..97b6e55f 100644 --- a/src/frontend/gadgets/mod.rs +++ b/src/frontend/gadgets/mod.rs @@ -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 { diff --git a/src/provider/poseidon/circuit2.rs b/src/frontend/gadgets/poseidon/circuit2.rs similarity index 100% rename from src/provider/poseidon/circuit2.rs rename to src/frontend/gadgets/poseidon/circuit2.rs diff --git a/src/provider/poseidon/circuit2_witness.rs b/src/frontend/gadgets/poseidon/circuit2_witness.rs similarity index 100% rename from src/provider/poseidon/circuit2_witness.rs rename to src/frontend/gadgets/poseidon/circuit2_witness.rs diff --git a/src/provider/poseidon/hash_type.rs b/src/frontend/gadgets/poseidon/hash_type.rs similarity index 100% rename from src/provider/poseidon/hash_type.rs rename to src/frontend/gadgets/poseidon/hash_type.rs diff --git a/src/provider/poseidon/matrix.rs b/src/frontend/gadgets/poseidon/matrix.rs similarity index 100% rename from src/provider/poseidon/matrix.rs rename to src/frontend/gadgets/poseidon/matrix.rs diff --git a/src/provider/poseidon/mds.rs b/src/frontend/gadgets/poseidon/mds.rs similarity index 100% rename from src/provider/poseidon/mds.rs rename to src/frontend/gadgets/poseidon/mds.rs diff --git a/src/frontend/gadgets/poseidon/mod.rs b/src/frontend/gadgets/poseidon/mod.rs new file mode 100644 index 00000000..b01d2deb --- /dev/null +++ b/src/frontend/gadgets/poseidon/mod.rs @@ -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(arity: usize, strength: &Strength) -> Vec { + 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::(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(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 {} diff --git a/src/provider/poseidon/poseidon_inner.rs b/src/frontend/gadgets/poseidon/poseidon_inner.rs similarity index 100% rename from src/provider/poseidon/poseidon_inner.rs rename to src/frontend/gadgets/poseidon/poseidon_inner.rs diff --git a/src/provider/poseidon/preprocessing.rs b/src/frontend/gadgets/poseidon/preprocessing.rs similarity index 100% rename from src/provider/poseidon/preprocessing.rs rename to src/frontend/gadgets/poseidon/preprocessing.rs diff --git a/src/provider/poseidon/round_constants.rs b/src/frontend/gadgets/poseidon/round_constants.rs similarity index 100% rename from src/provider/poseidon/round_constants.rs rename to src/frontend/gadgets/poseidon/round_constants.rs diff --git a/src/provider/poseidon/round_numbers.rs b/src/frontend/gadgets/poseidon/round_numbers.rs similarity index 100% rename from src/provider/poseidon/round_numbers.rs rename to src/frontend/gadgets/poseidon/round_numbers.rs diff --git a/src/provider/poseidon/serde_impl.rs b/src/frontend/gadgets/poseidon/serde_impl.rs similarity index 100% rename from src/provider/poseidon/serde_impl.rs rename to src/frontend/gadgets/poseidon/serde_impl.rs diff --git a/src/provider/poseidon/sponge/api.rs b/src/frontend/gadgets/poseidon/sponge/api.rs similarity index 99% rename from src/provider/poseidon/sponge/api.rs rename to src/frontend/gadgets/poseidon/sponge/api.rs index 86ce867d..3063689d 100644 --- a/src/provider/poseidon/sponge/api.rs +++ b/src/frontend/gadgets/poseidon/sponge/api.rs @@ -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)] diff --git a/src/provider/poseidon/sponge/circuit.rs b/src/frontend/gadgets/poseidon/sponge/circuit.rs similarity index 97% rename from src/provider/poseidon/sponge/circuit.rs rename to src/frontend/gadgets/poseidon/sponge/circuit.rs index d1b0ec0f..e98a66fd 100644 --- a/src/provider/poseidon/sponge/circuit.rs +++ b/src/frontend/gadgets/poseidon/sponge/circuit.rs @@ -1,6 +1,5 @@ -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::{ @@ -8,6 +7,8 @@ use crate::{ vanilla::{Direction, Mode, SpongeTrait}, }, }, + util_cs::witness_cs::SizedWitness, + ConstraintSystem, Namespace, SynthesisError, }; use ff::PrimeField; diff --git a/src/provider/poseidon/sponge/mod.rs b/src/frontend/gadgets/poseidon/sponge/mod.rs similarity index 100% rename from src/provider/poseidon/sponge/mod.rs rename to src/frontend/gadgets/poseidon/sponge/mod.rs diff --git a/src/provider/poseidon/sponge/vanilla.rs b/src/frontend/gadgets/poseidon/sponge/vanilla.rs similarity index 99% rename from src/provider/poseidon/sponge/vanilla.rs rename to src/frontend/gadgets/poseidon/sponge/vanilla.rs index e6bdaeef..c3cd31f9 100644 --- a/src/provider/poseidon/sponge/vanilla.rs +++ b/src/frontend/gadgets/poseidon/sponge/vanilla.rs @@ -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}, diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 0a5f6b83..47304da6 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -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, }; diff --git a/src/provider/poseidon/mod.rs b/src/provider/poseidon.rs similarity index 75% rename from src/provider/poseidon/mod.rs rename to src/provider/poseidon.rs index b2e51497..0ad56f36 100644 --- a/src/provider/poseidon/mod.rs +++ b/src/provider/poseidon.rs @@ -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(arity: usize, strength: &Strength) -> Vec { - 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::(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(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)]