Skip to content

Commit c91cc5c

Browse files
authored
Merge pull request #831 from zcash/poseidon-primitive
Move Poseidon primitive into `halo2_poseidon`
2 parents 0d1851b + 5893850 commit c91cc5c

File tree

13 files changed

+541
-459
lines changed

13 files changed

+541
-459
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

halo2_gadgets/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ arrayvec = "0.7.0"
2626
bitvec = "1"
2727
ff = "0.13"
2828
group = "0.13"
29+
halo2_poseidon = { version = "0.0", path = "../halo2_poseidon", default-features = false }
2930
halo2_proofs = { version = "0.3", path = "../halo2_proofs", default-features = false }
3031
lazy_static = "1"
3132
pasta_curves = "0.5"
@@ -40,6 +41,7 @@ plotters = { version = "0.3.0", default-features = false, optional = true }
4041

4142
[dev-dependencies]
4243
criterion = "0.3"
44+
halo2_poseidon = { version = "0.0", path = "../halo2_poseidon", default-features = false, features = ["test-dependencies"] }
4345
proptest = "1.0.0"
4446
sinsemilla = { version = "0.1", features = ["test-dependencies"] }
4547

halo2_gadgets/src/poseidon.rs

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! The Poseidon algebraic hash function.
22
3-
use std::convert::TryInto;
43
use std::fmt;
54
use std::marker::PhantomData;
65

@@ -13,7 +12,7 @@ use halo2_proofs::{
1312
mod pow5;
1413
pub use pow5::{Pow5Chip, Pow5Config, StateWord};
1514

16-
pub mod primitives;
15+
pub use ::halo2_poseidon as primitives;
1716
use primitives::{Absorbing, ConstantLength, Domain, Spec, SpongeMode, Squeezing, State};
1817

1918
/// A word from the padded input to a Poseidon sponge.
@@ -148,13 +147,7 @@ impl<
148147
pub fn new(chip: PoseidonChip, mut layouter: impl Layouter<F>) -> Result<Self, Error> {
149148
chip.initial_state(&mut layouter).map(|state| Sponge {
150149
chip,
151-
mode: Absorbing(
152-
(0..RATE)
153-
.map(|_| None)
154-
.collect::<Vec<_>>()
155-
.try_into()
156-
.unwrap(),
157-
),
150+
mode: Absorbing::init_empty(),
158151
state,
159152
_marker: PhantomData::default(),
160153
})
@@ -166,12 +159,10 @@ impl<
166159
mut layouter: impl Layouter<F>,
167160
value: PaddedWord<F>,
168161
) -> Result<(), Error> {
169-
for entry in self.mode.0.iter_mut() {
170-
if entry.is_none() {
171-
*entry = Some(value);
172-
return Ok(());
173-
}
174-
}
162+
let value = match self.mode.absorb(value) {
163+
Ok(()) => return Ok(()),
164+
Err(value) => value,
165+
};
175166

176167
// We've already absorbed as many elements as we can
177168
let _ = poseidon_sponge(
@@ -180,7 +171,8 @@ impl<
180171
&mut self.state,
181172
Some(&self.mode),
182173
)?;
183-
self.mode = Absorbing::init_with(value);
174+
self.mode = Absorbing::init_empty();
175+
self.mode.absorb(value).expect("state is not full");
184176

185177
Ok(())
186178
}
@@ -220,10 +212,8 @@ impl<
220212
/// Squeezes an element from the sponge.
221213
pub fn squeeze(&mut self, mut layouter: impl Layouter<F>) -> Result<AssignedCell<F, F>, Error> {
222214
loop {
223-
for entry in self.mode.0.iter_mut() {
224-
if let Some(inner) = entry.take() {
225-
return Ok(inner.into());
226-
}
215+
if let Some(value) = self.mode.squeeze() {
216+
return Ok(value.into());
227217
}
228218

229219
// We've already squeezed out all available elements

halo2_gadgets/src/poseidon/pow5.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -340,19 +340,20 @@ impl<
340340
let initial_state = initial_state?;
341341

342342
// Load the input into this region.
343-
let load_input_word = |i: usize| {
344-
let (cell, value) = match input.0[i].clone() {
343+
let load_input_word = |(i, input_word): (usize, &Option<PaddedWord<F>>)| {
344+
let (cell, value) = match input_word {
345345
Some(PaddedWord::Message(word)) => (word.cell(), word.value().copied()),
346346
Some(PaddedWord::Padding(padding_value)) => {
347+
let value = Value::known(*padding_value);
347348
let cell = region
348349
.assign_fixed(
349350
|| format!("load pad_{}", i),
350351
config.rc_b[i],
351352
1,
352-
|| Value::known(padding_value),
353+
|| value,
353354
)?
354355
.cell();
355-
(cell, Value::known(padding_value))
356+
(cell, value)
356357
}
357358
_ => panic!("Input is not padded"),
358359
};
@@ -366,7 +367,12 @@ impl<
366367

367368
Ok(StateWord(var))
368369
};
369-
let input: Result<Vec<_>, Error> = (0..RATE).map(load_input_word).collect();
370+
let input: Result<Vec<_>, Error> = input
371+
.expose_inner()
372+
.iter()
373+
.enumerate()
374+
.map(load_input_word)
375+
.collect();
370376
let input = input?;
371377

372378
// Constrain the output.
@@ -394,14 +400,8 @@ impl<
394400
}
395401

396402
fn get_output(state: &State<Self::Word, WIDTH>) -> Squeezing<Self::Word, RATE> {
397-
Squeezing(
398-
state[..RATE]
399-
.iter()
400-
.map(|word| Some(word.clone()))
401-
.collect::<Vec<_>>()
402-
.try_into()
403-
.unwrap(),
404-
)
403+
let vals = state[..RATE].to_vec();
404+
Squeezing::init_full(vals.try_into().expect("correct length"))
405405
}
406406
}
407407

@@ -687,7 +687,7 @@ mod tests {
687687
.try_into()
688688
.unwrap();
689689
let (round_constants, mds, _) = S::constants();
690-
poseidon::permute::<_, S, WIDTH, RATE>(
690+
poseidon::test_only_permute::<_, S, WIDTH, RATE>(
691691
&mut expected_final_state,
692692
&mds,
693693
&round_constants,

0 commit comments

Comments
 (0)