Replace PoseidonInstructions::State with PoseidonInstructions::Word

This commit is contained in:
Jack Grigg 2021-04-02 17:03:56 +13:00 committed by Jack Grigg
parent 01eb431f1f
commit d1fe466812
2 changed files with 33 additions and 26 deletions

View File

@ -11,15 +11,19 @@ use halo2::{
mod pow5t3; mod pow5t3;
pub use pow5t3::{Pow5T3Chip, Pow5T3Config}; pub use pow5t3::{Pow5T3Chip, Pow5T3Config};
/// The set of circuit instructions required to use the [`Poseidon`] gadget. use crate::primitives::poseidon::{Spec, State};
pub trait PoseidonInstructions<F: FieldExt>: Chip<F> {
/// Variable representing the state over which the Poseidon permutation operates. /// The set of circuit instructions required to use the Poseidon permutation.
type State: fmt::Debug; pub trait PoseidonInstructions<F: FieldExt, S: Spec<F, T, RATE>, const T: usize, const RATE: usize>:
Chip<F>
{
/// Variable representing the word over which the Poseidon permutation operates.
type Word: fmt::Debug;
/// Applies the Poseidon permutation to the given state. /// Applies the Poseidon permutation to the given state.
fn permute( fn permute(
&self, &self,
layouter: &mut impl Layouter<F>, layouter: &mut impl Layouter<F>,
initial_state: &Self::State, initial_state: &State<Self::Word, T>,
) -> Result<Self::State, Error>; ) -> Result<State<Self::Word, T>, Error>;
} }

View File

@ -6,7 +6,7 @@ use halo2::{
}; };
use super::PoseidonInstructions; use super::PoseidonInstructions;
use crate::primitives::poseidon::{Mds, Spec}; use crate::primitives::poseidon::{Mds, Spec, State};
const WIDTH: usize = 3; const WIDTH: usize = 3;
@ -186,14 +186,14 @@ impl<F: FieldExt> Chip<F> for Pow5T3Chip<F> {
} }
} }
impl<F: FieldExt> PoseidonInstructions<F> for Pow5T3Chip<F> { impl<F: FieldExt, S: Spec<F, WIDTH, 2>> PoseidonInstructions<F, S, WIDTH, 2> for Pow5T3Chip<F> {
type State = Pow5T3State<F>; type Word = StateWord<F>;
fn permute( fn permute(
&self, &self,
layouter: &mut impl Layouter<F>, layouter: &mut impl Layouter<F>,
initial_state: &Self::State, initial_state: &State<Self::Word, WIDTH>,
) -> Result<Self::State, Error> { ) -> Result<State<Self::Word, WIDTH>, Error> {
let config = self.config(); let config = self.config();
layouter.assign_region( layouter.assign_region(
@ -217,7 +217,7 @@ impl<F: FieldExt> PoseidonInstructions<F> for Pow5T3Chip<F> {
}) })
})?; })?;
(0..config.half_full_rounds).fold(Ok(state), |res, r| { let state = (0..config.half_full_rounds).fold(Ok(state), |res, r| {
res.and_then(|state| { res.and_then(|state| {
state.full_round( state.full_round(
&mut region, &mut region,
@ -226,20 +226,22 @@ impl<F: FieldExt> PoseidonInstructions<F> for Pow5T3Chip<F> {
config.half_full_rounds + config.half_partial_rounds + r, config.half_full_rounds + config.half_partial_rounds + r,
) )
}) })
}) })?;
Ok(state.0)
}, },
) )
} }
} }
#[derive(Debug)] #[derive(Debug)]
struct StateWord<F: FieldExt> { pub struct StateWord<F: FieldExt> {
var: Cell, var: Cell,
value: Option<F>, value: Option<F>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Pow5T3State<F: FieldExt>([StateWord<F>; WIDTH]); struct Pow5T3State<F: FieldExt>([StateWord<F>; WIDTH]);
impl<F: FieldExt> Pow5T3State<F> { impl<F: FieldExt> Pow5T3State<F> {
fn full_round( fn full_round(
@ -352,17 +354,17 @@ impl<F: FieldExt> Pow5T3State<F> {
fn load( fn load(
region: &mut Region<F>, region: &mut Region<F>,
config: &Pow5T3Config<F>, config: &Pow5T3Config<F>,
initial_state: &Self, initial_state: &State<StateWord<F>, WIDTH>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let mut load_state_word = |i: usize| { let mut load_state_word = |i: usize| {
let value = initial_state.0[i].value; let value = initial_state[i].value;
let var = region.assign_advice( let var = region.assign_advice(
|| format!("load state_{}", i), || format!("load state_{}", i),
config.state[i], config.state[i],
0, 0,
|| value.ok_or(Error::SynthesisError), || value.ok_or(Error::SynthesisError),
)?; )?;
region.constrain_equal(&config.state_permutation, initial_state.0[i].var, var)?; region.constrain_equal(&config.state_permutation, initial_state[i].var, var)?;
Ok(StateWord { var, value }) Ok(StateWord { var, value })
}; };
@ -429,7 +431,7 @@ mod tests {
plonk::{Assignment, Circuit, ConstraintSystem, Error}, plonk::{Assignment, Circuit, ConstraintSystem, Error},
}; };
use super::{PoseidonInstructions, Pow5T3Chip, Pow5T3Config, Pow5T3State, StateWord, WIDTH}; use super::{PoseidonInstructions, Pow5T3Chip, Pow5T3Config, StateWord, WIDTH};
use crate::primitives::poseidon::{self, OrchardNullifier, Spec}; use crate::primitives::poseidon::{self, OrchardNullifier, Spec};
struct MyCircuit {} struct MyCircuit {}
@ -468,16 +470,17 @@ mod tests {
Ok(StateWord { var, value }) Ok(StateWord { var, value })
}; };
Ok(Pow5T3State([ Ok([state_word(0)?, state_word(1)?, state_word(2)?])
state_word(0)?,
state_word(1)?,
state_word(2)?,
]))
}, },
)?; )?;
let chip = Pow5T3Chip::construct(config.clone()); let chip = Pow5T3Chip::construct(config.clone());
let final_state = chip.permute(&mut layouter, &initial_state)?; let final_state = <Pow5T3Chip<_> as PoseidonInstructions<
Fp,
OrchardNullifier,
WIDTH,
2,
>>::permute(&chip, &mut layouter, &initial_state)?;
// For the purpose of this test, compute the real final state inline. // For the purpose of this test, compute the real final state inline.
let mut expected_final_state = [Fp::zero(), Fp::one(), Fp::from_u64(2)]; let mut expected_final_state = [Fp::zero(), Fp::one(), Fp::from_u64(2)];
@ -498,7 +501,7 @@ mod tests {
0, 0,
|| Ok(expected_final_state[i]), || Ok(expected_final_state[i]),
)?; )?;
region.constrain_equal(&config.state_permutation, final_state.0[i].var, var) region.constrain_equal(&config.state_permutation, final_state[i].var, var)
}; };
final_state_word(0)?; final_state_word(0)?;