From b0299962320858b13934573bd20d90215c8fe876 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 16 Mar 2023 19:26:05 -0400 Subject: [PATCH 1/5] sync group 0.13.0 --- Cargo.toml | 17 ++++- src/hash.rs | 50 +++++++-------- src/poseidon.rs | 30 +++++---- src/poseidon/pow5.rs | 48 ++++++++------- src/poseidon/primitives.rs | 89 ++++++++++++++++++--------- src/poseidon/primitives/bn256/mod.rs | 4 +- src/poseidon/primitives/grain.rs | 12 ++-- src/poseidon/primitives/mds.rs | 14 ++--- src/poseidon/primitives/p128pow5t3.rs | 16 ++--- src/poseidon/primitives/pasta/mod.rs | 4 +- 10 files changed, 170 insertions(+), 114 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b8baddc..2e16b7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,18 +6,31 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "scroll-dev-1220" } +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } lazy_static = "1.4.0" thiserror = "1.0" bitvec = "0.22" +[patch."https://github.com/privacy-scaling-explorations/halo2.git"] +halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "halo2-ecc-snark-verifier-0220" } + +# remove once +# https://github.com/privacy-scaling-explorations/poseidon/pull/7 +# https://github.com/privacy-scaling-explorations/halo2curves/pull/31 +# are merged +[patch."https://github.com/privacy-scaling-explorations/poseidon.git"] +poseidon = { git = "https://github.com/scroll-tech/poseidon.git", branch = "halo2-ecc-snark-verifier-0220" } + +[patch."https://github.com/privacy-scaling-explorations/halo2curves.git"] +halo2curves = { git = "https://github.com/scroll-tech/halo2curves.git", branch = "halo2-ecc-snark-verifier-0220" } + [patch.crates-io] # temporary solution to funty@1.2.0 being yanked, tracking issue: https://github.com/ferrilab/funty/issues/7 funty = { git = "https://github.com/ferrilab/funty/", rev = "7ef0d890fbcd8b3def1635ac1a877fc298488446" } [features] # printout the layout of circuits for demo and some unittests -print_layout = ["halo2_proofs/dev-graph"] +# print_layout = ["halo2_proofs/dev-graph"] [dev-dependencies] rand = "0.8" diff --git a/src/hash.rs b/src/hash.rs index 8c1b8bf..ed6baa5 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -3,11 +3,11 @@ use crate::poseidon::primitives::{ ConstantLengthIden3, Domain, Hash, P128Pow5T3, Spec, VariableLengthIden3, }; -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use halo2_proofs::halo2curves::bn256::Fr; /// indicate an field can be hashed in merkle tree (2 Fields to 1 Field) -pub trait Hashable: FieldExt { +pub trait Hashable: FromUniformBytes<64> + Ord { /// the spec type used in circuit for this hashable field type SpecType: Spec; /// the domain type used for hash calculation @@ -65,7 +65,7 @@ use halo2_proofs::{ /// The config for poseidon hash circuit #[derive(Clone, Debug)] -pub struct PoseidonHashConfig { +pub struct PoseidonHashConfig { permute_config: Pow5Config, hash_table: [Column; 4], hash_table_aux: [Column; 6], @@ -123,8 +123,8 @@ impl PoseidonHashConfig { let s_continue = meta.query_advice(s_sponge_continue, Rotation::cur()); vec![ - s_enable.clone() * ctrl * (Expression::Constant(Fp::one()) - ctrl_bool.clone()), - s_enable * s_continue * (Expression::Constant(Fp::one()) - ctrl_bool), + s_enable.clone() * ctrl * (Expression::Constant(Fp::ONE) - ctrl_bool.clone()), + s_enable * s_continue * (Expression::Constant(Fp::ONE) - ctrl_bool), ] }); @@ -147,7 +147,7 @@ impl PoseidonHashConfig { let ctrl = meta.query_advice(control, Rotation::prev()); vec![( - s_enable * (Expression::Constant(Fp::one()) - s_continue) * ctrl, + s_enable * (Expression::Constant(Fp::ONE) - s_continue) * ctrl, control_step_range, )] }); @@ -162,7 +162,7 @@ impl PoseidonHashConfig { vec![ s_enable.clone() * s_continue_hash.clone() * (hash_ind - hash_prev.clone()), s_enable - * (Expression::Constant(Fp::one()) - s_continue_hash) + * (Expression::Constant(Fp::ONE) - s_continue_hash) * (hash_out - hash_prev), ] }); @@ -194,7 +194,7 @@ impl PoseidonHashConfig { // hash output: must inherit prev state or apply current control flag (for new hash) ret.push( s_enable.clone() - * (Expression::Constant(Fp::one()) - s_continue_hash.clone()) + * (Expression::Constant(Fp::ONE) - s_continue_hash.clone()) * (inp_hash.clone() - inp_hash_init), ); ret.push(s_enable * s_continue_hash * (inp_hash - inp_hash_prev)); @@ -231,7 +231,7 @@ pub struct PoseidonHashTable { pub checks: Vec>, } -impl PoseidonHashTable { +impl PoseidonHashTable { /// Add common inputs pub fn constant_inputs<'d>(&mut self, src: impl IntoIterator) { let mut new_inps: Vec<_> = src.into_iter().copied().collect(); @@ -279,7 +279,7 @@ impl PoseidonHashTable { /// Represent the chip for Poseidon hash table #[derive(Debug)] -pub struct PoseidonHashChip<'d, Fp: FieldExt, const STEP: usize> { +pub struct PoseidonHashChip<'d, Fp: PrimeField, const STEP: usize> { calcs: usize, data: &'d PoseidonHashTable, config: PoseidonHashConfig, @@ -309,7 +309,7 @@ impl<'d, Fp: Hashable, const STEP: usize> PoseidonHashChip<'d, Fp, STEP> { || "constant zero", config.constants[0], 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; Ok([c0]) @@ -364,7 +364,7 @@ impl<'d, Fp: Hashable, const STEP: usize> PoseidonHashChip<'d, Fp, STEP> { // notice our hash table has a (0, 0, 0) at the beginning for col in config.hash_table { - region.assign_advice(|| "dummy inputs", col, 0, || Value::known(Fp::zero()))?; + region.assign_advice(|| "dummy inputs", col, 0, || Value::known(Fp::ZERO))?; } for col in config.hash_table_aux { @@ -372,7 +372,7 @@ impl<'d, Fp: Hashable, const STEP: usize> PoseidonHashChip<'d, Fp, STEP> { || "dummy aux inputs", col, 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; } @@ -380,14 +380,14 @@ impl<'d, Fp: Hashable, const STEP: usize> PoseidonHashChip<'d, Fp, STEP> { || "control aux head", config.control_aux, 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; let c_ctrl = region.assign_advice( || "control sponge continue head", config.s_sponge_continue, 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; // contraint 0 to zero constant @@ -396,12 +396,12 @@ impl<'d, Fp: Hashable, const STEP: usize> PoseidonHashChip<'d, Fp, STEP> { let mut is_new_sponge = true; let mut process_start = 0; let mut offset = 1; - let mut state: [Fp; 3] = [Fp::zero(); 3]; + let mut state: [Fp; 3] = [Fp::ZERO; 3]; for (i, ((inp, control), check)) in inputs_i.zip(controls_i).zip(checks_i).enumerate() { - let control = control.copied().unwrap_or_else(Fp::zero); + let control = control.copied().unwrap_or(Fp::ZERO); offset = i + 1; if is_new_sponge { @@ -411,7 +411,7 @@ impl<'d, Fp: Hashable, const STEP: usize> PoseidonHashChip<'d, Fp, STEP> { let inp = inp .map(|[a, b]| [*a, *b]) - .unwrap_or_else(|| [Fp::zero(), Fp::zero()]); + .unwrap_or_else(|| [Fp::ZERO, Fp::ZERO]); state.iter_mut().skip(1).zip(inp).for_each(|(s, inp)| { if is_new_sponge { @@ -485,14 +485,14 @@ impl<'d, Fp: Hashable, const STEP: usize> PoseidonHashChip<'d, Fp, STEP> { || format!("state input control_aux_{}", i), config.control_aux, offset, - || Value::known(control.invert().unwrap_or_else(Fp::zero)), + || Value::known(control.invert().unwrap_or(Fp::ZERO)), )?; region.assign_advice( || format!("state continue control_{}", i), config.s_sponge_continue, offset, - || Value::known(if is_new_sponge { Fp::zero() } else { Fp::one() }), + || Value::known(if is_new_sponge { Fp::ZERO } else { Fp::ONE }), )?; region.assign_advice( @@ -536,7 +536,7 @@ impl<'d, Fp: Hashable, const STEP: usize> PoseidonHashChip<'d, Fp, STEP> { || "control sponge continue last", config.s_sponge_continue, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; // contraint 0 to tail line @@ -573,7 +573,7 @@ impl<'d, Fp: Hashable, const STEP: usize> PoseidonHashChip<'d, Fp, STEP> { } } -impl Chip for PoseidonHashChip<'_, Fp, STEP> { +impl Chip for PoseidonHashChip<'_, Fp, STEP> { type Config = PoseidonHashConfig; type Loaded = PoseidonHashTable; @@ -623,7 +623,7 @@ mod tests { Fr::from_str_vartime("1").unwrap(), Fr::from_str_vartime("2").unwrap(), Fr::from_str_vartime("3").unwrap(), - Fr::zero(), + FrZERO, ]; let supposed_bytes = 50u64; @@ -716,7 +716,7 @@ mod tests { Fr::from_str_vartime("2").unwrap(), ]; - let message2 = [Fr::from_str_vartime("50331648").unwrap(), Fr::zero()]; + let message2 = [Fr::from_str_vartime("50331648").unwrap(), FrZERO]; let k = 8; let circuit = PoseidonHashTable { @@ -729,7 +729,7 @@ mod tests { let circuit = PoseidonHashTable { inputs: vec![message1, message2, message1], - controls: vec![Fr::from_u128(64), Fr::from_u128(32), Fr::zero()], + controls: vec![Fr::from_u128(64), Fr::from_u128(32), FrZERO], checks: Vec::new(), }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); diff --git a/src/poseidon.rs b/src/poseidon.rs index 8857f7e..ef67986 100644 --- a/src/poseidon.rs +++ b/src/poseidon.rs @@ -5,8 +5,8 @@ use std::fmt; use std::marker::PhantomData; use halo2_proofs::{ - arithmetic::{Field, FieldExt}, circuit::{AssignedCell, Chip, Layouter}, + ff::{Field, FromUniformBytes}, plonk::Error, }; @@ -26,8 +26,12 @@ pub enum PaddedWord { } /// The set of circuit instructions required to use the Poseidon permutation. -pub trait PoseidonInstructions, const T: usize, const RATE: usize>: - Chip +pub trait PoseidonInstructions< + F: FromUniformBytes<64> + Ord, + S: Spec, + const T: usize, + const RATE: usize, +>: Chip { /// Variable representing the word over which the Poseidon permutation operates. type Word: Clone + fmt::Debug + From> + Into>; @@ -44,7 +48,7 @@ pub trait PoseidonInstructions, const T: usize, /// /// [`Hash`]: self::Hash pub trait PoseidonSpongeInstructions< - F: FieldExt, + F: FromUniformBytes<64> + Ord, S: Spec, D: Domain, const T: usize, @@ -70,7 +74,7 @@ pub trait PoseidonSpongeInstructions< /// A word over which the Poseidon permutation operates. #[derive(Debug)] pub struct Word< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonInstructions, S: Spec, const T: usize, @@ -80,7 +84,7 @@ pub struct Word< } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonInstructions, S: Spec, const T: usize, @@ -99,7 +103,7 @@ impl< } fn poseidon_sponge< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -121,7 +125,7 @@ fn poseidon_sponge< /// A Poseidon sponge. #[derive(Debug)] pub struct Sponge< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, M: SpongeMode, @@ -136,7 +140,7 @@ pub struct Sponge< } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -209,7 +213,7 @@ impl< } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -240,7 +244,7 @@ impl< /// A Poseidon hash function, built around a sponge. #[derive(Debug)] pub struct Hash< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -251,7 +255,7 @@ pub struct Hash< } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -266,7 +270,7 @@ impl< } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, T, RATE>, S: Spec, const T: usize, diff --git a/src/poseidon/pow5.rs b/src/poseidon/pow5.rs index 45c5170..ec11919 100644 --- a/src/poseidon/pow5.rs +++ b/src/poseidon/pow5.rs @@ -2,8 +2,8 @@ use std::convert::TryInto; use std::iter; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{AssignedCell, Cell, Chip, Layouter, Region, Value}, + ff::{FromUniformBytes, PrimeField}, plonk::{Advice, Any, Column, ConstraintSystem, Error, Expression, Fixed, Selector}, poly::Rotation, }; @@ -14,7 +14,7 @@ use super::{ }; /// Trait for a variable in the circuit. -pub trait Var: Clone + std::fmt::Debug + From> { +pub trait Var: Clone + std::fmt::Debug + From> { /// The cell at which this variable was allocated. fn cell(&self) -> Cell; @@ -22,7 +22,7 @@ pub trait Var: Clone + std::fmt::Debug + From> { fn value(&self) -> Value; } -impl Var for AssignedCell { +impl Var for AssignedCell { fn cell(&self) -> Cell { self.cell() } @@ -34,7 +34,7 @@ impl Var for AssignedCell { /// Configuration for a [`Pow5Chip`]. #[derive(Clone, Debug)] -pub struct Pow5Config { +pub struct Pow5Config { pub(crate) state: [Column; WIDTH], partial_sbox: Column, rc_a: [Column; WIDTH], @@ -57,11 +57,13 @@ pub struct Pow5Config { /// The chip is implemented using a single round per row for full rounds, and two rounds /// per row for partial rounds. #[derive(Debug)] -pub struct Pow5Chip { +pub struct Pow5Chip { config: Pow5Config, } -impl Pow5Chip { +impl + Ord, const WIDTH: usize, const RATE: usize> + Pow5Chip +{ /// Configures this chip for use in a circuit. /// /// # Side-effects @@ -245,7 +247,7 @@ impl Pow5Chip Chip for Pow5Chip { +impl Chip for Pow5Chip { type Config = Pow5Config; type Loaded = (); @@ -258,8 +260,12 @@ impl Chip for Pow5Chip, const WIDTH: usize, const RATE: usize> - PoseidonInstructions for Pow5Chip +impl< + F: FromUniformBytes<64> + Ord, + S: Spec, + const WIDTH: usize, + const RATE: usize, + > PoseidonInstructions for Pow5Chip { type Word = StateWord; @@ -325,7 +331,7 @@ impl, const WIDTH: usize, const RATE: usize } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, S: Spec, D: Domain, const WIDTH: usize, @@ -354,7 +360,7 @@ impl< }; for i in 0..RATE { - load_state_word(i, F::zero())?; + load_state_word(i, F::ZERO)?; } load_state_word(RATE, D::initial_capacity_element())?; @@ -455,21 +461,21 @@ impl< /// A word in the Poseidon state. #[derive(Clone, Debug)] -pub struct StateWord(AssignedCell); +pub struct StateWord(AssignedCell); -impl From> for AssignedCell { +impl From> for AssignedCell { fn from(state_word: StateWord) -> AssignedCell { state_word.0 } } -impl From> for StateWord { +impl From> for StateWord { fn from(cell_value: AssignedCell) -> StateWord { StateWord(cell_value) } } -impl Var for StateWord { +impl Var for StateWord { fn cell(&self) -> Cell { self.0.cell() } @@ -480,9 +486,9 @@ impl Var for StateWord { } #[derive(Debug)] -struct Pow5State([StateWord; WIDTH]); +struct Pow5State([StateWord; WIDTH]); -impl Pow5State { +impl Pow5State { fn full_round( self, region: &mut Region, @@ -500,7 +506,7 @@ impl Pow5State { let state = m.iter().map(|m_i| { r.iter() .enumerate() - .fold(Value::known(F::zero()), |acc, (j, r_j)| { + .fold(Value::known(F::ZERO), |acc, (j, r_j)| { acc + Value::known(m_i[j]) * r_j }) }); @@ -538,7 +544,7 @@ impl Pow5State { let state = m.iter().map(|m_i| { r.iter() .enumerate() - .fold(Value::known(F::zero()), |acc, (j, r_j)| { + .fold(Value::known(F::ZERO), |acc, (j, r_j)| { acc + Value::known(m_i[j]) * r_j }) }); @@ -579,7 +585,7 @@ impl Pow5State { .map(|m_i| { m_i.iter() .zip(r.iter()) - .fold(Value::known(F::zero()), |acc, (m_ij, r_j)| { + .fold(Value::known(F::ZERO), |acc, (m_ij, r_j)| { acc + Value::known(*m_ij) * r_j }) }) @@ -611,7 +617,7 @@ impl Pow5State { .map(|m_i| { m_i.iter() .zip(r_mid.iter()) - .fold(Value::known(F::zero()), |acc, (m_ij, r_j)| { + .fold(Value::known(F::ZERO), |acc, (m_ij, r_j)| { acc + Value::known(*m_ij) * r_j }) }) diff --git a/src/poseidon/primitives.rs b/src/poseidon/primitives.rs index dc7865d..3eadbab 100644 --- a/src/poseidon/primitives.rs +++ b/src/poseidon/primitives.rs @@ -5,7 +5,8 @@ use std::fmt; use std::iter; use std::marker::PhantomData; -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::FromUniformBytes; +use halo2_proofs::ff::PrimeField; //pub(crate) mod fp; //pub(crate) mod fq; @@ -38,7 +39,9 @@ pub(crate) type SpongeRate = [Option; RATE]; pub(crate) type Mds = [[F; T]; T]; /// A specification for a Poseidon permutation. -pub trait Spec: fmt::Debug { +pub trait Spec + Ord, const T: usize, const RATE: usize>: + fmt::Debug +{ /// The number of full rounds for this specification. /// /// This must be an even number. @@ -66,7 +69,7 @@ pub trait Spec: fmt::Debug { let round_constants = (0..(r_f + r_p)) .map(|_| { - let mut rc_row = [F::zero(); T]; + let mut rc_row = [F::ZERO; T]; for (rc, value) in rc_row .iter_mut() .zip((0..T).map(|_| grain.next_field_element())) @@ -84,7 +87,12 @@ pub trait Spec: fmt::Debug { } /// Runs the Poseidon permutation on the given state. -pub(crate) fn permute, const T: usize, const RATE: usize>( +pub(crate) fn permute< + F: FromUniformBytes<64> + Ord, + S: Spec, + const T: usize, + const RATE: usize, +>( state: &mut State, mds: &Mds, round_constants: &[[F; T]], @@ -93,7 +101,7 @@ pub(crate) fn permute, const T: usize, const RA let r_p = S::partial_rounds(); let apply_mds = |state: &mut State| { - let mut new_state = [F::zero(); T]; + let mut new_state = [F::ZERO; T]; // Matrix multiplication #[allow(clippy::needless_range_loop)] for i in 0..T { @@ -131,7 +139,12 @@ pub(crate) fn permute, const T: usize, const RA }); } -fn poseidon_sponge, const T: usize, const RATE: usize>( +fn poseidon_sponge< + F: FromUniformBytes<64> + Ord, + S: Spec, + const T: usize, + const RATE: usize, +>( state: &mut State, input: Option<(&Absorbing, usize)>, mds_matrix: &Mds, @@ -189,7 +202,7 @@ impl Absorbing { /// A Poseidon sponge. pub(crate) struct Sponge< - F: FieldExt, + F: FromUniformBytes<64> + Ord, S: Spec, M: SpongeMode, const T: usize, @@ -203,7 +216,7 @@ pub(crate) struct Sponge< _marker: PhantomData, } -impl, const T: usize, const RATE: usize> +impl + Ord, S: Spec, const T: usize, const RATE: usize> Sponge, T, RATE> { /// Constructs a new sponge for the given Poseidon specification. @@ -211,7 +224,7 @@ impl, const T: usize, const RATE: usize> let (round_constants, mds_matrix, _) = S::constants(); let mode = Absorbing([None; RATE]); - let mut state = [F::zero(); T]; + let mut state = [F::ZERO; T]; state[(RATE + layout) % T] = initial_capacity_element; Sponge { @@ -268,7 +281,7 @@ impl, const T: usize, const RATE: usize> } } -impl, const T: usize, const RATE: usize> +impl + Ord, S: Spec, const T: usize, const RATE: usize> Sponge, T, RATE> { /// Squeezes an element from the sponge. @@ -292,7 +305,7 @@ impl, const T: usize, const RATE: usize> } /// A domain in which a Poseidon hash function is being used. -pub trait Domain { +pub trait Domain { /// Iterator that outputs padding field elements. type Padding: IntoIterator; @@ -319,7 +332,7 @@ pub trait Domain { #[derive(Clone, Copy, Debug)] pub struct ConstantLength; -impl Domain for ConstantLength { +impl Domain for ConstantLength { type Padding = iter::Take>; fn name() -> String { @@ -339,7 +352,7 @@ impl Domain for Constan // Poseidon authors encode the constant length into the capacity element, ensuring // that inputs of different lengths do not share the same permutation. let k = (L + RATE - 1) / RATE; - iter::repeat(F::zero()).take(k * RATE - L) + iter::repeat(F::ZERO).take(k * RATE - L) } } @@ -347,7 +360,7 @@ impl Domain for Constan #[derive(Clone, Copy, Debug)] pub struct ConstantLengthIden3; -impl Domain for ConstantLengthIden3 { +impl Domain for ConstantLengthIden3 { type Padding = as Domain>::Padding; fn name() -> String { @@ -356,7 +369,7 @@ impl Domain for Constan // iden3's scheme do not set any capacity mark fn initial_capacity_element() -> F { - F::zero() + F::ZERO } fn padding(input_len: usize) -> Self::Padding { @@ -372,7 +385,7 @@ impl Domain for Constan #[derive(Clone, Copy, Debug)] pub struct VariableLengthIden3; -impl Domain for VariableLengthIden3 { +impl Domain for VariableLengthIden3 { type Padding = as Domain>::Padding; fn name() -> String { @@ -386,7 +399,7 @@ impl Domain for VariableLengthIden3 { fn padding(input_len: usize) -> Self::Padding { let k = input_len % RATE; - iter::repeat(F::zero()).take(if k == 0 { 0 } else { RATE - k }) + iter::repeat(F::ZERO).take(if k == 0 { 0 } else { RATE - k }) } fn layout(width: usize) -> usize { @@ -396,7 +409,7 @@ impl Domain for VariableLengthIden3 { /// A Poseidon hash function, built around a sponge. pub struct Hash< - F: FieldExt, + F: FromUniformBytes<64> + Ord, S: Spec, D: Domain, const T: usize, @@ -406,8 +419,13 @@ pub struct Hash< _domain: PhantomData, } -impl, D: Domain, const T: usize, const RATE: usize> - fmt::Debug for Hash +impl< + F: FromUniformBytes<64> + Ord, + S: Spec, + D: Domain, + const T: usize, + const RATE: usize, + > fmt::Debug for Hash { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Hash") @@ -420,8 +438,13 @@ impl, D: Domain, const T: usize, const } } -impl, D: Domain, const T: usize, const RATE: usize> - Hash +impl< + F: FromUniformBytes<64> + Ord, + S: Spec, + D: Domain, + const T: usize, + const RATE: usize, + > Hash { /// Initializes a new hasher. pub fn init() -> Self { @@ -437,8 +460,13 @@ impl, D: Domain, const T: usize, const } } -impl, const T: usize, const RATE: usize, const L: usize> - Hash, T, RATE> +impl< + F: FromUniformBytes<64> + Ord, + S: Spec, + const T: usize, + const RATE: usize, + const L: usize, + > Hash, T, RATE> { /// Hashes the given input. pub fn hash(mut self, message: [F; L]) -> F { @@ -452,8 +480,13 @@ impl, const T: usize, const RATE: usize, const } } -impl, const T: usize, const RATE: usize, const L: usize> - Hash, T, RATE> +impl< + F: FromUniformBytes<64> + Ord, + S: Spec, + const T: usize, + const RATE: usize, + const L: usize, + > Hash, T, RATE> { /// Hashes the given input. pub fn hash(mut self, message: [F; L]) -> F { @@ -467,7 +500,7 @@ impl, const T: usize, const RATE: usize, const } } -impl, const T: usize, const RATE: usize> +impl + Ord, S: Spec, const T: usize, const RATE: usize> Hash { /// Hashes the given input. @@ -488,7 +521,7 @@ impl, const T: usize, const RATE: usize> #[cfg(test)] mod tests { use super::pasta::Fp; - use halo2_proofs::arithmetic::FieldExt; + use halo2_proofs::ff::PrimeField; use super::{permute, ConstantLength, Hash, P128Pow5T3, Spec}; type OrchardNullifier = P128Pow5T3; diff --git a/src/poseidon/primitives/bn256/mod.rs b/src/poseidon/primitives/bn256/mod.rs index 3c49ab5..efc14fb 100644 --- a/src/poseidon/primitives/bn256/mod.rs +++ b/src/poseidon/primitives/bn256/mod.rs @@ -104,9 +104,9 @@ mod tests { #[allow(clippy::needless_range_loop)] for i in 0..3 { for j in 0..3 { - let expected = if i == j { Fp::one() } else { Fp::zero() }; + let expected = if i == j { Fp::ONE } else { Fp::ZERO }; assert_eq!( - (0..3).fold(Fp::zero(), |acc, k| acc + (mds[i][k] * mds_inv[k][j])), + (0..3).fold(Fp::ZERO, |acc, k| acc + (mds[i][k] * mds_inv[k][j])), expected ); } diff --git a/src/poseidon/primitives/grain.rs b/src/poseidon/primitives/grain.rs index bfc0715..2412258 100644 --- a/src/poseidon/primitives/grain.rs +++ b/src/poseidon/primitives/grain.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use bitvec::prelude::*; -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::FromUniformBytes; const STATE: usize = 80; @@ -43,13 +43,13 @@ impl SboxType { } } -pub(super) struct Grain { +pub(super) struct Grain + Ord> { state: BitArr!(for 80, in Msb0, u8), next_bit: usize, _field: PhantomData, } -impl Grain { +impl + Ord> Grain { pub(super) fn new(sbox: SboxType, t: u16, r_f: u16, r_p: u16) -> Self { // Initialize the LFSR state. let mut state = bitarr![Msb0, u8; 1; STATE]; @@ -151,7 +151,7 @@ impl Grain { // // Given that we don't want to diverge from the reference implementation, we hack // around this restriction by serializing the bits into a 64-byte array and then - // calling F::from_bytes_wide. PLEASE DO NOT COPY THIS INTO YOUR OWN CODE! + // calling F::from_uniform_bytes. PLEASE DO NOT COPY THIS INTO YOUR OWN CODE! let view = bytes.as_mut(); for (i, bit) in self.take(F::NUM_BITS as usize).enumerate() { // If we diverged from the reference impl and interpreted the bits in LSB @@ -161,11 +161,11 @@ impl Grain { view[i / 8] |= if bit { 1 << (i % 8) } else { 0 }; } - F::from_bytes_wide(&bytes) + F::from_uniform_bytes(&bytes) } } -impl Iterator for Grain { +impl + Ord> Iterator for Grain { type Item = bool; fn next(&mut self) -> Option { diff --git a/src/poseidon/primitives/mds.rs b/src/poseidon/primitives/mds.rs index fbc7282..551ee07 100644 --- a/src/poseidon/primitives/mds.rs +++ b/src/poseidon/primitives/mds.rs @@ -1,8 +1,8 @@ -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::FromUniformBytes; use super::{grain::Grain, Mds}; -pub(super) fn generate_mds( +pub(super) fn generate_mds + Ord, const T: usize>( grain: &mut Grain, mut select: usize, ) -> (Mds, Mds) { @@ -48,7 +48,7 @@ pub(super) fn generate_mds( // However, the Poseidon paper and reference impl use the positive formulation, // and we want to rely on the reference impl for MDS security, so we use the same // formulation. - let mut mds = [[F::zero(); T]; T]; + let mut mds = [[F::ZERO; T]; T]; #[allow(clippy::needless_range_loop)] for i in 0..T { for j in 0..T { @@ -74,10 +74,10 @@ pub(super) fn generate_mds( // where A_i(x) and B_i(x) are the Lagrange polynomials for xs and ys respectively. // // We adapt this to the positive Cauchy formulation by negating ys. - let mut mds_inv = [[F::zero(); T]; T]; + let mut mds_inv = [[F::ZERO; T]; T]; let l = |xs: &[F], j, x: F| { let x_j = xs[j]; - xs.iter().enumerate().fold(F::one(), |acc, (m, x_m)| { + xs.iter().enumerate().fold(F::ZERO, |acc, (m, x_m)| { if m == j { acc } else { @@ -113,9 +113,9 @@ mod tests { #[allow(clippy::needless_range_loop)] for i in 0..T { for j in 0..T { - let expected = if i == j { Fp::one() } else { Fp::zero() }; + let expected = if i == j { Fp::ONE } else { Fp::ZERO }; assert_eq!( - (0..T).fold(Fp::zero(), |acc, k| acc + (mds[i][k] * mds_inv[k][j])), + (0..T).fold(Fp::ZERO, |acc, k| acc + (mds[i][k] * mds_inv[k][j])), expected ); } diff --git a/src/poseidon/primitives/p128pow5t3.rs b/src/poseidon/primitives/p128pow5t3.rs index 6d06386..0a159d7 100644 --- a/src/poseidon/primitives/p128pow5t3.rs +++ b/src/poseidon/primitives/p128pow5t3.rs @@ -1,9 +1,9 @@ -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use std::marker::PhantomData; use super::{Mds, Spec}; -pub trait P128Pow5T3Constants: FieldExt { +pub trait P128Pow5T3Constants: PrimeField { fn partial_rounds() -> usize { 56 } @@ -23,7 +23,7 @@ pub struct P128Pow5T3 { _marker: PhantomData, } -impl Spec for P128Pow5T3 { +impl + Ord> Spec for P128Pow5T3 { fn full_rounds() -> usize { 8 } @@ -49,7 +49,7 @@ impl Spec for P128Pow5T3 { mod tests { use std::marker::PhantomData; - use halo2_proofs::arithmetic::FieldExt; + use halo2_proofs::ff::PrimeField; use halo2_proofs::halo2curves::group::ff::PrimeField; use super::super::pasta::{fp, test_vectors, Fp}; @@ -58,17 +58,17 @@ mod tests { /// The same Poseidon specification as poseidon::P128Pow5T3, but constructed /// such that its constants will be generated at runtime. #[derive(Debug)] - pub struct P128Pow5T3Gen(PhantomData); + pub struct P128Pow5T3Gen(PhantomData); type P128Pow5T3Pasta = super::P128Pow5T3; - impl P128Pow5T3Gen { + impl P128Pow5T3Gen { pub fn new() -> Self { P128Pow5T3Gen(PhantomData::default()) } } - impl Spec for P128Pow5T3Gen { + impl Spec for P128Pow5T3Gen { fn full_rounds() -> usize { 8 } @@ -88,7 +88,7 @@ mod tests { #[test] fn verify_constants() { - fn verify_constants_helper( + fn verify_constants_helper( expected_round_constants: [[F; 3]; 64], expected_mds: [[F; 3]; 3], expected_mds_inv: [[F; 3]; 3], diff --git a/src/poseidon/primitives/pasta/mod.rs b/src/poseidon/primitives/pasta/mod.rs index 7293044..afcb67b 100644 --- a/src/poseidon/primitives/pasta/mod.rs +++ b/src/poseidon/primitives/pasta/mod.rs @@ -37,7 +37,7 @@ fn sqrt_tonelli_shanks>(f: &F, tm1d2: S) -> subtl let mut j_less_than_v: Choice = 1.into(); for j in 2..max_v { - let tmp_is_one = tmp.ct_eq(&F::one()); + let tmp_is_one = tmp.ct_eq(&F::ZERO); let squared = F::conditional_select(&tmp, &z, tmp_is_one).square(); tmp = F::conditional_select(&squared, &tmp, tmp_is_one); let new_z = F::conditional_select(&z, &squared, tmp_is_one); @@ -47,7 +47,7 @@ fn sqrt_tonelli_shanks>(f: &F, tm1d2: S) -> subtl } let result = x * z; - x = F::conditional_select(&result, &x, b.ct_eq(&F::one())); + x = F::conditional_select(&result, &x, b.ct_eq(&F::ZERO)); z = z.square(); b *= z; v = k; From 06faa17f28615ca23748d2da8827b3bd78555070 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 16 Mar 2023 19:42:24 -0400 Subject: [PATCH 2/5] fix tests --- rust-toolchain | 2 +- src/hash.rs | 7 ++++--- src/poseidon/primitives/bn256/mod.rs | 4 +++- src/poseidon/primitives/mds.rs | 4 +++- src/poseidon/primitives/p128pow5t3.rs | 9 +++++---- src/poseidon/primitives/pasta/mod.rs | 2 +- tests/hash_proving.rs | 5 +++-- 7 files changed, 20 insertions(+), 13 deletions(-) diff --git a/rust-toolchain b/rust-toolchain index 7d80f30..07ade69 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2022-08-23 \ No newline at end of file +nightly \ No newline at end of file diff --git a/src/hash.rs b/src/hash.rs index ed6baa5..aa03cb3 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -588,6 +588,7 @@ impl Chip for PoseidonHashChip<'_, Fp, ST #[cfg(test)] mod tests { use super::*; + use halo2_proofs::ff::Field; use halo2_proofs::halo2curves::group::ff::PrimeField; use halo2_proofs::{circuit::SimpleFloorPlanner, plonk::Circuit}; @@ -623,7 +624,7 @@ mod tests { Fr::from_str_vartime("1").unwrap(), Fr::from_str_vartime("2").unwrap(), Fr::from_str_vartime("3").unwrap(), - FrZERO, + Fr::ZERO, ]; let supposed_bytes = 50u64; @@ -716,7 +717,7 @@ mod tests { Fr::from_str_vartime("2").unwrap(), ]; - let message2 = [Fr::from_str_vartime("50331648").unwrap(), FrZERO]; + let message2 = [Fr::from_str_vartime("50331648").unwrap(), Fr::ZERO]; let k = 8; let circuit = PoseidonHashTable { @@ -729,7 +730,7 @@ mod tests { let circuit = PoseidonHashTable { inputs: vec![message1, message2, message1], - controls: vec![Fr::from_u128(64), Fr::from_u128(32), FrZERO], + controls: vec![Fr::from_u128(64), Fr::from_u128(32), Fr::ZERO], checks: Vec::new(), }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); diff --git a/src/poseidon/primitives/bn256/mod.rs b/src/poseidon/primitives/bn256/mod.rs index efc14fb..594dec7 100644 --- a/src/poseidon/primitives/bn256/mod.rs +++ b/src/poseidon/primitives/bn256/mod.rs @@ -25,6 +25,8 @@ impl P128Pow5T3Constants for Fp { mod tests { use std::marker::PhantomData; + use halo2_proofs::ff::{Field, FromUniformBytes}; + use crate::poseidon::primitives::p128pow5t3::P128Pow5T3; use crate::poseidon::primitives::Spec; @@ -41,7 +43,7 @@ mod tests { } } - impl Spec for P128Pow5T3Gen { + impl + Ord> Spec for P128Pow5T3Gen { fn full_rounds() -> usize { P128Pow5T3::::full_rounds() } diff --git a/src/poseidon/primitives/mds.rs b/src/poseidon/primitives/mds.rs index 551ee07..0461599 100644 --- a/src/poseidon/primitives/mds.rs +++ b/src/poseidon/primitives/mds.rs @@ -77,7 +77,7 @@ pub(super) fn generate_mds + Ord, const T: usize>( let mut mds_inv = [[F::ZERO; T]; T]; let l = |xs: &[F], j, x: F| { let x_j = xs[j]; - xs.iter().enumerate().fold(F::ZERO, |acc, (m, x_m)| { + xs.iter().enumerate().fold(F::ONE, |acc, (m, x_m)| { if m == j { acc } else { @@ -99,6 +99,8 @@ pub(super) fn generate_mds + Ord, const T: usize>( #[cfg(test)] mod tests { + use halo2_proofs::ff::Field; + use super::super::pasta::Fp; use super::{generate_mds, Grain}; diff --git a/src/poseidon/primitives/p128pow5t3.rs b/src/poseidon/primitives/p128pow5t3.rs index 0a159d7..95f59e5 100644 --- a/src/poseidon/primitives/p128pow5t3.rs +++ b/src/poseidon/primitives/p128pow5t3.rs @@ -49,8 +49,7 @@ impl + Ord> Spec for P1 mod tests { use std::marker::PhantomData; - use halo2_proofs::ff::PrimeField; - use halo2_proofs::halo2curves::group::ff::PrimeField; + use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use super::super::pasta::{fp, test_vectors, Fp}; use crate::poseidon::primitives::{permute, ConstantLength, Hash, Spec}; @@ -68,7 +67,9 @@ mod tests { } } - impl Spec for P128Pow5T3Gen { + impl + Ord, const SECURE_MDS: usize> Spec + for P128Pow5T3Gen + { fn full_rounds() -> usize { 8 } @@ -88,7 +89,7 @@ mod tests { #[test] fn verify_constants() { - fn verify_constants_helper( + fn verify_constants_helper + Ord>( expected_round_constants: [[F; 3]; 64], expected_mds: [[F; 3]; 3], expected_mds_inv: [[F; 3]; 3], diff --git a/src/poseidon/primitives/pasta/mod.rs b/src/poseidon/primitives/pasta/mod.rs index afcb67b..0ff9ae7 100644 --- a/src/poseidon/primitives/pasta/mod.rs +++ b/src/poseidon/primitives/pasta/mod.rs @@ -29,7 +29,7 @@ fn sqrt_tonelli_shanks>(f: &F, tm1d2: S) -> subtl let mut b = x * w; // Initialize z as the 2^S root of unity. - let mut z = F::root_of_unity(); + let mut z = F::ROOT_OF_UNITY; for max_v in (1..=F::S).rev() { let mut k = 1; diff --git a/tests/hash_proving.rs b/tests/hash_proving.rs index ee148b9..b519e13 100644 --- a/tests/hash_proving.rs +++ b/tests/hash_proving.rs @@ -13,6 +13,7 @@ use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::transcript::{ Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }; +use halo2_proofs::SerdeFormat; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, plonk::{Circuit, ConstraintSystem, Error}, @@ -78,7 +79,7 @@ fn vk_validity() { let vk1 = keygen_vk(¶ms, &circuit).unwrap(); let mut vk1_buf: Vec = Vec::new(); - vk1.write(&mut vk1_buf).unwrap(); + vk1.write(&mut vk1_buf, SerdeFormat::RawBytes).unwrap(); let circuit = TestCircuit( PoseidonHashTable { @@ -99,7 +100,7 @@ fn vk_validity() { let vk2 = keygen_vk(¶ms, &circuit).unwrap(); let mut vk2_buf: Vec = Vec::new(); - vk2.write(&mut vk2_buf).unwrap(); + vk2.write(&mut vk2_buf, SerdeFormat::RawBytes).unwrap(); assert_eq!(vk1_buf, vk2_buf); } From fd91bb78ead6a8cb3648861554976f57a29ae538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Nicolas?= Date: Mon, 20 Mar 2023 21:22:21 +0100 Subject: [PATCH 3/5] halo2-ecc-snark-verifier-0220: fixes after merge --- src/hash.rs | 4 ++-- src/poseidon.rs | 4 ++-- src/poseidon/primitives/p128pow5t3_compact.rs | 19 ++++++++++--------- src/septidon/util.rs | 16 ++++++++-------- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/hash.rs b/src/hash.rs index 326064d..d0c1c94 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -173,7 +173,7 @@ impl> PoseidonHashConfig { vec![ s_enable.clone() * (ctrl + Expression::Constant(Fp::from_u128(step as u128)) - ctrl_prev), - s_enable * (Expression::Constant(Fp::one()) - ctrl_bool), + s_enable * (Expression::Constant(Fp::ONE) - ctrl_bool), ] }); @@ -278,7 +278,7 @@ impl PoseidonHashTable { for (a, b, c) in src { self.inputs.push([*a, *b]); self.checks.push(Some(*c)); - self.controls.push(Fp::zero()); + self.controls.push(Fp::ZERO); } } diff --git a/src/poseidon.rs b/src/poseidon.rs index 7e60816..b558aee 100644 --- a/src/poseidon.rs +++ b/src/poseidon.rs @@ -6,7 +6,7 @@ use std::marker::PhantomData; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter}, - ff::{Field, FromUniformBytes}, + ff::{Field, FromUniformBytes, PrimeField}, plonk::{ConstraintSystem, Error}, }; @@ -27,7 +27,7 @@ pub enum PaddedWord { } /// This trait is the interface to chips that implement a permutation. -pub trait PermuteChip: Chip + Clone + DebugT { +pub trait PermuteChip: Chip + Clone + DebugT { /// Configure the permutation chip. fn configure(meta: &mut ConstraintSystem) -> Self::Config; diff --git a/src/poseidon/primitives/p128pow5t3_compact.rs b/src/poseidon/primitives/p128pow5t3_compact.rs index f6db10c..d669525 100644 --- a/src/poseidon/primitives/p128pow5t3_compact.rs +++ b/src/poseidon/primitives/p128pow5t3_compact.rs @@ -1,7 +1,6 @@ +use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use std::marker::PhantomData; -use halo2_proofs::arithmetic::FieldExt; - pub use super::p128pow5t3::P128Pow5T3Constants; use super::{Mds, Spec}; @@ -13,7 +12,9 @@ pub struct P128Pow5T3CompactSpec { _marker: PhantomData, } -impl Spec for P128Pow5T3CompactSpec { +impl + Ord> Spec + for P128Pow5T3CompactSpec +{ fn full_rounds() -> usize { 8 } @@ -55,8 +56,8 @@ impl Spec for P128Pow5T3CompactSpec { } } -fn mat_mul(mat: &Mds, input: &[Fp; T]) -> [Fp; T] { - let mut out = [Fp::zero(); T]; +fn mat_mul(mat: &Mds, input: &[Fp; T]) -> [Fp; T] { + let mut out = [Fp::ZERO; T]; #[allow(clippy::needless_range_loop)] for i in 0..T { for j in 0..T { @@ -66,17 +67,17 @@ fn mat_mul(mat: &Mds, input: &[Fp; T]) -> [ out } -fn vec_accumulate(a: &mut [Fp; T], b: &[Fp; T]) { +fn vec_accumulate(a: &mut [Fp; T], b: &[Fp; T]) { for i in 0..T { a[i] += b[i]; } } -fn vec_remove_tail(a: &mut [Fp; T]) -> [Fp; T] { - let mut tail = [Fp::zero(); T]; +fn vec_remove_tail(a: &mut [Fp; T]) -> [Fp; T] { + let mut tail = [Fp::ZERO; T]; for i in 1..T { tail[i] = a[i]; - a[i] = Fp::zero(); + a[i] = Fp::ZERO; } tail } diff --git a/src/septidon/util.rs b/src/septidon/util.rs index 847e0ab..f7df926 100644 --- a/src/septidon/util.rs +++ b/src/septidon/util.rs @@ -90,11 +90,11 @@ pub mod matmul { /// Returns `when_true` when `selector == 1`, and returns `when_false` when /// `selector == 0`. `selector` needs to be boolean. pub mod select { - use halo2_proofs::{arithmetic::FieldExt, plonk::Expression}; + use halo2_proofs::{ff::PrimeField, plonk::Expression}; /// Returns the `when_true` expression when the selector is true, else /// returns the `when_false` expression. - pub fn expr( + pub fn expr( selector: Expression, when_true: Expression, when_false: Expression, @@ -105,25 +105,25 @@ pub mod select { /// Returns the `when_true` value when the selector is true, else returns /// the `when_false` value. - pub fn value(selector: F, when_true: F, when_false: F) -> F { - selector * when_true + (F::one() - selector) * when_false + pub fn value(selector: F, when_true: F, when_false: F) -> F { + selector * when_true + (F::ONE - selector) * when_false } } /// Gadget for boolean OR. pub mod or { - use halo2_proofs::{arithmetic::FieldExt, plonk::Expression}; + use halo2_proofs::{ff::PrimeField, plonk::Expression}; /// Return (a OR b), assuming a and b are boolean expressions. - pub fn expr(a: Expression, b: Expression) -> Expression { + pub fn expr(a: Expression, b: Expression) -> Expression { let one = Expression::Constant(F::from(1)); // a OR b <=> !(!a AND !b) one.clone() - ((one.clone() - a) * (one.clone() - b)) } /// Return (a OR b), assuming a and b are boolean values. - pub fn value(a: F, b: F) -> F { - let one = F::one(); + pub fn value(a: F, b: F) -> F { + let one = F::ONE; // a OR b <=> !(!a AND !b) one - ((one - a) * (one - b)) } From 6c2c7c449b958976c46a00b774b8cfcf85a94793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Nicolas?= Date: Tue, 21 Mar 2023 01:46:43 +0100 Subject: [PATCH 4/5] Remove merged cargo patches --- Cargo.toml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 236b44d..d9af5b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,16 +14,6 @@ bitvec = "1" [patch."https://github.com/privacy-scaling-explorations/halo2.git"] halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "halo2-ecc-snark-verifier-0220" } -# remove once -# https://github.com/privacy-scaling-explorations/poseidon/pull/7 -# https://github.com/privacy-scaling-explorations/halo2curves/pull/31 -# are merged -[patch."https://github.com/privacy-scaling-explorations/poseidon.git"] -poseidon = { git = "https://github.com/scroll-tech/poseidon.git", branch = "halo2-ecc-snark-verifier-0220" } - -[patch."https://github.com/privacy-scaling-explorations/halo2curves.git"] -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 = [] From 8deed292a2c0930a85e555c8d42e9c71392b576d Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Sat, 8 Apr 2023 15:07:34 +0800 Subject: [PATCH 5/5] update for septidon refactoring --- src/hash.rs | 2 +- src/poseidon.rs | 10 +++++++--- src/poseidon/pow5.rs | 12 +++++++----- src/poseidon/primitives/p128pow5t3.rs | 6 +++--- src/poseidon/septidon/control.rs | 14 +++++++------- src/poseidon/septidon/instruction.rs | 4 ++-- src/poseidon/septidon/loop_chip.rs | 4 ++-- src/poseidon/septidon/params.rs | 9 ++++++--- src/poseidon/septidon/state.rs | 20 ++++++++++---------- src/poseidon/septidon/transition_round.rs | 4 ++-- src/poseidon/septidon/util.rs | 22 +++++++++++----------- tests/hash_proving.rs | 1 - 12 files changed, 58 insertions(+), 50 deletions(-) diff --git a/src/hash.rs b/src/hash.rs index 61ecafc..3398496 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -43,7 +43,7 @@ pub use chip_long::*; pub use chip_short::*; /// indicate an field can be hashed in merkle tree (2 Fields to 1 Field) -pub trait Hashable: Hashablebase + FromUniformBytes<64> + Ord{ +pub trait Hashable: Hashablebase + FromUniformBytes<64> + Ord { /// the spec type used in circuit for this hashable field type SpecType: Spec; /// the domain type used for hash calculation diff --git a/src/poseidon.rs b/src/poseidon.rs index d91036a..12b2aa3 100644 --- a/src/poseidon.rs +++ b/src/poseidon.rs @@ -6,7 +6,7 @@ use std::marker::PhantomData; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter}, - ff::{Field, FromUniformBytes, PrimeField}, + ff::{Field, FromUniformBytes}, plonk::{ConstraintSystem, Error}, }; @@ -30,8 +30,12 @@ pub enum PaddedWord { } /// This trait is the interface to chips that implement a permutation. -pub trait PermuteChip, const T: usize, const RATE: usize>: - Chip + Clone + DebugT + PoseidonInstructions +pub trait PermuteChip< + F: FromUniformBytes<64> + Ord, + S: Spec, + const T: usize, + const RATE: usize, +>: Chip + Clone + DebugT + PoseidonInstructions { /// Configure the permutation chip. fn configure(meta: &mut ConstraintSystem) -> Self::Config; diff --git a/src/poseidon/pow5.rs b/src/poseidon/pow5.rs index 21a3a36..b15a9be 100644 --- a/src/poseidon/pow5.rs +++ b/src/poseidon/pow5.rs @@ -260,7 +260,9 @@ impl Chip for Pow5Chip< } } -impl> PermuteChip for Pow5Chip { +impl + Ord, S: Spec> PermuteChip + for Pow5Chip +{ fn configure(meta: &mut ConstraintSystem) -> Self::Config { let state = [0; 3].map(|_| meta.advice_column()); let partial_sbox = meta.advice_column(); @@ -521,7 +523,7 @@ impl Pow5State { self.0.iter().enumerate().map(|(idx, word)| { word.value() + Value::known(config.round_constants[round][idx]) }); - let r: Vec> = q.map(|q| q.map(|q| q.pow(&config.alpha))).collect(); + let r: Vec> = q.map(|q| q.map(|q| q.pow(config.alpha))).collect(); let m = &config.m_reg; let state = m.iter().map(|m_i| { r.iter() @@ -556,7 +558,7 @@ impl Pow5State { .map(|(idx, word)| { word.value() .map(|v| v + config.round_constants[round][idx]) - .map(|v| if idx == 0 { v.pow(&config.alpha) } else { v }) + .map(|v| if idx == 0 { v.pow(config.alpha) } else { v }) }) .collect(); @@ -586,7 +588,7 @@ impl Pow5State { let p: Vec<_> = self.0.iter().map(|word| word.value()).collect(); let r_0 = (p[0] + Value::known(config.round_constants[round][0])) - .map(|v| v.pow(&config.alpha)); + .map(|v| v.pow(config.alpha)); let r_i = p[1..] .iter() .enumerate() @@ -625,7 +627,7 @@ impl Pow5State { } let r_0 = (p_mid[0] + Value::known(config.round_constants[round + 1][0])) - .map(|v| v.pow(&config.alpha)); + .map(|v| v.pow(config.alpha)); let r_i = p_mid[1..] .iter() .enumerate() diff --git a/src/poseidon/primitives/p128pow5t3.rs b/src/poseidon/primitives/p128pow5t3.rs index 6fe64d0..9b10724 100644 --- a/src/poseidon/primitives/p128pow5t3.rs +++ b/src/poseidon/primitives/p128pow5t3.rs @@ -1,10 +1,10 @@ -use halo2_proofs::ff::{FromUniformBytes, PrimeField}; +use halo2_proofs::ff::FromUniformBytes; use std::marker::PhantomData; use super::{Mds, Spec}; /// The trait required for fields can handle a pow5 sbox, 3 field, 2 rate permutation -pub trait P128Pow5T3Constants: PrimeField { +pub trait P128Pow5T3Constants: FromUniformBytes<64> + Ord { fn partial_rounds() -> usize { 56 } @@ -24,7 +24,7 @@ pub struct P128Pow5T3 { _marker: PhantomData, } -impl + Ord> Spec for P128Pow5T3 { +impl Spec for P128Pow5T3 { fn full_rounds() -> usize { 8 } diff --git a/src/poseidon/septidon/control.rs b/src/poseidon/septidon/control.rs index 4bff20d..ea7f2f6 100644 --- a/src/poseidon/septidon/control.rs +++ b/src/poseidon/septidon/control.rs @@ -1,7 +1,7 @@ use super::params::GATE_DEGREE_5; use super::util::query; -use halo2_proofs::arithmetic::FieldExt; use halo2_proofs::circuit::{Region, Value}; +use halo2_proofs::ff::PrimeField; //use halo2_proofs::halo2curves::bn256::Fr as F; use halo2_proofs::plonk::{Column, ConstraintSystem, Error, Expression, Fixed, VirtualCells}; use halo2_proofs::poly::Rotation; @@ -11,7 +11,7 @@ pub struct ControlChip { is_last: Column, } -pub struct ControlSignals { +pub struct ControlSignals { // Signals that control the switches between steps of the permutation. pub break_full_rounds: Expression, pub transition_round: Expression, @@ -22,7 +22,7 @@ pub struct ControlSignals { } impl ControlChip { - pub fn configure(cs: &mut ConstraintSystem) -> (Self, ControlSignals) { + pub fn configure(cs: &mut ConstraintSystem) -> (Self, ControlSignals) { let is_last = cs.fixed_column(); let signals = query(cs, |meta| { @@ -43,18 +43,18 @@ impl ControlChip { } /// Assign the fixed positions of the last row of permutations. - pub fn assign(&self, region: &mut Region<'_, F>) -> Result<(), Error> { - region.assign_fixed(|| "", self.is_last, 7, || Value::known(F::one()))?; + pub fn assign(&self, region: &mut Region<'_, F>) -> Result<(), Error> { + region.assign_fixed(|| "", self.is_last, 7, || Value::known(F::ONE))?; Ok(()) } - fn derive_selector( + fn derive_selector( is_last: Column, meta: &mut VirtualCells<'_, F>, ) -> Expression { if GATE_DEGREE_5 { // Variant with no selector. Do not disable gates, do not increase the gate degree. - Expression::Constant(F::one()) + Expression::Constant(F::ONE) } else { // Variant with a selector enabled on all rows of valid permutations. // Detect is_last=1, seen from its own row or up to 7 rows below. diff --git a/src/poseidon/septidon/instruction.rs b/src/poseidon/septidon/instruction.rs index ac721bb..a79ff0e 100644 --- a/src/poseidon/septidon/instruction.rs +++ b/src/poseidon/septidon/instruction.rs @@ -3,7 +3,7 @@ use super::super::{ PermuteChip, PoseidonInstructions, StateWord, Var, }; use super::{params::CachedConstants, util::map_array, SeptidonChip}; -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ circuit::{Chip, Layouter}, plonk::{ConstraintSystem, Error}, @@ -83,7 +83,7 @@ impl> PoseidonInstructions Chip for SeptidonChip { +impl Chip for SeptidonChip { type Config = Self; type Loaded = (); diff --git a/src/poseidon/septidon/loop_chip.rs b/src/poseidon/septidon/loop_chip.rs index bc933da..edea789 100644 --- a/src/poseidon/septidon/loop_chip.rs +++ b/src/poseidon/septidon/loop_chip.rs @@ -1,6 +1,6 @@ use super::state::Cell; use super::util::select; -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::PrimeField; //use halo2_proofs::halo2curves::bn256::Fr as F; use halo2_proofs::plonk::{ConstraintSystem, Constraints, Expression}; @@ -14,7 +14,7 @@ pub struct LoopBody { } impl LoopChip { - pub fn configure( + pub fn configure( cs: &mut ConstraintSystem, q: Expression, body: LoopBody, diff --git a/src/poseidon/septidon/params.rs b/src/poseidon/septidon/params.rs index 823f2bb..c0ab520 100644 --- a/src/poseidon/septidon/params.rs +++ b/src/poseidon/septidon/params.rs @@ -16,14 +16,17 @@ pub trait CachedConstants: P128Pow5T3Constants { pub mod sbox { use super::super::util::pow_5; - use halo2_proofs::arithmetic::FieldExt; + use halo2_proofs::ff::PrimeField; use halo2_proofs::plonk::Expression; - pub fn expr(input: Expression, round_constant: Expression) -> Expression { + pub fn expr( + input: Expression, + round_constant: Expression, + ) -> Expression { pow_5::expr(input + round_constant) } - pub fn value(input: F, round_constant: F) -> F { + pub fn value(input: F, round_constant: F) -> F { pow_5::value(input + round_constant) } } diff --git a/src/poseidon/septidon/state.rs b/src/poseidon/septidon/state.rs index b0faee7..ba750d5 100644 --- a/src/poseidon/septidon/state.rs +++ b/src/poseidon/septidon/state.rs @@ -1,7 +1,7 @@ use super::params; use halo2_proofs::circuit::{Region, Value}; //use halo2_proofs::halo2curves::bn256::Fr as F; -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::PrimeField; use halo2_proofs::plonk::{ Advice, Column, ConstraintSystem, Error, Expression, Fixed, VirtualCells, }; @@ -17,7 +17,7 @@ pub struct Cell { } impl Cell { - pub fn configure(cs: &mut ConstraintSystem) -> Self { + pub fn configure(cs: &mut ConstraintSystem) -> Self { Cell { column: cs.advice_column(), offset: 0, @@ -35,7 +35,7 @@ impl Cell { } } - pub fn query(&self, meta: &mut VirtualCells, offset: i32) -> Expression { + pub fn query(&self, meta: &mut VirtualCells, offset: i32) -> Expression { meta.query_advice(self.column, Rotation(self.offset + offset)) } @@ -44,7 +44,7 @@ impl Cell { self.offset as usize } - pub fn assign( + pub fn assign( &self, region: &mut Region<'_, F>, origin_offset: usize, @@ -64,7 +64,7 @@ pub struct SBox { } impl SBox { - pub fn configure(cs: &mut ConstraintSystem) -> Self { + pub fn configure(cs: &mut ConstraintSystem) -> Self { SBox { input: Cell::configure(cs), round_constant: cs.fixed_column(), @@ -72,7 +72,7 @@ impl SBox { } /// Assign the witness of the input. - pub fn assign( + pub fn assign( &self, region: &mut Region<'_, F>, offset: usize, @@ -95,15 +95,15 @@ impl SBox { Ok(output) } - pub fn input_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { + pub fn input_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { self.input.query(meta, 0) } - pub fn rc_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { + pub fn rc_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { meta.query_fixed(self.round_constant, Rotation(self.input.offset)) } - pub fn output_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { + pub fn output_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { let input = self.input_expr(meta); let round_constant = self.rc_expr(meta); params::sbox::expr(input, round_constant) @@ -114,7 +114,7 @@ impl SBox { pub struct FullState(pub [SBox; 3]); impl FullState { - pub fn configure(cs: &mut ConstraintSystem) -> Self { + pub fn configure(cs: &mut ConstraintSystem) -> Self { Self([ SBox::configure(cs), SBox::configure(cs), diff --git a/src/poseidon/septidon/transition_round.rs b/src/poseidon/septidon/transition_round.rs index ab55e7f..01bacac 100644 --- a/src/poseidon/septidon/transition_round.rs +++ b/src/poseidon/septidon/transition_round.rs @@ -96,7 +96,7 @@ impl TransitionRoundChip { cell.assign(region, middle_break_offset, value)?; } self.helper_cell() - .assign(region, middle_break_offset, Value::known(F::zero()))?; + .assign(region, middle_break_offset, Value::known(F::ZERO))?; Ok(output) } @@ -121,7 +121,7 @@ impl TransitionRoundChip { cell.assign(region, final_break_offset, value)?; } self.helper_cell() - .assign(region, final_break_offset, Value::known(F::zero()))?; + .assign(region, final_break_offset, Value::known(F::ZERO))?; Ok(()) } } diff --git a/src/poseidon/septidon/util.rs b/src/poseidon/septidon/util.rs index 4a10c7a..b7f4b30 100644 --- a/src/poseidon/septidon/util.rs +++ b/src/poseidon/septidon/util.rs @@ -1,6 +1,6 @@ use halo2_proofs::circuit::Value; //use halo2_proofs::halo2curves::bn256::Fr as F; -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::PrimeField; use halo2_proofs::plonk::{ConstraintSystem, Expression, VirtualCells}; pub fn map_array(array: &[IN; 3], mut f: FN) -> [OUT; 3] @@ -14,26 +14,26 @@ where } /// Helper to make queries to a ConstraintSystem. Escape the "create_gate" closures. -pub fn query( +pub fn query( cs: &mut ConstraintSystem, f: impl FnOnce(&mut VirtualCells<'_, F>) -> T, ) -> T { let mut queries: Option = None; cs.create_gate("query", |meta| { queries = Some(f(meta)); - [Expression::Constant(F::zero())] + [Expression::Constant(F::ZERO)] }); queries.unwrap() } -pub fn join_values(values: [Value; 3]) -> Value<[F; 3]> { +pub fn join_values(values: [Value; 3]) -> Value<[F; 3]> { values[0] .zip(values[1]) .zip(values[2]) .map(|((v0, v1), v2)| [v0, v1, v2]) } -pub fn split_values(values: Value<[F; 3]>) -> [Value; 3] { +pub fn split_values(values: Value<[F; 3]>) -> [Value; 3] { [ values.map(|v| v[0]), values.map(|v| v[1]), @@ -42,15 +42,15 @@ pub fn split_values(values: Value<[F; 3]>) -> [Value; 3] { } pub mod pow_5 { - use super::FieldExt; + use super::PrimeField; use halo2_proofs::plonk::Expression; - pub fn expr(v: Expression) -> Expression { + pub fn expr(v: Expression) -> Expression { let v2 = v.clone() * v.clone(); v2.clone() * v2 * v } - pub fn value(v: F) -> F { + pub fn value(v: F) -> F { let v2 = v * v; v2 * v2 * v } @@ -59,12 +59,12 @@ pub mod pow_5 { /// Matrix multiplication expressions and values. pub mod matmul { use super::super::params::Mds; - use super::FieldExt; + use super::PrimeField; use halo2_proofs::plonk::Expression; use std::convert::TryInto; /// Multiply a vector of expressions by a constant matrix. - pub fn expr(matrix: &Mds, vector: [Expression; 3]) -> [Expression; 3] { + pub fn expr(matrix: &Mds, vector: [Expression; 3]) -> [Expression; 3] { (0..3) .map(|next_idx| { (0..3) @@ -78,7 +78,7 @@ pub mod matmul { } /// Multiply a vector of values by a constant matrix. - pub fn value(matrix: &Mds, vector: [F; 3]) -> [F; 3] { + pub fn value(matrix: &Mds, vector: [F; 3]) -> [F; 3] { (0..3) .map(|next_idx| { (0..3) diff --git a/tests/hash_proving.rs b/tests/hash_proving.rs index fbe2c70..c8becca 100644 --- a/tests/hash_proving.rs +++ b/tests/hash_proving.rs @@ -13,7 +13,6 @@ use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::transcript::{ Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }; -use halo2_proofs::SerdeFormat; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, plonk::{Circuit, ConstraintSystem, Error},