From 00e3ebc550655e6d946d6efc848b11be5ca38e23 Mon Sep 17 00:00:00 2001 From: Xinding Wei Date: Fri, 18 Aug 2023 11:26:45 -0700 Subject: [PATCH] Rename PoseidonHasherChip to PoseidonHasher --- halo2-base/src/poseidon/{ => hasher}/mds.rs | 0 halo2-base/src/poseidon/hasher/mod.rs | 116 +++++++++++++++++ halo2-base/src/poseidon/{ => hasher}/spec.rs | 2 +- halo2-base/src/poseidon/{ => hasher}/state.rs | 2 +- .../{ => hasher}/tests/compatibility.rs | 4 +- .../src/poseidon/{ => hasher}/tests/mod.rs | 4 +- halo2-base/src/poseidon/mod.rs | 118 +----------------- 7 files changed, 124 insertions(+), 122 deletions(-) rename halo2-base/src/poseidon/{ => hasher}/mds.rs (100%) create mode 100644 halo2-base/src/poseidon/hasher/mod.rs rename halo2-base/src/poseidon/{ => hasher}/spec.rs (98%) rename halo2-base/src/poseidon/{ => hasher}/state.rs (99%) rename halo2-base/src/poseidon/{ => hasher}/tests/compatibility.rs (96%) rename halo2-base/src/poseidon/{ => hasher}/tests/mod.rs (95%) diff --git a/halo2-base/src/poseidon/mds.rs b/halo2-base/src/poseidon/hasher/mds.rs similarity index 100% rename from halo2-base/src/poseidon/mds.rs rename to halo2-base/src/poseidon/hasher/mds.rs diff --git a/halo2-base/src/poseidon/hasher/mod.rs b/halo2-base/src/poseidon/hasher/mod.rs new file mode 100644 index 00000000..d7843b1b --- /dev/null +++ b/halo2-base/src/poseidon/hasher/mod.rs @@ -0,0 +1,116 @@ +use std::mem; + +use crate::{ + gates::GateInstructions, + poseidon::hasher::{spec::OptimizedPoseidonSpec, state::PoseidonState}, + AssignedValue, Context, ScalarField, +}; + +#[cfg(test)] +mod tests; + +/// Module for maximum distance separable matrix operations. +pub mod mds; +/// Module for poseidon specification. +pub mod spec; +/// Module for poseidon states. +pub mod state; + +/// Poseidon hasher. This is stateful. +pub struct PoseidonHasher { + init_state: PoseidonState, + state: PoseidonState, + spec: OptimizedPoseidonSpec, + absorbing: Vec>, +} + +impl PoseidonHasher { + /// Create new Poseidon hasher. + pub fn new( + ctx: &mut Context, + ) -> Self { + let init_state = PoseidonState::default(ctx); + let state = init_state.clone(); + Self { + init_state, + state, + spec: OptimizedPoseidonSpec::new::(), + absorbing: Vec::new(), + } + } + + /// Initialize a poseidon hasher from an existing spec. + pub fn from_spec(ctx: &mut Context, spec: OptimizedPoseidonSpec) -> Self { + let init_state = PoseidonState::default(ctx); + Self { spec, state: init_state.clone(), init_state, absorbing: Vec::new() } + } + + /// Reset state to default and clear the buffer. + pub fn clear(&mut self) { + self.state = self.init_state.clone(); + self.absorbing.clear(); + } + + /// Store given `elements` into buffer. + pub fn update(&mut self, elements: &[AssignedValue]) { + self.absorbing.extend_from_slice(elements); + } + + /// Consume buffer and perform permutation, then output second element of + /// state. + pub fn squeeze( + &mut self, + ctx: &mut Context, + gate: &impl GateInstructions, + ) -> AssignedValue { + let input_elements = mem::take(&mut self.absorbing); + let exact = input_elements.len() % RATE == 0; + + for chunk in input_elements.chunks(RATE) { + self.permutation(ctx, gate, chunk.to_vec()); + } + if exact { + self.permutation(ctx, gate, vec![]); + } + + self.state.s[1] + } + + fn permutation( + &mut self, + ctx: &mut Context, + gate: &impl GateInstructions, + inputs: Vec>, + ) { + let r_f = self.spec.r_f / 2; + let mds = &self.spec.mds_matrices.mds.0; + let pre_sparse_mds = &self.spec.mds_matrices.pre_sparse_mds.0; + let sparse_matrices = &self.spec.mds_matrices.sparse_matrices; + + // First half of the full round + let constants = &self.spec.constants.start; + self.state.absorb_with_pre_constants(ctx, gate, inputs, &constants[0]); + for constants in constants.iter().skip(1).take(r_f - 1) { + self.state.sbox_full(ctx, gate, constants); + self.state.apply_mds(ctx, gate, mds); + } + self.state.sbox_full(ctx, gate, constants.last().unwrap()); + self.state.apply_mds(ctx, gate, pre_sparse_mds); + + // Partial rounds + let constants = &self.spec.constants.partial; + for (constant, sparse_mds) in constants.iter().zip(sparse_matrices.iter()) { + self.state.sbox_part(ctx, gate, constant); + self.state.apply_sparse_mds(ctx, gate, sparse_mds); + } + + // Second half of the full rounds + let constants = &self.spec.constants.end; + for constants in constants.iter() { + self.state.sbox_full(ctx, gate, constants); + self.state.apply_mds(ctx, gate, mds); + } + self.state.sbox_full(ctx, gate, &[F::ZERO; T]); + self.state.apply_mds(ctx, gate, mds); + } +} diff --git a/halo2-base/src/poseidon/spec.rs b/halo2-base/src/poseidon/hasher/spec.rs similarity index 98% rename from halo2-base/src/poseidon/spec.rs rename to halo2-base/src/poseidon/hasher/spec.rs index 24dcf7fc..c0e7142c 100644 --- a/halo2-base/src/poseidon/spec.rs +++ b/halo2-base/src/poseidon/hasher/spec.rs @@ -1,4 +1,4 @@ -use crate::{poseidon::mds::*, utils::ScalarField}; +use crate::{poseidon::hasher::mds::*, utils::ScalarField}; use poseidon_rs::poseidon::primitives::Spec as PoseidonSpec; // trait use std::marker::PhantomData; diff --git a/halo2-base/src/poseidon/state.rs b/halo2-base/src/poseidon/hasher/state.rs similarity index 99% rename from halo2-base/src/poseidon/state.rs rename to halo2-base/src/poseidon/hasher/state.rs index baceb023..97883cc8 100644 --- a/halo2-base/src/poseidon/state.rs +++ b/halo2-base/src/poseidon/hasher/state.rs @@ -2,7 +2,7 @@ use std::iter; use crate::{ gates::GateInstructions, - poseidon::mds::SparseMDSMatrix, + poseidon::hasher::mds::SparseMDSMatrix, utils::ScalarField, AssignedValue, Context, QuantumCell::{Constant, Existing}, diff --git a/halo2-base/src/poseidon/tests/compatibility.rs b/halo2-base/src/poseidon/hasher/tests/compatibility.rs similarity index 96% rename from halo2-base/src/poseidon/tests/compatibility.rs rename to halo2-base/src/poseidon/hasher/tests/compatibility.rs index 383a83a0..b8a48003 100644 --- a/halo2-base/src/poseidon/tests/compatibility.rs +++ b/halo2-base/src/poseidon/hasher/tests/compatibility.rs @@ -3,7 +3,7 @@ use std::{cmp::max, iter::zip}; use crate::{ gates::{builder::GateThreadBuilder, GateChip}, halo2_proofs::halo2curves::bn256::Fr, - poseidon::PoseidonHasherChip, + poseidon::hasher::PoseidonHasher, utils::ScalarField, }; use pse_poseidon::Poseidon; @@ -31,7 +31,7 @@ fn poseidon_compatiblity_verification< // constructing native and in-circuit Poseidon sponges let mut native_sponge = Poseidon::::new(R_F, R_P); // assuming SECURE_MDS = 0 - let mut circuit_sponge = PoseidonHasherChip::::new::(ctx); + let mut circuit_sponge = PoseidonHasher::::new::(ctx); // preparing to interleave absorptions and squeezings let n_iterations = max(absorptions.len(), squeezings.len()); diff --git a/halo2-base/src/poseidon/tests/mod.rs b/halo2-base/src/poseidon/hasher/tests/mod.rs similarity index 95% rename from halo2-base/src/poseidon/tests/mod.rs rename to halo2-base/src/poseidon/hasher/tests/mod.rs index f4289ac0..7deefefc 100644 --- a/halo2-base/src/poseidon/tests/mod.rs +++ b/halo2-base/src/poseidon/hasher/tests/mod.rs @@ -50,7 +50,7 @@ fn test_poseidon_against_test_vectors() { const T: usize = 3; const RATE: usize = 2; - let mut hasher = PoseidonHasherChip::::new::(ctx); + let mut hasher = PoseidonHasher::::new::(ctx); let state = [0u64, 1, 2]; hasher.state = @@ -76,7 +76,7 @@ fn test_poseidon_against_test_vectors() { const T: usize = 5; const RATE: usize = 4; - let mut hasher = PoseidonHasherChip::::new::(ctx); + let mut hasher = PoseidonHasher::::new::(ctx); let state = [0u64, 1, 2, 3, 4]; hasher.state = diff --git a/halo2-base/src/poseidon/mod.rs b/halo2-base/src/poseidon/mod.rs index dcb1549a..31628389 100644 --- a/halo2-base/src/poseidon/mod.rs +++ b/halo2-base/src/poseidon/mod.rs @@ -1,116 +1,2 @@ -use std::mem; - -use crate::{ - gates::GateInstructions, - poseidon::{spec::OptimizedPoseidonSpec, state::PoseidonState}, - AssignedValue, Context, ScalarField, -}; - -#[cfg(test)] -mod tests; - -/// Module for maximum distance separable matrix operations. -pub mod mds; -/// Module for poseidon specification. -pub mod spec; -/// Module for poseidon states. -pub mod state; - -/// Chip for Poseidon hasher. The chip is stateful. -pub struct PoseidonHasherChip { - init_state: PoseidonState, - state: PoseidonState, - spec: OptimizedPoseidonSpec, - absorbing: Vec>, -} - -impl PoseidonHasherChip { - /// Create new Poseidon hasher chip. - pub fn new( - ctx: &mut Context, - ) -> Self { - let init_state = PoseidonState::default(ctx); - let state = init_state.clone(); - Self { - init_state, - state, - spec: OptimizedPoseidonSpec::new::(), - absorbing: Vec::new(), - } - } - - /// Initialize a poseidon hasher from an existing spec. - pub fn from_spec(ctx: &mut Context, spec: OptimizedPoseidonSpec) -> Self { - let init_state = PoseidonState::default(ctx); - Self { spec, state: init_state.clone(), init_state, absorbing: Vec::new() } - } - - /// Reset state to default and clear the buffer. - pub fn clear(&mut self) { - self.state = self.init_state.clone(); - self.absorbing.clear(); - } - - /// Store given `elements` into buffer. - pub fn update(&mut self, elements: &[AssignedValue]) { - self.absorbing.extend_from_slice(elements); - } - - /// Consume buffer and perform permutation, then output second element of - /// state. - pub fn squeeze( - &mut self, - ctx: &mut Context, - gate: &impl GateInstructions, - ) -> AssignedValue { - let input_elements = mem::take(&mut self.absorbing); - let exact = input_elements.len() % RATE == 0; - - for chunk in input_elements.chunks(RATE) { - self.permutation(ctx, gate, chunk.to_vec()); - } - if exact { - self.permutation(ctx, gate, vec![]); - } - - self.state.s[1] - } - - fn permutation( - &mut self, - ctx: &mut Context, - gate: &impl GateInstructions, - inputs: Vec>, - ) { - let r_f = self.spec.r_f / 2; - let mds = &self.spec.mds_matrices.mds.0; - let pre_sparse_mds = &self.spec.mds_matrices.pre_sparse_mds.0; - let sparse_matrices = &self.spec.mds_matrices.sparse_matrices; - - // First half of the full round - let constants = &self.spec.constants.start; - self.state.absorb_with_pre_constants(ctx, gate, inputs, &constants[0]); - for constants in constants.iter().skip(1).take(r_f - 1) { - self.state.sbox_full(ctx, gate, constants); - self.state.apply_mds(ctx, gate, mds); - } - self.state.sbox_full(ctx, gate, constants.last().unwrap()); - self.state.apply_mds(ctx, gate, pre_sparse_mds); - - // Partial rounds - let constants = &self.spec.constants.partial; - for (constant, sparse_mds) in constants.iter().zip(sparse_matrices.iter()) { - self.state.sbox_part(ctx, gate, constant); - self.state.apply_sparse_mds(ctx, gate, sparse_mds); - } - - // Second half of the full rounds - let constants = &self.spec.constants.end; - for constants in constants.iter() { - self.state.sbox_full(ctx, gate, constants); - self.state.apply_mds(ctx, gate, mds); - } - self.state.sbox_full(ctx, gate, &[F::ZERO; T]); - self.state.apply_mds(ctx, gate, mds); - } -} +/// Module for Poseidon hasher +pub mod hasher;