diff --git a/Cargo.toml b/Cargo.toml index df6c725..236b44d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,8 @@ poseidon = { git = "https://github.com/scroll-tech/poseidon.git", branch = "halo halo2curves = { git = "https://github.com/scroll-tech/halo2curves.git", branch = "halo2-ecc-snark-verifier-0220" } [features] +# Use an implementation using fewer rows (8) per permutation. +short = [] # printout the layout of circuits for demo and some unittests # print_layout = ["halo2_proofs/dev-graph"] diff --git a/src/septidon/Septidon.png b/spec/Septidon.png similarity index 100% rename from src/septidon/Septidon.png rename to spec/Septidon.png diff --git a/src/septidon/README.md b/spec/septidon.md similarity index 100% rename from src/septidon/README.md rename to spec/septidon.md diff --git a/src/hash.rs b/src/hash.rs index d0c1c94..e6520fa 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -7,6 +7,33 @@ use halo2_proofs::circuit::AssignedCell; use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use halo2_proofs::halo2curves::bn256::Fr; +mod chip_long { + use super::{SpongeChip, SpongeConfig}; + use crate::poseidon::Pow5Chip; + /// The configuration of the Poseidon hash chip. + pub type PoseidonHashConfig = SpongeConfig>; + /// The Poseidon hash chip. + pub type PoseidonHashChip<'d, F, const STEP: usize> = + SpongeChip<'d, F, STEP, Pow5Chip>; +} + +mod chip_short { + use super::{SpongeChip, SpongeConfig}; + use crate::poseidon::SeptidonChip; + /// The configuration of the Poseidon hash chip. + pub type PoseidonHashConfig = SpongeConfig; + /// The Poseidon hash chip. + pub type PoseidonHashChip<'d, F, const STEP: usize> = SpongeChip<'d, F, STEP, SeptidonChip>; +} + +// By default, use a chip with double rounds over 38 rows. +#[cfg(not(feature = "short"))] +pub use chip_long::*; + +// If feature `short` is enabled, use the chip with septuple rounds on 8 rows. +#[cfg(feature = "short")] +pub use chip_short::*; + /// indicate an field can be hashed in merkle tree (2 Fields to 1 Field) pub trait Hashable: FromUniformBytes<64> + Ord { /// the spec type used in circuit for this hashable field @@ -60,25 +87,24 @@ impl MessageHashable for Fr { use crate::poseidon::{PermuteChip, PoseidonInstructions}; use halo2_proofs::{ circuit::{Chip, Layouter, Region, Value}, - plonk::{Advice, Column, ConstraintSystem, Error, Expression, Fixed, Selector, TableColumn}, + plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector, TableColumn}, poly::Rotation, }; /// The config for poseidon hash circuit #[derive(Clone, Debug)] -pub struct PoseidonHashConfig> { +pub struct SpongeConfig> { permute_config: PC::Config, hash_table: [Column; 5], hash_table_aux: [Column; 6], control_aux: Column, s_sponge_continue: Column, - constants: [Column; 1], control_step_range: TableColumn, s_table: Selector, s_custom: Selector, } -impl> PoseidonHashConfig { +impl> SpongeConfig { /// obtain the commitment index of hash table pub fn commitment_index(&self) -> [usize; 5] { self.hash_table.map(|col| col.index()) @@ -95,8 +121,6 @@ impl> PoseidonHashConfig { hash_table: [Column; 5], step: usize, ) -> Self { - // TODO: remove this "constants". - let constants = [0; 1].map(|_| meta.fixed_column()); let s_table = meta.selector(); let s_custom = meta.selector(); @@ -238,7 +262,6 @@ impl> PoseidonHashConfig { hash_table, hash_table_aux, control_aux, - constants, control_step_range, s_table, s_custom, @@ -324,12 +347,12 @@ impl PoseidonHashTable { /// Represent the chip for Poseidon hash table #[derive(Debug)] -pub struct PoseidonHashChip<'d, Fp: PrimeField, const STEP: usize, PC: PermuteChip> { +pub struct SpongeChip<'d, Fp: PrimeField, const STEP: usize, PC: PermuteChip> { calcs: usize, nil_msg_hash: Option, mpt_only: bool, data: &'d PoseidonHashTable, - config: PoseidonHashConfig, + config: SpongeConfig, } type PermutedState = Vec<[Word; 3]>; @@ -339,11 +362,11 @@ impl< Fp: Hashable, const STEP: usize, PC: PermuteChip + PoseidonInstructions, - > PoseidonHashChip<'d, Fp, STEP, PC> + > SpongeChip<'d, Fp, STEP, PC> { ///construct the chip pub fn construct( - config: PoseidonHashConfig, + config: SpongeConfig, data: &'d PoseidonHashTable, calcs: usize, mpt_only: bool, @@ -635,9 +658,9 @@ impl< } impl> Chip - for PoseidonHashChip<'_, Fp, STEP, PC> + for SpongeChip<'_, Fp, STEP, PC> { - type Config = PoseidonHashConfig; + type Config = SpongeConfig; type Loaded = PoseidonHashTable; fn config(&self) -> &Self::Config { @@ -652,8 +675,7 @@ impl> Chip mod tests { use std::marker::PhantomData; - use crate::poseidon::Pow5Chip; - use crate::septidon::SeptidonChip; + use crate::poseidon::{Pow5Chip, SeptidonChip}; use super::*; use halo2_proofs::ff::Field; @@ -726,7 +748,7 @@ mod tests { impl + PoseidonInstructions::SpecType, 3, 2>> Circuit for TestCircuit { - type Config = (PoseidonHashConfig, usize); + type Config = (SpongeConfig, usize); type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -735,10 +757,7 @@ mod tests { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let hash_tbl = [0; 5].map(|_| meta.advice_column()); - ( - PoseidonHashConfig::configure_sub(meta, hash_tbl, TEST_STEP), - 4, - ) + (SpongeConfig::configure_sub(meta, hash_tbl, TEST_STEP), 4) } fn synthesize( @@ -746,7 +765,7 @@ mod tests { (config, max_rows): Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - let chip = PoseidonHashChip::::construct( + let chip = SpongeChip::::construct( config, &self.table, max_rows, diff --git a/src/lib.rs b/src/lib.rs index dc69c08..dfe9686 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ pub mod hash; pub mod poseidon; -pub mod septidon; pub use halo2_proofs::halo2curves::bn256::Fr as Bn256Fr; pub use hash::Hashable; diff --git a/src/poseidon.rs b/src/poseidon.rs index b558aee..73b5c2b 100644 --- a/src/poseidon.rs +++ b/src/poseidon.rs @@ -13,6 +13,9 @@ use halo2_proofs::{ mod pow5; pub use pow5::{Pow5Chip, Pow5Config, StateWord, Var}; +mod septidon; +pub use septidon::SeptidonChip; + pub mod primitives; use primitives::{Absorbing, ConstantLength, Domain, Spec, SpongeMode, Squeezing, State}; use std::fmt::Debug as DebugT; diff --git a/src/poseidon/primitives.rs b/src/poseidon/primitives.rs index def7a1b..c87eb69 100644 --- a/src/poseidon/primitives.rs +++ b/src/poseidon/primitives.rs @@ -25,10 +25,10 @@ pub(crate) mod pasta; //pub(crate) mod test_vectors; mod p128pow5t3; -pub(crate) mod p128pow5t3_compact; +mod p128pow5t3_compact; pub use p128pow5t3::P128Pow5T3; -pub use p128pow5t3_compact::P128Pow5T3CompactSpec as P128Pow5T3Compact; +pub use p128pow5t3_compact::P128Pow5T3Compact; use grain::SboxType; diff --git a/src/poseidon/primitives/bn256/mod.rs b/src/poseidon/primitives/bn256/mod.rs index 20ee3e2..49e2c4e 100644 --- a/src/poseidon/primitives/bn256/mod.rs +++ b/src/poseidon/primitives/bn256/mod.rs @@ -27,9 +27,7 @@ mod tests { use halo2_proofs::ff::{Field, FromUniformBytes}; - use crate::poseidon::primitives::p128pow5t3::P128Pow5T3; - use crate::poseidon::primitives::p128pow5t3_compact::P128Pow5T3CompactSpec; - use crate::poseidon::primitives::{permute, Spec}; + use crate::poseidon::primitives::{permute, P128Pow5T3, P128Pow5T3Compact, Spec}; use super::*; @@ -154,8 +152,8 @@ mod tests { let output_compact = { let mut state = input.clone(); - let (rc, mds, _inv) = P128Pow5T3CompactSpec::::constants(); - permute::, 3, 2>(&mut state, &mds, &rc[..]); + let (rc, mds, _inv) = P128Pow5T3Compact::::constants(); + permute::, 3, 2>(&mut state, &mds, &rc[..]); // This is the compact form with 1 constant per partial round. for i in 4..4 + 57 { diff --git a/src/poseidon/primitives/p128pow5t3_compact.rs b/src/poseidon/primitives/p128pow5t3_compact.rs index d669525..0469149 100644 --- a/src/poseidon/primitives/p128pow5t3_compact.rs +++ b/src/poseidon/primitives/p128pow5t3_compact.rs @@ -1,19 +1,19 @@ use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use std::marker::PhantomData; -pub use super::p128pow5t3::P128Pow5T3Constants; +use super::p128pow5t3::P128Pow5T3Constants; use super::{Mds, Spec}; /// Poseidon-128 using the $x^5$ S-box, with a width of 3 field elements, and the /// standard number of rounds for 128-bit security "with margin". /// #[derive(Debug)] -pub struct P128Pow5T3CompactSpec { +pub struct P128Pow5T3Compact { _marker: PhantomData, } impl + Ord> Spec - for P128Pow5T3CompactSpec + for P128Pow5T3Compact { fn full_rounds() -> usize { 8 diff --git a/src/septidon.rs b/src/poseidon/septidon.rs similarity index 100% rename from src/septidon.rs rename to src/poseidon/septidon.rs diff --git a/src/septidon/control.rs b/src/poseidon/septidon/control.rs similarity index 98% rename from src/septidon/control.rs rename to src/poseidon/septidon/control.rs index 368afc0..d1b3178 100644 --- a/src/septidon/control.rs +++ b/src/poseidon/septidon/control.rs @@ -1,5 +1,5 @@ +use super::params::GATE_DEGREE_5; use super::util::query; -use crate::septidon::params::GATE_DEGREE_5; use halo2_proofs::circuit::{Region, Value}; use halo2_proofs::halo2curves::bn256::Fr as F; use halo2_proofs::plonk::{Column, ConstraintSystem, Error, Expression, Fixed, VirtualCells}; diff --git a/src/septidon/full_round.rs b/src/poseidon/septidon/full_round.rs similarity index 93% rename from src/septidon/full_round.rs rename to src/poseidon/septidon/full_round.rs index e26f755..ccc7d74 100644 --- a/src/septidon/full_round.rs +++ b/src/poseidon/septidon/full_round.rs @@ -1,9 +1,7 @@ use super::loop_chip::LoopBody; use super::params::mds; use super::state::{Cell, FullState, SBox}; -use super::util::matmul; -use super::util::query; -use crate::septidon::util::{join_values, split_values}; +use super::util::{join_values, matmul, query, split_values}; use halo2_proofs::circuit::{Region, Value}; use halo2_proofs::halo2curves::bn256::Fr as F; use halo2_proofs::plonk::{ConstraintSystem, Error, Expression, VirtualCells}; diff --git a/src/septidon/instruction.rs b/src/poseidon/septidon/instruction.rs similarity index 99% rename from src/septidon/instruction.rs rename to src/poseidon/septidon/instruction.rs index ca9e7bd..caa5c60 100644 --- a/src/septidon/instruction.rs +++ b/src/poseidon/septidon/instruction.rs @@ -1,8 +1,8 @@ -use super::{params::F, util::map_array, SeptidonChip}; -use crate::poseidon::{ +use super::super::{ primitives::{Spec, State}, PermuteChip, PoseidonInstructions, StateWord, Var, }; +use super::{params::F, util::map_array, SeptidonChip}; use halo2_proofs::{ circuit::{Chip, Layouter}, plonk::{ConstraintSystem, Error}, diff --git a/src/septidon/loop_chip.rs b/src/poseidon/septidon/loop_chip.rs similarity index 100% rename from src/septidon/loop_chip.rs rename to src/poseidon/septidon/loop_chip.rs diff --git a/src/septidon/params.rs b/src/poseidon/septidon/params.rs similarity index 71% rename from src/septidon/params.rs rename to src/poseidon/septidon/params.rs index 1293472..2bb4061 100644 --- a/src/septidon/params.rs +++ b/src/poseidon/septidon/params.rs @@ -1,6 +1,4 @@ -use crate::poseidon::primitives::p128pow5t3_compact::{P128Pow5T3CompactSpec, P128Pow5T3Constants}; -use crate::poseidon::primitives::Mds as MdsT; -use crate::poseidon::primitives::Spec; +use super::super::primitives::{Mds as MdsT, P128Pow5T3Compact, Spec}; use lazy_static::lazy_static; /// This implementation can be limited to gate degree 5. However, this mode will not work with @@ -30,20 +28,14 @@ pub mod sbox { pub type Mds = MdsT; lazy_static! { - static ref MDS: Mds = F::mds(); + // Cache the round constants and the MDS matrix (and unused inverse MDS matrix). + static ref CONSTANTS: (Vec<[F; 3]>, Mds, Mds) = P128Pow5T3Compact::::constants(); } -pub fn mds() -> &'static Mds { - &MDS -} - -lazy_static! { - static ref ROUND_CONSTANTS: Vec<[F; 3]> = { - let (rc, _, _) = P128Pow5T3CompactSpec::::constants(); - rc - }; +pub fn round_constant(index: usize) -> [F; 3] { + CONSTANTS.0[index] } -pub fn round_constant(index: usize) -> [F; 3] { - ROUND_CONSTANTS[index] +pub fn mds() -> &'static Mds { + &CONSTANTS.1 } diff --git a/src/septidon/septidon_chip.rs b/src/poseidon/septidon/septidon_chip.rs similarity index 98% rename from src/septidon/septidon_chip.rs rename to src/poseidon/septidon/septidon_chip.rs index 720b3bd..1b172d7 100644 --- a/src/septidon/septidon_chip.rs +++ b/src/poseidon/septidon/septidon_chip.rs @@ -5,18 +5,18 @@ use halo2_proofs::plonk::{ConstraintSystem, Error}; use super::control::ControlChip; use super::full_round::FullRoundChip; use super::loop_chip::LoopChip; +use super::params::round_constant; use super::septuple_round::SeptupleRoundChip; use super::state::Cell; use super::transition_round::TransitionRoundChip; use super::util::map_array; -use crate::septidon::params::round_constant; /// The configuration of the permutation chip. /// /// ``` /// use halo2_proofs::halo2curves::bn256::Fr as F; /// use halo2_proofs::plonk::ConstraintSystem; -/// use poseidon_circuit::septidon::SeptidonChip; +/// use poseidon_circuit::poseidon::SeptidonChip; /// /// let mut cs = ConstraintSystem::::default(); /// let config = SeptidonChip::configure(&mut cs); diff --git a/src/septidon/septuple_round.rs b/src/poseidon/septidon/septuple_round.rs similarity index 97% rename from src/septidon/septuple_round.rs rename to src/poseidon/septidon/septuple_round.rs index ab80498..85f8b9e 100644 --- a/src/septidon/septuple_round.rs +++ b/src/poseidon/septidon/septuple_round.rs @@ -1,8 +1,7 @@ use super::loop_chip::LoopBody; +use super::params::mds; use super::state::{Cell, SBox}; -use super::util::query; -use crate::septidon::params::mds; -use crate::septidon::util::{join_values, matmul, split_values}; +use super::util::{join_values, matmul, query, split_values}; use halo2_proofs::circuit::{Region, Value}; use halo2_proofs::halo2curves::bn256::Fr as F; use halo2_proofs::plonk::{ConstraintSystem, Constraints, Error, Expression, VirtualCells}; diff --git a/src/septidon/state.rs b/src/poseidon/septidon/state.rs similarity index 99% rename from src/septidon/state.rs rename to src/poseidon/septidon/state.rs index 72f11a4..a5f8bca 100644 --- a/src/septidon/state.rs +++ b/src/poseidon/septidon/state.rs @@ -1,4 +1,4 @@ -use crate::septidon::params; +use super::params; use halo2_proofs::circuit::{Region, Value}; use halo2_proofs::halo2curves::bn256::Fr as F; use halo2_proofs::plonk::{ diff --git a/src/septidon/tests.rs b/src/poseidon/septidon/tests.rs similarity index 96% rename from src/septidon/tests.rs rename to src/poseidon/septidon/tests.rs index e0af700..6d28d9e 100644 --- a/src/septidon/tests.rs +++ b/src/poseidon/septidon/tests.rs @@ -3,8 +3,7 @@ use halo2_proofs::dev::MockProver; use halo2_proofs::halo2curves::bn256::Fr as F; use halo2_proofs::plonk::{Circuit, ConstraintSystem, Error}; -use super::SeptidonChip; -use crate::septidon::util::join_values; +use super::{util::join_values, SeptidonChip}; #[test] fn septidon_permutation() { diff --git a/src/septidon/transition_round.rs b/src/poseidon/septidon/transition_round.rs similarity index 96% rename from src/septidon/transition_round.rs rename to src/poseidon/septidon/transition_round.rs index 7d6c1f5..d4b5843 100644 --- a/src/septidon/transition_round.rs +++ b/src/poseidon/septidon/transition_round.rs @@ -1,7 +1,7 @@ +use super::params; +use super::params::{mds, round_constant}; use super::state::Cell; -use crate::septidon::params; -use crate::septidon::params::{mds, round_constant}; -use crate::septidon::util::{join_values, matmul, split_values}; +use super::util::{join_values, matmul, split_values}; use halo2_proofs::circuit::{Region, Value}; use halo2_proofs::halo2curves::bn256::Fr as F; use halo2_proofs::plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression}; diff --git a/src/septidon/util.rs b/src/poseidon/septidon/util.rs similarity index 100% rename from src/septidon/util.rs rename to src/poseidon/septidon/util.rs diff --git a/tests/hash_proving.rs b/tests/hash_proving.rs index d513028..54c09ce 100644 --- a/tests/hash_proving.rs +++ b/tests/hash_proving.rs @@ -27,7 +27,7 @@ struct TestCircuit(PoseidonHashTable, usize); // test circuit derived from table data impl Circuit for TestCircuit { - type Config = PoseidonHashConfig>; + type Config = SpongeConfig>; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -36,7 +36,7 @@ impl Circuit for TestCircuit { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let hash_tbl = [0; 5].map(|_| meta.advice_column()); - PoseidonHashConfig::configure_sub(meta, hash_tbl, DEFAULT_STEP) + SpongeConfig::configure_sub(meta, hash_tbl, DEFAULT_STEP) } fn synthesize( @@ -44,7 +44,7 @@ impl Circuit for TestCircuit { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - let chip = PoseidonHashChip::>::construct( + let chip = SpongeChip::>::construct( config, &self.0, self.1,