@@ -12,16 +12,16 @@ pub(crate) mod fq;
1212pub ( crate ) mod grain;
1313pub ( crate ) mod mds;
1414
15- #[ cfg( test) ]
16- pub ( crate ) mod test_vectors;
15+ #[ cfg( any ( test, feature = "test-dependencies" ) ) ]
16+ pub mod test_vectors;
1717
1818mod p128pow5t3;
1919pub use p128pow5t3:: P128Pow5T3 ;
2020
2121use grain:: SboxType ;
2222
2323/// The type used to hold permutation state.
24- pub ( crate ) type State < F , const T : usize > = [ F ; T ] ;
24+ pub type State < F , const T : usize > = [ F ; T ] ;
2525
2626/// The type used to hold sponge rate.
2727pub ( crate ) type SpongeRate < F , const RATE : usize > = [ Option < F > ; RATE ] ;
@@ -83,6 +83,18 @@ pub fn generate_constants<
8383 ( round_constants, mds, mds_inv)
8484}
8585
86+ /// Runs the Poseidon permutation on the given state.
87+ ///
88+ /// Exposed for testing purposes only.
89+ #[ cfg( feature = "test-dependencies" ) ]
90+ pub fn test_only_permute < F : Field , S : Spec < F , T , RATE > , const T : usize , const RATE : usize > (
91+ state : & mut State < F , T > ,
92+ mds : & Mds < F , T > ,
93+ round_constants : & [ [ F ; T ] ] ,
94+ ) {
95+ permute :: < F , S , T , RATE > ( state, mds, round_constants) ;
96+ }
97+
8698/// Runs the Poseidon permutation on the given state.
8799pub ( crate ) fn permute < F : Field , S : Spec < F , T , RATE > , const T : usize , const RATE : usize > (
88100 state : & mut State < F , T > ,
@@ -176,16 +188,82 @@ impl<F, const RATE: usize> SpongeMode for Squeezing<F, RATE> {}
176188
177189impl < F : fmt:: Debug , const RATE : usize > Absorbing < F , RATE > {
178190 pub ( crate ) fn init_with ( val : F ) -> Self {
191+ let mut state = Self :: init_empty ( ) ;
192+ state. absorb ( val) . expect ( "state is not full" ) ;
193+ state
194+ }
195+
196+ /// Initializes an empty sponge in the absorbing state.
197+ pub fn init_empty ( ) -> Self {
179198 Self (
180- iter :: once ( Some ( val ) )
181- . chain ( ( 1 .. RATE ) . map ( |_| None ) )
199+ ( 0 .. RATE )
200+ . map ( |_| None )
182201 . collect :: < Vec < _ > > ( )
183202 . try_into ( )
184203 . unwrap ( ) ,
185204 )
186205 }
187206}
188207
208+ impl < F , const RATE : usize > Absorbing < F , RATE > {
209+ /// Attempts to absorb a value into the sponge state.
210+ ///
211+ /// Returns the value if it was not absorbed because the sponge is full.
212+ pub fn absorb ( & mut self , value : F ) -> Result < ( ) , F > {
213+ for entry in self . 0 . iter_mut ( ) {
214+ if entry. is_none ( ) {
215+ * entry = Some ( value) ;
216+ return Ok ( ( ) ) ;
217+ }
218+ }
219+ // Sponge is full.
220+ Err ( value)
221+ }
222+
223+ /// Exposes the inner state of the sponge.
224+ ///
225+ /// This is a low-level API, requiring a detailed understanding of this specific
226+ /// Poseidon implementation to use correctly and securely. It is exposed for use by
227+ /// the circuit implementation in `halo2_gadgets`, and may be removed from the public
228+ /// API if refactoring enables the circuit implementation to move into this crate.
229+ pub fn expose_inner ( & self ) -> & SpongeRate < F , RATE > {
230+ & self . 0
231+ }
232+ }
233+
234+ impl < F : fmt:: Debug , const RATE : usize > Squeezing < F , RATE > {
235+ /// Initializes a full sponge in the squeezing state.
236+ ///
237+ /// This is a low-level API, requiring a detailed understanding of this specific
238+ /// Poseidon implementation to use correctly and securely. It is exposed for use by
239+ /// the circuit implementation in `halo2_gadgets`, and may be removed from the public
240+ /// API if refactoring enables the circuit implementation to move into this crate.
241+ pub fn init_full ( vals : [ F ; RATE ] ) -> Self {
242+ Self (
243+ vals. into_iter ( )
244+ . map ( Some )
245+ . collect :: < Vec < _ > > ( )
246+ . try_into ( )
247+ . unwrap ( ) ,
248+ )
249+ }
250+ }
251+
252+ impl < F , const RATE : usize > Squeezing < F , RATE > {
253+ /// Attempts to squeeze a value from the sponge state.
254+ ///
255+ /// Returns `None` if the sponge is empty.
256+ pub fn squeeze ( & mut self ) -> Option < F > {
257+ for entry in self . 0 . iter_mut ( ) {
258+ if let Some ( inner) = entry. take ( ) {
259+ return Some ( inner) ;
260+ }
261+ }
262+ // Sponge is empty.
263+ None
264+ }
265+ }
266+
189267/// A Poseidon sponge.
190268pub ( crate ) struct Sponge <
191269 F : Field ,
0 commit comments