diff --git a/Cargo.toml b/Cargo.toml index 3c5e630..3061179 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +ff = "0.13.0" halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } lazy_static = "1.4.0" thiserror = "1.0" @@ -15,7 +16,7 @@ rand_xorshift = "0.3.0" rand = "0.8" [patch."https://github.com/privacy-scaling-explorations/halo2.git"] -halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "develop" } +halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "sync-halo2-lib-0.4.0" } [features] default = ["halo2_proofs/parallel_syn", "short"] diff --git a/src/hash.rs b/src/hash.rs index 7a5989f..6e91a68 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -1,9 +1,10 @@ //! The hash circuit base on poseidon. use crate::poseidon::primitives::{ConstantLengthIden3, Domain, Hash, Spec, VariableLengthIden3}; +use ff::{FromUniformBytes, PrimeField}; +use halo2_proofs::circuit::AssignedCell; use halo2_proofs::halo2curves::bn256::Fr; use halo2_proofs::plonk::Fixed; -use halo2_proofs::{arithmetic::FieldExt, circuit::AssignedCell}; use log; use std::time::Instant; @@ -45,7 +46,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 { +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 @@ -54,7 +55,7 @@ pub trait Hashable: Hashablebase { /// execute hash for any sequence of fields #[deprecated] fn hash(inp: [Self; 2]) -> Self { - Self::hash_with_domain(inp, Self::zero()) + Self::hash_with_domain(inp, Self::ZERO) } /// execute hash for any sequence of fields, with domain being specified @@ -126,7 +127,7 @@ use std::fmt::Debug as DebugT; /// The config for poseidon hash circuit #[derive(Clone, Debug)] -pub struct SpongeConfig + Clone + DebugT> { +pub struct SpongeConfig + Clone + DebugT> { permute_config: PC::Config, hash_table: [Column; 6], hash_table_aux: [Column; 6], @@ -201,13 +202,11 @@ impl> SpongeConfig { vec![ q_enable.clone() * s_continue.clone() - * (Expression::Constant(F::one()) - s_continue.clone()), - q_enable.clone() * ctrl * (Expression::Constant(F::one()) - ctrl_bool.clone()), - q_enable.clone() - * s_continue.clone() - * (Expression::Constant(F::one()) - ctrl_bool), + * (Expression::Constant(F::ONE) - s_continue.clone()), + q_enable.clone() * ctrl * (Expression::Constant(F::ONE) - ctrl_bool.clone()), + q_enable.clone() * s_continue.clone() * (Expression::Constant(F::ONE) - ctrl_bool), q_enable - * (Expression::Constant(F::one()) + * (Expression::Constant(F::ONE) - s_continue - meta.query_advice(header_mark, Rotation::cur())), ] @@ -230,7 +229,7 @@ impl> SpongeConfig { * (ctrl + Expression::Constant(F::from_u128(step as u128 * HASHABLE_DOMAIN_SPEC)) - ctrl_prev), - q_enable * (Expression::Constant(F::one()) - ctrl_bool), + q_enable * (Expression::Constant(F::ONE) - ctrl_bool), ] }); @@ -251,7 +250,7 @@ impl> SpongeConfig { vec![ q_enable.clone() * s_continue_hash.clone() * (hash_ind - hash_prev.clone()), q_enable - * (Expression::Constant(F::one()) - s_continue_hash) + * (Expression::Constant(F::ONE) - s_continue_hash) * (hash_out - hash_prev), ] }); @@ -284,7 +283,7 @@ impl> SpongeConfig { // hash output: must inherit prev state or apply current control flag (for new hash) ret.push( q_enable.clone() - * (Expression::Constant(F::one()) - s_continue_hash.clone()) + * (Expression::Constant(F::ONE) - s_continue_hash.clone()) * (inp_hash.clone() - inp_hash_init), ); ret.push(q_enable * s_continue_hash * (inp_hash - inp_hash_prev - doman_spec)); @@ -320,7 +319,7 @@ pub struct PoseidonHashTable { pub checks: Vec>, } -impl PoseidonHashTable { +impl PoseidonHashTable { /// Add common inputs #[deprecated] pub fn constant_inputs<'d>(&mut self, src: impl IntoIterator) { @@ -412,7 +411,7 @@ impl PoseidonHashTable { /// Represent the chip for Poseidon hash table #[derive(Debug)] -pub struct SpongeChip<'d, F: FieldExt, const STEP: usize, PC: Chip + Clone + DebugT> +pub struct SpongeChip<'d, F: PrimeField, const STEP: usize, PC: Chip + Clone + DebugT> where PC::Config: Sync, { @@ -457,7 +456,7 @@ where ), ] { for col in cols { - region.assign_advice(|| tip, *col, 0, || Value::known(F::zero()))?; + region.assign_advice(|| tip, *col, 0, || Value::known(F::ZERO))?; } } @@ -506,7 +505,7 @@ where let mut is_new_sponge = true; let mut process_start = 0; - let mut state: [F; 3] = [F::zero(); 3]; + let mut state: [F; 3] = [F::ZERO; 3]; let mut last_offset = 0; for (i, ((inp, control), (domain, check))) in inputs_i @@ -515,7 +514,7 @@ where .enumerate() { let control = control.copied().unwrap_or(0); - let domain = domain.copied().unwrap_or_else(F::zero); + let domain = domain.copied().unwrap_or(F::ZERO); let offset = i + begin_offset; last_offset = offset; @@ -528,7 +527,7 @@ where let inp = inp .map(|[a, b]| [*a, *b]) - .unwrap_or_else(|| [F::zero(), F::zero()]); + .unwrap_or_else(|| [F::ZERO, F::ZERO]); state.iter_mut().skip(1).zip(inp).for_each(|(s, inp)| { if is_new_sponge { @@ -556,7 +555,7 @@ where || "assign q_enable", self.config.q_enable, offset, - || Value::known(F::one()), + || Value::known(F::ONE), )?; let c_start = [0; 3] @@ -593,17 +592,17 @@ where ( "state beginning flag", config.hash_table[5], - if is_new_sponge { F::one() } else { F::zero() }, + if is_new_sponge { F::ONE } else { F::ZERO }, ), ( "state input control_aux", config.control_aux, - control_as_flag.invert().unwrap_or_else(F::zero), + control_as_flag.invert().unwrap_or(F::ZERO), ), ( "state continue control", config.s_sponge_continue, - if is_new_sponge { F::zero() } else { F::one() }, + if is_new_sponge { F::ZERO } else { F::ONE }, ), ] { region.assign_advice( @@ -662,7 +661,7 @@ where // any advice that we access in this region can be used config.hash_table_aux[0], data.len() - 1, - || Value::known(F::zero()), + || Value::known(F::ZERO), )?; *is_first_pass = false; return Ok((states_in, states_out)); @@ -672,11 +671,11 @@ where let mut is_new_sponge = true; let mut process_start = 0; - let mut state = [F::zero(); 3]; + let mut state = [F::ZERO; 3]; for (i, ((inp, control), (domain, check))) in data.iter().enumerate() { let control = control.copied().unwrap_or(0u64); - let domain = domain.copied().unwrap_or_else(F::zero); + let domain = domain.copied().unwrap_or(F::ZERO); let offset = i; let control_as_flag = F::from_u128(control as u128 * HASHABLE_DOMAIN_SPEC); @@ -688,7 +687,7 @@ where let inp = inp .map(|[a, b]| [*a, *b]) - .unwrap_or_else(|| [F::zero(), F::zero()]); + .unwrap_or_else(|| [F::ZERO, F::ZERO]); state.iter_mut().skip(1).zip(inp).for_each(|(s, inp)| { if is_new_sponge { @@ -716,7 +715,7 @@ where || "assign q_enable", self.config.q_enable, offset, - || Value::known(F::one()), + || Value::known(F::ONE), )?; let c_start = [0; 3] @@ -753,17 +752,17 @@ where ( "state beginning flag", config.hash_table[5], - if is_new_sponge { F::one() } else { F::zero() }, + if is_new_sponge { F::ONE } else { F::ZERO }, ), ( "state input control_aux", config.control_aux, - control_as_flag.invert().unwrap_or_else(F::zero), + control_as_flag.invert().unwrap_or(F::ZERO), ), ( "state continue control", config.s_sponge_continue, - if is_new_sponge { F::zero() } else { F::one() }, + if is_new_sponge { F::ZERO } else { F::ONE }, ), ] { region.assign_advice( @@ -978,7 +977,7 @@ where } } -impl + Clone + DebugT> Chip +impl + Clone + DebugT> Chip for SpongeChip<'_, F, STEP, PC> where PC::Config: Sync, diff --git a/src/poseidon.rs b/src/poseidon.rs index ebce53d..989c6f9 100644 --- a/src/poseidon.rs +++ b/src/poseidon.rs @@ -4,8 +4,8 @@ use std::convert::TryInto; use std::fmt; use std::marker::PhantomData; +use ff::{Field, FromUniformBytes}; use halo2_proofs::{ - arithmetic::{Field, FieldExt}, circuit::{AssignedCell, Chip, Layouter}, 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; @@ -41,8 +45,12 @@ pub trait PermuteChip, const T: usize, const RA } /// 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 @@ -76,7 +84,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, @@ -102,7 +110,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, @@ -112,7 +120,7 @@ pub struct Word< } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonInstructions, S: Spec, const T: usize, @@ -131,7 +139,7 @@ impl< } fn poseidon_sponge< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -153,7 +161,7 @@ fn poseidon_sponge< /// A Poseidon sponge. #[derive(Debug)] pub struct Sponge< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, M: SpongeMode, @@ -168,7 +176,7 @@ pub struct Sponge< } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -241,7 +249,7 @@ impl< } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -272,7 +280,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, @@ -283,7 +291,7 @@ pub struct Hash< } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -298,7 +306,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 6de70e4..b31e7b6 100644 --- a/src/poseidon/pow5.rs +++ b/src/poseidon/pow5.rs @@ -1,8 +1,8 @@ use std::convert::TryInto; use std::iter; +use ff::{FromUniformBytes, PrimeField}; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{AssignedCell, Cell, Chip, Layouter, Region, Value}, 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(Clone, 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,9 @@ impl Pow5Chip Chip for Pow5Chip { +impl + Ord, const WIDTH: usize, const RATE: usize> Chip + for Pow5Chip +{ type Config = Pow5Config; type Loaded = (); @@ -258,7 +262,9 @@ impl Chip for Pow5Chip> 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(); @@ -278,8 +284,12 @@ impl> PermuteChip 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; @@ -345,7 +355,7 @@ impl, const WIDTH: usize, const RATE: usize } impl< - F: FieldExt, + F: FromUniformBytes<64> + Ord, S: Spec, D: Domain, const WIDTH: usize, @@ -374,7 +384,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())?; @@ -475,21 +485,21 @@ impl< /// A word in the Poseidon state. #[derive(Clone, Debug)] -pub struct StateWord(pub AssignedCell); +pub struct StateWord(pub 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() } @@ -500,9 +510,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, @@ -520,7 +530,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 }) }); @@ -558,7 +568,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 }) }); @@ -599,7 +609,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 }) }) @@ -631,7 +641,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 fe439fb..0a54f95 100644 --- a/src/poseidon/primitives.rs +++ b/src/poseidon/primitives.rs @@ -5,10 +5,8 @@ use std::fmt; use std::iter; use std::marker::PhantomData; -use halo2_proofs::arithmetic::FieldExt; +use ff::FromUniformBytes; -//pub(crate) mod fp; -//pub(crate) mod fq; pub(crate) mod grain; pub(crate) mod mds; @@ -42,7 +40,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. @@ -70,7 +70,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())) @@ -88,7 +88,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]], @@ -97,7 +102,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 { @@ -135,7 +140,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, @@ -193,7 +203,7 @@ impl Absorbing { /// A Poseidon sponge. pub(crate) struct Sponge< - F: FieldExt, + F: FromUniformBytes<64> + Ord, S: Spec, M: SpongeMode, const T: usize, @@ -207,7 +217,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. @@ -215,7 +225,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 { @@ -272,7 +282,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. @@ -296,7 +306,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 + Ord, const RATE: usize> { /// Iterator that outputs padding field elements. type Padding: IntoIterator; @@ -323,7 +333,9 @@ pub trait Domain { #[derive(Clone, Copy, Debug)] pub struct ConstantLength; -impl Domain for ConstantLength { +impl + Ord, const RATE: usize, const L: usize> Domain + for ConstantLength +{ type Padding = iter::Take>; fn name() -> String { @@ -343,7 +355,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) } } @@ -351,7 +363,9 @@ impl Domain for Constan #[derive(Clone, Copy, Debug)] pub struct ConstantLengthIden3; -impl Domain for ConstantLengthIden3 { +impl + Ord, const RATE: usize, const L: usize> Domain + for ConstantLengthIden3 +{ type Padding = as Domain>::Padding; fn name() -> String { @@ -360,7 +374,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 { @@ -376,7 +390,7 @@ impl Domain for Constan #[derive(Clone, Copy, Debug)] pub struct VariableLengthIden3; -impl Domain for VariableLengthIden3 { +impl + Ord, const RATE: usize> Domain for VariableLengthIden3 { type Padding = as Domain>::Padding; fn name() -> String { @@ -390,7 +404,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 { @@ -400,7 +414,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, @@ -410,8 +424,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") @@ -424,8 +443,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 { @@ -441,8 +465,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 { @@ -456,8 +485,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], domain: F) -> F { @@ -473,7 +507,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. @@ -494,7 +528,6 @@ impl, const T: usize, const RATE: usize> #[cfg(test)] mod tests { use super::pasta::Fp; - use halo2_proofs::arithmetic::FieldExt; use super::{permute, ConstantLength, Hash, P128Pow5T3, P128Pow5T3Compact, Spec}; type OrchardNullifier = P128Pow5T3; @@ -510,7 +543,10 @@ mod tests { // The result should be equivalent to just directly applying the permutation and // taking the first state element as the output. - let mut state = [message[0], message[1], Fp::from_u128(2 << 64)]; + let mut two_to_sixty_five = Fp::from(1 << 63); + two_to_sixty_five = two_to_sixty_five.double(); + two_to_sixty_five = two_to_sixty_five.double(); + let mut state = [message[0], message[1], two_to_sixty_five]; permute::<_, OrchardNullifier, 3, 2>(&mut state, &mds, &round_constants); assert_eq!(state[0], result); } @@ -521,7 +557,10 @@ mod tests { let hasher = Hash::<_, OrchardNullifier, ConstantLength<2>, 3, 2>::init(); // The result should be equivalent to just directly applying the permutation and // taking the first state element as the output. - let mut state = [Fp::from(6), Fp::from(42), Fp::from_u128(2 << 64)]; + let mut two_to_sixty_five = Fp::from(1 << 63); + two_to_sixty_five = two_to_sixty_five.double(); + two_to_sixty_five = two_to_sixty_five.double(); + let mut state = [Fp::from(6), Fp::from(42), two_to_sixty_five]; hasher.permute(&mut state); diff --git a/src/poseidon/primitives/grain.rs b/src/poseidon/primitives/grain.rs index 6ed9bf5..4c8bce2 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 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 u8, Msb0), 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![u8, Msb0; 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..0b01f84 100644 --- a/src/poseidon/primitives/mds.rs +++ b/src/poseidon/primitives/mds.rs @@ -1,8 +1,8 @@ -use halo2_proofs::arithmetic::FieldExt; +use 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::ONE, |acc, (m, x_m)| { if m == j { acc } else { diff --git a/src/poseidon/primitives/p128pow5t3.rs b/src/poseidon/primitives/p128pow5t3.rs index 87e302d..b9dab2f 100644 --- a/src/poseidon/primitives/p128pow5t3.rs +++ b/src/poseidon/primitives/p128pow5t3.rs @@ -1,10 +1,11 @@ -use halo2_proofs::arithmetic::FieldExt; use std::marker::PhantomData; +use ff::FromUniformBytes; + use super::{Mds, Spec}; /// The trait required for fields can handle a pow5 sbox, 3 field, 2 rate permutation -pub trait P128Pow5T3Constants: FieldExt { +pub trait P128Pow5T3Constants: FromUniformBytes<64> + Ord { fn partial_rounds() -> usize { 56 } @@ -50,8 +51,7 @@ impl Spec for P128Pow5T3 { mod tests { use std::marker::PhantomData; - use halo2_proofs::arithmetic::FieldExt; - use halo2_proofs::halo2curves::group::ff::PrimeField; + use ff::{FromUniformBytes, PrimeField}; use super::super::pasta::{fp, test_vectors, Fp}; use crate::poseidon::primitives::{permute, ConstantLength, Hash, Spec}; @@ -59,17 +59,19 @@ 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 + Ord, const SECURE_MDS: usize> Spec + for P128Pow5T3Gen + { fn full_rounds() -> usize { 8 } @@ -89,7 +91,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/p128pow5t3_compact.rs b/src/poseidon/primitives/p128pow5t3_compact.rs index 0802d7a..43ed1c4 100644 --- a/src/poseidon/primitives/p128pow5t3_compact.rs +++ b/src/poseidon/primitives/p128pow5t3_compact.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use halo2_proofs::arithmetic::FieldExt; +use ff::{FromUniformBytes, PrimeField}; use super::p128pow5t3::P128Pow5T3Constants; use super::{Mds, Spec}; @@ -13,7 +13,9 @@ pub struct P128Pow5T3Compact { _marker: PhantomData, } -impl Spec for P128Pow5T3Compact { +impl + Ord> Spec + for P128Pow5T3Compact +{ fn full_rounds() -> usize { 8 } @@ -55,8 +57,8 @@ impl Spec for P128Pow5T3Compact { } } -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 +68,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/poseidon/primitives/pasta/mod.rs b/src/poseidon/primitives/pasta/mod.rs index 7293044..8fa1ec3 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; @@ -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::ONE); 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::ONE)); z = z.square(); b *= z; v = k; diff --git a/src/poseidon/septidon/control.rs b/src/poseidon/septidon/control.rs index f866ce7..307e750 100644 --- a/src/poseidon/septidon/control.rs +++ b/src/poseidon/septidon/control.rs @@ -1,8 +1,8 @@ use super::params::GATE_DEGREE_5; use super::util::query; -use halo2_proofs::arithmetic::FieldExt; + +use ff::PrimeField; use halo2_proofs::circuit::{Region, Value}; -//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,12 +43,12 @@ impl ControlChip { } /// Assign the fixed positions of the last row of permutations for a new region. - pub fn assign(&self, region: &mut Region<'_, F>) -> Result<(), Error> { + pub fn assign(&self, region: &mut Region<'_, F>) -> Result<(), Error> { self.assign_with_offset(region, 0) } /// Assign the fixed positions of the last row of permutations. - pub fn assign_with_offset( + pub fn assign_with_offset( &self, region: &mut Region<'_, F>, begin_offset: usize, @@ -57,18 +57,18 @@ impl ControlChip { || "", self.is_last, 7 + begin_offset, - || Value::known(F::one()), + || 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 fa1c9fc..acfd954 100644 --- a/src/poseidon/septidon/instruction.rs +++ b/src/poseidon/septidon/instruction.rs @@ -3,10 +3,8 @@ use super::super::{ PermuteChip, PoseidonInstructions, StateWord, Var, }; use super::{params::CachedConstants, util::map_array, SeptidonChip}; -use halo2_proofs::{ - arithmetic::FieldExt, - circuit::{Region, Value}, -}; +use ff::PrimeField; +use halo2_proofs::circuit::{Region, Value}; use halo2_proofs::{ circuit::{Chip, Layouter}, plonk::{ConstraintSystem, Error}, @@ -111,7 +109,7 @@ impl> PoseidonInstructions> 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..e1ee001 100644 --- a/src/poseidon/septidon/loop_chip.rs +++ b/src/poseidon/septidon/loop_chip.rs @@ -1,7 +1,7 @@ use super::state::Cell; use super::util::select; -use halo2_proofs::arithmetic::FieldExt; -//use halo2_proofs::halo2curves::bn256::Fr as F; + +use ff::PrimeField; use halo2_proofs::plonk::{ConstraintSystem, Constraints, Expression}; #[derive(Clone, Debug)] @@ -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..e4aab4a 100644 --- a/src/poseidon/septidon/params.rs +++ b/src/poseidon/septidon/params.rs @@ -16,14 +16,18 @@ pub trait CachedConstants: P128Pow5T3Constants { pub mod sbox { use super::super::util::pow_5; - use halo2_proofs::arithmetic::FieldExt; + + use 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..e464a3f 100644 --- a/src/poseidon/septidon/state.rs +++ b/src/poseidon/septidon/state.rs @@ -1,7 +1,6 @@ use super::params; +use ff::PrimeField; use halo2_proofs::circuit::{Region, Value}; -//use halo2_proofs::halo2curves::bn256::Fr as F; -use halo2_proofs::arithmetic::FieldExt; use halo2_proofs::plonk::{ Advice, Column, ConstraintSystem, Error, Expression, Fixed, VirtualCells, }; @@ -17,7 +16,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 +34,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 +43,7 @@ impl Cell { self.offset as usize } - pub fn assign( + pub fn assign( &self, region: &mut Region<'_, F>, origin_offset: usize, @@ -64,7 +63,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 +71,7 @@ impl SBox { } /// Assign the witness of the input. - pub fn assign( + pub fn assign( &self, region: &mut Region<'_, F>, offset: usize, @@ -95,15 +94,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 +113,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..db536d7 100644 --- a/src/poseidon/septidon/transition_round.rs +++ b/src/poseidon/septidon/transition_round.rs @@ -3,7 +3,6 @@ use super::params::{mds, round_constant, CachedConstants}; use super::state::Cell; use super::util::{join_values, matmul, split_values}; use halo2_proofs::circuit::{Region, Value}; -//use halo2_proofs::halo2curves::bn256::Fr as F; use halo2_proofs::plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression}; #[derive(Clone, Debug)] @@ -96,7 +95,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 +120,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 142afe9..2face13 100644 --- a/src/poseidon/septidon/util.rs +++ b/src/poseidon/septidon/util.rs @@ -1,6 +1,5 @@ +use ff::PrimeField; use halo2_proofs::circuit::Value; -//use halo2_proofs::halo2curves::bn256::Fr as F; -use halo2_proofs::arithmetic::FieldExt; use halo2_proofs::plonk::{ConstraintSystem, Expression, VirtualCells}; pub fn map_array(array: &[IN; 3], mut f: FN) -> [OUT; 3] @@ -14,26 +13,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 +41,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 +58,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 +77,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) @@ -95,11 +94,12 @@ 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 ff::PrimeField; + use halo2_proofs::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, @@ -110,25 +110,26 @@ 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 ff::PrimeField; + use halo2_proofs::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 - 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)) }