From 54c4d8a50e0add5d862f5b8450dc21fc6df5cdf4 Mon Sep 17 00:00:00 2001 From: Mickey Date: Fri, 15 Jul 2022 11:10:32 +0800 Subject: [PATCH 01/62] speed up generate vk pk with multi-thread --- halo2_proofs/src/plonk/permutation/keygen.rs | 32 ++++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/halo2_proofs/src/plonk/permutation/keygen.rs b/halo2_proofs/src/plonk/permutation/keygen.rs index cdb8cc02f9..e1bd0d1e4e 100644 --- a/halo2_proofs/src/plonk/permutation/keygen.rs +++ b/halo2_proofs/src/plonk/permutation/keygen.rs @@ -3,7 +3,7 @@ use group::Curve; use super::{Argument, ProvingKey, VerifyingKey}; use crate::{ - arithmetic::{CurveAffine, FieldExt}, + arithmetic::{parallelize, CurveAffine, FieldExt}, plonk::{Any, Column, Error}, poly::{ commitment::{Blind, CommitmentScheme, Params}, @@ -104,13 +104,16 @@ impl Assembly { p: &Argument, ) -> VerifyingKey { // Compute [omega^0, omega^1, ..., omega^{params.n - 1}] - let mut omega_powers = Vec::with_capacity(params.n() as usize); + let mut omega_powers = vec![C::Scalar::zero(); params.n() as usize]; { - let mut cur = C::Scalar::one(); - for _ in 0..params.n() { - omega_powers.push(cur); - cur *= &domain.get_omega(); - } + let omega = domain.get_omega(); + parallelize(&mut omega_powers, |o, start| { + let mut cur = omega.pow_vartime(&[start as u64]); + for v in o.iter_mut() { + *v = cur; + cur *= ω + } + }) } // Compute [omega_powers * \delta^0, omega_powers * \delta^1, ..., omega_powers * \delta^m] @@ -157,13 +160,16 @@ impl Assembly { p: &Argument, ) -> ProvingKey { // Compute [omega^0, omega^1, ..., omega^{params.n - 1}] - let mut omega_powers = Vec::with_capacity(params.n() as usize); + let mut omega_powers = vec![C::Scalar::zero(); params.n() as usize]; { - let mut cur = C::Scalar::one(); - for _ in 0..params.n() { - omega_powers.push(cur); - cur *= &domain.get_omega(); - } + let omega = domain.get_omega(); + parallelize(&mut omega_powers, |o, start| { + let mut cur = omega.pow_vartime(&[start as u64]); + for v in o.iter_mut() { + *v = cur; + cur *= ω + } + }) } // Compute [omega_powers * \delta^0, omega_powers * \delta^1, ..., omega_powers * \delta^m] From d8d7235bb19009d8f327c4ac43b18be133ecf2ad Mon Sep 17 00:00:00 2001 From: spherel Date: Fri, 24 Jun 2022 14:45:13 +0000 Subject: [PATCH 02/62] Add parallel verifying process. --- halo2_proofs/src/dev.rs | 388 ++++------------------------------------ 1 file changed, 36 insertions(+), 352 deletions(-) diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index 68d211cde7..6b243fd948 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -1,5 +1,4 @@ //! Tools for developing circuits. - use std::collections::HashMap; use std::collections::HashSet; use std::fmt; @@ -8,6 +7,10 @@ use std::ops::{Add, Mul, Neg, Range}; use std::time::{Duration, Instant}; use ff::Field; +use rayon::iter::IndexedParallelIterator; +use rayon::iter::IntoParallelIterator; +use rayon::iter::IntoParallelRefIterator; +use rayon::iter::ParallelIterator; use crate::plonk::Assigned; use crate::{ @@ -20,9 +23,6 @@ use crate::{ poly::Rotation, }; use rayon::{ - iter::{ - IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, ParallelIterator, - }, slice::ParallelSliceMut, }; @@ -479,6 +479,37 @@ impl Assignment for MockProver { } } +fn home_made_par_iter_flat_map( + row_indexes: &[usize], + f: Fun, +) -> Vec +where + Fun: Fn(i32) -> Vec, +{ + if ISPAR { + row_indexes + .par_iter() + .flat_map(|row| f(*row as i32)) + .collect() + } else { + row_indexes.iter().flat_map(|row| f(*row as i32)).collect() + } +} + +fn home_made_par_iter_map( + row_indexes: &[usize], + f: Fun, +) -> Vec +where + Fun: Fn(i32) -> U, +{ + if ISPAR { + row_indexes.par_iter().map(|row| f(*row as i32)).collect() + } else { + row_indexes.iter().map(|row| f(*row as i32)).collect() + } +} + impl MockProver { /// Runs a synthetic keygen-and-prove operation on the given circuit, collecting data /// about the constraints and their assignments. @@ -565,354 +596,7 @@ impl MockProver { /// Returns `Ok(())` if this `MockProver` is satisfied, or a list of errors indicating /// the reasons that the circuit is not satisfied. pub fn verify(&self) -> Result<(), Vec> { - self.verify_at_rows(self.usable_rows.clone(), self.usable_rows.clone()) - } - - /// Returns `Ok(())` if this `MockProver` is satisfied, or a list of errors indicating - /// the reasons that the circuit is not satisfied. - /// Constraints are only checked at `gate_row_ids`, - /// and lookup inputs are only checked at `lookup_input_row_ids` - pub fn verify_at_rows>( - &self, - gate_row_ids: I, - lookup_input_row_ids: I, - ) -> Result<(), Vec> { - let n = self.n as i32; - - // check all the row ids are valid - for row_id in gate_row_ids.clone() { - if !self.usable_rows.contains(&row_id) { - panic!("invalid gate row id {}", row_id) - } - } - for row_id in lookup_input_row_ids.clone() { - if !self.usable_rows.contains(&row_id) { - panic!("invalid lookup row id {}", row_id) - } - } - - // Check that within each region, all cells used in instantiated gates have been - // assigned to. - let selector_errors = self.regions.iter().enumerate().flat_map(|(r_i, r)| { - r.enabled_selectors.iter().flat_map(move |(selector, at)| { - // Find the gates enabled by this selector - self.cs - .gates - .iter() - // Assume that if a queried selector is enabled, the user wants to use the - // corresponding gate in some way. - // - // TODO: This will trip up on the reverse case, where leaving a selector - // un-enabled keeps a gate enabled. We could alternatively require that - // every selector is explicitly enabled or disabled on every row? But that - // seems messy and confusing. - .enumerate() - .filter(move |(_, g)| g.queried_selectors().contains(selector)) - .flat_map(move |(gate_index, gate)| { - at.iter().flat_map(move |selector_row| { - // Selectors are queried with no rotation. - let gate_row = *selector_row as i32; - - gate.queried_cells().iter().filter_map(move |cell| { - // Determine where this cell should have been assigned. - let cell_row = ((gate_row + n + cell.rotation.0) % n) as usize; - - // Check that it was assigned! - if r.cells.contains_key(&(cell.column, cell_row)) { - None - } else { - Some(VerifyFailure::CellNotAssigned { - gate: (gate_index, gate.name()).into(), - region: (r_i, r.name.clone()).into(), - gate_offset: *selector_row, - column: cell.column, - offset: cell_row as isize - r.rows.unwrap().0 as isize, - }) - } - }) - }) - }) - }) - }); - - // Check that all gates are satisfied for all rows. - let gate_errors = - self.cs - .gates - .iter() - .enumerate() - .flat_map(|(gate_index, gate)| { - let blinding_rows = - (self.n as usize - (self.cs.blinding_factors() + 1))..(self.n as usize); - (gate_row_ids - .clone() - .into_iter() - .chain(blinding_rows.into_iter())) - .flat_map(move |row| { - let row = row as i32 + n; - gate.polynomials().iter().enumerate().filter_map( - move |(poly_index, poly)| match poly.evaluate_lazy( - &|scalar| Value::Real(scalar), - &|_| panic!("virtual selectors are removed during optimization"), - &util::load(n, row, &self.cs.fixed_queries, &self.fixed), - &util::load(n, row, &self.cs.advice_queries, &self.advice), - &util::load_instance( - n, - row, - &self.cs.instance_queries, - &self.instance, - ), - &|a| -a, - &|a, b| a + b, - &|a, b| a * b, - &|a, scalar| a * scalar, - &Value::Real(F::zero()), - ) { - Value::Real(x) if x.is_zero_vartime() => None, - Value::Real(_) => Some(VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (gate_index, gate.name()).into(), - poly_index, - gate.constraint_name(poly_index), - ) - .into(), - location: FailureLocation::find_expressions( - &self.cs, - &self.regions, - (row - n) as usize, - Some(poly).into_iter(), - ), - cell_values: util::cell_values( - gate, - poly, - &util::load(n, row, &self.cs.fixed_queries, &self.fixed), - &util::load(n, row, &self.cs.advice_queries, &self.advice), - &util::load_instance( - n, - row, - &self.cs.instance_queries, - &self.instance, - ), - ), - }), - Value::Poison => Some(VerifyFailure::ConstraintPoisoned { - constraint: ( - (gate_index, gate.name()).into(), - poly_index, - gate.constraint_name(poly_index), - ) - .into(), - }), - }, - ) - }) - }); - - let mut cached_table = Vec::new(); - let mut cached_table_identifier = Vec::new(); - // Check that all lookups exist in their respective tables. - let lookup_errors = - self.cs - .lookups - .iter() - .enumerate() - .flat_map(|(lookup_index, lookup)| { - let load = |expression: &Expression, row| { - expression.evaluate_lazy( - &|scalar| Value::Real(scalar), - &|_| panic!("virtual selectors are removed during optimization"), - &|query| { - let query = self.cs.fixed_queries[query.index]; - let column_index = query.0.index(); - let rotation = query.1 .0; - self.fixed[column_index] - [(row as i32 + n + rotation) as usize % n as usize] - .into() - }, - &|query| { - let query = self.cs.advice_queries[query.index]; - let column_index = query.0.index(); - let rotation = query.1 .0; - self.advice[column_index] - [(row as i32 + n + rotation) as usize % n as usize] - .into() - }, - &|query| { - let query = self.cs.instance_queries[query.index]; - let column_index = query.0.index(); - let rotation = query.1 .0; - Value::Real( - self.instance[column_index] - [(row as i32 + n + rotation) as usize % n as usize], - ) - }, - &|a| -a, - &|a, b| a + b, - &|a, b| a * b, - &|a, scalar| a * scalar, - &Value::Real(F::zero()), - ) - }; - - assert!(lookup.table_expressions.len() == lookup.input_expressions.len()); - assert!(self.usable_rows.end > 0); - - // We optimize on the basis that the table might have been filled so that the last - // usable row now has the fill contents (it doesn't matter if there was no filling). - // Note that this "fill row" necessarily exists in the table, and we use that fact to - // slightly simplify the optimization: we're only trying to check that all input rows - // are contained in the table, and so we can safely just drop input rows that - // match the fill row. - let fill_row: Vec<_> = lookup - .table_expressions - .iter() - .map(move |c| load(c, self.usable_rows.end - 1)) - .collect(); - - let table_identifier = lookup - .table_expressions - .iter() - .map(Expression::identifier) - .collect::>(); - if table_identifier != cached_table_identifier { - cached_table_identifier = table_identifier; - - // In the real prover, the lookup expressions are never enforced on - // unusable rows, due to the (1 - (l_last(X) + l_blind(X))) term. - cached_table = self - .usable_rows - .clone() - .filter_map(|table_row| { - let t = lookup - .table_expressions - .iter() - .map(move |c| load(c, table_row)) - .collect(); - - if t != fill_row { - Some(t) - } else { - None - } - }) - .collect(); - cached_table.sort_unstable(); - } - let table = &cached_table; - - let mut inputs: Vec<(Vec<_>, usize)> = lookup_input_row_ids - .clone() - .into_iter() - .filter_map(|input_row| { - let t = lookup - .input_expressions - .iter() - .map(move |c| load(c, input_row)) - .collect(); - - if t != fill_row { - // Also keep track of the original input row, since we're going to sort. - Some((t, input_row)) - } else { - None - } - }) - .collect(); - inputs.sort_unstable(); - - let mut i = 0; - inputs - .iter() - .filter_map(move |(input, input_row)| { - while i < table.len() && &table[i] < input { - i += 1; - } - if i == table.len() || &table[i] > input { - assert!(table.binary_search(input).is_err()); - - Some(VerifyFailure::Lookup { - name: lookup.name, - lookup_index, - location: FailureLocation::find_expressions( - &self.cs, - &self.regions, - *input_row, - lookup.input_expressions.iter(), - ), - }) - } else { - None - } - }) - .collect::>() - }); - - // Check that permutations preserve the original values of the cells. - let perm_errors = { - // Original values of columns involved in the permutation. - let original = |column, row| { - self.cs - .permutation - .get_columns() - .get(column) - .map(|c: &Column| match c.column_type() { - Any::Advice => self.advice[c.index()][row], - Any::Fixed => self.fixed[c.index()][row], - Any::Instance => CellValue::Assigned(self.instance[c.index()][row]), - }) - .unwrap() - }; - - // Iterate over each column of the permutation - self.permutation - .mapping - .iter() - .enumerate() - .flat_map(move |(column, values)| { - // Iterate over each row of the column to check that the cell's - // value is preserved by the mapping. - values.iter().enumerate().filter_map(move |(row, cell)| { - let original_cell = original(column, row); - let permuted_cell = original(cell.0, cell.1); - if original_cell == permuted_cell { - None - } else { - let columns = self.cs.permutation.get_columns(); - let column = columns.get(column).unwrap(); - Some(VerifyFailure::Permutation { - column: (*column).into(), - location: FailureLocation::find( - &self.regions, - row, - Some(column).into_iter().cloned().collect(), - ), - }) - } - }) - }) - }; - - let mut errors: Vec<_> = iter::empty() - .chain(selector_errors) - .chain(gate_errors) - .chain(lookup_errors) - .chain(perm_errors) - .collect(); - if errors.is_empty() { - Ok(()) - } else { - // Remove any duplicate `ConstraintPoisoned` errors (we check all unavailable - // rows in case the trigger is row-specific, but the error message only points - // at the constraint). - errors.dedup_by(|a, b| match (a, b) { - ( - a @ VerifyFailure::ConstraintPoisoned { .. }, - b @ VerifyFailure::ConstraintPoisoned { .. }, - ) => a == b, - _ => false, - }); - Err(errors) - } + self.verify_at_rows_par(self.usable_rows.clone(), self.usable_rows.clone()) } /// Returns `Ok(())` if this `MockProver` is satisfied, or a list of errors indicating From 81c654ab5354b52cf62bae15adf805d94c145ae8 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Thu, 4 Aug 2022 22:11:53 +0800 Subject: [PATCH 03/62] use binary_search to check if an input is included in table --- halo2_proofs/src/dev.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index 6b243fd948..e36cc195a1 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -7,10 +7,12 @@ use std::ops::{Add, Mul, Neg, Range}; use std::time::{Duration, Instant}; use ff::Field; +use rand_core::OsRng; use rayon::iter::IndexedParallelIterator; use rayon::iter::IntoParallelIterator; use rayon::iter::IntoParallelRefIterator; use rayon::iter::ParallelIterator; +use rayon::prelude::ParallelSliceMut; use crate::plonk::Assigned; use crate::{ @@ -22,9 +24,6 @@ use crate::{ }, poly::Rotation, }; -use rayon::{ - slice::ParallelSliceMut, -}; pub mod metadata; mod util; From 48c5fa99ca596c9b698452d0e03740809b215225 Mon Sep 17 00:00:00 2001 From: Zhuo Zhang Date: Tue, 14 Jun 2022 07:49:09 +0000 Subject: [PATCH 04/62] make blinding rows for advice columns are 0, only last row is 1 --- halo2_proofs/src/plonk/prover.rs | 59 +++++++++++++++++++++++--------- halo2_proofs/src/transcript.rs | 53 ++++++++++++++++++---------- 2 files changed, 77 insertions(+), 35 deletions(-) diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index 48d89de654..2406af08ad 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -299,23 +299,48 @@ pub fn create_proof< .iter() .map(|_| Blind(Scheme::Scalar::random(&mut rng))) .collect(); - let advice_commitments_projective: Vec<_> = advice - .iter() - .zip(advice_blinds.iter()) - .map(|(poly, blind)| params.commit_lagrange(poly, *blind)) - .collect(); - let mut advice_commitments = - vec![Scheme::Curve::identity(); advice_commitments_projective.len()]; - ::CurveExt::batch_normalize( - &advice_commitments_projective, - &mut advice_commitments, - ); - let advice_commitments = advice_commitments; - drop(advice_commitments_projective); - - for commitment in &advice_commitments { - transcript.write_point(*commitment)?; - } + + let unusable_rows_start = params.n() as usize - (meta.blinding_factors() + 1); + + let mut witness = WitnessCollection { + k: params.k(), + advice: vec![domain.empty_lagrange_assigned(); meta.num_advice_columns], + instances, + // The prover will not be allowed to assign values to advice + // cells that exist within inactive rows, which include some + // number of blinding factors and an extra row for use in the + // permutation argument. + usable_rows: ..unusable_rows_start, + _marker: std::marker::PhantomData, + }; + + // Synthesize the circuit to obtain the witness and other information. + ConcreteCircuit::FloorPlanner::synthesize( + &mut witness, + circuit, + config.clone(), + meta.constants.clone(), + )?; + + let mut advice = batch_invert_assigned(witness.advice); + + // Add blinding factors to advice columns + for advic in &mut advice { + //for cell in &mut advice[unusable_rows_start..] { + //*cell = C::Scalar::random(&mut rng); + //*cell = C::Scalar::one(); + //} + let idx = advic.len() - 1; + advic[idx] = Scheme::Scalar::one(); + } + + let advice_commitments_projective: Vec<_> = advice + .iter().zip(advice_blinds.iter()) + .map(|(poly, blind)| params.commit_lagrange(poly,*blind)) + .collect(); + let mut advice_commitments = vec![Scheme::Curve::identity(); advice_commitments_projective.len()]; + ::CurveExt::batch_normalize(&advice_commitments_projective, &mut advice_commitments); + drop(advice_commitments_projective); Ok(AdviceSingle { advice_polys: advice, diff --git a/halo2_proofs/src/transcript.rs b/halo2_proofs/src/transcript.rs index 5262f3c1c7..fa7b10f554 100644 --- a/halo2_proofs/src/transcript.rs +++ b/halo2_proofs/src/transcript.rs @@ -4,7 +4,7 @@ use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; use group::ff::PrimeField; use std::convert::TryInto; - +use ff::Field; use halo2curves::{Coordinates, CurveAffine, FieldExt}; use std::io::{self, Read, Write}; @@ -142,18 +142,27 @@ impl Transcript> let result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap(); Challenge255::::new(&result) } - + + // This function is slightly modified from PSE's version. + // In PSE's version, an error is returned if the input point is infinity. + // Here we want to be able to absorb infinity point because of the + // randomness we used in the polynomial commitment is 0. fn common_point(&mut self, point: C) -> io::Result<()> { self.state.update(&[BLAKE2B_PREFIX_POINT]); - let coords: Coordinates = Option::from(point.coordinates()).ok_or_else(|| { - io::Error::new( - io::ErrorKind::Other, - "cannot write points at infinity to the transcript", - ) - })?; - self.state.update(coords.x().to_repr().as_ref()); - self.state.update(coords.y().to_repr().as_ref()); + let tmp:Option> = Option::from(point.coordinates()); + match tmp { + + Some(coords)=>{ + self.state.update(coords.x().to_repr().as_ref()); + self.state.update(coords.y().to_repr().as_ref()); + }, + None =>{ + // Infinity point + self.state.update(&C::Base::zero().to_repr().as_ref()); + self.state.update(&C::Base::from(5).to_repr().as_ref()); + } + } Ok(()) } @@ -218,16 +227,24 @@ impl Transcript> Challenge255::::new(&result) } + // This function is slightly modified from PSE's version. + // In PSE's version, an error is returned if the input point is infinity. + // Here we want to be able to absorb infinity point because of the + // randomness we used in the polynomial commitment is 0. fn common_point(&mut self, point: C) -> io::Result<()> { self.state.update(&[BLAKE2B_PREFIX_POINT]); - let coords: Coordinates = Option::from(point.coordinates()).ok_or_else(|| { - io::Error::new( - io::ErrorKind::Other, - "cannot write points at infinity to the transcript", - ) - })?; - self.state.update(coords.x().to_repr().as_ref()); - self.state.update(coords.y().to_repr().as_ref()); + let tmp:Option> = Option::from(point.coordinates()); + match tmp { + Some(coords)=>{ + self.state.update(coords.x().to_repr().as_ref()); + self.state.update(coords.y().to_repr().as_ref()); + }, + None =>{ + // Infinity point + self.state.update(&C::Base::zero().to_repr().as_ref()); + self.state.update(&C::Base::from(5).to_repr().as_ref()); + } + } Ok(()) } From 4a67031b356bb2e11a9560842094f4c507ef7678 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 6 Jul 2022 08:50:36 +0800 Subject: [PATCH 05/62] random poly is full of 0 --- halo2_proofs/src/plonk/vanishing/prover.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/halo2_proofs/src/plonk/vanishing/prover.rs b/halo2_proofs/src/plonk/vanishing/prover.rs index cc52273b59..7c1783c188 100644 --- a/halo2_proofs/src/plonk/vanishing/prover.rs +++ b/halo2_proofs/src/plonk/vanishing/prover.rs @@ -43,19 +43,19 @@ impl Argument { >( params: &P, domain: &EvaluationDomain, - mut rng: R, + mut _rng: R, transcript: &mut T, ) -> Result, Error> { // Sample a random polynomial of degree n - 1 - let mut random_poly = domain.empty_coeff(); - for coeff in random_poly.iter_mut() { - *coeff = C::Scalar::random(&mut rng); - } - // Sample a random blinding factor - let random_blind = Blind(C::Scalar::random(rng)); + let random_poly = domain.empty_coeff(); + //for coeff in random_poly.iter_mut() { + // *coeff = C::Scalar::random(&mut rng); + //} + let random_blind = Blind(C::Scalar::zero()); // Commit - let c = params.commit(&random_poly, random_blind).to_affine(); + //let c = params.commit(&random_poly).to_affine(); + let c = C::identity(); transcript.write_point(c)?; Ok(Committed { From 15a90b3b82a21db312f19ddd6ae19a75dbf5c1f5 Mon Sep 17 00:00:00 2001 From: Heng Zhang Date: Tue, 5 Apr 2022 03:11:22 +0800 Subject: [PATCH 06/62] add brief transcript with poseidon --- halo2_proofs/Cargo.toml | 5 + halo2_proofs/src/helpers.rs | 51 +++++- .../{transcript.rs => transcript/blake2b.rs} | 164 +---------------- halo2_proofs/src/transcript/mod.rs | 166 +++++++++++++++++ halo2_proofs/src/transcript/poseidon.rs | 171 ++++++++++++++++++ 5 files changed, 400 insertions(+), 157 deletions(-) rename halo2_proofs/src/{transcript.rs => transcript/blake2b.rs} (55%) create mode 100644 halo2_proofs/src/transcript/mod.rs create mode 100644 halo2_proofs/src/transcript/poseidon.rs diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 8b8dee7f18..c166fec73c 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -52,6 +52,11 @@ halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curv rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" +subtle = "2.3" +cfg-if = "0.1" +poseidon = { git = 'https://github.com/appliedzkp/poseidon.git' } +num-integer = "0.1" +num-bigint = { version = "0.4", features = ["rand"] } # Developer tooling dependencies plotters = { version = "0.3.0", optional = true } diff --git a/halo2_proofs/src/helpers.rs b/halo2_proofs/src/helpers.rs index 297fd7b9ca..382b88581f 100644 --- a/halo2_proofs/src/helpers.rs +++ b/halo2_proofs/src/helpers.rs @@ -1,7 +1,8 @@ +use ff::Field; +use halo2curves::{CurveAffine, FieldExt}; +use num_bigint::BigUint; use std::io; -use halo2curves::CurveAffine; - pub(crate) trait CurveRead: CurveAffine { /// Reads a compressed element from the buffer and attempts to parse it /// using `from_bytes`. @@ -14,3 +15,49 @@ pub(crate) trait CurveRead: CurveAffine { } impl CurveRead for C {} + +pub fn field_to_bn(f: &F) -> BigUint { + BigUint::from_bytes_le(f.to_repr().as_ref()) +} + +/// Input a big integer `bn`, compute a field element `f` +/// such that `f == bn % F::MODULUS`. +pub fn bn_to_field(bn: &BigUint) -> F { + let mut buf = bn.to_bytes_le(); + buf.resize(64, 0u8); + + let mut buf_array = [0u8;64]; + buf_array.copy_from_slice(buf.as_ref()); + F::from_bytes_wide(&buf_array) +} + +/// Input a base field element `b`, output a scalar field +/// element `s` s.t. `s == b % ScalarField::MODULUS` +pub(crate) fn base_to_scalar(base: &C::Base) -> C::Scalar { + let bn = field_to_bn(base); + // bn_to_field will perform a mod reduction + bn_to_field(&bn) +} + +#[cfg(test)] +mod test { + use halo2curves::bn256::{G1Affine, Fq}; + use rand_core::OsRng; + use super::*; + #[test] + fn test_conversion(){ + // random numbers + for _ in 0..100{ + let b = Fq::random(OsRng); + let bi = field_to_bn(&b); + let b_rec = bn_to_field(&bi); + assert_eq!(b, b_rec); + + // TODO: FIXME + let s = base_to_scalar::(&b); + let si = field_to_bn(&s); + assert_eq!(si, bi); + } + } + +} \ No newline at end of file diff --git a/halo2_proofs/src/transcript.rs b/halo2_proofs/src/transcript/blake2b.rs similarity index 55% rename from halo2_proofs/src/transcript.rs rename to halo2_proofs/src/transcript/blake2b.rs index fa7b10f554..a6bdd54468 100644 --- a/halo2_proofs/src/transcript.rs +++ b/halo2_proofs/src/transcript/blake2b.rs @@ -1,12 +1,13 @@ -//! This module contains utilities and traits for dealing with Fiat-Shamir -//! transcripts. - +use super::{ + Challenge255, EncodedChallenge, Transcript, TranscriptRead, TranscriptReadBuffer, + TranscriptWrite, TranscriptWriterBuffer, +}; use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; -use group::ff::PrimeField; -use std::convert::TryInto; use ff::Field; +use group::ff::PrimeField; use halo2curves::{Coordinates, CurveAffine, FieldExt}; - +use num_bigint::BigUint; +use std::convert::TryInto; use std::io::{self, Read, Write}; use std::marker::PhantomData; @@ -19,66 +20,7 @@ const BLAKE2B_PREFIX_POINT: u8 = 1; /// Prefix to a prover's message containing a scalar const BLAKE2B_PREFIX_SCALAR: u8 = 2; -/// Generic transcript view (from either the prover or verifier's perspective) -pub trait Transcript> { - /// Squeeze an encoded verifier challenge from the transcript. - fn squeeze_challenge(&mut self) -> E; - - /// Squeeze a typed challenge (in the scalar field) from the transcript. - fn squeeze_challenge_scalar(&mut self) -> ChallengeScalar { - ChallengeScalar { - inner: self.squeeze_challenge().get_scalar(), - _marker: PhantomData, - } - } - - /// Writing the point to the transcript without writing it to the proof, - /// treating it as a common input. - fn common_point(&mut self, point: C) -> io::Result<()>; - - /// Writing the scalar to the transcript without writing it to the proof, - /// treating it as a common input. - fn common_scalar(&mut self, scalar: C::Scalar) -> io::Result<()>; -} - -/// Transcript view from the perspective of a verifier that has access to an -/// input stream of data from the prover to the verifier. -pub trait TranscriptRead>: Transcript { - /// Read a curve point from the prover. - fn read_point(&mut self) -> io::Result; - - /// Read a curve scalar from the prover. - fn read_scalar(&mut self) -> io::Result; -} - -/// Transcript view from the perspective of a prover that has access to an -/// output stream of messages from the prover to the verifier. -pub trait TranscriptWrite>: Transcript { - /// Write a curve point to the proof and the transcript. - fn write_point(&mut self, point: C) -> io::Result<()>; - - /// Write a scalar to the proof and the transcript. - fn write_scalar(&mut self, scalar: C::Scalar) -> io::Result<()>; -} - -/// Initializes transcript at verifier side. -pub trait TranscriptReadBuffer>: - TranscriptRead -{ - /// Initialize a transcript given an input buffer. - fn init(reader: R) -> Self; -} - -/// Manages begining and finising of transcript pipeline. -pub trait TranscriptWriterBuffer>: - TranscriptWrite -{ - /// Initialize a transcript given an output buffer. - fn init(writer: W) -> Self; - - /// Conclude the interaction and return the output buffer (writer). - fn finalize(self) -> W; -} +// ----------------------Blake2bRead /// We will replace BLAKE2b with an algebraic hash function in a later version. #[derive(Debug, Clone)] @@ -142,7 +84,7 @@ impl Transcript> let result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap(); Challenge255::::new(&result) } - + // This function is slightly modified from PSE's version. // In PSE's version, an error is returned if the input point is infinity. // Here we want to be able to absorb infinity point because of the @@ -256,91 +198,3 @@ impl Transcript> Ok(()) } } - -/// The scalar representation of a verifier challenge. -/// -/// The `Type` type can be used to scope the challenge to a specific context, or -/// set to `()` if no context is required. -#[derive(Copy, Clone, Debug)] -pub struct ChallengeScalar { - inner: C::Scalar, - _marker: PhantomData, -} - -impl std::ops::Deref for ChallengeScalar { - type Target = C::Scalar; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -/// `EncodedChallenge` defines a challenge encoding with a [`Self::Input`] -/// that is used to derive the challenge encoding and `get_challenge` obtains -/// the _real_ `C::Scalar` that the challenge encoding represents. -pub trait EncodedChallenge { - /// The Input type used to derive the challenge encoding. For example, - /// an input from the Poseidon hash would be a base field element; - /// an input from the Blake2b hash would be a [u8; 64]. - type Input; - - /// Get an encoded challenge from a given input challenge. - fn new(challenge_input: &Self::Input) -> Self; - - /// Get a scalar field element from an encoded challenge. - fn get_scalar(&self) -> C::Scalar; - - /// Cast an encoded challenge as a typed `ChallengeScalar`. - fn as_challenge_scalar(&self) -> ChallengeScalar { - ChallengeScalar { - inner: self.get_scalar(), - _marker: PhantomData, - } - } -} - -/// A 255-bit challenge. -#[derive(Copy, Clone, Debug)] -pub struct Challenge255([u8; 32], PhantomData); - -impl std::ops::Deref for Challenge255 { - type Target = [u8; 32]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl EncodedChallenge for Challenge255 { - type Input = [u8; 64]; - - fn new(challenge_input: &[u8; 64]) -> Self { - Challenge255( - C::Scalar::from_bytes_wide(challenge_input) - .to_repr() - .as_ref() - .try_into() - .expect("Scalar fits into 256 bits"), - PhantomData, - ) - } - fn get_scalar(&self) -> C::Scalar { - let mut repr = ::Repr::default(); - repr.as_mut().copy_from_slice(&self.0); - C::Scalar::from_repr(repr).unwrap() - } -} - -pub(crate) fn read_n_points, T: TranscriptRead>( - transcript: &mut T, - n: usize, -) -> io::Result> { - (0..n).map(|_| transcript.read_point()).collect() -} - -pub(crate) fn read_n_scalars, T: TranscriptRead>( - transcript: &mut T, - n: usize, -) -> io::Result> { - (0..n).map(|_| transcript.read_scalar()).collect() -} diff --git a/halo2_proofs/src/transcript/mod.rs b/halo2_proofs/src/transcript/mod.rs new file mode 100644 index 0000000000..f33cdad523 --- /dev/null +++ b/halo2_proofs/src/transcript/mod.rs @@ -0,0 +1,166 @@ +//! This module contains utilities and traits for dealing with Fiat-Shamir +//! transcripts. + +mod blake2b; +mod poseidon; + +pub use self::poseidon::{PoseidonRead, PoseidonWrite}; +pub use blake2b::{Blake2bRead, Blake2bWrite}; + +use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; +use ff::Field; +use group::ff::PrimeField; +use halo2curves::{Coordinates, CurveAffine, FieldExt}; +use num_bigint::BigUint; +use std::convert::TryInto; +use std::io::{self, Read, Write}; +use std::marker::PhantomData; + +/// Generic transcript view (from either the prover or verifier's perspective) +pub trait Transcript> { + /// Squeeze an encoded verifier challenge from the transcript. + fn squeeze_challenge(&mut self) -> E; + + /// Squeeze a typed challenge (in the scalar field) from the transcript. + fn squeeze_challenge_scalar(&mut self) -> ChallengeScalar { + ChallengeScalar { + inner: self.squeeze_challenge().get_scalar(), + _marker: PhantomData, + } + } + + /// Writing the point to the transcript without writing it to the proof, + /// treating it as a common input. + fn common_point(&mut self, point: C) -> io::Result<()>; + + /// Writing the scalar to the transcript without writing it to the proof, + /// treating it as a common input. + fn common_scalar(&mut self, scalar: C::Scalar) -> io::Result<()>; +} + +/// Transcript view from the perspective of a verifier that has access to an +/// input stream of data from the prover to the verifier. +pub trait TranscriptRead>: Transcript { + /// Read a curve point from the prover. + fn read_point(&mut self) -> io::Result; + + /// Read a curve scalar from the prover. + fn read_scalar(&mut self) -> io::Result; +} + +/// Transcript view from the perspective of a prover that has access to an +/// output stream of messages from the prover to the verifier. +pub trait TranscriptWrite>: Transcript { + /// Write a curve point to the proof and the transcript. + fn write_point(&mut self, point: C) -> io::Result<()>; + + /// Write a scalar to the proof and the transcript. + fn write_scalar(&mut self, scalar: C::Scalar) -> io::Result<()>; +} + +/// Initializes transcript at verifier side. +pub trait TranscriptReadBuffer>: + TranscriptRead +{ + /// Initialize a transcript given an input buffer. + fn init(reader: R) -> Self; +} + +/// Manages begining and finising of transcript pipeline. +pub trait TranscriptWriterBuffer>: + TranscriptWrite +{ + /// Initialize a transcript given an output buffer. + fn init(writer: W) -> Self; + + /// Conclude the interaction and return the output buffer (writer). + fn finalize(self) -> W; +} + +/// The scalar representation of a verifier challenge. +/// +/// The `Type` type can be used to scope the challenge to a specific context, or +/// set to `()` if no context is required. +#[derive(Copy, Clone, Debug)] +pub struct ChallengeScalar { + inner: C::Scalar, + _marker: PhantomData, +} + +impl std::ops::Deref for ChallengeScalar { + type Target = C::Scalar; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +/// `EncodedChallenge` defines a challenge encoding with a [`Self::Input`] +/// that is used to derive the challenge encoding and `get_challenge` obtains +/// the _real_ `C::Scalar` that the challenge encoding represents. +pub trait EncodedChallenge { + /// The Input type used to derive the challenge encoding. For example, + /// an input from the Poseidon hash would be a base field element; + /// an input from the Blake2b hash would be a [u8; 64]. + type Input; + + /// Get an encoded challenge from a given input challenge. + fn new(challenge_input: &Self::Input) -> Self; + + /// Get a scalar field element from an encoded challenge. + fn get_scalar(&self) -> C::Scalar; + + /// Cast an encoded challenge as a typed `ChallengeScalar`. + fn as_challenge_scalar(&self) -> ChallengeScalar { + ChallengeScalar { + inner: self.get_scalar(), + _marker: PhantomData, + } + } +} + +/// A 255-bit challenge. +#[derive(Copy, Clone, Debug)] +pub struct Challenge255([u8; 32], PhantomData); + +impl std::ops::Deref for Challenge255 { + type Target = [u8; 32]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl EncodedChallenge for Challenge255 { + type Input = [u8; 64]; + + fn new(challenge_input: &[u8; 64]) -> Self { + Challenge255( + C::Scalar::from_bytes_wide(challenge_input) + .to_repr() + .as_ref() + .try_into() + .expect("Scalar fits into 256 bits"), + PhantomData, + ) + } + fn get_scalar(&self) -> C::Scalar { + let mut repr = ::Repr::default(); + repr.as_mut().copy_from_slice(&self.0); + C::Scalar::from_repr(repr).unwrap() + } +} +/// TODO +pub fn read_n_points, T: TranscriptRead>( + transcript: &mut T, + n: usize, +) -> io::Result> { + (0..n).map(|_| transcript.read_point()).collect() +} +/// TODO +pub fn read_n_scalars, T: TranscriptRead>( + transcript: &mut T, + n: usize, +) -> io::Result> { + (0..n).map(|_| transcript.read_scalar()).collect() +} diff --git a/halo2_proofs/src/transcript/poseidon.rs b/halo2_proofs/src/transcript/poseidon.rs new file mode 100644 index 0000000000..a37b3a1a0e --- /dev/null +++ b/halo2_proofs/src/transcript/poseidon.rs @@ -0,0 +1,171 @@ +use super::{Challenge255, EncodedChallenge, Transcript, TranscriptRead, TranscriptWrite}; +use crate::helpers::base_to_scalar; +use ff::Field; +use group::ff::PrimeField; +use halo2curves::{Coordinates, CurveAffine, FieldExt}; +use num_bigint::BigUint; +use poseidon::Poseidon; +use std::convert::TryInto; +use std::io::{self, Read, Write}; +use std::marker::PhantomData; + +const POSEIDON_RATE: usize = 8usize; +const POSEIDON_T: usize = POSEIDON_RATE + 1usize; + +/// TODO +#[derive(Debug, Clone)] +pub struct PoseidonRead> { + state: Poseidon, + reader: R, + _marker: PhantomData<(C, E)>, +} + +/// TODO +impl> PoseidonRead { + /// Initialize a transcript given an input buffer. + pub fn init(reader: R) -> Self { + PoseidonRead { + state: Poseidon::new(8usize, 33usize), + reader, + _marker: PhantomData, + } + } +} + +impl TranscriptRead> + for PoseidonRead> +{ + fn read_point(&mut self) -> io::Result { + let mut compressed = C::Repr::default(); + self.reader.read_exact(compressed.as_mut())?; + let point: C = Option::from(C::from_bytes(&compressed)).ok_or_else(|| { + io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof") + })?; + self.common_point(point)?; + + Ok(point) + } + + fn read_scalar(&mut self) -> io::Result { + let mut data = ::Repr::default(); + self.reader.read_exact(data.as_mut())?; + let scalar: C::Scalar = Option::from(C::Scalar::from_repr(data)).ok_or_else(|| { + io::Error::new( + io::ErrorKind::Other, + "invalid field element encoding in proof", + ) + })?; + self.common_scalar(scalar)?; + + Ok(scalar) + } +} + +impl Transcript> + for PoseidonRead> +{ + fn squeeze_challenge(&mut self) -> Challenge255 { + //self.state.update(&[PREFIX_SQUEEZE]); + let scalar = self.state.squeeze(); + let mut scalar_bytes = scalar.to_repr().as_ref().to_vec(); + scalar_bytes.resize(64, 0u8); + Challenge255::::new(&scalar_bytes.try_into().unwrap()) + } + + fn common_point(&mut self, point: C) -> io::Result<()> { + //self.state.update(&[PREFIX_POINT]); + let coords: Coordinates = Option::from(point.coordinates()).ok_or_else(|| { + io::Error::new( + io::ErrorKind::Other, + "cannot write points at infinity to the transcript", + ) + })?; + let x = coords.x(); + let y = coords.y(); + self.state + .update(&[base_to_scalar::(x), base_to_scalar::(y)]); + + Ok(()) + } + + fn common_scalar(&mut self, scalar: C::Scalar) -> io::Result<()> { + //self.state.update(&[BLAKE2B_PREFIX_SCALAR]); + self.state.update(&[scalar]); + + Ok(()) + } +} +/// TODO +#[derive(Debug, Clone)] +pub struct PoseidonWrite> { + state: Poseidon, + writer: W, + _marker: PhantomData<(C, E)>, +} + +impl> PoseidonWrite { + /// Initialize a transcript given an output buffer. + pub fn init(writer: W) -> Self { + PoseidonWrite { + state: Poseidon::new(8usize, 33usize), + writer, + _marker: PhantomData, + } + } + + /// Conclude the interaction and return the output buffer (writer). + pub fn finalize(self) -> W { + // TODO: handle outstanding scalars? see issue #138 + self.writer + } +} + +impl TranscriptWrite> + for PoseidonWrite> +{ + fn write_point(&mut self, point: C) -> io::Result<()> { + self.common_point(point)?; + let compressed = point.to_bytes(); + self.writer.write_all(compressed.as_ref()) + } + fn write_scalar(&mut self, scalar: C::Scalar) -> io::Result<()> { + self.common_scalar(scalar)?; + let data = scalar.to_repr(); + self.writer.write_all(data.as_ref()) + } +} + +impl Transcript> + for PoseidonWrite> +{ + fn squeeze_challenge(&mut self) -> Challenge255 { + //self.state.update(&[PREFIX_SQUEEZE]); + let scalar = self.state.squeeze(); + let mut scalar_bytes = scalar.to_repr().as_ref().to_vec(); + scalar_bytes.resize(64, 0u8); + Challenge255::::new(&scalar_bytes.try_into().unwrap()) + } + + fn common_point(&mut self, point: C) -> io::Result<()> { + //self.state.update(&[PREFIX_POINT]); + let coords: Coordinates = Option::from(point.coordinates()).ok_or_else(|| { + io::Error::new( + io::ErrorKind::Other, + "cannot write points at infinity to the transcript", + ) + })?; + let x = coords.x(); + let y = coords.y(); + self.state + .update(&[base_to_scalar::(x), base_to_scalar::(y)]); + + Ok(()) + } + + fn common_scalar(&mut self, scalar: C::Scalar) -> io::Result<()> { + //self.state.update(&[BLAKE2B_PREFIX_SCALAR]); + self.state.update(&[scalar]); + + Ok(()) + } +} From ae82f7593cf1df0ab101e1ba3b3a0e4b8047d221 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Fri, 2 Sep 2022 07:49:05 +0800 Subject: [PATCH 07/62] make some struct fields pub for aggregation; use gwc by default --- .github/workflows/ci.yml | 1 + halo2_proofs/Cargo.toml | 9 +- halo2_proofs/src/circuit.rs | 12 +- halo2_proofs/src/lib.rs | 1 - halo2_proofs/src/plonk/circuit.rs | 23 +- halo2_proofs/src/plonk/lookup.rs | 7 +- halo2_proofs/src/plonk/lookup/verifier.rs | 32 +- halo2_proofs/src/plonk/permutation.rs | 6 +- .../src/plonk/permutation/verifier.rs | 22 +- halo2_proofs/src/poly/multiopen.rs | 372 ++++++++++++++++++ 10 files changed, 432 insertions(+), 53 deletions(-) create mode 100644 halo2_proofs/src/poly/multiopen.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6cd03bdc7..36a53aca3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,7 @@ jobs: args: --verbose --release --all --all-features build: + if: ${{ false }} name: Build target ${{ matrix.target }} runs-on: ubuntu-latest strategy: diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index c166fec73c..b2e1e4b5f1 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -52,9 +52,10 @@ halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curv rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" +# pairing = { git = 'https://github.com/appliedzkp/pairing', package = "pairing_bn256", tag = "v0.1.1" } subtle = "2.3" cfg-if = "0.1" -poseidon = { git = 'https://github.com/appliedzkp/poseidon.git' } +poseidon = { git = 'https://github.com/appliedzkp/poseidon.git' } #, branch = 'circuit' } num-integer = "0.1" num-bigint = { version = "0.4", features = ["rand"] } @@ -73,15 +74,17 @@ rand_core = { version = "0.6", default-features = false, features = ["getrandom" getrandom = { version = "0.2", features = ["js"] } [features] -default = ["batch"] +default = ["batch", "gwc"] dev-graph = ["plotters", "tabbycat"] gadget-traces = ["backtrace"] sanity-checks = [] batch = ["rand_core/getrandom"] +shplonk = [] +gwc = [] [lib] bench = false [[example]] name = "circuit-layout" -required-features = ["dev-graph"] +required-features = ["dev-graph"] \ No newline at end of file diff --git a/halo2_proofs/src/circuit.rs b/halo2_proofs/src/circuit.rs index 9451735d54..b3c47c524a 100644 --- a/halo2_proofs/src/circuit.rs +++ b/halo2_proofs/src/circuit.rs @@ -49,8 +49,8 @@ pub trait Chip: Sized { } /// Index of a region in a layouter -#[derive(Clone, Copy, Debug)] -pub struct RegionIndex(usize); +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct RegionIndex(pub usize); impl From for RegionIndex { fn from(idx: usize) -> RegionIndex { @@ -85,14 +85,14 @@ impl std::ops::Deref for RegionStart { } /// A pointer to a cell within a circuit. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub struct Cell { /// Identifies the region in which this cell resides. - region_index: RegionIndex, + pub region_index: RegionIndex, /// The relative offset of this cell within its region. - row_offset: usize, + pub row_offset: usize, /// The column of this cell. - column: Column, + pub column: Column, } /// An assigned cell. diff --git a/halo2_proofs/src/lib.rs b/halo2_proofs/src/lib.rs index c84e482675..b4bdcd5baf 100644 --- a/halo2_proofs/src/lib.rs +++ b/halo2_proofs/src/lib.rs @@ -19,7 +19,6 @@ )] #![deny(broken_intra_doc_links)] #![deny(missing_debug_implementations)] -#![deny(missing_docs)] #![deny(unsafe_code)] // Remove this once we update pasta_curves #![allow(unused_imports)] diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index 6dbd4a5455..b3e7136490 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -23,7 +23,7 @@ pub trait ColumnType: /// A column with an index and type #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] pub struct Column { - index: usize, + pub index: usize, column_type: C, } @@ -1096,7 +1096,7 @@ impl>, Iter: IntoIterator> IntoIterato pub struct Gate { name: &'static str, constraint_names: Vec<&'static str>, - polys: Vec>, + pub polys: Vec>, /// We track queried selectors separately from other cells, so that we can use them to /// trigger debug checks on gates. queried_selectors: Vec, @@ -1131,30 +1131,29 @@ impl Gate { #[derive(Debug, Clone)] pub struct ConstraintSystem { pub(crate) num_fixed_columns: usize, - pub(crate) num_advice_columns: usize, - pub(crate) num_instance_columns: usize, + pub num_advice_columns: usize, + pub num_instance_columns: usize, pub(crate) num_selectors: usize, /// This is a cached vector that maps virtual selectors to the concrete /// fixed column that they were compressed into. This is just used by dev /// tooling right now. pub(crate) selector_map: Vec>, - - pub(crate) gates: Vec>, - pub(crate) advice_queries: Vec<(Column, Rotation)>, + pub gates: Vec>, + pub advice_queries: Vec<(Column, Rotation)>, // Contains an integer for each advice column // identifying how many distinct queries it has // so far; should be same length as num_advice_columns. num_advice_queries: Vec, - pub(crate) instance_queries: Vec<(Column, Rotation)>, - pub(crate) fixed_queries: Vec<(Column, Rotation)>, + pub instance_queries: Vec<(Column, Rotation)>, + pub fixed_queries: Vec<(Column, Rotation)>, // Permutation argument for performing equality constraints - pub(crate) permutation: permutation::Argument, + pub permutation: permutation::Argument, // Vector of lookup arguments, where each corresponds to a sequence of // input expressions and a sequence of table expressions involved in the lookup. - pub(crate) lookups: Vec>, + pub lookups: Vec>, // Vector of fixed columns, which can be used to store constant values // that are copied into advice columns. @@ -1387,7 +1386,7 @@ impl ConstraintSystem { panic!("get_instance_query_index called for non-existent query"); } - pub(crate) fn get_any_query_index(&self, column: Column, at: Rotation) -> usize { + pub fn get_any_query_index(&self, column: Column, at: Rotation) -> usize { match column.column_type() { Any::Advice => { self.get_advice_query_index(Column::::try_from(column).unwrap(), at) diff --git a/halo2_proofs/src/plonk/lookup.rs b/halo2_proofs/src/plonk/lookup.rs index 68cda75d37..f10306f2f2 100644 --- a/halo2_proofs/src/plonk/lookup.rs +++ b/halo2_proofs/src/plonk/lookup.rs @@ -7,11 +7,12 @@ pub(crate) mod verifier; #[derive(Clone)] pub struct Argument { - pub(crate) name: &'static str, - pub(crate) input_expressions: Vec>, - pub(crate) table_expressions: Vec>, + pub name: &'static str, + pub input_expressions: Vec>, + pub table_expressions: Vec>, } + impl Debug for Argument { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Argument") diff --git a/halo2_proofs/src/plonk/lookup/verifier.rs b/halo2_proofs/src/plonk/lookup/verifier.rs index 07522e478d..1557c3cb85 100644 --- a/halo2_proofs/src/plonk/lookup/verifier.rs +++ b/halo2_proofs/src/plonk/lookup/verifier.rs @@ -12,27 +12,30 @@ use crate::{ }; use ff::Field; +#[derive(Debug)] pub struct PermutationCommitments { - permuted_input_commitment: C, - permuted_table_commitment: C, + pub permuted_input_commitment: C, + pub permuted_table_commitment: C, } +#[derive(Debug)] pub struct Committed { - permuted: PermutationCommitments, - product_commitment: C, + pub permuted: PermutationCommitments, + pub product_commitment: C, } +#[derive(Debug)] pub struct Evaluated { - committed: Committed, - product_eval: C::Scalar, - product_next_eval: C::Scalar, - permuted_input_eval: C::Scalar, - permuted_input_inv_eval: C::Scalar, - permuted_table_eval: C::Scalar, + pub committed: Committed, + pub product_eval: C::Scalar, + pub product_next_eval: C::Scalar, + pub permuted_input_eval: C::Scalar, + pub permuted_input_inv_eval: C::Scalar, + pub permuted_table_eval: C::Scalar, } impl Argument { - pub(in crate::plonk) fn read_permuted_commitments< + pub fn read_permuted_commitments< C: CurveAffine, E: EncodedChallenge, T: TranscriptRead, @@ -51,10 +54,7 @@ impl Argument { } impl PermutationCommitments { - pub(in crate::plonk) fn read_product_commitment< - E: EncodedChallenge, - T: TranscriptRead, - >( + pub fn read_product_commitment, T: TranscriptRead>( self, transcript: &mut T, ) -> Result, Error> { @@ -68,7 +68,7 @@ impl PermutationCommitments { } impl Committed { - pub(crate) fn evaluate, T: TranscriptRead>( + pub fn evaluate, T: TranscriptRead>( self, transcript: &mut T, ) -> Result, Error> { diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index 26a4d805d6..bd15cff05b 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -15,7 +15,7 @@ use std::io; #[derive(Debug, Clone)] pub struct Argument { /// A sequence of columns involved in the argument. - pub(super) columns: Vec>, + pub columns: Vec>, } impl Argument { @@ -73,9 +73,9 @@ impl Argument { } /// The verifying key for a single permutation argument. -#[derive(Clone, Debug)] +#[derive(Debug, Clone)] pub struct VerifyingKey { - commitments: Vec, + pub commitments: Vec, } impl VerifyingKey { diff --git a/halo2_proofs/src/plonk/permutation/verifier.rs b/halo2_proofs/src/plonk/permutation/verifier.rs index 2ac18a6758..b5eb65c98f 100644 --- a/halo2_proofs/src/plonk/permutation/verifier.rs +++ b/halo2_proofs/src/plonk/permutation/verifier.rs @@ -10,27 +10,31 @@ use crate::{ transcript::{EncodedChallenge, TranscriptRead}, }; +#[derive(Debug)] pub struct Committed { permutation_product_commitments: Vec, } +#[derive(Debug)] pub struct EvaluatedSet { - permutation_product_commitment: C, - permutation_product_eval: C::Scalar, - permutation_product_next_eval: C::Scalar, - permutation_product_last_eval: Option, + pub permutation_product_commitment: C, + pub permutation_product_eval: C::Scalar, + pub permutation_product_next_eval: C::Scalar, + pub permutation_product_last_eval: Option, } +#[derive(Debug)] pub struct CommonEvaluated { - permutation_evals: Vec, + pub permutation_evals: Vec, } +#[derive(Debug)] pub struct Evaluated { - sets: Vec>, + pub sets: Vec>, } impl Argument { - pub(crate) fn read_product_commitments< + pub fn read_product_commitments< C: CurveAffine, E: EncodedChallenge, T: TranscriptRead, @@ -54,7 +58,7 @@ impl Argument { } impl VerifyingKey { - pub(in crate::plonk) fn evaluate, T: TranscriptRead>( + pub fn evaluate, T: TranscriptRead>( &self, transcript: &mut T, ) -> Result, Error> { @@ -69,7 +73,7 @@ impl VerifyingKey { } impl Committed { - pub(crate) fn evaluate, T: TranscriptRead>( + pub fn evaluate, T: TranscriptRead>( self, transcript: &mut T, ) -> Result, Error> { diff --git a/halo2_proofs/src/poly/multiopen.rs b/halo2_proofs/src/poly/multiopen.rs new file mode 100644 index 0000000000..854018e90a --- /dev/null +++ b/halo2_proofs/src/poly/multiopen.rs @@ -0,0 +1,372 @@ +//! This module contains an optimisation of the polynomial commitment opening +//! scheme described in the [Halo][halo] paper. +//! +//! [halo]: https://eprint.iacr.org/2019/1021 + +use super::{commitment::ParamsVerifier, PairMSM}; +use crate::{ + arithmetic::{eval_polynomial, CurveAffine, FieldExt}, + pairing::arithmetic::{MillerLoopResult, MultiMillerLoop}, + poly::{msm::MSM, Coeff, Error, Polynomial}, +}; + +use crate::poly::Rotation; +use ff::Field; +use group::Group; +use rand::RngCore; +use std::{ + collections::{BTreeMap, BTreeSet}, + marker::PhantomData, + thread::AccessError, +}; +use subtle::Choice; + +cfg_if::cfg_if! { + if #[cfg(feature = "shplonk")] { + mod shplonk; + pub use shplonk::*; + } else { + mod gwc; + pub use gwc::*; + } +} + +/// Decider performs final pairing check with given verifier params and two channel linear combination +#[derive(Debug)] +pub struct Decider { + _marker: PhantomData, +} + +impl Decider { + fn prepare(params: &ParamsVerifier) -> (E::G2Prepared, E::G2Prepared) { + let s_g2_prepared = E::G2Prepared::from(params.s_g2); + let n_g2_prepared = E::G2Prepared::from(-params.g2); + (s_g2_prepared, n_g2_prepared) + } + + fn pairing_check(terms: &[(&E::G1Affine, &E::G2Prepared); 2]) -> bool { + bool::from( + E::multi_miller_loop(&terms[..]) + .final_exponentiation() + .is_identity(), + ) + } + + /// Performs final pairing check with given verifier params and two channel linear combination + pub fn verify(params: &ParamsVerifier, msm: PairMSM) -> bool { + let (s_g2, n_g2) = Self::prepare(params); + let (left, right) = msm.eval(); + let (term_1, term_2) = ((&left, &s_g2), (&right, &n_g2)); + Self::pairing_check(&[term_1, term_2]) + } +} + +#[doc(hidden)] +#[derive(Debug, Clone, Copy)] +pub struct ProverQuery<'a, C: CurveAffine> { + /// point at which polynomial is queried + pub point: C::Scalar, + pub rotation: Rotation, + /// coefficients of polynomial + pub poly: &'a Polynomial, +} + +/// A polynomial query at a point +#[derive(Debug, Clone, Copy)] +pub struct VerifierQuery<'r, C: CurveAffine> { + /// point at which polynomial is queried + pub point: C::Scalar, + /// rotation at which polynomial is queried + rotation: Rotation, + /// commitment to polynomial + pub commitment: CommitmentReference<'r, C>, + /// evaluation of polynomial at query point + pub eval: C::Scalar, +} + +impl<'r, 'params: 'r, C: CurveAffine> VerifierQuery<'r, C> { + /// Create a new verifier query based on a commitment + pub fn new_commitment( + commitment: &'r C, + point: C::Scalar, + rotation: Rotation, + eval: C::Scalar, + ) -> Self { + VerifierQuery { + point, + rotation, + eval, + commitment: CommitmentReference::Commitment(commitment), + } + } + + /// Create a new verifier query based on a linear combination of commitments + pub fn new_msm(msm: &'r MSM, point: C::Scalar, rotation: Rotation, eval: C::Scalar) -> Self { + VerifierQuery { + point, + rotation, + eval, + commitment: CommitmentReference::MSM(msm), + } + } +} + +#[derive(Copy, Clone, Debug)] +pub enum CommitmentReference<'r, C: CurveAffine> { + Commitment(&'r C), + MSM(&'r MSM), +} + +impl<'r, 'params: 'r, C: CurveAffine> PartialEq for CommitmentReference<'r, C> { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (&CommitmentReference::Commitment(a), &CommitmentReference::Commitment(b)) => { + std::ptr::eq(a, b) + } + (&CommitmentReference::MSM(a), &CommitmentReference::MSM(b)) => std::ptr::eq(a, b), + _ => false, + } + } +} + +trait Query: Sized + Clone { + type Commitment: PartialEq + Clone; + + fn get_rotation(&self) -> Rotation; + fn get_point(&self) -> F; + fn get_eval(&self) -> F; + fn get_commitment(&self) -> Self::Commitment; +} + +#[cfg(test)] +mod tests { + + use crate::arithmetic::{eval_polynomial, FieldExt}; + use crate::pairing::bn256::{Bn256, Fr, G1Affine}; + use crate::poly::{ + commitment::{Params, ParamsVerifier}, + multiopen::{create_proof, verify_proof, Decider, ProverQuery, Query, VerifierQuery}, + Coeff, Polynomial, Rotation, + }; + use crate::transcript::{ + Blake2bRead, Blake2bWrite, Challenge255, ChallengeScalar, Transcript, TranscriptRead, + TranscriptWrite, + }; + + use ff::Field; + use rand::RngCore; + use rand_core::OsRng; + use std::collections::BTreeSet; + use std::marker::PhantomData; + + fn rand_poly(n: usize, mut rng: impl RngCore) -> Polynomial { + Polynomial { + values: (0..n).into_iter().map(|_| Fr::random(&mut rng)).collect(), + _marker: PhantomData, + } + } + + #[test] + fn test_roundtrip() { + use ff::Field; + use group::Curve; + use rand_core::OsRng; + + use super::*; + use crate::arithmetic::{eval_polynomial, FieldExt}; + use crate::poly::{commitment::Params, EvaluationDomain}; + use crate::transcript::Challenge255; + + use pairing::bn256::{Bn256, Fr as Fp, G1Affine}; + + const K: u32 = 4; + + let params: Params = Params::::unsafe_setup::(K); + let params_verifier: ParamsVerifier = params.verifier(0).unwrap(); + + let domain = EvaluationDomain::new(1, K); + let rng = OsRng; + + let mut ax = domain.empty_coeff(); + for (i, a) in ax.iter_mut().enumerate() { + *a = Fp::from(10 + i as u64); + } + + let mut bx = domain.empty_coeff(); + for (i, a) in bx.iter_mut().enumerate() { + *a = Fp::from(100 + i as u64); + } + + let mut cx = domain.empty_coeff(); + for (i, a) in cx.iter_mut().enumerate() { + *a = Fp::from(100 + i as u64); + } + + let a = params.commit(&ax).to_affine(); + let b = params.commit(&bx).to_affine(); + let c = params.commit(&cx).to_affine(); + + let cur = Rotation::cur(); + let next = Rotation::next(); + let x = Fp::random(rng); + let y = domain.rotate_omega(x, next); + let avx = eval_polynomial(&ax, x); + let bvx = eval_polynomial(&bx, x); + let cvy = eval_polynomial(&cx, y); + + let mut transcript = crate::transcript::Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]); + create_proof( + ¶ms, + &mut transcript, + std::iter::empty() + .chain(Some(ProverQuery { + point: x, + rotation: cur, + poly: &ax, + })) + .chain(Some(ProverQuery { + point: x, + rotation: cur, + poly: &bx, + })) + .chain(Some(ProverQuery { + point: y, + rotation: Rotation::next(), + poly: &cx, + })), + ) + .unwrap(); + let proof = transcript.finalize(); + + { + let mut proof = &proof[..]; + let mut transcript = + crate::transcript::Blake2bRead::<_, _, Challenge255<_>>::init(&mut proof); + + let pair = verify_proof( + ¶ms_verifier, + &mut transcript, + std::iter::empty() + .chain(Some(VerifierQuery::new_commitment(&a, x, cur, avx))) + .chain(Some(VerifierQuery::new_commitment(&b, x, cur, avx))) // NB: wrong! + .chain(Some(VerifierQuery::new_commitment(&c, y, next, cvy))), + ) + .unwrap(); + + // Should fail. + assert!(!Decider::verify(¶ms_verifier, pair)); + } + + { + let mut proof = &proof[..]; + + let mut transcript = + crate::transcript::Blake2bRead::<_, _, Challenge255<_>>::init(&mut proof); + + let guard = verify_proof( + ¶ms_verifier, + &mut transcript, + std::iter::empty() + .chain(Some(VerifierQuery::new_commitment(&a, x, cur, avx))) + .chain(Some(VerifierQuery::new_commitment(&b, x, cur, bvx))) + .chain(Some(VerifierQuery::new_commitment(&c, y, next, cvy))), + ) + .unwrap(); + + // Should succeed. + assert!(Decider::verify(¶ms_verifier, guard)); + } + } + + #[test] + fn test_multiopen() { + const K: u32 = 3; + + let params = Params::::unsafe_setup::(K); + let params_verifier: ParamsVerifier = params.verifier(0).unwrap(); + + let rotation_sets_init = vec![ + vec![1i32, 2, 3], + vec![2, 3, 4], + vec![2, 3, 4], + vec![4, 5, 6, 7], + vec![8], + vec![9], + vec![10, 11], + vec![10, 11], + vec![10, 11], + ]; + let commitment_per_set: Vec = rotation_sets_init + .iter() + .enumerate() + .map(|(i, _)| i) + .collect(); + let rotation_sets: Vec> = rotation_sets_init + .into_iter() + .map(|rot_set| { + rot_set + .into_iter() + .map(|i| (Rotation(i), Fr::from(i as u64))) + .collect() + }) + .collect(); + + let mut prover_queries = vec![]; + let mut verifier_queries = vec![]; + + #[allow(clippy::type_complexity)] + let (polynomials, commitments): ( + Vec>>, + Vec>, + ) = rotation_sets + .iter() + .enumerate() + .map(|(i, _)| { + (0..commitment_per_set[i]) + .map(|_| { + let poly = rand_poly(params.n as usize, OsRng); + let commitment: G1Affine = params.commit(&poly).into(); + (poly, commitment) + }) + .unzip() + }) + .unzip(); + + for (i, rotation_set) in rotation_sets.iter().enumerate() { + for (rot, point) in rotation_set.iter() { + for j in 0..commitment_per_set[i] { + { + let query: ProverQuery = ProverQuery { + poly: &polynomials[i][j], + point: *point, + rotation: *rot, + }; + prover_queries.push(query); + } + + { + let poly = &polynomials[i][j]; + let commitment: &G1Affine = &commitments[i][j]; + let eval = eval_polynomial(poly, *point); + let query = VerifierQuery::new_commitment(commitment, *point, *rot, eval); + verifier_queries.push(query); + } + } + } + } + + // prover + let proof = { + let mut transcript = Blake2bWrite::<_, G1Affine, Challenge255<_>>::init(vec![]); + create_proof(¶ms, &mut transcript, prover_queries).unwrap(); + transcript.finalize() + }; + + // verifier + { + let mut transcript = Blake2bRead::<_, G1Affine, Challenge255<_>>::init(&proof[..]); + let pair = verify_proof(¶ms_verifier, &mut transcript, verifier_queries).unwrap(); + assert!(Decider::verify(¶ms_verifier, pair)); + } + } +} From a1b4726cf5e5f273bebeb685304d2dab76add33c Mon Sep 17 00:00:00 2001 From: zhenfei Date: Mon, 5 Sep 2022 15:10:50 -0400 Subject: [PATCH 08/62] clean up after merge --- halo2_proofs/src/dev.rs | 31 ----------- halo2_proofs/src/helpers.rs | 18 +++---- halo2_proofs/src/plonk/lookup.rs | 1 - halo2_proofs/src/plonk/prover.rs | 61 +++++++--------------- halo2_proofs/src/plonk/vanishing/prover.rs | 14 ++--- halo2_proofs/src/transcript/blake2b.rs | 50 +++++++++--------- halo2_proofs/src/transcript/poseidon.rs | 7 ++- halo2_proofs/tests/plonk_api.rs | 1 - 8 files changed, 65 insertions(+), 118 deletions(-) diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index e36cc195a1..ea4e84c0e4 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -478,37 +478,6 @@ impl Assignment for MockProver { } } -fn home_made_par_iter_flat_map( - row_indexes: &[usize], - f: Fun, -) -> Vec -where - Fun: Fn(i32) -> Vec, -{ - if ISPAR { - row_indexes - .par_iter() - .flat_map(|row| f(*row as i32)) - .collect() - } else { - row_indexes.iter().flat_map(|row| f(*row as i32)).collect() - } -} - -fn home_made_par_iter_map( - row_indexes: &[usize], - f: Fun, -) -> Vec -where - Fun: Fn(i32) -> U, -{ - if ISPAR { - row_indexes.par_iter().map(|row| f(*row as i32)).collect() - } else { - row_indexes.iter().map(|row| f(*row as i32)).collect() - } -} - impl MockProver { /// Runs a synthetic keygen-and-prove operation on the given circuit, collecting data /// about the constraints and their assignments. diff --git a/halo2_proofs/src/helpers.rs b/halo2_proofs/src/helpers.rs index 382b88581f..aef72b8338 100644 --- a/halo2_proofs/src/helpers.rs +++ b/halo2_proofs/src/helpers.rs @@ -26,12 +26,12 @@ pub fn bn_to_field(bn: &BigUint) -> F { let mut buf = bn.to_bytes_le(); buf.resize(64, 0u8); - let mut buf_array = [0u8;64]; + let mut buf_array = [0u8; 64]; buf_array.copy_from_slice(buf.as_ref()); F::from_bytes_wide(&buf_array) } -/// Input a base field element `b`, output a scalar field +/// Input a base field element `b`, output a scalar field /// element `s` s.t. `s == b % ScalarField::MODULUS` pub(crate) fn base_to_scalar(base: &C::Base) -> C::Scalar { let bn = field_to_bn(base); @@ -41,23 +41,23 @@ pub(crate) fn base_to_scalar(base: &C::Base) -> C::Scalar { #[cfg(test)] mod test { - use halo2curves::bn256::{G1Affine, Fq}; - use rand_core::OsRng; use super::*; + use halo2curves::bn256::{Fq, G1Affine}; + use rand_core::OsRng; #[test] - fn test_conversion(){ + fn test_conversion() { // random numbers - for _ in 0..100{ + for _ in 0..100 { let b = Fq::random(OsRng); let bi = field_to_bn(&b); let b_rec = bn_to_field(&bi); assert_eq!(b, b_rec); - // TODO: FIXME let s = base_to_scalar::(&b); let si = field_to_bn(&s); + // TODO: fixme -- this test has a small probability to fail + // because |base field| > |scalar field| assert_eq!(si, bi); } } - -} \ No newline at end of file +} diff --git a/halo2_proofs/src/plonk/lookup.rs b/halo2_proofs/src/plonk/lookup.rs index f10306f2f2..e0d0db5c0c 100644 --- a/halo2_proofs/src/plonk/lookup.rs +++ b/halo2_proofs/src/plonk/lookup.rs @@ -12,7 +12,6 @@ pub struct Argument { pub table_expressions: Vec>, } - impl Debug for Argument { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Argument") diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index 2406af08ad..eeb9acab36 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -299,48 +299,23 @@ pub fn create_proof< .iter() .map(|_| Blind(Scheme::Scalar::random(&mut rng))) .collect(); - - let unusable_rows_start = params.n() as usize - (meta.blinding_factors() + 1); - - let mut witness = WitnessCollection { - k: params.k(), - advice: vec![domain.empty_lagrange_assigned(); meta.num_advice_columns], - instances, - // The prover will not be allowed to assign values to advice - // cells that exist within inactive rows, which include some - // number of blinding factors and an extra row for use in the - // permutation argument. - usable_rows: ..unusable_rows_start, - _marker: std::marker::PhantomData, - }; - - // Synthesize the circuit to obtain the witness and other information. - ConcreteCircuit::FloorPlanner::synthesize( - &mut witness, - circuit, - config.clone(), - meta.constants.clone(), - )?; - - let mut advice = batch_invert_assigned(witness.advice); - - // Add blinding factors to advice columns - for advic in &mut advice { - //for cell in &mut advice[unusable_rows_start..] { - //*cell = C::Scalar::random(&mut rng); - //*cell = C::Scalar::one(); - //} - let idx = advic.len() - 1; - advic[idx] = Scheme::Scalar::one(); - } - - let advice_commitments_projective: Vec<_> = advice - .iter().zip(advice_blinds.iter()) - .map(|(poly, blind)| params.commit_lagrange(poly,*blind)) - .collect(); - let mut advice_commitments = vec![Scheme::Curve::identity(); advice_commitments_projective.len()]; - ::CurveExt::batch_normalize(&advice_commitments_projective, &mut advice_commitments); - drop(advice_commitments_projective); + let advice_commitments_projective: Vec<_> = advice + .iter() + .zip(advice_blinds.iter()) + .map(|(poly, blind)| params.commit_lagrange(poly, *blind)) + .collect(); + let mut advice_commitments = + vec![Scheme::Curve::identity(); advice_commitments_projective.len()]; + ::CurveExt::batch_normalize( + &advice_commitments_projective, + &mut advice_commitments, + ); + let advice_commitments = advice_commitments; + drop(advice_commitments_projective); + + for commitment in &advice_commitments { + transcript.write_point(*commitment)?; + } Ok(AdviceSingle { advice_polys: advice, @@ -593,4 +568,4 @@ pub fn create_proof< prover .create_proof(rng, transcript, instances) .map_err(|_| Error::ConstraintSystemFailure) -} +} \ No newline at end of file diff --git a/halo2_proofs/src/plonk/vanishing/prover.rs b/halo2_proofs/src/plonk/vanishing/prover.rs index 7c1783c188..d85f2988e4 100644 --- a/halo2_proofs/src/plonk/vanishing/prover.rs +++ b/halo2_proofs/src/plonk/vanishing/prover.rs @@ -34,6 +34,9 @@ pub(in crate::plonk) struct Evaluated { } impl Argument { + /// This commitment scheme commits to a _zero polynomial_, + /// that means our commitment scheme is binding but not hidding. + /// This is fine for schemes that does not require zero-knowledge. pub(in crate::plonk) fn commit< 'params, P: ParamsProver<'params, C>, @@ -41,21 +44,18 @@ impl Argument { R: RngCore, T: TranscriptWrite, >( - params: &P, + _params: &P, domain: &EvaluationDomain, mut _rng: R, transcript: &mut T, ) -> Result, Error> { // Sample a random polynomial of degree n - 1 let random_poly = domain.empty_coeff(); - //for coeff in random_poly.iter_mut() { - // *coeff = C::Scalar::random(&mut rng); - //} - + // Sample a random blinding factor let random_blind = Blind(C::Scalar::zero()); - // Commit - //let c = params.commit(&random_poly).to_affine(); let c = C::identity(); + // We write the identity point to the transcript which + // is the commitment of the zero polynomial. transcript.write_point(c)?; Ok(Committed { diff --git a/halo2_proofs/src/transcript/blake2b.rs b/halo2_proofs/src/transcript/blake2b.rs index a6bdd54468..99954e6efd 100644 --- a/halo2_proofs/src/transcript/blake2b.rs +++ b/halo2_proofs/src/transcript/blake2b.rs @@ -52,9 +52,12 @@ impl TranscriptRead> fn read_point(&mut self) -> io::Result { let mut compressed = C::Repr::default(); self.reader.read_exact(compressed.as_mut())?; - let point: C = Option::from(C::from_bytes(&compressed)).ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof") - })?; + let point: C = match Option::from(C::from_bytes(&compressed)) { + Some(p) => p, + // TODO: check that this is actually safe to push an + // identity point to the transcript + None => C::identity(), + }; self.common_point(point)?; Ok(point) @@ -63,12 +66,12 @@ impl TranscriptRead> fn read_scalar(&mut self) -> io::Result { let mut data = ::Repr::default(); self.reader.read_exact(data.as_mut())?; - let scalar: C::Scalar = Option::from(C::Scalar::from_repr(data)).ok_or_else(|| { - io::Error::new( - io::ErrorKind::Other, - "invalid field element encoding in proof", - ) - })?; + let scalar = match Option::from(C::Scalar::from_repr(data)) { + Some(p) => p, + // TODO: check that this is actually safe to push an + // identity point to the transcript + None => C::Scalar::zero(), + }; self.common_scalar(scalar)?; Ok(scalar) @@ -87,22 +90,21 @@ impl Transcript> // This function is slightly modified from PSE's version. // In PSE's version, an error is returned if the input point is infinity. - // Here we want to be able to absorb infinity point because of the + // Here we want to be able to absorb infinity point because of the // randomness we used in the polynomial commitment is 0. fn common_point(&mut self, point: C) -> io::Result<()> { self.state.update(&[BLAKE2B_PREFIX_POINT]); - let tmp:Option> = Option::from(point.coordinates()); + let tmp: Option> = Option::from(point.coordinates()); match tmp { - - Some(coords)=>{ + Some(coords) => { self.state.update(coords.x().to_repr().as_ref()); self.state.update(coords.y().to_repr().as_ref()); - }, - None =>{ + } + None => { // Infinity point - self.state.update(&C::Base::zero().to_repr().as_ref()); - self.state.update(&C::Base::from(5).to_repr().as_ref()); + self.state.update(C::Base::zero().to_repr().as_ref()); + self.state.update(C::Base::from(5).to_repr().as_ref()); } } Ok(()) @@ -171,20 +173,20 @@ impl Transcript> // This function is slightly modified from PSE's version. // In PSE's version, an error is returned if the input point is infinity. - // Here we want to be able to absorb infinity point because of the + // Here we want to be able to absorb infinity point because of the // randomness we used in the polynomial commitment is 0. fn common_point(&mut self, point: C) -> io::Result<()> { self.state.update(&[BLAKE2B_PREFIX_POINT]); - let tmp:Option> = Option::from(point.coordinates()); + let tmp: Option> = Option::from(point.coordinates()); match tmp { - Some(coords)=>{ + Some(coords) => { self.state.update(coords.x().to_repr().as_ref()); self.state.update(coords.y().to_repr().as_ref()); - }, - None =>{ + } + None => { // Infinity point - self.state.update(&C::Base::zero().to_repr().as_ref()); - self.state.update(&C::Base::from(5).to_repr().as_ref()); + self.state.update(C::Base::zero().to_repr().as_ref()); + self.state.update(C::Base::from(5).to_repr().as_ref()); } } diff --git a/halo2_proofs/src/transcript/poseidon.rs b/halo2_proofs/src/transcript/poseidon.rs index a37b3a1a0e..672db710bd 100644 --- a/halo2_proofs/src/transcript/poseidon.rs +++ b/halo2_proofs/src/transcript/poseidon.rs @@ -39,7 +39,10 @@ impl TranscriptRead> let mut compressed = C::Repr::default(); self.reader.read_exact(compressed.as_mut())?; let point: C = Option::from(C::from_bytes(&compressed)).ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof") + io::Error::new( + io::ErrorKind::Other, + "invalid point encoding in proof for poseidon", + ) })?; self.common_point(point)?; @@ -52,7 +55,7 @@ impl TranscriptRead> let scalar: C::Scalar = Option::from(C::Scalar::from_repr(data)).ok_or_else(|| { io::Error::new( io::ErrorKind::Other, - "invalid field element encoding in proof", + "invalid field element encoding in proof for poseidon", ) })?; self.common_scalar(scalar)?; diff --git a/halo2_proofs/tests/plonk_api.rs b/halo2_proofs/tests/plonk_api.rs index af63b5fb30..913762c0da 100644 --- a/halo2_proofs/tests/plonk_api.rs +++ b/halo2_proofs/tests/plonk_api.rs @@ -1020,7 +1020,6 @@ fn plonk_api() { ); } } - test_plonk_api_ipa(); test_plonk_api_gwc(); test_plonk_api_shplonk(); From 4b53eee6d3f2db2f525e69d2f0d8baddeb7e417c Mon Sep 17 00:00:00 2001 From: zhenfei Date: Fri, 9 Sep 2022 20:47:04 -0400 Subject: [PATCH 09/62] address comments --- halo2_proofs/src/plonk/prover.rs | 13 ++++++++----- halo2_proofs/src/poly/kzg/commitment.rs | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index eeb9acab36..1001fa7db3 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -288,10 +288,13 @@ pub fn create_proof< let mut advice = batch_invert_assigned(witness.advice); // Add blinding factors to advice columns - for advice in &mut advice { - for cell in &mut advice[unusable_rows_start..] { - *cell = Scheme::Scalar::random(&mut rng); - } + for advic in &mut advice { + //for cell in &mut advice[unusable_rows_start..] { + //*cell = C::Scalar::random(&mut rng); + //*cell = C::Scalar::one(); + //} + let idx = advic.len() - 1; + advic[idx] = Scheme::Scalar::one(); } // Compute commitments to advice column polynomials @@ -568,4 +571,4 @@ pub fn create_proof< prover .create_proof(rng, transcript, instances) .map_err(|_| Error::ConstraintSystemFailure) -} \ No newline at end of file +} diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index 3e8cce6d09..e0517a727b 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -54,6 +54,20 @@ impl ParamsKZG { /// Initializes parameters for the curve, draws toxic secret from given rng. /// MUST NOT be used in production. pub fn setup(k: u32, rng: R) -> Self { + let s = ::random(rng); + Self::unsafe_setup_with_s(k, s) + } + + /// Initializes parameters for the curve, Draws random toxic point inside of the function + /// MUST NOT be used in production + pub fn unsafe_setup(k: u32) -> Self { + let s = E::Scalar::random(OsRng); + Self::unsafe_setup_with_s(k, s) + } + + /// Initializes parameters for the curve, using given random `s` + /// MUST NOT be used in production + pub fn unsafe_setup_with_s(k: u32, s: ::Scalar) -> Self { // Largest root of unity exponent of the Engine is `2^E::Scalar::S`, so we can // only support FFTs of polynomials below degree `2^E::Scalar::S`. assert!(k <= E::Scalar::S); @@ -61,8 +75,6 @@ impl ParamsKZG { // Calculate g = [G1, [s] G1, [s^2] G1, ..., [s^(n-1)] G1] in parallel. let g1 = E::G1Affine::generator(); - let s = ::random(rng); - let mut g_projective = vec![E::G1::group_zero(); n as usize]; parallelize(&mut g_projective, |g, start| { let mut current_g: E::G1 = g1.into(); From be443ceeca47e9ad3916816f90f141098934d6de Mon Sep 17 00:00:00 2001 From: zhenfei Date: Sat, 10 Sep 2022 22:57:10 -0400 Subject: [PATCH 10/62] bring back reader and writer --- halo2_proofs/src/plonk.rs | 32 +++++++++++++++++++++++++++ halo2_proofs/src/plonk/permutation.rs | 17 ++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index f9a6587af6..164d68bcff 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -7,6 +7,7 @@ use blake2b_simd::Params as Blake2bParams; use group::ff::Field; +use halo2curves::pairing::Engine; use crate::arithmetic::{CurveAffine, FieldExt}; use crate::helpers::CurveRead; @@ -53,6 +54,37 @@ pub struct VerifyingKey { } impl VerifyingKey { + /// Writes a verifying key to a buffer. + pub fn write(&self, writer: &mut W) -> io::Result<()> { + for commitment in &self.fixed_commitments { + writer.write_all(commitment.to_bytes().as_ref())?; + } + self.permutation.write(writer)?; + + Ok(()) + } + + /// Reads a verification key from a buffer. + pub fn read< + 'param, + R: io::Read, + ConcreteCircuit: Circuit, + E: Engine, + P: Params<'param, C>, + >( + reader: &mut R, + params: &P, + ) -> io::Result { + let (domain, cs, _) = keygen::create_domain::(params.k()); + + let fixed_commitments: Vec<_> = (0..cs.num_fixed_columns) + .map(|_| C::read(reader)) + .collect::>()?; + + let permutation = permutation::VerifyingKey::read(reader, &cs.permutation)?; + Ok(Self::from_parts(domain, fixed_commitments, permutation, cs)) + } + fn from_parts( domain: EvaluationDomain, fixed_commitments: Vec, diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index bd15cff05b..765a1cf975 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -85,6 +85,23 @@ impl VerifyingKey { } } +impl VerifyingKey { + pub(crate) fn write(&self, writer: &mut W) -> io::Result<()> { + for commitment in &self.commitments { + writer.write_all(commitment.to_bytes().as_ref())?; + } + + Ok(()) + } + + pub(crate) fn read(reader: &mut R, argument: &Argument) -> io::Result { + let commitments = (0..argument.columns.len()) + .map(|_| C::read(reader)) + .collect::, _>>()?; + Ok(VerifyingKey { commitments }) + } +} + /// The proving key for a single permutation argument. #[derive(Clone, Debug)] pub(crate) struct ProvingKey { From 8c6b1666140c92e09849fd332fc201b34e8422a5 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Tue, 20 Sep 2022 12:37:05 +0800 Subject: [PATCH 11/62] revert halo2_proofs/src/dev.rs as upstream --- halo2_proofs/src/dev.rs | 362 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 355 insertions(+), 7 deletions(-) diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index ea4e84c0e4..68d211cde7 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -1,4 +1,5 @@ //! Tools for developing circuits. + use std::collections::HashMap; use std::collections::HashSet; use std::fmt; @@ -7,12 +8,6 @@ use std::ops::{Add, Mul, Neg, Range}; use std::time::{Duration, Instant}; use ff::Field; -use rand_core::OsRng; -use rayon::iter::IndexedParallelIterator; -use rayon::iter::IntoParallelIterator; -use rayon::iter::IntoParallelRefIterator; -use rayon::iter::ParallelIterator; -use rayon::prelude::ParallelSliceMut; use crate::plonk::Assigned; use crate::{ @@ -24,6 +19,12 @@ use crate::{ }, poly::Rotation, }; +use rayon::{ + iter::{ + IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, ParallelIterator, + }, + slice::ParallelSliceMut, +}; pub mod metadata; mod util; @@ -564,7 +565,354 @@ impl MockProver { /// Returns `Ok(())` if this `MockProver` is satisfied, or a list of errors indicating /// the reasons that the circuit is not satisfied. pub fn verify(&self) -> Result<(), Vec> { - self.verify_at_rows_par(self.usable_rows.clone(), self.usable_rows.clone()) + self.verify_at_rows(self.usable_rows.clone(), self.usable_rows.clone()) + } + + /// Returns `Ok(())` if this `MockProver` is satisfied, or a list of errors indicating + /// the reasons that the circuit is not satisfied. + /// Constraints are only checked at `gate_row_ids`, + /// and lookup inputs are only checked at `lookup_input_row_ids` + pub fn verify_at_rows>( + &self, + gate_row_ids: I, + lookup_input_row_ids: I, + ) -> Result<(), Vec> { + let n = self.n as i32; + + // check all the row ids are valid + for row_id in gate_row_ids.clone() { + if !self.usable_rows.contains(&row_id) { + panic!("invalid gate row id {}", row_id) + } + } + for row_id in lookup_input_row_ids.clone() { + if !self.usable_rows.contains(&row_id) { + panic!("invalid lookup row id {}", row_id) + } + } + + // Check that within each region, all cells used in instantiated gates have been + // assigned to. + let selector_errors = self.regions.iter().enumerate().flat_map(|(r_i, r)| { + r.enabled_selectors.iter().flat_map(move |(selector, at)| { + // Find the gates enabled by this selector + self.cs + .gates + .iter() + // Assume that if a queried selector is enabled, the user wants to use the + // corresponding gate in some way. + // + // TODO: This will trip up on the reverse case, where leaving a selector + // un-enabled keeps a gate enabled. We could alternatively require that + // every selector is explicitly enabled or disabled on every row? But that + // seems messy and confusing. + .enumerate() + .filter(move |(_, g)| g.queried_selectors().contains(selector)) + .flat_map(move |(gate_index, gate)| { + at.iter().flat_map(move |selector_row| { + // Selectors are queried with no rotation. + let gate_row = *selector_row as i32; + + gate.queried_cells().iter().filter_map(move |cell| { + // Determine where this cell should have been assigned. + let cell_row = ((gate_row + n + cell.rotation.0) % n) as usize; + + // Check that it was assigned! + if r.cells.contains_key(&(cell.column, cell_row)) { + None + } else { + Some(VerifyFailure::CellNotAssigned { + gate: (gate_index, gate.name()).into(), + region: (r_i, r.name.clone()).into(), + gate_offset: *selector_row, + column: cell.column, + offset: cell_row as isize - r.rows.unwrap().0 as isize, + }) + } + }) + }) + }) + }) + }); + + // Check that all gates are satisfied for all rows. + let gate_errors = + self.cs + .gates + .iter() + .enumerate() + .flat_map(|(gate_index, gate)| { + let blinding_rows = + (self.n as usize - (self.cs.blinding_factors() + 1))..(self.n as usize); + (gate_row_ids + .clone() + .into_iter() + .chain(blinding_rows.into_iter())) + .flat_map(move |row| { + let row = row as i32 + n; + gate.polynomials().iter().enumerate().filter_map( + move |(poly_index, poly)| match poly.evaluate_lazy( + &|scalar| Value::Real(scalar), + &|_| panic!("virtual selectors are removed during optimization"), + &util::load(n, row, &self.cs.fixed_queries, &self.fixed), + &util::load(n, row, &self.cs.advice_queries, &self.advice), + &util::load_instance( + n, + row, + &self.cs.instance_queries, + &self.instance, + ), + &|a| -a, + &|a, b| a + b, + &|a, b| a * b, + &|a, scalar| a * scalar, + &Value::Real(F::zero()), + ) { + Value::Real(x) if x.is_zero_vartime() => None, + Value::Real(_) => Some(VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (gate_index, gate.name()).into(), + poly_index, + gate.constraint_name(poly_index), + ) + .into(), + location: FailureLocation::find_expressions( + &self.cs, + &self.regions, + (row - n) as usize, + Some(poly).into_iter(), + ), + cell_values: util::cell_values( + gate, + poly, + &util::load(n, row, &self.cs.fixed_queries, &self.fixed), + &util::load(n, row, &self.cs.advice_queries, &self.advice), + &util::load_instance( + n, + row, + &self.cs.instance_queries, + &self.instance, + ), + ), + }), + Value::Poison => Some(VerifyFailure::ConstraintPoisoned { + constraint: ( + (gate_index, gate.name()).into(), + poly_index, + gate.constraint_name(poly_index), + ) + .into(), + }), + }, + ) + }) + }); + + let mut cached_table = Vec::new(); + let mut cached_table_identifier = Vec::new(); + // Check that all lookups exist in their respective tables. + let lookup_errors = + self.cs + .lookups + .iter() + .enumerate() + .flat_map(|(lookup_index, lookup)| { + let load = |expression: &Expression, row| { + expression.evaluate_lazy( + &|scalar| Value::Real(scalar), + &|_| panic!("virtual selectors are removed during optimization"), + &|query| { + let query = self.cs.fixed_queries[query.index]; + let column_index = query.0.index(); + let rotation = query.1 .0; + self.fixed[column_index] + [(row as i32 + n + rotation) as usize % n as usize] + .into() + }, + &|query| { + let query = self.cs.advice_queries[query.index]; + let column_index = query.0.index(); + let rotation = query.1 .0; + self.advice[column_index] + [(row as i32 + n + rotation) as usize % n as usize] + .into() + }, + &|query| { + let query = self.cs.instance_queries[query.index]; + let column_index = query.0.index(); + let rotation = query.1 .0; + Value::Real( + self.instance[column_index] + [(row as i32 + n + rotation) as usize % n as usize], + ) + }, + &|a| -a, + &|a, b| a + b, + &|a, b| a * b, + &|a, scalar| a * scalar, + &Value::Real(F::zero()), + ) + }; + + assert!(lookup.table_expressions.len() == lookup.input_expressions.len()); + assert!(self.usable_rows.end > 0); + + // We optimize on the basis that the table might have been filled so that the last + // usable row now has the fill contents (it doesn't matter if there was no filling). + // Note that this "fill row" necessarily exists in the table, and we use that fact to + // slightly simplify the optimization: we're only trying to check that all input rows + // are contained in the table, and so we can safely just drop input rows that + // match the fill row. + let fill_row: Vec<_> = lookup + .table_expressions + .iter() + .map(move |c| load(c, self.usable_rows.end - 1)) + .collect(); + + let table_identifier = lookup + .table_expressions + .iter() + .map(Expression::identifier) + .collect::>(); + if table_identifier != cached_table_identifier { + cached_table_identifier = table_identifier; + + // In the real prover, the lookup expressions are never enforced on + // unusable rows, due to the (1 - (l_last(X) + l_blind(X))) term. + cached_table = self + .usable_rows + .clone() + .filter_map(|table_row| { + let t = lookup + .table_expressions + .iter() + .map(move |c| load(c, table_row)) + .collect(); + + if t != fill_row { + Some(t) + } else { + None + } + }) + .collect(); + cached_table.sort_unstable(); + } + let table = &cached_table; + + let mut inputs: Vec<(Vec<_>, usize)> = lookup_input_row_ids + .clone() + .into_iter() + .filter_map(|input_row| { + let t = lookup + .input_expressions + .iter() + .map(move |c| load(c, input_row)) + .collect(); + + if t != fill_row { + // Also keep track of the original input row, since we're going to sort. + Some((t, input_row)) + } else { + None + } + }) + .collect(); + inputs.sort_unstable(); + + let mut i = 0; + inputs + .iter() + .filter_map(move |(input, input_row)| { + while i < table.len() && &table[i] < input { + i += 1; + } + if i == table.len() || &table[i] > input { + assert!(table.binary_search(input).is_err()); + + Some(VerifyFailure::Lookup { + name: lookup.name, + lookup_index, + location: FailureLocation::find_expressions( + &self.cs, + &self.regions, + *input_row, + lookup.input_expressions.iter(), + ), + }) + } else { + None + } + }) + .collect::>() + }); + + // Check that permutations preserve the original values of the cells. + let perm_errors = { + // Original values of columns involved in the permutation. + let original = |column, row| { + self.cs + .permutation + .get_columns() + .get(column) + .map(|c: &Column| match c.column_type() { + Any::Advice => self.advice[c.index()][row], + Any::Fixed => self.fixed[c.index()][row], + Any::Instance => CellValue::Assigned(self.instance[c.index()][row]), + }) + .unwrap() + }; + + // Iterate over each column of the permutation + self.permutation + .mapping + .iter() + .enumerate() + .flat_map(move |(column, values)| { + // Iterate over each row of the column to check that the cell's + // value is preserved by the mapping. + values.iter().enumerate().filter_map(move |(row, cell)| { + let original_cell = original(column, row); + let permuted_cell = original(cell.0, cell.1); + if original_cell == permuted_cell { + None + } else { + let columns = self.cs.permutation.get_columns(); + let column = columns.get(column).unwrap(); + Some(VerifyFailure::Permutation { + column: (*column).into(), + location: FailureLocation::find( + &self.regions, + row, + Some(column).into_iter().cloned().collect(), + ), + }) + } + }) + }) + }; + + let mut errors: Vec<_> = iter::empty() + .chain(selector_errors) + .chain(gate_errors) + .chain(lookup_errors) + .chain(perm_errors) + .collect(); + if errors.is_empty() { + Ok(()) + } else { + // Remove any duplicate `ConstraintPoisoned` errors (we check all unavailable + // rows in case the trigger is row-specific, but the error message only points + // at the constraint). + errors.dedup_by(|a, b| match (a, b) { + ( + a @ VerifyFailure::ConstraintPoisoned { .. }, + b @ VerifyFailure::ConstraintPoisoned { .. }, + ) => a == b, + _ => false, + }); + Err(errors) + } } /// Returns `Ok(())` if this `MockProver` is satisfied, or a list of errors indicating From 1bd4afde45a11f9ea809f0c407adec91e12ed70d Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 21 Sep 2022 14:07:58 +0800 Subject: [PATCH 12/62] add is_none to Value --- halo2_proofs/src/circuit/value.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/halo2_proofs/src/circuit/value.rs b/halo2_proofs/src/circuit/value.rs index e6ae26cd1b..ca31dffda9 100644 --- a/halo2_proofs/src/circuit/value.rs +++ b/halo2_proofs/src/circuit/value.rs @@ -49,6 +49,11 @@ impl Value { self.inner.ok_or(Error::Synthesis) } + /// ... + pub fn is_none(&self) -> bool { + self.inner.is_none() + } + /// Converts from `&Value` to `Value<&V>`. pub fn as_ref(&self) -> Value<&V> { Value { From b04667b8faa65694d7c9c601707cf820de9c54bf Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Tue, 27 Sep 2022 14:07:03 +0800 Subject: [PATCH 13/62] expose inner --- halo2_proofs/src/circuit/value.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/halo2_proofs/src/circuit/value.rs b/halo2_proofs/src/circuit/value.rs index ca31dffda9..920b70d330 100644 --- a/halo2_proofs/src/circuit/value.rs +++ b/halo2_proofs/src/circuit/value.rs @@ -14,7 +14,8 @@ use crate::plonk::{Assigned, Error}; /// for improved usability. #[derive(Clone, Copy, Debug)] pub struct Value { - inner: Option, + /// for adhoc usage... + pub inner: Option, } impl Default for Value { From 3a5a6006a37f2b8ca8eae81324807d2937b7f4f4 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 12 Oct 2022 07:13:01 +0800 Subject: [PATCH 14/62] log pairing --- halo2_proofs/Cargo.toml | 3 ++- halo2_proofs/src/poly/kzg/msm.rs | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index b2e1e4b5f1..241e4f5073 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -62,6 +62,7 @@ num-bigint = { version = "0.4", features = ["rand"] } # Developer tooling dependencies plotters = { version = "0.3.0", optional = true } tabbycat = { version = "0.1", features = ["attributes"], optional = true } +log = "0.4.17" [dev-dependencies] assert_matches = "1.5" @@ -87,4 +88,4 @@ bench = false [[example]] name = "circuit-layout" -required-features = ["dev-graph"] \ No newline at end of file +required-features = ["dev-graph"] diff --git a/halo2_proofs/src/poly/kzg/msm.rs b/halo2_proofs/src/poly/kzg/msm.rs index 19754146a0..553057978b 100644 --- a/halo2_proofs/src/poly/kzg/msm.rs +++ b/halo2_proofs/src/poly/kzg/msm.rs @@ -152,8 +152,8 @@ impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E> { let s_g2_prepared = E::G2Prepared::from(self.params.s_g2); let n_g2_prepared = E::G2Prepared::from(-self.params.g2); - let left = self.left.eval(); - let right = self.right.eval(); + let left: ::G1Affine = self.left.eval().into(); + let right: ::G1Affine = self.right.eval().into(); let (term_1, term_2) = ( (&left.into(), &s_g2_prepared), @@ -161,6 +161,10 @@ impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E> { ); let terms = &[term_1, term_2]; + log::debug!( + "check pairing: {:?}", + (left, right, self.params.s_g2, -self.params.g2) + ); bool::from( E::multi_miller_loop(&terms[..]) .final_exponentiation() From 85bf2ed5ec7140a591759b50ecf7e725630ad089 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Thu, 13 Oct 2022 17:44:07 +0800 Subject: [PATCH 15/62] poseidon hash to 63 --- halo2_proofs/src/transcript/poseidon.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/halo2_proofs/src/transcript/poseidon.rs b/halo2_proofs/src/transcript/poseidon.rs index 672db710bd..d9da18a440 100644 --- a/halo2_proofs/src/transcript/poseidon.rs +++ b/halo2_proofs/src/transcript/poseidon.rs @@ -25,7 +25,7 @@ impl> PoseidonRead { /// Initialize a transcript given an input buffer. pub fn init(reader: R) -> Self { PoseidonRead { - state: Poseidon::new(8usize, 33usize), + state: Poseidon::new(8usize, 63usize), reader, _marker: PhantomData, } @@ -110,7 +110,7 @@ impl> PoseidonWrite { /// Initialize a transcript given an output buffer. pub fn init(writer: W) -> Self { PoseidonWrite { - state: Poseidon::new(8usize, 33usize), + state: Poseidon::new(8usize, 63usize), writer, _marker: PhantomData, } From a960c7ebe7152ad70d899d8d59b1bcca14bebc4d Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Fri, 14 Oct 2022 19:35:49 +0800 Subject: [PATCH 16/62] make query index public --- halo2_proofs/src/plonk/circuit.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index b3e7136490..f4184bad6a 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -282,6 +282,10 @@ pub struct FixedQuery { } impl FixedQuery { + /// Index + pub fn index(&self) -> usize { + self.index + } /// Column index pub fn column_index(&self) -> usize { self.column_index @@ -305,6 +309,10 @@ pub struct AdviceQuery { } impl AdviceQuery { + /// Index + pub fn index(&self) -> usize { + self.index + } /// Column index pub fn column_index(&self) -> usize { self.column_index @@ -328,6 +336,10 @@ pub struct InstanceQuery { } impl InstanceQuery { + /// Index + pub fn index(&self) -> usize { + self.index + } /// Column index pub fn column_index(&self) -> usize { self.column_index From 6f18f38e82d302cd8b6ce8809b59c32350b019a3 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Sat, 15 Oct 2022 13:48:36 +0800 Subject: [PATCH 17/62] make g_lagrange public --- halo2_proofs/src/poly/kzg/commitment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index e0517a727b..d7ce1cc02d 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -23,7 +23,7 @@ pub struct ParamsKZG { pub(crate) k: u32, pub(crate) n: u64, pub(crate) g: Vec, - pub(crate) g_lagrange: Vec, + pub g_lagrange: Vec, pub(crate) g2: E::G2Affine, pub(crate) s_g2: E::G2Affine, } From 9c2e786aeaafdce7970e45480a99f5d478357491 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Tue, 13 Dec 2022 17:34:37 +0800 Subject: [PATCH 18/62] lint --- halo2_proofs/src/poly/kzg/msm.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/halo2_proofs/src/poly/kzg/msm.rs b/halo2_proofs/src/poly/kzg/msm.rs index 553057978b..6cc90a5103 100644 --- a/halo2_proofs/src/poly/kzg/msm.rs +++ b/halo2_proofs/src/poly/kzg/msm.rs @@ -155,10 +155,7 @@ impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E> { let left: ::G1Affine = self.left.eval().into(); let right: ::G1Affine = self.right.eval().into(); - let (term_1, term_2) = ( - (&left.into(), &s_g2_prepared), - (&right.into(), &n_g2_prepared), - ); + let (term_1, term_2) = ((&left, &s_g2_prepared), (&right, &n_g2_prepared)); let terms = &[term_1, term_2]; log::debug!( From 5b38c9973fe5200833e26400f4d38842cf3ac855 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Tue, 13 Dec 2022 17:40:19 +0800 Subject: [PATCH 19/62] fix --- halo2_proofs/src/plonk/prover.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index cae9ea09b2..8d8e60b6d5 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -338,8 +338,8 @@ pub fn create_proof< //*cell = C::Scalar::random(&mut rng); //*cell = C::Scalar::one(); //} - let idx = advic.len() - 1; - advic[idx] = Scheme::Scalar::one(); + let idx = advice_values.len() - 1; + advice_values[idx] = Scheme::Scalar::one(); } // Compute commitments to advice column polynomials From 3f856797da5f9a3e122e1e54cc7606b9b6f60a86 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Tue, 13 Dec 2022 21:28:04 +0800 Subject: [PATCH 20/62] better logging with region shape --- halo2_proofs/src/circuit/floor_planner/v1.rs | 25 ++++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/halo2_proofs/src/circuit/floor_planner/v1.rs b/halo2_proofs/src/circuit/floor_planner/v1.rs index 62207a91a7..1a3b5b676b 100644 --- a/halo2_proofs/src/circuit/floor_planner/v1.rs +++ b/halo2_proofs/src/circuit/floor_planner/v1.rs @@ -73,10 +73,19 @@ impl FloorPlanner for V1 { .without_witnesses() .synthesize(config.clone(), V1Pass::<_, CS>::measure(pass))?; } + for (name, shape) in &measure.regions { + log::debug!("region height {}: {}", name, shape.row_count()) + } // Planning: // - Position the regions. - let (regions, column_allocations) = strategy::slot_in_biggest_advice_first(measure.regions); + let (regions, column_allocations) = strategy::slot_in_biggest_advice_first( + measure + .regions + .into_iter() + .map(|(_name, shape)| shape) + .collect(), + ); plan.regions = regions; // - Determine how many rows our planned circuit will require. @@ -170,7 +179,7 @@ impl<'p, 'a, F: Field, CS: Assignment + 'a> Layouter for V1Pass<'p, 'a, F, NR: Into, { match &mut self.0 { - Pass::Measurement(pass) => pass.assign_region(assignment), + Pass::Measurement(pass) => pass.assign_region(name, assignment), Pass::Assignment(pass) => pass.assign_region(name, assignment), } } @@ -230,7 +239,7 @@ impl<'p, 'a, F: Field, CS: Assignment + 'a> Layouter for V1Pass<'p, 'a, F, /// Measures the circuit. #[derive(Debug)] pub struct MeasurementPass { - regions: Vec, + regions: Vec<(String, RegionShape)>, } impl MeasurementPass { @@ -238,9 +247,15 @@ impl MeasurementPass { MeasurementPass { regions: vec![] } } - fn assign_region(&mut self, mut assignment: A) -> Result + fn assign_region( + &mut self, + name: N, + mut assignment: A, + ) -> Result where A: FnMut(Region<'_, F>) -> Result, + N: Fn() -> NR, + NR: Into, { let region_index = self.regions.len(); @@ -250,7 +265,7 @@ impl MeasurementPass { let region: &mut dyn RegionLayouter = &mut shape; assignment(region.into()) }?; - self.regions.push(shape); + self.regions.push((name().into(), shape)); Ok(result) } From 255634a2121357ae70f96e0cfe079bfa88bf9a3d Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Tue, 13 Dec 2022 21:28:04 +0800 Subject: [PATCH 21/62] better logging with region shape --- halo2_proofs/src/circuit/floor_planner/v1.rs | 25 ++++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/halo2_proofs/src/circuit/floor_planner/v1.rs b/halo2_proofs/src/circuit/floor_planner/v1.rs index 333d46278a..f8d2f03804 100644 --- a/halo2_proofs/src/circuit/floor_planner/v1.rs +++ b/halo2_proofs/src/circuit/floor_planner/v1.rs @@ -73,10 +73,19 @@ impl FloorPlanner for V1 { .without_witnesses() .synthesize(config.clone(), V1Pass::<_, CS>::measure(pass))?; } + for (name, shape) in &measure.regions { + log::debug!("region height {}: {}", name, shape.row_count()) + } // Planning: // - Position the regions. - let (regions, column_allocations) = strategy::slot_in_biggest_advice_first(measure.regions); + let (regions, column_allocations) = strategy::slot_in_biggest_advice_first( + measure + .regions + .into_iter() + .map(|(_name, shape)| shape) + .collect(), + ); plan.regions = regions; // - Determine how many rows our planned circuit will require. @@ -170,7 +179,7 @@ impl<'p, 'a, F: Field, CS: Assignment + 'a> Layouter for V1Pass<'p, 'a, F, NR: Into, { match &mut self.0 { - Pass::Measurement(pass) => pass.assign_region(assignment), + Pass::Measurement(pass) => pass.assign_region(name, assignment), Pass::Assignment(pass) => pass.assign_region(name, assignment), } } @@ -223,7 +232,7 @@ impl<'p, 'a, F: Field, CS: Assignment + 'a> Layouter for V1Pass<'p, 'a, F, /// Measures the circuit. #[derive(Debug)] pub struct MeasurementPass { - regions: Vec, + regions: Vec<(String, RegionShape)>, } impl MeasurementPass { @@ -231,9 +240,15 @@ impl MeasurementPass { MeasurementPass { regions: vec![] } } - fn assign_region(&mut self, mut assignment: A) -> Result + fn assign_region( + &mut self, + name: N, + mut assignment: A, + ) -> Result where A: FnMut(Region<'_, F>) -> Result, + N: Fn() -> NR, + NR: Into, { let region_index = self.regions.len(); @@ -243,7 +258,7 @@ impl MeasurementPass { let region: &mut dyn RegionLayouter = &mut shape; assignment(region.into()) }?; - self.regions.push(shape); + self.regions.push((name().into(), shape)); Ok(result) } From dedbb5ea0d6d6e3ee25911592166683204f007a1 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Tue, 13 Dec 2022 21:36:24 +0800 Subject: [PATCH 22/62] lint --- halo2_proofs/src/poly/kzg/msm.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/halo2_proofs/src/poly/kzg/msm.rs b/halo2_proofs/src/poly/kzg/msm.rs index 553057978b..6cc90a5103 100644 --- a/halo2_proofs/src/poly/kzg/msm.rs +++ b/halo2_proofs/src/poly/kzg/msm.rs @@ -155,10 +155,7 @@ impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E> { let left: ::G1Affine = self.left.eval().into(); let right: ::G1Affine = self.right.eval().into(); - let (term_1, term_2) = ( - (&left.into(), &s_g2_prepared), - (&right.into(), &n_g2_prepared), - ); + let (term_1, term_2) = ((&left, &s_g2_prepared), (&right, &n_g2_prepared)); let terms = &[term_1, term_2]; log::debug!( From 15dd97605554b9170c2f69cb26bf45e8b7f405a4 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 14 Dec 2022 11:47:30 +0800 Subject: [PATCH 23/62] log region shape --- halo2_proofs/src/circuit/floor_planner/single_pass.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index 33a6605206..2a6c45067b 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -90,6 +90,8 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a let region: &mut dyn RegionLayouter = &mut shape; assignment(region.into())?; } + let region_name: String = name().into(); + log::debug!("region row_count {}: {}", region_name, shape.row_count()); // Lay out this region. We implement the simplest approach here: position the // region starting at the earliest row for which none of the columns are in use. From 8860f0361e62381a9e05d5f1e02e53a70cb278ed Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Thu, 15 Dec 2022 22:43:39 +0800 Subject: [PATCH 24/62] log::warn region piling --- halo2_proofs/src/circuit/floor_planner/single_pass.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index 2a6c45067b..91e772e0f5 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -97,7 +97,16 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a // region starting at the earliest row for which none of the columns are in use. let mut region_start = 0; for column in &shape.columns { - region_start = cmp::max(region_start, self.columns.get(column).cloned().unwrap_or(0)); + let column_start = self.columns.get(column).cloned().unwrap_or(0); + if column_start != 0 { + log::warn!( + "columns {:?} reused between multi regions. Start: {}. Region: {}", + column, + column_start, + region_name + ); + } + region_start = cmp::max(region_start, column_start); } self.regions.push(region_start.into()); From b46c23bcda77fe01ac76099796e6ddeecdccb535 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Mon, 19 Dec 2022 15:17:12 +0800 Subject: [PATCH 25/62] make num_fixed_columns public --- halo2_proofs/src/plonk/circuit.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index f4184bad6a..7d9be66d84 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -1142,10 +1142,10 @@ impl Gate { /// permutation arrangements. #[derive(Debug, Clone)] pub struct ConstraintSystem { - pub(crate) num_fixed_columns: usize, + pub num_fixed_columns: usize, pub num_advice_columns: usize, pub num_instance_columns: usize, - pub(crate) num_selectors: usize, + pub num_selectors: usize, /// This is a cached vector that maps virtual selectors to the concrete /// fixed column that they were compressed into. This is just used by dev From 88f6fdae4037034dab3d7406f671d446adecf04d Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Mon, 19 Dec 2022 17:39:44 +0800 Subject: [PATCH 26/62] change some log level --- halo2_proofs/src/circuit/floor_planner/single_pass.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index 91e772e0f5..94cc426696 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -99,7 +99,7 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a for column in &shape.columns { let column_start = self.columns.get(column).cloned().unwrap_or(0); if column_start != 0 { - log::warn!( + log::debug!( "columns {:?} reused between multi regions. Start: {}. Region: {}", column, column_start, From b46b5ac8d0fb802a065e324aaea5dd9e26ca6703 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 21 Dec 2022 14:52:40 +0800 Subject: [PATCH 27/62] fix empty region failure panic --- halo2_proofs/src/dev/failure.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/halo2_proofs/src/dev/failure.rs b/halo2_proofs/src/dev/failure.rs index e98d964696..0cdaaffc14 100644 --- a/halo2_proofs/src/dev/failure.rs +++ b/halo2_proofs/src/dev/failure.rs @@ -89,6 +89,9 @@ impl FailureLocation { .iter() .enumerate() .find(|(_, r)| { + if r.rows.is_none() { + return false; + } let (start, end) = r.rows.unwrap(); // We match the region if any input columns overlap, rather than all of // them, because matching complex selector columns is hard. As long as From aa09e106e573a30ca9262c357619a6f2b75cdcbf Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Wed, 21 Dec 2022 12:16:56 -0500 Subject: [PATCH 28/62] feat: read `VerifyingKey` and `ProvingKey` does not require `params` as long as we serialize `params.k()` --- halo2_proofs/Cargo.toml | 6 ++- halo2_proofs/src/helpers.rs | 83 +++++++++++++++++++++++++++++++++---- halo2_proofs/src/plonk.rs | 70 +++++++++++++++++-------------- halo2_proofs/src/poly.rs | 8 ++-- 4 files changed, 121 insertions(+), 46 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index abf200061a..8231074902 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -48,7 +48,7 @@ backtrace = { version = "0.3", optional = true } rayon = "1.5.1" ff = "0.12" group = "0.12" -halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves', tag = '0.3.0' } +halo2curves = { git = 'https://github.com/jonathanpwang/halo2curves', branch = 'feat/serde-field' } rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" @@ -68,11 +68,13 @@ rand_core = { version = "0.6", default-features = false, features = ["getrandom" getrandom = { version = "0.2", features = ["js"] } [features] -default = ["batch"] +default = ["batch", "serde-raw"] dev-graph = ["plotters", "tabbycat"] gadget-traces = ["backtrace"] sanity-checks = [] batch = ["rand_core/getrandom"] +serde-raw = [] +raw-unchecked = ["serde-raw"] [lib] bench = false diff --git a/halo2_proofs/src/helpers.rs b/halo2_proofs/src/helpers.rs index f601eab984..eb42d0787e 100644 --- a/halo2_proofs/src/helpers.rs +++ b/halo2_proofs/src/helpers.rs @@ -1,9 +1,12 @@ use crate::poly::Polynomial; use ff::PrimeField; +#[cfg(feature = "serde-raw")] +use halo2curves::serde::SerdeObject; use halo2curves::CurveAffine; use std::io; -pub(crate) trait CurveRead: CurveAffine { +#[cfg(not(feature = "serde-raw"))] +pub(crate) trait SerdeCurveAffine: CurveAffine { /// Reads a compressed element from the buffer and attempts to parse it /// using `from_bytes`. fn read(reader: &mut R) -> io::Result { @@ -12,10 +15,45 @@ pub(crate) trait CurveRead: CurveAffine { Option::from(Self::from_bytes(&compressed)) .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Invalid point encoding in proof")) } + /// Writes a curve element as a compressed affine point in bytes. + fn write(&self, writer: &mut W) -> io::Result<()> { + writer.write_all(self.to_bytes().as_ref()) + } } +#[cfg(not(feature = "serde-raw"))] +impl SerdeCurveAffine for C {} -impl CurveRead for C {} +#[cfg(feature = "serde-raw")] +pub(crate) trait SerdeCurveAffine: CurveAffine + SerdeObject { + /// Reads a curve element from raw bytes. + /// The curve element is stored exactly as it is in memory (two field elements in Montgomery representation). + fn read(reader: &mut R) -> io::Result { + #[cfg(feature = "raw-unchecked")] + { + Ok(Self::read_raw_unchecked(reader)) + } + #[cfg(not(feature = "raw-unchecked"))] + { + Self::read_raw(reader) + } + } + /// Writes a curve element into raw bytes. + /// The curve element is stored exactly as it is in memory (two field elements in Montgomery representation). + fn write(&self, writer: &mut W) -> io::Result<()> { + #[cfg(feature = "raw-unchecked")] + { + Ok(self.write_raw_unchecked(writer)) + } + #[cfg(not(feature = "raw-unchecked"))] + { + self.write_raw(writer) + } + } +} +#[cfg(feature = "serde-raw")] +impl SerdeCurveAffine for C {} +#[cfg(not(feature = "serde-raw"))] pub(crate) trait SerdePrimeField: PrimeField { /// Reads a field element as bytes from the buffer using `from_repr`. /// Endianness is specified by `PrimeField` implementation. @@ -33,9 +71,38 @@ pub(crate) trait SerdePrimeField: PrimeField { writer.write_all(self.to_repr().as_ref()) } } - +#[cfg(not(feature = "serde-raw"))] impl SerdePrimeField for F {} +#[cfg(feature = "serde-raw")] +pub(crate) trait SerdePrimeField: PrimeField + SerdeObject { + /// Reads a field element from raw bytes in its internal Montgomery representation. + fn read(reader: &mut R) -> io::Result { + #[cfg(feature = "raw-unchecked")] + { + Ok(Self::read_raw_unchecked(reader)) + } + #[cfg(not(feature = "raw-unchecked"))] + { + Self::read_raw(reader) + } + } + /// Writes a field element into raw bytes in its internal Montgomery representation, + /// WITHOUT performing the expensive Montgomery reduction. + fn write(&self, writer: &mut W) -> io::Result<()> { + #[cfg(feature = "raw-unchecked")] + { + Ok(self.write_raw_unchecked(writer)) + } + #[cfg(not(feature = "raw-unchecked"))] + { + self.write_raw(writer) + } + } +} +#[cfg(feature = "serde-raw")] +impl SerdePrimeField for F {} + /// Convert a slice of `bool` into a `u8`. /// /// Panics if the slice has length greater than 8. @@ -56,12 +123,12 @@ pub fn unpack(byte: u8, bits: &mut [bool]) { } /// Reads a vector of polynomials from buffer -pub(crate) fn read_polynomial_vec( +pub(crate) fn read_polynomial_vec( reader: &mut R, ) -> io::Result>> { - let mut len_be_bytes = [0u8; 4]; - reader.read_exact(&mut len_be_bytes)?; - let len = u32::from_be_bytes(len_be_bytes); + let mut len = [0u8; 4]; + reader.read_exact(&mut len)?; + let len = u32::from_be_bytes(len); (0..len) .map(|_| Polynomial::::read(reader)) @@ -69,7 +136,7 @@ pub(crate) fn read_polynomial_vec( } /// Writes a slice of polynomials to buffer -pub(crate) fn write_polynomial_slice( +pub(crate) fn write_polynomial_slice( slice: &[Polynomial], writer: &mut W, ) -> io::Result<()> { diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index 70ae557eed..a2d9cf2af2 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -11,7 +11,7 @@ use group::ff::Field; use crate::arithmetic::{CurveAffine, FieldExt}; use crate::helpers::{ - polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice, CurveRead, + polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice, SerdeCurveAffine, SerdePrimeField, }; use crate::poly::{ @@ -57,9 +57,13 @@ pub struct VerifyingKey { selectors: Vec>, } -impl VerifyingKey { +impl VerifyingKey +where + C::Scalar: SerdePrimeField, +{ /// Writes a verifying key to a buffer. pub fn write(&self, writer: &mut W) -> io::Result<()> { + writer.write_all(&self.domain.k().to_be_bytes())?; writer.write_all(&(self.fixed_commitments.len() as u32).to_be_bytes())?; for commitment in &self.fixed_commitments { writer.write_all(commitment.to_bytes().as_ref())?; @@ -77,11 +81,13 @@ impl VerifyingKey { } /// Reads a verification key from a buffer. - pub fn read<'params, R: io::Read, ConcreteCircuit: Circuit>( + pub fn read>( reader: &mut R, - params: &impl Params<'params, C>, ) -> io::Result { - let (domain, cs, _) = keygen::create_domain::(params.k()); + let mut k = [0u8; 4]; + reader.read_exact(&mut k)?; + let k = u32::from_be_bytes(k); + let (domain, cs, _) = keygen::create_domain::(k); let mut num_fixed_columns_be_bytes = [0u8; 4]; reader.read_exact(&mut num_fixed_columns_be_bytes)?; let num_fixed_columns = u32::from_be_bytes(num_fixed_columns_be_bytes); @@ -93,7 +99,7 @@ impl VerifyingKey { let permutation = permutation::VerifyingKey::read(reader, &cs.permutation)?; // read selectors - let selectors: Vec> = vec![vec![false; params.n() as usize]; cs.num_selectors] + let selectors: Vec> = vec![vec![false; 1 << k]; cs.num_selectors] .into_iter() .map(|mut selector| { let mut selector_bytes = vec![0u8; (selector.len() + 7) / 8]; @@ -124,15 +130,14 @@ impl VerifyingKey { } /// Reads a verification key from a slice of bytes. - pub fn from_bytes<'params, ConcreteCircuit: Circuit>( - mut bytes: &[u8], - params: &impl Params<'params, C>, - ) -> io::Result { - Self::read::<_, ConcreteCircuit>(&mut bytes, params) + pub fn from_bytes>(mut bytes: &[u8]) -> io::Result { + Self::read::<_, ConcreteCircuit>(&mut bytes) } +} +impl VerifyingKey { fn bytes_length(&self) -> usize { - 4 + (self.fixed_commitments.len() * C::default().to_bytes().as_ref().len()) + 8 + (self.fixed_commitments.len() * C::default().to_bytes().as_ref().len()) + self.permutation.bytes_length() + self.selectors.len() * (self @@ -251,6 +256,23 @@ impl ProvingKey { &self.vk } + /// Gets the total number of bytes in the serialization of `self` + fn bytes_length(&self) -> usize { + let scalar_len = C::Scalar::default().to_repr().as_ref().len(); + self.vk.bytes_length() + + 12 + + scalar_len * (self.l0.len() + self.l_last.len() + self.l_active_row.len()) + + polynomial_slice_byte_length(&self.fixed_values) + + polynomial_slice_byte_length(&self.fixed_polys) + + polynomial_slice_byte_length(&self.fixed_cosets) + + self.permutation.bytes_length() + } +} + +impl ProvingKey +where + C::Scalar: SerdePrimeField, +{ /// Writes a proving key to a buffer. /// Does so by first writing the verifying key and then serializing the rest of the data (in the form of field polynomials) pub fn write(&self, writer: &mut W) -> io::Result<()> { @@ -267,11 +289,10 @@ impl ProvingKey { /// Reads a proving key from a buffer. /// Does so by reading verification key first, and then deserializing the rest of the file into the remaining proving key data. - pub fn read<'params, R: io::Read, ConcreteCircuit: Circuit>( + pub fn read>( reader: &mut R, - params: &impl Params<'params, C>, ) -> io::Result { - let vk = VerifyingKey::::read::(reader, params)?; + let vk = VerifyingKey::::read::(reader)?; let l0 = Polynomial::read(reader)?; let l_last = Polynomial::read(reader)?; let l_active_row = Polynomial::read(reader)?; @@ -301,23 +322,8 @@ impl ProvingKey { } /// Reads a proving key from a slice of bytes. - pub fn from_bytes<'params, ConcreteCircuit: Circuit>( - mut bytes: &[u8], - params: &impl Params<'params, C>, - ) -> io::Result { - Self::read::<_, ConcreteCircuit>(&mut bytes, params) - } - - /// Gets the total number of bytes in the serialization of `self` - fn bytes_length(&self) -> usize { - let scalar_len = C::Scalar::default().to_repr().as_ref().len(); - self.vk.bytes_length() - + 12 - + scalar_len * (self.l0.len() + self.l_last.len() + self.l_active_row.len()) - + polynomial_slice_byte_length(&self.fixed_values) - + polynomial_slice_byte_length(&self.fixed_polys) - + polynomial_slice_byte_length(&self.fixed_cosets) - + self.permutation.bytes_length() + pub fn from_bytes>(mut bytes: &[u8]) -> io::Result { + Self::read::<_, ConcreteCircuit>(&mut bytes) } } diff --git a/halo2_proofs/src/poly.rs b/halo2_proofs/src/poly.rs index 1e2ac6366c..d5c05ee866 100644 --- a/halo2_proofs/src/poly.rs +++ b/halo2_proofs/src/poly.rs @@ -146,12 +146,12 @@ impl Polynomial { } } -impl Polynomial { +impl Polynomial { /// Reads polynomial from buffer using `SerdePrimeField::read`. pub(crate) fn read(reader: &mut R) -> io::Result { - let mut poly_len_be_bytes = [0u8; 4]; - reader.read_exact(&mut poly_len_be_bytes)?; - let poly_len = u32::from_be_bytes(poly_len_be_bytes); + let mut poly_len = [0u8; 4]; + reader.read_exact(&mut poly_len)?; + let poly_len = u32::from_be_bytes(poly_len); (0..poly_len) .map(|_| F::read(reader)) From db67f1174af4682841a72cecd4ed32635afeb5de Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Wed, 21 Dec 2022 14:31:44 -0500 Subject: [PATCH 29/62] feat: add features "serde-raw" and "raw-unchecked" to serialize/deserialize KZG params, verifying key, and proving key directly into raw bytes in internal memory format. So field elements are stored in Montgomery form `a * R (mod p)` and curve points are stored without compression. --- halo2_proofs/examples/serialization.rs | 2 +- halo2_proofs/src/helpers.rs | 40 +++--- halo2_proofs/src/plonk.rs | 11 +- halo2_proofs/src/plonk/permutation.rs | 23 ++- halo2_proofs/src/poly/kzg/commitment.rs | 134 ++++++++++++------ .../src/poly/kzg/multiopen/gwc/prover.rs | 8 +- .../src/poly/kzg/multiopen/gwc/verifier.rs | 9 +- .../src/poly/kzg/multiopen/shplonk/prover.rs | 5 +- .../poly/kzg/multiopen/shplonk/verifier.rs | 8 +- halo2_proofs/src/poly/kzg/strategy.rs | 14 +- 10 files changed, 164 insertions(+), 90 deletions(-) diff --git a/halo2_proofs/examples/serialization.rs b/halo2_proofs/examples/serialization.rs index fbd19a89b4..1fe70feb13 100644 --- a/halo2_proofs/examples/serialization.rs +++ b/halo2_proofs/examples/serialization.rs @@ -139,7 +139,7 @@ fn main() { let f = File::open("serialization-test.pk").unwrap(); let mut reader = BufReader::new(f); - let pk = ProvingKey::::read::<_, StandardPlonk>(&mut reader, ¶ms).unwrap(); + let pk = ProvingKey::::read::<_, StandardPlonk>(&mut reader).unwrap(); std::fs::remove_file("serialization-test.pk").unwrap(); diff --git a/halo2_proofs/src/helpers.rs b/halo2_proofs/src/helpers.rs index eb42d0787e..206725162f 100644 --- a/halo2_proofs/src/helpers.rs +++ b/halo2_proofs/src/helpers.rs @@ -2,11 +2,11 @@ use crate::poly::Polynomial; use ff::PrimeField; #[cfg(feature = "serde-raw")] use halo2curves::serde::SerdeObject; -use halo2curves::CurveAffine; +use halo2curves::{pairing::Engine, CurveAffine}; use std::io; -#[cfg(not(feature = "serde-raw"))] -pub(crate) trait SerdeCurveAffine: CurveAffine { +// Keep this trait for compatibility with IPA serialization +pub(crate) trait CurveRead: CurveAffine { /// Reads a compressed element from the buffer and attempts to parse it /// using `from_bytes`. fn read(reader: &mut R) -> io::Result { @@ -15,6 +15,16 @@ pub(crate) trait SerdeCurveAffine: CurveAffine { Option::from(Self::from_bytes(&compressed)) .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Invalid point encoding in proof")) } +} +impl CurveRead for C {} + +#[cfg(not(feature = "serde-raw"))] +pub trait SerdeCurveAffine: CurveAffine { + /// Reads a compressed element from the buffer and attempts to parse it + /// using `from_bytes`. + fn read(reader: &mut R) -> io::Result { + ::read(reader) + } /// Writes a curve element as a compressed affine point in bytes. fn write(&self, writer: &mut W) -> io::Result<()> { writer.write_all(self.to_bytes().as_ref()) @@ -24,7 +34,7 @@ pub(crate) trait SerdeCurveAffine: CurveAffine { impl SerdeCurveAffine for C {} #[cfg(feature = "serde-raw")] -pub(crate) trait SerdeCurveAffine: CurveAffine + SerdeObject { +pub trait SerdeCurveAffine: CurveAffine + SerdeObject { /// Reads a curve element from raw bytes. /// The curve element is stored exactly as it is in memory (two field elements in Montgomery representation). fn read(reader: &mut R) -> io::Result { @@ -40,21 +50,14 @@ pub(crate) trait SerdeCurveAffine: CurveAffine + SerdeObject { /// Writes a curve element into raw bytes. /// The curve element is stored exactly as it is in memory (two field elements in Montgomery representation). fn write(&self, writer: &mut W) -> io::Result<()> { - #[cfg(feature = "raw-unchecked")] - { - Ok(self.write_raw_unchecked(writer)) - } - #[cfg(not(feature = "raw-unchecked"))] - { - self.write_raw(writer) - } + self.write_raw(writer) } } #[cfg(feature = "serde-raw")] impl SerdeCurveAffine for C {} #[cfg(not(feature = "serde-raw"))] -pub(crate) trait SerdePrimeField: PrimeField { +pub trait SerdePrimeField: PrimeField { /// Reads a field element as bytes from the buffer using `from_repr`. /// Endianness is specified by `PrimeField` implementation. fn read(reader: &mut R) -> io::Result { @@ -75,7 +78,7 @@ pub(crate) trait SerdePrimeField: PrimeField { impl SerdePrimeField for F {} #[cfg(feature = "serde-raw")] -pub(crate) trait SerdePrimeField: PrimeField + SerdeObject { +pub trait SerdePrimeField: PrimeField + SerdeObject { /// Reads a field element from raw bytes in its internal Montgomery representation. fn read(reader: &mut R) -> io::Result { #[cfg(feature = "raw-unchecked")] @@ -90,14 +93,7 @@ pub(crate) trait SerdePrimeField: PrimeField + SerdeObject { /// Writes a field element into raw bytes in its internal Montgomery representation, /// WITHOUT performing the expensive Montgomery reduction. fn write(&self, writer: &mut W) -> io::Result<()> { - #[cfg(feature = "raw-unchecked")] - { - Ok(self.write_raw_unchecked(writer)) - } - #[cfg(not(feature = "raw-unchecked"))] - { - self.write_raw(writer) - } + self.write_raw(writer) } } #[cfg(feature = "serde-raw")] diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index a2d9cf2af2..38c4078571 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -66,7 +66,7 @@ where writer.write_all(&self.domain.k().to_be_bytes())?; writer.write_all(&(self.fixed_commitments.len() as u32).to_be_bytes())?; for commitment in &self.fixed_commitments { - writer.write_all(commitment.to_bytes().as_ref())?; + commitment.write(writer)?; } self.permutation.write(writer)?; @@ -88,9 +88,9 @@ where reader.read_exact(&mut k)?; let k = u32::from_be_bytes(k); let (domain, cs, _) = keygen::create_domain::(k); - let mut num_fixed_columns_be_bytes = [0u8; 4]; - reader.read_exact(&mut num_fixed_columns_be_bytes)?; - let num_fixed_columns = u32::from_be_bytes(num_fixed_columns_be_bytes); + let mut num_fixed_columns = [0u8; 4]; + reader.read_exact(&mut num_fixed_columns)?; + let num_fixed_columns = u32::from_be_bytes(num_fixed_columns); let fixed_commitments: Vec<_> = (0..num_fixed_columns) .map(|_| C::read(reader)) @@ -109,8 +109,7 @@ where } Ok(selector) }) - .collect::>>>() - .unwrap(); + .collect::>()?; let (cs, _) = cs.compress_selectors(selectors.clone()); Ok(Self::from_parts( diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index 7d0d8cc774..c0dc26dddd 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -2,7 +2,8 @@ use super::circuit::{Any, Column}; use crate::{ arithmetic::CurveAffine, helpers::{ - polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice, CurveRead, + polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice, + SerdeCurveAffine, SerdePrimeField, }, poly::{Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial}, }; @@ -87,15 +88,20 @@ impl VerifyingKey { &self.commitments } - pub(crate) fn write(&self, writer: &mut W) -> io::Result<()> { + pub(crate) fn write(&self, writer: &mut W) -> io::Result<()> + where + C: SerdeCurveAffine, + { for commitment in &self.commitments { - writer.write_all(commitment.to_bytes().as_ref())?; + commitment.write(writer)?; } - Ok(()) } - pub(crate) fn read(reader: &mut R, argument: &Argument) -> io::Result { + pub(crate) fn read(reader: &mut R, argument: &Argument) -> io::Result + where + C: SerdeCurveAffine, + { let commitments = (0..argument.columns.len()) .map(|_| C::read(reader)) .collect::, _>>()?; @@ -115,7 +121,10 @@ pub(crate) struct ProvingKey { pub(super) cosets: Vec>, } -impl ProvingKey { +impl ProvingKey +where + C::Scalar: SerdePrimeField, +{ /// Reads proving key for a single permutation argument from buffer using `Polynomial::read`. pub(super) fn read(reader: &mut R) -> io::Result { let permutations = read_polynomial_vec(reader)?; @@ -135,7 +144,9 @@ impl ProvingKey { write_polynomial_slice(&self.cosets, writer)?; Ok(()) } +} +impl ProvingKey { /// Gets the total number of bytes in the serialization of `self` pub(super) fn bytes_length(&self) -> usize { polynomial_slice_byte_length(&self.permutations) diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index 3e8cce6d09..c801d9401b 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -1,7 +1,7 @@ use crate::arithmetic::{ best_fft, best_multiexp, g_to_lagrange, parallelize, CurveAffine, CurveExt, FieldExt, Group, }; -use crate::helpers::CurveRead; +use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, ParamsVerifier, MSM}; use crate::poly::{Coeff, LagrangeCoeff, Polynomial}; @@ -34,7 +34,11 @@ pub struct KZGCommitmentScheme { _marker: PhantomData, } -impl CommitmentScheme for KZGCommitmentScheme { +impl CommitmentScheme for KZGCommitmentScheme +where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, +{ type Scalar = E::Scalar; type Curve = E::G1Affine; @@ -139,7 +143,11 @@ impl ParamsKZG { /// KZG multi-open verification parameters pub type ParamsVerifierKZG = ParamsKZG; -impl<'params, E: Engine + Debug> Params<'params, E::G1Affine> for ParamsKZG { +impl<'params, E: Engine + Debug> Params<'params, E::G1Affine> for ParamsKZG +where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, +{ type MSM = MSMKZG; fn k(&self) -> u32 { @@ -179,61 +187,88 @@ impl<'params, E: Engine + Debug> Params<'params, E::G1Affine> for ParamsKZG { /// Writes params to a buffer. fn write(&self, writer: &mut W) -> io::Result<()> { - use group::GroupEncoding; writer.write_all(&self.k.to_le_bytes())?; for el in self.g.iter() { - writer.write_all(el.to_bytes().as_ref())?; + el.write(writer)?; } for el in self.g_lagrange.iter() { - writer.write_all(el.to_bytes().as_ref())?; + el.write(writer)?; } - writer.write_all(self.g2.to_bytes().as_ref())?; - writer.write_all(self.s_g2.to_bytes().as_ref())?; + self.g2.write(writer)?; + self.s_g2.write(writer)?; Ok(()) } /// Reads params from a buffer. fn read(reader: &mut R) -> io::Result { - use group::GroupEncoding; - let mut k = [0u8; 4]; reader.read_exact(&mut k[..])?; let k = u32::from_le_bytes(k); let n = 1 << k; - let load_points_from_file_parallelly = - |reader: &mut R| -> io::Result>> { - let mut points_compressed = - vec![<::G1Affine as GroupEncoding>::Repr::default(); n]; - for points_compressed in points_compressed.iter_mut() { - reader.read_exact((*points_compressed).as_mut())?; - } - - let mut points = vec![Option::::None; n]; - parallelize(&mut points, |points, chunks| { - for (i, point) in points.iter_mut().enumerate() { - *point = - Option::from(E::G1Affine::from_bytes(&points_compressed[chunks + i])); + #[cfg(not(feature = "serde-raw"))] + let (g, g_lagrange) = { + use group::GroupEncoding; + let load_points_from_file_parallelly = + |reader: &mut R| -> io::Result>> { + let mut points_compressed = + vec![<::G1Affine as GroupEncoding>::Repr::default(); n]; + for points_compressed in points_compressed.iter_mut() { + reader.read_exact((*points_compressed).as_mut())?; } - }); - Ok(points) - }; - - let g = load_points_from_file_parallelly(reader)?; - let g: Vec<::G1Affine> = g - .iter() - .map(|point| { - point.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point encoding")) - }) - .collect::>()?; - - let g_lagrange = load_points_from_file_parallelly(reader)?; - let g_lagrange: Vec<::G1Affine> = g_lagrange - .iter() - .map(|point| { - point.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point encoding")) - }) - .collect::>()?; + + let mut points = vec![Option::::None; n]; + parallelize(&mut points, |points, chunks| { + for (i, point) in points.iter_mut().enumerate() { + *point = Option::from(E::G1Affine::from_bytes( + &points_compressed[chunks + i], + )); + } + }); + Ok(points) + }; + + let g = load_points_from_file_parallelly(reader)?; + let g: Vec<::G1Affine> = g + .iter() + .map(|point| { + point.ok_or_else(|| { + io::Error::new(io::ErrorKind::Other, "invalid point encoding") + }) + }) + .collect::>()?; + let g_lagrange = load_points_from_file_parallelly(reader)?; + let g_lagrange: Vec<::G1Affine> = g_lagrange + .iter() + .map(|point| { + point.ok_or_else(|| { + io::Error::new(io::ErrorKind::Other, "invalid point encoding") + }) + }) + .collect::>()?; + (g, g_lagrange) + }; + #[cfg(all(feature = "serde-raw", not(feature = "raw-unchecked")))] + let (g, g_lagrange) = { + let g = (0..n) + .map(|_| ::read(reader)) + .collect::, _>>()?; + let g_lagrange = (0..n) + .map(|_| ::read(reader)) + .collect::, _>>()?; + (g, g_lagrange) + }; + #[cfg(all(feature = "serde-raw", feature = "raw-unchecked"))] + let (g, g_lagrange) = { + // avoid try branching for performance + let g = (0..n) + .map(|_| ::read(reader).unwrap()) + .collect::>(); + let g_lagrange = (0..n) + .map(|_| ::read(reader).unwrap()) + .collect::>(); + (g, g_lagrange) + }; let g2 = E::G2Affine::read(reader)?; let s_g2 = E::G2Affine::read(reader)?; @@ -249,9 +284,18 @@ impl<'params, E: Engine + Debug> Params<'params, E::G1Affine> for ParamsKZG { } } -impl<'params, E: Engine + Debug> ParamsVerifier<'params, E::G1Affine> for ParamsKZG {} +impl<'params, E: Engine + Debug> ParamsVerifier<'params, E::G1Affine> for ParamsKZG +where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, +{ +} -impl<'params, E: Engine + Debug> ParamsProver<'params, E::G1Affine> for ParamsKZG { +impl<'params, E: Engine + Debug> ParamsProver<'params, E::G1Affine> for ParamsKZG +where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, +{ type ParamsVerifier = ParamsVerifierKZG; fn verifier_params(&'params self) -> &'params Self::ParamsVerifier { @@ -278,11 +322,9 @@ impl<'params, E: Engine + Debug> ParamsProver<'params, E::G1Affine> for ParamsKZ #[cfg(test)] mod test { - use crate::arithmetic::{ best_fft, best_multiexp, parallelize, CurveAffine, CurveExt, FieldExt, Group, }; - use crate::helpers::CurveRead; use crate::poly::commitment::ParamsProver; use crate::poly::commitment::{Blind, CommitmentScheme, Params, MSM}; use crate::poly::kzg::commitment::{ParamsKZG, ParamsVerifierKZG}; diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs index e5077b1b58..e7bff84ade 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs @@ -1,6 +1,6 @@ use super::{construct_intermediate_sets, ChallengeV, Query}; use crate::arithmetic::{eval_polynomial, kate_division, powers, CurveAffine, FieldExt}; - +use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::ParamsProver; use crate::poly::commitment::Prover; use crate::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; @@ -27,7 +27,11 @@ pub struct ProverGWC<'params, E: Engine> { } /// Create a multi-opening proof -impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme> for ProverGWC<'params, E> { +impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme> for ProverGWC<'params, E> +where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, +{ const QUERY_INSTANCE: bool = false; fn new(params: &'params ParamsKZG) -> Self { diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs index 8f9d348942..1ec003d638 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs @@ -4,7 +4,7 @@ use std::marker::PhantomData; use super::{construct_intermediate_sets, ChallengeU, ChallengeV}; use crate::arithmetic::{eval_polynomial, lagrange_interpolate, powers, CurveAffine, FieldExt}; - +use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::Verifier; use crate::poly::commitment::MSM; use crate::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; @@ -30,8 +30,11 @@ pub struct VerifierGWC<'params, E: Engine> { params: &'params ParamsKZG, } -impl<'params, E: MultiMillerLoop + Debug> Verifier<'params, KZGCommitmentScheme> - for VerifierGWC<'params, E> +impl<'params, E> Verifier<'params, KZGCommitmentScheme> for VerifierGWC<'params, E> +where + E: MultiMillerLoop + Debug, + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, { type Guard = GuardKZG<'params, E>; type MSMAccumulator = DualMSM<'params, E>; diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs index 2585d9ab69..8b144d85b6 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs @@ -5,7 +5,7 @@ use crate::arithmetic::{ eval_polynomial, evaluate_vanishing_polynomial, kate_division, lagrange_interpolate, parallelize, powers, CurveAffine, FieldExt, }; - +use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::{Blind, ParamsProver, Prover}; use crate::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; use crate::poly::query::{PolynomialPointer, ProverQuery}; @@ -103,6 +103,9 @@ impl<'a, E: Engine> ProverSHPLONK<'a, E> { /// Create a multi-opening proof impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme> for ProverSHPLONK<'params, E> +where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, { const QUERY_INSTANCE: bool = false; diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs index 75626d74c6..11ffa880ef 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs @@ -7,6 +7,7 @@ use crate::arithmetic::{ eval_polynomial, evaluate_vanishing_polynomial, lagrange_interpolate, powers, CurveAffine, FieldExt, }; +use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::Verifier; use crate::poly::commitment::MSM; use crate::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; @@ -33,8 +34,11 @@ pub struct VerifierSHPLONK<'params, E: Engine> { params: &'params ParamsKZG, } -impl<'params, E: MultiMillerLoop + Debug> Verifier<'params, KZGCommitmentScheme> - for VerifierSHPLONK<'params, E> +impl<'params, E> Verifier<'params, KZGCommitmentScheme> for VerifierSHPLONK<'params, E> +where + E: MultiMillerLoop + Debug, + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, { type Guard = GuardKZG<'params, E>; type MSMAccumulator = DualMSM<'params, E>; diff --git a/halo2_proofs/src/poly/kzg/strategy.rs b/halo2_proofs/src/poly/kzg/strategy.rs index 896760067d..ca4b4fb18a 100644 --- a/halo2_proofs/src/poly/kzg/strategy.rs +++ b/halo2_proofs/src/poly/kzg/strategy.rs @@ -6,6 +6,7 @@ use super::{ multiopen::VerifierGWC, }; use crate::{ + helpers::SerdeCurveAffine, plonk::Error, poly::{ commitment::{Verifier, MSM}, @@ -29,7 +30,12 @@ pub struct GuardKZG<'params, E: MultiMillerLoop + Debug> { } /// Define accumulator type as `DualMSM` -impl<'params, E: MultiMillerLoop + Debug> Guard> for GuardKZG<'params, E> { +impl<'params, E> Guard> for GuardKZG<'params, E> +where + E: MultiMillerLoop + Debug, + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, +{ type MSMAccumulator = DualMSM<'params, E>; } @@ -85,6 +91,9 @@ impl< Guard = GuardKZG<'params, E>, >, > VerificationStrategy<'params, KZGCommitmentScheme, V> for AccumulatorStrategy<'params, E> +where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, { type Output = Self; @@ -120,6 +129,9 @@ impl< Guard = GuardKZG<'params, E>, >, > VerificationStrategy<'params, KZGCommitmentScheme, V> for SingleStrategy<'params, E> +where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, { type Output = (); From 2739742f0eb5d1f61934f8d0be1d7b055e57261e Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Thu, 29 Dec 2022 13:10:03 +0800 Subject: [PATCH 30/62] add meta.max_phase() --- halo2_proofs/src/plonk/circuit.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index f662c141a6..696d84f0f5 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -1899,6 +1899,15 @@ impl ConstraintSystem { }); } + /// .. + pub fn max_phase(&self) -> u8 { + self.advice_column_phase + .iter() + .max() + .map(|phase| phase.0) + .unwrap_or_default() + } + pub(crate) fn phases(&self) -> impl Iterator { let max_phase = self .advice_column_phase From a6312fee2560e6eed50ee3bb0d972cec4c71ca89 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Thu, 29 Dec 2022 13:46:37 +0800 Subject: [PATCH 31/62] fix log level --- halo2_proofs/src/circuit/floor_planner/single_pass.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index f562fb65f9..5267905a85 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -99,7 +99,7 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a for column in &shape.columns { let column_start = self.columns.get(column).cloned().unwrap_or(0); if column_start != 0 { - log::debug!( + log::trace!( "columns {:?} reused between multi regions. Start: {}. Region: {}", column, column_start, From 75a602b57037d4982019e4fab9d1b02463891378 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Mon, 2 Jan 2023 19:20:26 +0800 Subject: [PATCH 32/62] add assignment timer --- halo2_proofs/Cargo.toml | 3 +++ .../src/circuit/floor_planner/single_pass.rs | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 241e4f5073..3215ff8535 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -64,6 +64,9 @@ plotters = { version = "0.3.0", optional = true } tabbycat = { version = "0.1", features = ["attributes"], optional = true } log = "0.4.17" +# timer +ark-std = "0.3.0" + [dev-dependencies] assert_matches = "1.5" criterion = "0.3" diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index 5267905a85..2fa2302ea7 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -5,6 +5,8 @@ use std::marker::PhantomData; use ff::Field; +use ark_std::{end_timer, start_timer}; + use crate::{ circuit::{ layouter::{RegionColumn, RegionLayouter, RegionShape, TableLayouter}, @@ -31,8 +33,11 @@ impl FloorPlanner for SimpleFloorPlanner { config: C::Config, constants: Vec>, ) -> Result<(), Error> { + let timer = start_timer!(|| format!("SimpleFloorPlanner synthesize")); let layouter = SingleChipLayouter::new(cs, constants)?; - circuit.synthesize(config, layouter) + let result = circuit.synthesize(config, layouter); + end_timer!(timer); + result } } @@ -82,15 +87,18 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a N: Fn() -> NR, NR: Into, { + let region_name: String = name().into(); + let timer = start_timer!(|| format!("assign region: {}", region_name)); let region_index = self.regions.len(); // Get shape of the region. let mut shape = RegionShape::new(region_index.into()); { + let timer_1st = start_timer!(|| format!("assign region 1st pass: {}", region_name)); let region: &mut dyn RegionLayouter = &mut shape; assignment(region.into())?; + end_timer!(timer_1st); } - let region_name: String = name().into(); log::debug!("region row_count {}: {}", region_name, shape.row_count()); // Lay out this region. We implement the simplest approach here: position the @@ -119,8 +127,11 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a self.cs.enter_region(name); let mut region = SingleChipLayouterRegion::new(self, region_index.into()); let result = { + let timer_2nd = start_timer!(|| format!("assign region 2nd pass: {}", region_name)); let region: &mut dyn RegionLayouter = &mut region; - assignment(region.into()) + let result = assignment(region.into()); + end_timer!(timer_2nd); + result }?; let constants_to_assign = region.constants; self.cs.exit_region(); @@ -154,6 +165,7 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a } } + end_timer!(timer); Ok(result) } From 95200760355645b78dd36bac79bc5ef8d46c7aa3 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Mon, 2 Jan 2023 19:39:49 +0800 Subject: [PATCH 33/62] add assignment timer --- halo2_proofs/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 3215ff8535..11cdfef695 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -65,7 +65,7 @@ tabbycat = { version = "0.1", features = ["attributes"], optional = true } log = "0.4.17" # timer -ark-std = "0.3.0" +ark-std = { version = "0.3.0", features = ["print-trace"] } [dev-dependencies] assert_matches = "1.5" From 09506036ae601225f9a7c5d4ca016b2c57df3cff Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Tue, 3 Jan 2023 16:03:38 +0800 Subject: [PATCH 34/62] creating pk no longer needs vk; avoid assignment twice --- halo2_proofs/Cargo.toml | 1 + halo2_proofs/src/plonk/keygen.rs | 51 +++++++++++++++++--- halo2_proofs/src/plonk/permutation/keygen.rs | 2 +- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 11cdfef695..a04533fdc5 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -85,6 +85,7 @@ sanity-checks = [] batch = ["rand_core/getrandom"] shplonk = [] gwc = [] +profile = ["ark-std/print-trace"] [lib] bench = false diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index 39cef34c0f..e18d9c62d2 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -249,7 +249,20 @@ where )) } -/// Generate a `ProvingKey` from a `VerifyingKey` and an instance of `Circuit`. +/// Generate a `ProvingKey` from an instance of `Circuit`. +pub fn keygen_pk2<'params, C, P, ConcreteCircuit>( + params: &P, + circuit: &ConcreteCircuit, +) -> Result, Error> +where + C: CurveAffine, + P: Params<'params, C>, + ConcreteCircuit: Circuit, +{ + keygen_pk_impl(params, None, circuit) +} + +/// Generate a `ProvingKey` from a `VerifyingKey` and an instance of `Circuit` pub fn keygen_pk<'params, C, P, ConcreteCircuit>( params: &P, vk: VerifyingKey, @@ -260,10 +273,21 @@ where P: Params<'params, C>, ConcreteCircuit: Circuit, { - let mut cs = ConstraintSystem::default(); - let config = ConcreteCircuit::configure(&mut cs); + keygen_pk_impl(params, Some(vk), circuit) +} - let cs = cs; +/// Generate a `ProvingKey` from a `VerifyingKey` and an instance of `Circuit`. +pub fn keygen_pk_impl<'params, C, P, ConcreteCircuit>( + params: &P, + vk: Option>, + circuit: &ConcreteCircuit, +) -> Result, Error> +where + C: CurveAffine, + P: Params<'params, C>, + ConcreteCircuit: Circuit, +{ + let (domain, cs, config) = create_domain::(params.k()); if (params.n() as usize) < cs.minimum_rows() { return Err(Error::not_enough_rows_available(params.k())); @@ -271,7 +295,7 @@ where let mut assembly: Assembly = Assembly { k: params.k(), - fixed: vec![vk.domain.empty_lagrange_assigned(); cs.num_fixed_columns], + fixed: vec![domain.empty_lagrange_assigned(); cs.num_fixed_columns], permutation: permutation::keygen::Assembly::new(params.n() as usize, &cs.permutation), selectors: vec![vec![false; params.n() as usize]; cs.num_selectors], usable_rows: 0..params.n() as usize - (cs.blinding_factors() + 1), @@ -291,9 +315,24 @@ where fixed.extend( selector_polys .into_iter() - .map(|poly| vk.domain.lagrange_from_vec(poly)), + .map(|poly| domain.lagrange_from_vec(poly)), ); + let vk = vk.unwrap_or_else(|| { + let permutation_vk = + assembly + .permutation + .clone() + .build_vk(params, &domain, &cs.permutation); + + let fixed_commitments = fixed + .iter() + .map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine()) + .collect(); + + VerifyingKey::from_parts(domain, fixed_commitments, permutation_vk, cs.clone()) + }); + let fixed_polys: Vec<_> = fixed .iter() .map(|poly| vk.domain.lagrange_to_coeff(poly.clone())) diff --git a/halo2_proofs/src/plonk/permutation/keygen.rs b/halo2_proofs/src/plonk/permutation/keygen.rs index e1bd0d1e4e..3b2552f64f 100644 --- a/halo2_proofs/src/plonk/permutation/keygen.rs +++ b/halo2_proofs/src/plonk/permutation/keygen.rs @@ -11,7 +11,7 @@ use crate::{ }, }; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct Assembly { columns: Vec>, pub(crate) mapping: Vec>, From 7a444d3384ae1860781a96a656682a7b8ad645e3 Mon Sep 17 00:00:00 2001 From: Jonathan Wang Date: Thu, 5 Jan 2023 16:31:47 -0500 Subject: [PATCH 35/62] chore: switch to halo2curves 0.3.1 tag --- halo2_proofs/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 8231074902..de0ed10f8e 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -48,7 +48,7 @@ backtrace = { version = "0.3", optional = true } rayon = "1.5.1" ff = "0.12" group = "0.12" -halo2curves = { git = 'https://github.com/jonathanpwang/halo2curves', branch = 'feat/serde-field' } +halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves.git', tag = "0.3.1" } rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" From 3370852df4044313faaf3e582ad73a99c7de87bc Mon Sep 17 00:00:00 2001 From: sinka Date: Mon, 9 Jan 2023 20:38:32 +1100 Subject: [PATCH 36/62] multi-phases: make phases related field public --- halo2_proofs/src/plonk/circuit.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index 696d84f0f5..bbc4ae15b3 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -1331,9 +1331,9 @@ pub struct ConstraintSystem { pub(crate) num_challenges: usize, /// Contains the phase for each advice column. Should have same length as num_advice_columns. - pub(crate) advice_column_phase: Vec, + pub advice_column_phase: Vec, /// Contains the phase for each challenge. Should have same length as num_challenges. - pub(crate) challenge_phase: Vec, + pub challenge_phase: Vec, /// This is a cached vector that maps virtual selectors to the concrete /// fixed column that they were compressed into. This is just used by dev @@ -1908,7 +1908,7 @@ impl ConstraintSystem { .unwrap_or_default() } - pub(crate) fn phases(&self) -> impl Iterator { + pub fn phases(&self) -> impl Iterator { let max_phase = self .advice_column_phase .iter() From 7724ce20935228f0e81bdbedcb77802f8a00f615 Mon Sep 17 00:00:00 2001 From: Velaciela Date: Wed, 11 Jan 2023 04:56:08 +0000 Subject: [PATCH 37/62] Revert "optimize fft" This reverts commit 9a9873a2c5e8ccf4817c798d415f831bb109a7f9. --- halo2_proofs/src/arithmetic.rs | 150 ++++++++++++++++----------------- 1 file changed, 71 insertions(+), 79 deletions(-) diff --git a/halo2_proofs/src/arithmetic.rs b/halo2_proofs/src/arithmetic.rs index 69b63502bf..4868c7322c 100644 --- a/halo2_proofs/src/arithmetic.rs +++ b/halo2_proofs/src/arithmetic.rs @@ -169,7 +169,18 @@ pub fn best_multiexp(coeffs: &[C::Scalar], bases: &[C]) -> C::Cu /// /// This will use multithreading if beneficial. pub fn best_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { - fn bitreverse(mut n: usize, l: usize) -> usize { + let threads = multicore::current_num_threads(); + let log_threads = log2_floor(threads); + + if log_n <= log_threads { + serial_fft(a, omega, log_n); + } else { + parallel_fft(a, omega, log_n, log_threads); + } +} + +fn serial_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { + fn bitreverse(mut n: u32, l: u32) -> u32 { let mut r = 0; for _ in 0..l { r = (r << 1) | (n & 1); @@ -178,98 +189,79 @@ pub fn best_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { r } - let threads = multicore::current_num_threads(); - let log_threads = log2_floor(threads); - let n = a.len() as usize; + let n = a.len() as u32; assert_eq!(n, 1 << log_n); for k in 0..n { - let rk = bitreverse(k, log_n as usize); + let rk = bitreverse(k, log_n); if k < rk { - a.swap(rk, k); + a.swap(rk as usize, k as usize); } } - // precompute twiddle factors - let twiddles: Vec<_> = (0..(n / 2) as usize) - .scan(G::Scalar::one(), |w, _| { - let tw = *w; - w.group_scale(&omega); - Some(tw) - }) - .collect(); + let mut m = 1; + for _ in 0..log_n { + let w_m = omega.pow_vartime(&[u64::from(n / (2 * m)), 0, 0, 0]); + + let mut k = 0; + while k < n { + let mut w = G::Scalar::one(); + for j in 0..m { + let mut t = a[(k + j + m) as usize]; + t.group_scale(&w); + a[(k + j + m) as usize] = a[(k + j) as usize]; + a[(k + j + m) as usize].group_sub(&t); + a[(k + j) as usize].group_add(&t); + w *= &w_m; + } - if log_n <= log_threads { - let mut chunk = 2_usize; - let mut twiddle_chunk = (n / 2) as usize; - for _ in 0..log_n { - a.chunks_mut(chunk).for_each(|coeffs| { - let (left, right) = coeffs.split_at_mut(chunk / 2); - - // case when twiddle factor is one - let (a, left) = left.split_at_mut(1); - let (b, right) = right.split_at_mut(1); - let t = b[0]; - b[0] = a[0]; - a[0].group_add(&t); - b[0].group_sub(&t); - - left.iter_mut() - .zip(right.iter_mut()) - .enumerate() - .for_each(|(i, (a, b))| { - let mut t = *b; - t.group_scale(&twiddles[(i + 1) * twiddle_chunk]); - *b = *a; - a.group_add(&t); - b.group_sub(&t); - }); - }); - chunk *= 2; - twiddle_chunk /= 2; + k += 2 * m; } - } else { - recursive_butterfly_arithmetic(a, n, 1, &twiddles) + + m *= 2; } } -/// This perform recursive butterfly arithmetic -pub fn recursive_butterfly_arithmetic( - a: &mut [G], - n: usize, - twiddle_chunk: usize, - twiddles: &[G::Scalar], -) { - if n == 2 { - let t = a[1]; - a[1] = a[0]; - a[0].group_add(&t); - a[1].group_sub(&t); - } else { - let (left, right) = a.split_at_mut(n / 2); - rayon::join( - || recursive_butterfly_arithmetic(left, n / 2, twiddle_chunk * 2, twiddles), - || recursive_butterfly_arithmetic(right, n / 2, twiddle_chunk * 2, twiddles), - ); +fn parallel_fft(a: &mut [G], omega: G::Scalar, log_n: u32, log_threads: u32) { + assert!(log_n >= log_threads); + + let num_threads = 1 << log_threads; + let log_new_n = log_n - log_threads; + let mut tmp = vec![vec![G::group_zero(); 1 << log_new_n]; num_threads]; + let new_omega = omega.pow_vartime(&[num_threads as u64, 0, 0, 0]); - // case when twiddle factor is one - let (a, left) = left.split_at_mut(1); - let (b, right) = right.split_at_mut(1); - let t = b[0]; - b[0] = a[0]; - a[0].group_add(&t); - b[0].group_sub(&t); - - left.iter_mut() - .zip(right.iter_mut()) - .enumerate() - .for_each(|(i, (a, b))| { - let mut t = *b; - t.group_scale(&twiddles[(i + 1) * twiddle_chunk]); - *b = *a; - a.group_add(&t); - b.group_sub(&t); + multicore::scope(|scope| { + let a = &*a; + + for (j, tmp) in tmp.iter_mut().enumerate() { + scope.spawn(move |_| { + // Shuffle into a sub-FFT + let omega_j = omega.pow_vartime(&[j as u64, 0, 0, 0]); + let omega_step = omega.pow_vartime(&[(j as u64) << log_new_n, 0, 0, 0]); + + let mut elt = G::Scalar::one(); + + for (i, tmp) in tmp.iter_mut().enumerate() { + for s in 0..num_threads { + let idx = (i + (s << log_new_n)) % (1 << log_n); + let mut t = a[idx]; + t.group_scale(&elt); + tmp.group_add(&t); + elt *= &omega_step; + } + elt *= &omega_j; + } + + // Perform sub-FFT + serial_fft(tmp, new_omega, log_new_n); }); + } + }); + + // Unshuffle + let mask = (1 << log_threads) - 1; + for (idx, a) in a.iter_mut().enumerate() { + *a = tmp[idx & mask][idx >> log_threads]; } } From d5a75d7d18b946815a94812cdf4862f733a735a7 Mon Sep 17 00:00:00 2001 From: Velaciela Date: Wed, 11 Jan 2023 05:13:31 +0000 Subject: [PATCH 38/62] optimize parallel fft --- halo2_proofs/src/arithmetic.rs | 215 ++++++++++++++++++++++++++------- 1 file changed, 172 insertions(+), 43 deletions(-) diff --git a/halo2_proofs/src/arithmetic.rs b/halo2_proofs/src/arithmetic.rs index 4868c7322c..f493687d46 100644 --- a/halo2_proofs/src/arithmetic.rs +++ b/halo2_proofs/src/arithmetic.rs @@ -10,6 +10,8 @@ use group::{ pub use halo2curves::{CurveAffine, CurveExt, FieldExt, Group}; +pub const SPARSE_TWIDDLE_DEGREE: u32 = 10; + fn multiexp_serial(coeffs: &[C::Scalar], bases: &[C], acc: &mut C::Curve) { let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect(); @@ -170,30 +172,33 @@ pub fn best_multiexp(coeffs: &[C::Scalar], bases: &[C]) -> C::Cu /// This will use multithreading if beneficial. pub fn best_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { let threads = multicore::current_num_threads(); - let log_threads = log2_floor(threads); + let log_split = log2_floor(threads) as usize; + let n = a.len() as usize; + let sub_n = n >> log_split; + let split_m = 1 << log_split; - if log_n <= log_threads { + if sub_n < split_m { serial_fft(a, omega, log_n); } else { - parallel_fft(a, omega, log_n, log_threads); + parallel_fft(a, omega, log_n); } } -fn serial_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { - fn bitreverse(mut n: u32, l: u32) -> u32 { - let mut r = 0; - for _ in 0..l { - r = (r << 1) | (n & 1); - n >>= 1; - } - r +fn bitreverse(mut n: usize, l: usize) -> usize { + let mut r = 0; + for _ in 0..l { + r = (r << 1) | (n & 1); + n >>= 1; } + r +} +fn serial_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { let n = a.len() as u32; assert_eq!(n, 1 << log_n); - for k in 0..n { - let rk = bitreverse(k, log_n); + for k in 0..n as usize { + let rk = bitreverse(k, log_n as usize); if k < rk { a.swap(rk as usize, k as usize); } @@ -222,47 +227,171 @@ fn serial_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { } } -fn parallel_fft(a: &mut [G], omega: G::Scalar, log_n: u32, log_threads: u32) { - assert!(log_n >= log_threads); +fn serial_split_fft(a: &mut [G], twiddle_lut: &[G::Scalar], twiddle_scale: usize, log_n: u32) { + let n = a.len() as u32; + assert_eq!(n, 1 << log_n); - let num_threads = 1 << log_threads; - let log_new_n = log_n - log_threads; - let mut tmp = vec![vec![G::group_zero(); 1 << log_new_n]; num_threads]; - let new_omega = omega.pow_vartime(&[num_threads as u64, 0, 0, 0]); + let mut m = 1; + for _ in 0..log_n { + let omega_idx = twiddle_scale * n as usize / (2 * m as usize); // 1/2, 1/4, 1/8, ... + let low_idx = omega_idx%(1<>SPARSE_TWIDDLE_DEGREE; + let mut w_m = twiddle_lut[low_idx]; + if high_idx > 0 { + w_m = w_m*twiddle_lut[(1<(tmp: &mut [G], a: &[G], twiddle_lut: &[G::Scalar], n: usize, sub_fft_offset: usize, log_split: usize) { + let split_m = 1 << log_split; + let sub_n = n >> log_split; + + // we use out-place bitreverse here, split_m <= num_threads, so the buffer spase is small + // and it's is good for data locality + let mut t1 = vec![G::group_zero(); split_m]; + // if unsafe code is allowed, a 10% performance improvement can be achieved + // let mut t1: Vec = Vec::with_capacity(split_m as usize); + // unsafe{ t1.set_len(split_m as usize); } + for i in 0..split_m { + t1[bitreverse(i,log_split)] = a[(i*sub_n + sub_fft_offset)]; + } + serial_split_fft(&mut t1, twiddle_lut, sub_n, log_split as u32); + + let sparse_degree = SPARSE_TWIDDLE_DEGREE; + let omega_idx = sub_fft_offset as usize; + let low_idx = omega_idx%(1<>sparse_degree; + let mut omega = twiddle_lut[low_idx]; + if high_idx > 0 { + omega = omega*twiddle_lut[(1<(omega: F, log_n: u32, sparse_degree: u32, with_last_level: bool) -> Vec { + let without_last_level = !with_last_level; + let is_lut_len_large = sparse_degree > log_n; + + // dense + if is_lut_len_large { + let mut twiddle_lut = vec![F::zero(); (1<(a: &mut [G], omega: G::Scalar, log_n: u32) { + let n = a.len() as usize; + assert_eq!(n, 1 << log_n); + + let log_split = log2_floor(multicore::current_num_threads()) as usize; + let split_m = 1 << log_split; + let sub_n = n >> log_split as usize; + let twiddle_lut = generate_twiddle_lookup_table(omega, log_n, SPARSE_TWIDDLE_DEGREE, true); + + // split fft + let mut tmp = vec![G::group_zero(); n]; + // if unsafe code is allowed, a 10% performance improvement can be achieved + // let mut tmp: Vec = Vec::with_capacity(n); + // unsafe{ tmp.set_len(n); } multicore::scope(|scope| { let a = &*a; - - for (j, tmp) in tmp.iter_mut().enumerate() { + let twiddle_lut = &*twiddle_lut; + for (chunk_idx, tmp) in tmp.chunks_mut(sub_n).enumerate() { scope.spawn(move |_| { - // Shuffle into a sub-FFT - let omega_j = omega.pow_vartime(&[j as u64, 0, 0, 0]); - let omega_step = omega.pow_vartime(&[(j as u64) << log_new_n, 0, 0, 0]); - - let mut elt = G::Scalar::one(); - - for (i, tmp) in tmp.iter_mut().enumerate() { - for s in 0..num_threads { - let idx = (i + (s << log_new_n)) % (1 << log_n); - let mut t = a[idx]; - t.group_scale(&elt); - tmp.group_add(&t); - elt *= &omega_step; - } - elt *= &omega_j; + let split_fft_offset = chunk_idx * sub_n >> log_split; + for (i, tmp) in tmp.chunks_mut(split_m).enumerate() { + let split_fft_offset = split_fft_offset + i; + split_radix_fft(tmp, a, twiddle_lut, n, split_fft_offset, log_split); } + }); + } + }); - // Perform sub-FFT - serial_fft(tmp, new_omega, log_new_n); + // shuffle + parallelize(a, |a, start| { + for (idx, a) in a.iter_mut().enumerate() { + let idx = start + idx; + let i = idx / sub_n; + let j = idx % sub_n; + *a = tmp[j*split_m + i]; + } + }); + + // sub fft + let new_omega = omega.pow_vartime(&[split_m as u64, 0, 0, 0]); + multicore::scope(|scope| { + for a in a.chunks_mut(sub_n) { + scope.spawn(move |_| { + serial_fft(a, new_omega, log_n - log_split as u32); }); } }); - // Unshuffle - let mask = (1 << log_threads) - 1; - for (idx, a) in a.iter_mut().enumerate() { - *a = tmp[idx & mask][idx >> log_threads]; - } + // copy & unshuffle + let mask = (1 << log_split) - 1; + parallelize(&mut tmp, |tmp, start| { + for (idx, tmp) in tmp.iter_mut().enumerate() { + let idx = start + idx; + *tmp = a[idx]; + } + }); + parallelize(a, |a, start| { + for (idx, a) in a.iter_mut().enumerate() { + let idx = start + idx; + *a = tmp[sub_n*(idx & mask) + (idx >> log_split)]; + } + }); } /// Convert coefficient bases group elements to lagrange basis by inverse FFT. From 18af374525375b1ce774849a7c4d2c015b0b1cfd Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 11 Jan 2023 18:16:18 +0800 Subject: [PATCH 39/62] disable profile by default --- halo2_proofs/Cargo.toml | 2 +- halo2_proofs/src/circuit/floor_planner/single_pass.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index a04533fdc5..c21153de90 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -65,7 +65,7 @@ tabbycat = { version = "0.1", features = ["attributes"], optional = true } log = "0.4.17" # timer -ark-std = { version = "0.3.0", features = ["print-trace"] } +ark-std = { version = "0.3.0" } [dev-dependencies] assert_matches = "1.5" diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index 2fa2302ea7..f0e9098d12 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -116,6 +116,7 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a } region_start = cmp::max(region_start, column_start); } + log::debug!("region{} start: {}", self.regions.len(), region_start); self.regions.push(region_start.into()); // Update column usage information. From 607c3a4eb25d5ae07f710accf1ec6c604f76903f Mon Sep 17 00:00:00 2001 From: Jonathan Wang Date: Sun, 15 Jan 2023 17:45:59 -0800 Subject: [PATCH 40/62] feat: add enum `SerdeFormat` for user to select serialization/deserialization format of curve and field elements --- halo2_proofs/Cargo.toml | 4 +- halo2_proofs/examples/serialization.rs | 6 +- halo2_proofs/src/helpers.rs | 138 ++++++++--------- halo2_proofs/src/lib.rs | 1 + halo2_proofs/src/plonk.rs | 111 +++++++++---- halo2_proofs/src/plonk/permutation.rs | 33 ++-- halo2_proofs/src/poly.rs | 13 +- halo2_proofs/src/poly/kzg/commitment.rs | 198 +++++++++++++----------- 8 files changed, 288 insertions(+), 216 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index de0ed10f8e..b611531f80 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -68,13 +68,11 @@ rand_core = { version = "0.6", default-features = false, features = ["getrandom" getrandom = { version = "0.2", features = ["js"] } [features] -default = ["batch", "serde-raw"] +default = ["batch"] dev-graph = ["plotters", "tabbycat"] gadget-traces = ["backtrace"] sanity-checks = [] batch = ["rand_core/getrandom"] -serde-raw = [] -raw-unchecked = ["serde-raw"] [lib] bench = false diff --git a/halo2_proofs/examples/serialization.rs b/halo2_proofs/examples/serialization.rs index 1fe70feb13..91ed5464e4 100644 --- a/halo2_proofs/examples/serialization.rs +++ b/halo2_proofs/examples/serialization.rs @@ -21,6 +21,7 @@ use halo2_proofs::{ transcript::{ Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }, + SerdeFormat, }; use halo2curves::bn256::{Bn256, Fr, G1Affine}; use rand_core::OsRng; @@ -134,12 +135,13 @@ fn main() { let f = File::create("serialization-test.pk").unwrap(); let mut writer = BufWriter::new(f); - pk.write(&mut writer).unwrap(); + pk.write(&mut writer, SerdeFormat::RawBytes).unwrap(); writer.flush().unwrap(); let f = File::open("serialization-test.pk").unwrap(); let mut reader = BufReader::new(f); - let pk = ProvingKey::::read::<_, StandardPlonk>(&mut reader).unwrap(); + let pk = ProvingKey::::read::<_, StandardPlonk>(&mut reader, SerdeFormat::RawBytes) + .unwrap(); std::fs::remove_file("serialization-test.pk").unwrap(); diff --git a/halo2_proofs/src/helpers.rs b/halo2_proofs/src/helpers.rs index 206725162f..41fc2e8d1e 100644 --- a/halo2_proofs/src/helpers.rs +++ b/halo2_proofs/src/helpers.rs @@ -1,10 +1,24 @@ use crate::poly::Polynomial; use ff::PrimeField; -#[cfg(feature = "serde-raw")] -use halo2curves::serde::SerdeObject; -use halo2curves::{pairing::Engine, CurveAffine}; +use halo2curves::{pairing::Engine, serde::SerdeObject, CurveAffine}; use std::io; +/// This enum specifies how various types are serialized and deserialized. +#[derive(Clone, Copy, Debug)] +pub enum SerdeFormat { + /// Curve elements are serialized in compressed form. + /// Field elements are serialized in standard form, with endianness specified by the + /// `PrimeField` implementation. + Processed, + /// Curve elements are serialized in uncompressed form. Field elements are serialized + /// in their internal Montgomery representation. + /// When deserializing, checks are performed to ensure curve elements indeed lie on the curve and field elements + /// are less than modulus. + RawBytes, + /// Serialization is the same as `RawBytes`, but no checks are performed. + RawBytesUnchecked, +} + // Keep this trait for compatibility with IPA serialization pub(crate) trait CurveRead: CurveAffine { /// Reads a compressed element from the buffer and attempts to parse it @@ -18,85 +32,65 @@ pub(crate) trait CurveRead: CurveAffine { } impl CurveRead for C {} -#[cfg(not(feature = "serde-raw"))] -pub trait SerdeCurveAffine: CurveAffine { - /// Reads a compressed element from the buffer and attempts to parse it - /// using `from_bytes`. - fn read(reader: &mut R) -> io::Result { - ::read(reader) - } - /// Writes a curve element as a compressed affine point in bytes. - fn write(&self, writer: &mut W) -> io::Result<()> { - writer.write_all(self.to_bytes().as_ref()) - } -} -#[cfg(not(feature = "serde-raw"))] -impl SerdeCurveAffine for C {} - -#[cfg(feature = "serde-raw")] pub trait SerdeCurveAffine: CurveAffine + SerdeObject { - /// Reads a curve element from raw bytes. - /// The curve element is stored exactly as it is in memory (two field elements in Montgomery representation). - fn read(reader: &mut R) -> io::Result { - #[cfg(feature = "raw-unchecked")] - { - Ok(Self::read_raw_unchecked(reader)) - } - #[cfg(not(feature = "raw-unchecked"))] - { - Self::read_raw(reader) + /// Reads an element from the buffer and parses it according to the `format`: + /// - `Processed`: Reads a compressed curve element and decompress it + /// - `RawBytes`: Reads an uncompressed curve element with coordinates in Montgomery form. + /// Checks that field elements are less than modulus, and then checks that the point is on the curve. + /// - `RawBytesUnchecked`: Reads an uncompressed curve element with coordinates in Montgomery form; + /// does not perform any checks + fn read(reader: &mut R, format: SerdeFormat) -> io::Result { + match format { + SerdeFormat::Processed => ::read(reader), + SerdeFormat::RawBytes => ::read_raw(reader), + SerdeFormat::RawBytesUnchecked => Ok(::read_raw_unchecked(reader)), } } - /// Writes a curve element into raw bytes. - /// The curve element is stored exactly as it is in memory (two field elements in Montgomery representation). - fn write(&self, writer: &mut W) -> io::Result<()> { - self.write_raw(writer) + /// Writes a curve element according to `format`: + /// - `Processed`: Writes a compressed curve element + /// - Otherwise: Writes an uncompressed curve element with coordinates in Montgomery form + fn write(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> { + match format { + SerdeFormat::Processed => writer.write_all(self.to_bytes().as_ref()), + _ => self.write_raw(writer), + } } } -#[cfg(feature = "serde-raw")] impl SerdeCurveAffine for C {} -#[cfg(not(feature = "serde-raw"))] -pub trait SerdePrimeField: PrimeField { - /// Reads a field element as bytes from the buffer using `from_repr`. - /// Endianness is specified by `PrimeField` implementation. - fn read(reader: &mut R) -> io::Result { - let mut compressed = Self::Repr::default(); - reader.read_exact(compressed.as_mut())?; - Option::from(Self::from_repr(compressed)).ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "Invalid prime field point encoding") - }) - } - - /// Writes a field element as bytes to the buffer using `to_repr`. - /// Endianness is specified by `PrimeField` implementation. - fn write(&self, writer: &mut W) -> io::Result<()> { - writer.write_all(self.to_repr().as_ref()) - } -} -#[cfg(not(feature = "serde-raw"))] -impl SerdePrimeField for F {} - -#[cfg(feature = "serde-raw")] pub trait SerdePrimeField: PrimeField + SerdeObject { - /// Reads a field element from raw bytes in its internal Montgomery representation. - fn read(reader: &mut R) -> io::Result { - #[cfg(feature = "raw-unchecked")] - { - Ok(Self::read_raw_unchecked(reader)) - } - #[cfg(not(feature = "raw-unchecked"))] - { - Self::read_raw(reader) + /// Reads a field element as bytes from the buffer according to the `format`: + /// - `Processed`: Reads a field element in standard form, with endianness specified by the + /// `PrimeField` implementation, and checks that the element is less than the modulus. + /// - `RawBytes`: Reads a field element from raw bytes in its internal Montgomery representations, + /// and checks that the element is less than the modulus. + /// - `RawBytesUnchecked`: Reads a field element in Montgomery form and performs no checks. + fn read(reader: &mut R, format: SerdeFormat) -> io::Result { + match format { + SerdeFormat::Processed => { + let mut compressed = Self::Repr::default(); + reader.read_exact(compressed.as_mut())?; + Option::from(Self::from_repr(compressed)).ok_or_else(|| { + io::Error::new(io::ErrorKind::Other, "Invalid prime field point encoding") + }) + } + SerdeFormat::RawBytes => ::read_raw(reader), + SerdeFormat::RawBytesUnchecked => Ok(::read_raw_unchecked(reader)), } } - /// Writes a field element into raw bytes in its internal Montgomery representation, + + /// Writes a field element as bytes to the buffer according to the `format`: + /// - `Processed`: Writes a field element in standard form, with endianness specified by the + /// `PrimeField` implementation. + /// - Otherwise: Writes a field element into raw bytes in its internal Montgomery representation, /// WITHOUT performing the expensive Montgomery reduction. - fn write(&self, writer: &mut W) -> io::Result<()> { - self.write_raw(writer) + fn write(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> { + match format { + SerdeFormat::Processed => writer.write_all(self.to_repr().as_ref()), + _ => self.write_raw(writer), + } } } -#[cfg(feature = "serde-raw")] impl SerdePrimeField for F {} /// Convert a slice of `bool` into a `u8`. @@ -121,13 +115,14 @@ pub fn unpack(byte: u8, bits: &mut [bool]) { /// Reads a vector of polynomials from buffer pub(crate) fn read_polynomial_vec( reader: &mut R, + format: SerdeFormat, ) -> io::Result>> { let mut len = [0u8; 4]; reader.read_exact(&mut len)?; let len = u32::from_be_bytes(len); (0..len) - .map(|_| Polynomial::::read(reader)) + .map(|_| Polynomial::::read(reader, format)) .collect::>>() } @@ -135,10 +130,11 @@ pub(crate) fn read_polynomial_vec( pub(crate) fn write_polynomial_slice( slice: &[Polynomial], writer: &mut W, + format: SerdeFormat, ) -> io::Result<()> { writer.write_all(&(slice.len() as u32).to_be_bytes())?; for poly in slice.iter() { - poly.write(writer)?; + poly.write(writer, format)?; } Ok(()) } diff --git a/halo2_proofs/src/lib.rs b/halo2_proofs/src/lib.rs index c84e482675..52676ddb19 100644 --- a/halo2_proofs/src/lib.rs +++ b/halo2_proofs/src/lib.rs @@ -35,3 +35,4 @@ pub mod transcript; pub mod dev; mod helpers; +pub use helpers::SerdeFormat; diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index 38c4078571..00f2c51586 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -19,6 +19,7 @@ use crate::poly::{ PinnedEvaluationDomain, Polynomial, }; use crate::transcript::{ChallengeScalar, EncodedChallenge, Transcript}; +use crate::SerdeFormat; mod assigned; mod circuit; @@ -62,13 +63,21 @@ where C::Scalar: SerdePrimeField, { /// Writes a verifying key to a buffer. - pub fn write(&self, writer: &mut W) -> io::Result<()> { + /// + /// Writes a curve element according to `format`: + /// - `Processed`: Writes a compressed curve element with coordinates in standard form. + /// Writes a field element in standard form, with endianness specified by the + /// `PrimeField` implementation. + /// - Otherwise: Writes an uncompressed curve element with coordinates in Montgomery form + /// Writes a field element into raw bytes in its internal Montgomery representation, + /// WITHOUT performing the expensive Montgomery reduction. + pub fn write(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> { writer.write_all(&self.domain.k().to_be_bytes())?; writer.write_all(&(self.fixed_commitments.len() as u32).to_be_bytes())?; for commitment in &self.fixed_commitments { - commitment.write(writer)?; + commitment.write(writer, format)?; } - self.permutation.write(writer)?; + self.permutation.write(writer, format)?; // write self.selectors for selector in &self.selectors { @@ -81,8 +90,18 @@ where } /// Reads a verification key from a buffer. + /// + /// Reads a curve element from the buffer and parses it according to the `format`: + /// - `Processed`: Reads a compressed curve element and decompresses it. + /// Reads a field element in standard form, with endianness specified by the + /// `PrimeField` implementation, and checks that the element is less than the modulus. + /// - `RawBytes`: Reads an uncompressed curve element with coordinates in Montgomery form. + /// Checks that field elements are less than modulus, and then checks that the point is on the curve. + /// - `RawBytesUnchecked`: Reads an uncompressed curve element with coordinates in Montgomery form; + /// does not perform any checks pub fn read>( reader: &mut R, + format: SerdeFormat, ) -> io::Result { let mut k = [0u8; 4]; reader.read_exact(&mut k)?; @@ -93,10 +112,10 @@ where let num_fixed_columns = u32::from_be_bytes(num_fixed_columns); let fixed_commitments: Vec<_> = (0..num_fixed_columns) - .map(|_| C::read(reader)) + .map(|_| C::read(reader, format)) .collect::>()?; - let permutation = permutation::VerifyingKey::read(reader, &cs.permutation)?; + let permutation = permutation::VerifyingKey::read(reader, &cs.permutation, format)?; // read selectors let selectors: Vec> = vec![vec![false; 1 << k]; cs.num_selectors] @@ -121,16 +140,19 @@ where )) } - /// Writes a verifying key to a vector of bytes. - pub fn to_bytes(&self) -> Vec { + /// Writes a verifying key to a vector of bytes using [`Self::write`]. + pub fn to_bytes(&self, format: SerdeFormat) -> Vec { let mut bytes = Vec::::with_capacity(self.bytes_length()); - Self::write(self, &mut bytes).expect("Writing to vector should not fail"); + Self::write(self, &mut bytes, format).expect("Writing to vector should not fail"); bytes } - /// Reads a verification key from a slice of bytes. - pub fn from_bytes>(mut bytes: &[u8]) -> io::Result { - Self::read::<_, ConcreteCircuit>(&mut bytes) + /// Reads a verification key from a slice of bytes using [`Self::read`]. + pub fn from_bytes>( + mut bytes: &[u8], + format: SerdeFormat, + ) -> io::Result { + Self::read::<_, ConcreteCircuit>(&mut bytes, format) } } @@ -273,32 +295,50 @@ where C::Scalar: SerdePrimeField, { /// Writes a proving key to a buffer. + /// + /// Writes a curve element according to `format`: + /// - `Processed`: Writes a compressed curve element with coordinates in standard form. + /// Writes a field element in standard form, with endianness specified by the + /// `PrimeField` implementation. + /// - Otherwise: Writes an uncompressed curve element with coordinates in Montgomery form + /// Writes a field element into raw bytes in its internal Montgomery representation, + /// WITHOUT performing the expensive Montgomery reduction. /// Does so by first writing the verifying key and then serializing the rest of the data (in the form of field polynomials) - pub fn write(&self, writer: &mut W) -> io::Result<()> { - self.vk.write(writer)?; - self.l0.write(writer)?; - self.l_last.write(writer)?; - self.l_active_row.write(writer)?; - write_polynomial_slice(&self.fixed_values, writer)?; - write_polynomial_slice(&self.fixed_polys, writer)?; - write_polynomial_slice(&self.fixed_cosets, writer)?; - self.permutation.write(writer)?; + pub fn write(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> { + self.vk.write(writer, format)?; + self.l0.write(writer, format)?; + self.l_last.write(writer, format)?; + self.l_active_row.write(writer, format)?; + write_polynomial_slice(&self.fixed_values, writer, format)?; + write_polynomial_slice(&self.fixed_polys, writer, format)?; + write_polynomial_slice(&self.fixed_cosets, writer, format)?; + self.permutation.write(writer, format)?; Ok(()) } /// Reads a proving key from a buffer. /// Does so by reading verification key first, and then deserializing the rest of the file into the remaining proving key data. + /// + /// Reads a curve element from the buffer and parses it according to the `format`: + /// - `Processed`: Reads a compressed curve element and decompresses it. + /// Reads a field element in standard form, with endianness specified by the + /// `PrimeField` implementation, and checks that the element is less than the modulus. + /// - `RawBytes`: Reads an uncompressed curve element with coordinates in Montgomery form. + /// Checks that field elements are less than modulus, and then checks that the point is on the curve. + /// - `RawBytesUnchecked`: Reads an uncompressed curve element with coordinates in Montgomery form; + /// does not perform any checks pub fn read>( reader: &mut R, + format: SerdeFormat, ) -> io::Result { - let vk = VerifyingKey::::read::(reader)?; - let l0 = Polynomial::read(reader)?; - let l_last = Polynomial::read(reader)?; - let l_active_row = Polynomial::read(reader)?; - let fixed_values = read_polynomial_vec(reader)?; - let fixed_polys = read_polynomial_vec(reader)?; - let fixed_cosets = read_polynomial_vec(reader)?; - let permutation = permutation::ProvingKey::read(reader)?; + let vk = VerifyingKey::::read::(reader, format)?; + let l0 = Polynomial::read(reader, format)?; + let l_last = Polynomial::read(reader, format)?; + let l_active_row = Polynomial::read(reader, format)?; + let fixed_values = read_polynomial_vec(reader, format)?; + let fixed_polys = read_polynomial_vec(reader, format)?; + let fixed_cosets = read_polynomial_vec(reader, format)?; + let permutation = permutation::ProvingKey::read(reader, format)?; let ev = Evaluator::new(vk.cs()); Ok(Self { vk, @@ -313,16 +353,19 @@ where }) } - /// Writes a proving key to a vector of bytes. - pub fn to_bytes(&self) -> Vec { + /// Writes a proving key to a vector of bytes using [`Self::write`]. + pub fn to_bytes(&self, format: SerdeFormat) -> Vec { let mut bytes = Vec::::with_capacity(self.bytes_length()); - Self::write(self, &mut bytes).expect("Writing to vector should not fail"); + Self::write(self, &mut bytes, format).expect("Writing to vector should not fail"); bytes } - /// Reads a proving key from a slice of bytes. - pub fn from_bytes>(mut bytes: &[u8]) -> io::Result { - Self::read::<_, ConcreteCircuit>(&mut bytes) + /// Reads a proving key from a slice of bytes using [`Self::read`]. + pub fn from_bytes>( + mut bytes: &[u8], + format: SerdeFormat, + ) -> io::Result { + Self::read::<_, ConcreteCircuit>(&mut bytes, format) } } diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index c0dc26dddd..05cae2d373 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -6,6 +6,7 @@ use crate::{ SerdeCurveAffine, SerdePrimeField, }, poly::{Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial}, + SerdeFormat, }; use ff::PrimeField; @@ -88,22 +89,26 @@ impl VerifyingKey { &self.commitments } - pub(crate) fn write(&self, writer: &mut W) -> io::Result<()> + pub(crate) fn write(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> where C: SerdeCurveAffine, { for commitment in &self.commitments { - commitment.write(writer)?; + commitment.write(writer, format)?; } Ok(()) } - pub(crate) fn read(reader: &mut R, argument: &Argument) -> io::Result + pub(crate) fn read( + reader: &mut R, + argument: &Argument, + format: SerdeFormat, + ) -> io::Result where C: SerdeCurveAffine, { let commitments = (0..argument.columns.len()) - .map(|_| C::read(reader)) + .map(|_| C::read(reader, format)) .collect::, _>>()?; Ok(VerifyingKey { commitments }) } @@ -126,10 +131,10 @@ where C::Scalar: SerdePrimeField, { /// Reads proving key for a single permutation argument from buffer using `Polynomial::read`. - pub(super) fn read(reader: &mut R) -> io::Result { - let permutations = read_polynomial_vec(reader)?; - let polys = read_polynomial_vec(reader)?; - let cosets = read_polynomial_vec(reader)?; + pub(super) fn read(reader: &mut R, format: SerdeFormat) -> io::Result { + let permutations = read_polynomial_vec(reader, format)?; + let polys = read_polynomial_vec(reader, format)?; + let cosets = read_polynomial_vec(reader, format)?; Ok(ProvingKey { permutations, polys, @@ -138,10 +143,14 @@ where } /// Writes proving key for a single permutation argument to buffer using `Polynomial::write`. - pub(super) fn write(&self, writer: &mut W) -> io::Result<()> { - write_polynomial_slice(&self.permutations, writer)?; - write_polynomial_slice(&self.polys, writer)?; - write_polynomial_slice(&self.cosets, writer)?; + pub(super) fn write( + &self, + writer: &mut W, + format: SerdeFormat, + ) -> io::Result<()> { + write_polynomial_slice(&self.permutations, writer, format)?; + write_polynomial_slice(&self.polys, writer, format)?; + write_polynomial_slice(&self.cosets, writer, format)?; Ok(()) } } diff --git a/halo2_proofs/src/poly.rs b/halo2_proofs/src/poly.rs index d5c05ee866..44cde43dd9 100644 --- a/halo2_proofs/src/poly.rs +++ b/halo2_proofs/src/poly.rs @@ -5,6 +5,7 @@ use crate::arithmetic::parallelize; use crate::helpers::SerdePrimeField; use crate::plonk::Assigned; +use crate::SerdeFormat; use ff::PrimeField; use group::ff::{BatchInvert, Field}; @@ -148,13 +149,13 @@ impl Polynomial { impl Polynomial { /// Reads polynomial from buffer using `SerdePrimeField::read`. - pub(crate) fn read(reader: &mut R) -> io::Result { + pub(crate) fn read(reader: &mut R, format: SerdeFormat) -> io::Result { let mut poly_len = [0u8; 4]; reader.read_exact(&mut poly_len)?; let poly_len = u32::from_be_bytes(poly_len); (0..poly_len) - .map(|_| F::read(reader)) + .map(|_| F::read(reader, format)) .collect::>>() .map(|values| Self { values, @@ -163,10 +164,14 @@ impl Polynomial { } /// Writes polynomial to buffer using `SerdePrimeField::write`. - pub(crate) fn write(&self, writer: &mut W) -> io::Result<()> { + pub(crate) fn write( + &self, + writer: &mut W, + format: SerdeFormat, + ) -> io::Result<()> { writer.write_all(&(self.values.len() as u32).to_be_bytes())?; for value in self.values.iter() { - value.write(writer)?; + value.write(writer, format)?; } Ok(()) } diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index c801d9401b..03f6340200 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -4,6 +4,7 @@ use crate::arithmetic::{ use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, ParamsVerifier, MSM}; use crate::poly::{Coeff, LagrangeCoeff, Polynomial}; +use crate::SerdeFormat; use ff::{Field, PrimeField}; use group::{prime::PrimeCurveAffine, Curve, Group as _}; @@ -136,6 +137,111 @@ impl ParamsKZG { pub fn s_g2(&self) -> E::G2Affine { self.s_g2 } + + /// Writes parameters to buffer + pub fn write_custom(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> + where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, + { + writer.write_all(&self.k.to_le_bytes())?; + for el in self.g.iter() { + el.write(writer, format)?; + } + for el in self.g_lagrange.iter() { + el.write(writer, format)?; + } + self.g2.write(writer, format)?; + self.s_g2.write(writer, format)?; + Ok(()) + } + + /// Reads params from a buffer. + pub fn read_custom(reader: &mut R, format: SerdeFormat) -> io::Result + where + E::G1Affine: SerdeCurveAffine, + E::G2Affine: SerdeCurveAffine, + { + let mut k = [0u8; 4]; + reader.read_exact(&mut k[..])?; + let k = u32::from_le_bytes(k); + let n = 1 << k; + + let (g, g_lagrange) = match format { + SerdeFormat::Processed => { + use group::GroupEncoding; + let load_points_from_file_parallelly = + |reader: &mut R| -> io::Result>> { + let mut points_compressed = + vec![<::G1Affine as GroupEncoding>::Repr::default(); n]; + for points_compressed in points_compressed.iter_mut() { + reader.read_exact((*points_compressed).as_mut())?; + } + + let mut points = vec![Option::::None; n]; + parallelize(&mut points, |points, chunks| { + for (i, point) in points.iter_mut().enumerate() { + *point = Option::from(E::G1Affine::from_bytes( + &points_compressed[chunks + i], + )); + } + }); + Ok(points) + }; + + let g = load_points_from_file_parallelly(reader)?; + let g: Vec<::G1Affine> = g + .iter() + .map(|point| { + point.ok_or_else(|| { + io::Error::new(io::ErrorKind::Other, "invalid point encoding") + }) + }) + .collect::>()?; + let g_lagrange = load_points_from_file_parallelly(reader)?; + let g_lagrange: Vec<::G1Affine> = g_lagrange + .iter() + .map(|point| { + point.ok_or_else(|| { + io::Error::new(io::ErrorKind::Other, "invalid point encoding") + }) + }) + .collect::>()?; + (g, g_lagrange) + } + SerdeFormat::RawBytes => { + let g = (0..n) + .map(|_| ::read(reader, format)) + .collect::, _>>()?; + let g_lagrange = (0..n) + .map(|_| ::read(reader, format)) + .collect::, _>>()?; + (g, g_lagrange) + } + SerdeFormat::RawBytesUnchecked => { + // avoid try branching for performance + let g = (0..n) + .map(|_| ::read(reader, format).unwrap()) + .collect::>(); + let g_lagrange = (0..n) + .map(|_| ::read(reader, format).unwrap()) + .collect::>(); + (g, g_lagrange) + } + }; + + let g2 = E::G2Affine::read(reader, format)?; + let s_g2 = E::G2Affine::read(reader, format)?; + + Ok(Self { + k, + n: n as u64, + g, + g_lagrange, + g2, + s_g2, + }) + } } // TODO: see the issue at https://github.com/appliedzkp/halo2/issues/45 @@ -187,100 +293,12 @@ where /// Writes params to a buffer. fn write(&self, writer: &mut W) -> io::Result<()> { - writer.write_all(&self.k.to_le_bytes())?; - for el in self.g.iter() { - el.write(writer)?; - } - for el in self.g_lagrange.iter() { - el.write(writer)?; - } - self.g2.write(writer)?; - self.s_g2.write(writer)?; - Ok(()) + self.write_custom(writer, SerdeFormat::RawBytes) } /// Reads params from a buffer. fn read(reader: &mut R) -> io::Result { - let mut k = [0u8; 4]; - reader.read_exact(&mut k[..])?; - let k = u32::from_le_bytes(k); - let n = 1 << k; - - #[cfg(not(feature = "serde-raw"))] - let (g, g_lagrange) = { - use group::GroupEncoding; - let load_points_from_file_parallelly = - |reader: &mut R| -> io::Result>> { - let mut points_compressed = - vec![<::G1Affine as GroupEncoding>::Repr::default(); n]; - for points_compressed in points_compressed.iter_mut() { - reader.read_exact((*points_compressed).as_mut())?; - } - - let mut points = vec![Option::::None; n]; - parallelize(&mut points, |points, chunks| { - for (i, point) in points.iter_mut().enumerate() { - *point = Option::from(E::G1Affine::from_bytes( - &points_compressed[chunks + i], - )); - } - }); - Ok(points) - }; - - let g = load_points_from_file_parallelly(reader)?; - let g: Vec<::G1Affine> = g - .iter() - .map(|point| { - point.ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "invalid point encoding") - }) - }) - .collect::>()?; - let g_lagrange = load_points_from_file_parallelly(reader)?; - let g_lagrange: Vec<::G1Affine> = g_lagrange - .iter() - .map(|point| { - point.ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "invalid point encoding") - }) - }) - .collect::>()?; - (g, g_lagrange) - }; - #[cfg(all(feature = "serde-raw", not(feature = "raw-unchecked")))] - let (g, g_lagrange) = { - let g = (0..n) - .map(|_| ::read(reader)) - .collect::, _>>()?; - let g_lagrange = (0..n) - .map(|_| ::read(reader)) - .collect::, _>>()?; - (g, g_lagrange) - }; - #[cfg(all(feature = "serde-raw", feature = "raw-unchecked"))] - let (g, g_lagrange) = { - // avoid try branching for performance - let g = (0..n) - .map(|_| ::read(reader).unwrap()) - .collect::>(); - let g_lagrange = (0..n) - .map(|_| ::read(reader).unwrap()) - .collect::>(); - (g, g_lagrange) - }; - - let g2 = E::G2Affine::read(reader)?; - let s_g2 = E::G2Affine::read(reader)?; - - Ok(Self { - k, - n: n as u64, - g, - g_lagrange, - g2, - s_g2, - }) + Self::read_custom(reader, SerdeFormat::RawBytes) } } From 1a92fa80d277b93c55ddf191bedf7eb67307beda Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 18 Jan 2023 10:37:39 +0800 Subject: [PATCH 41/62] fmt --- halo2_proofs/src/arithmetic.rs | 85 +++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 31 deletions(-) diff --git a/halo2_proofs/src/arithmetic.rs b/halo2_proofs/src/arithmetic.rs index f493687d46..e919f5d0b0 100644 --- a/halo2_proofs/src/arithmetic.rs +++ b/halo2_proofs/src/arithmetic.rs @@ -227,18 +227,23 @@ fn serial_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { } } -fn serial_split_fft(a: &mut [G], twiddle_lut: &[G::Scalar], twiddle_scale: usize, log_n: u32) { +fn serial_split_fft( + a: &mut [G], + twiddle_lut: &[G::Scalar], + twiddle_scale: usize, + log_n: u32, +) { let n = a.len() as u32; assert_eq!(n, 1 << log_n); let mut m = 1; for _ in 0..log_n { let omega_idx = twiddle_scale * n as usize / (2 * m as usize); // 1/2, 1/4, 1/8, ... - let low_idx = omega_idx%(1<>SPARSE_TWIDDLE_DEGREE; + let low_idx = omega_idx % (1 << SPARSE_TWIDDLE_DEGREE); + let high_idx = omega_idx >> SPARSE_TWIDDLE_DEGREE; let mut w_m = twiddle_lut[low_idx]; if high_idx > 0 { - w_m = w_m*twiddle_lut[(1<(a: &mut [G], twiddle_lut: &[G::Scalar], twiddle_sc } } -fn split_radix_fft(tmp: &mut [G], a: &[G], twiddle_lut: &[G::Scalar], n: usize, sub_fft_offset: usize, log_split: usize) { +fn split_radix_fft( + tmp: &mut [G], + a: &[G], + twiddle_lut: &[G::Scalar], + n: usize, + sub_fft_offset: usize, + log_split: usize, +) { let split_m = 1 << log_split; let sub_n = n >> log_split; @@ -271,33 +283,38 @@ fn split_radix_fft(tmp: &mut [G], a: &[G], twiddle_lut: &[G::Scalar], // let mut t1: Vec = Vec::with_capacity(split_m as usize); // unsafe{ t1.set_len(split_m as usize); } for i in 0..split_m { - t1[bitreverse(i,log_split)] = a[(i*sub_n + sub_fft_offset)]; + t1[bitreverse(i, log_split)] = a[(i * sub_n + sub_fft_offset)]; } serial_split_fft(&mut t1, twiddle_lut, sub_n, log_split as u32); let sparse_degree = SPARSE_TWIDDLE_DEGREE; let omega_idx = sub_fft_offset as usize; - let low_idx = omega_idx%(1<>sparse_degree; + let low_idx = omega_idx % (1 << sparse_degree); + let high_idx = omega_idx >> sparse_degree; let mut omega = twiddle_lut[low_idx]; if high_idx > 0 { - omega = omega*twiddle_lut[(1<(omega: F, log_n: u32, sparse_degree: u32, with_last_level: bool) -> Vec { +pub fn generate_twiddle_lookup_table( + omega: F, + log_n: u32, + sparse_degree: u32, + with_last_level: bool, +) -> Vec { let without_last_level = !with_last_level; let is_lut_len_large = sparse_degree > log_n; // dense if is_lut_len_large { - let mut twiddle_lut = vec![F::zero(); (1<(omega: F, log_n: u32, sparse_degr } // sparse - let low_degree_lut_len = 1<(a: &mut [G], omega: G::Scalar, log_n: u32) { let idx = start + idx; let i = idx / sub_n; let j = idx % sub_n; - *a = tmp[j*split_m + i]; + *a = tmp[j * split_m + i]; } }); - + // sub fft let new_omega = omega.pow_vartime(&[split_m as u64, 0, 0, 0]); multicore::scope(|scope| { @@ -389,7 +412,7 @@ pub fn parallel_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { parallelize(a, |a, start| { for (idx, a) in a.iter_mut().enumerate() { let idx = start + idx; - *a = tmp[sub_n*(idx & mask) + (idx >> log_split)]; + *a = tmp[sub_n * (idx & mask) + (idx >> log_split)]; } }); } From 7a62a6bdad8c7c878d4c9c4eaa4713a4d898b9ba Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 18 Jan 2023 21:38:01 +0800 Subject: [PATCH 42/62] add phase-check feature --- halo2_proofs/Cargo.toml | 1 + halo2_proofs/src/dev.rs | 106 +++++++++++++++++++++++++++--- halo2_proofs/src/plonk/circuit.rs | 2 +- halo2_proofs/src/plonk/prover.rs | 35 +++++++++- halo2_proofs/src/poly.rs | 2 +- 5 files changed, 134 insertions(+), 12 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index c21153de90..a941f0437f 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -85,6 +85,7 @@ sanity-checks = [] batch = ["rand_core/getrandom"] shplonk = [] gwc = [] +phase-check = [] profile = ["ark-std/print-trace"] [lib] diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index b5b92d390f..75847706a0 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -10,6 +10,9 @@ use std::time::{Duration, Instant}; use blake2b_simd::blake2b; use ff::Field; +use crate::plonk::sealed::SealedPhase; +use crate::plonk::FirstPhase; +use crate::plonk::ThirdPhase; use crate::{ arithmetic::{FieldExt, Group}, circuit, @@ -82,7 +85,7 @@ impl Region { /// The value of a particular cell within the circuit. #[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum CellValue { +pub(crate) enum CellValue { // An unassigned cell. Unassigned, // A cell that has been assigned a value. @@ -291,7 +294,8 @@ pub struct MockProver { // The fixed cells in the circuit, arranged as [column][row]. fixed: Vec>>, // The advice cells in the circuit, arranged as [column][row]. - advice: Vec>>, + pub(crate) advice: Vec>>, + advice_prev: Vec>>, // The instance cells in the circuit, arranged as [column][row]. instance: Vec>, @@ -303,6 +307,8 @@ pub struct MockProver { // A range of available rows for assignment and copies. usable_rows: Range, + + current_phase: crate::plonk::sealed::Phase, } impl Assignment for MockProver { @@ -378,6 +384,11 @@ impl Assignment for MockProver { A: FnOnce() -> AR, AR: Into, { + #[cfg(feature = "phase-check")] + if false && self.current_phase.0 < column.column_type().phase.0 { + return Ok(()); + } + if !self.usable_rows.contains(&row) { return Err(Error::not_enough_rows_available(self.k)); } @@ -391,12 +402,30 @@ impl Assignment for MockProver { .or_default(); } + let assigned = CellValue::Assigned(to().into_field().evaluate().assign()?); *self .advice .get_mut(column.index()) .and_then(|v| v.get_mut(row)) - .ok_or(Error::BoundsFailure)? = - CellValue::Assigned(to().into_field().evaluate().assign()?); + .ok_or(Error::BoundsFailure)? = assigned; + + #[cfg(feature = "phase-check")] + if false && self.current_phase.0 > column.column_type().phase.0 { + // Some circuits assign cells more than one times with different values + // So this check sometimes can be false alarm + if !self.advice_prev.is_empty() { + if self.advice_prev[column.index()][row] != assigned { + panic!("not same new {assigned:?} old {:?}, column idx {} row {} cur phase {:?} col phase {:?} region {:?}", + self.advice_prev[column.index()][row], + column.index(), + row, + self.current_phase, + column.column_type().phase, + self.current_region + ) + } + } + } Ok(()) } @@ -470,7 +499,10 @@ impl Assignment for MockProver { } fn get_challenge(&self, challenge: Challenge) -> circuit::Value { - circuit::Value::known(self.challenges[challenge.index()]) + match self.challenges.get(challenge.index()) { + None => circuit::Value::unknown(), + Some(v) => circuit::Value::known(*v), + } } fn push_namespace(&mut self, _: N) @@ -541,7 +573,7 @@ impl MockProver { let constants = cs.constants.clone(); // Use hash chain to derive deterministic challenges for testing - let challenges = { + let challenges: Vec = { let mut hash: [u8; 64] = blake2b(b"Halo2-MockProver").as_bytes().try_into().unwrap(); iter::repeat_with(|| { hash = blake2b(&hash).as_bytes().try_into().unwrap(); @@ -551,6 +583,63 @@ impl MockProver { .collect() }; + #[cfg(feature = "phase-check")] + { + // check1: phase1 should not assign expr including phase2 challenges + // check2: phase2 assigns same phase1 columns with phase1 + let mut cur_challenges: Vec = Vec::new(); + let mut last_advice: Vec>> = Vec::new(); + for current_phase in cs.phases() { + let mut prover = MockProver { + k, + n: n as u32, + cs: cs.clone(), + regions: vec![], + current_region: None, + fixed: fixed.clone(), + advice: advice.clone(), + advice_prev: last_advice.clone(), + instance: instance.clone(), + selectors: selectors.clone(), + challenges: cur_challenges.clone(), + permutation: permutation.clone(), + usable_rows: 0..usable_rows, + current_phase, + }; + ConcreteCircuit::FloorPlanner::synthesize( + &mut prover, + circuit, + config.clone(), + constants.clone(), + )?; + for (index, phase) in cs.challenge_phase.iter().enumerate() { + if current_phase == *phase { + debug_assert_eq!(cur_challenges.len(), index); + cur_challenges.push(challenges[index].clone()); + } + } + if !last_advice.is_empty() { + let mut err = false; + for (idx, advice_values) in prover.advice.iter().enumerate() { + if cs.advice_column_phase[idx].0 < current_phase.0 { + if advice_values != &last_advice[idx] { + log::error!( + "PHASE ERR column{} not same after phase {:?}", + idx, + current_phase + ); + err = true; + } + } + } + if err { + panic!("wrong phase assignment"); + } + } + last_advice = prover.advice; + } + } + let mut prover = MockProver { k, n: n as u32, @@ -559,13 +648,14 @@ impl MockProver { current_region: None, fixed, advice, + advice_prev: vec![], instance, selectors, - challenges, + challenges: challenges.clone(), permutation, usable_rows: 0..usable_rows, + current_phase: ThirdPhase.to_sealed(), }; - ConcreteCircuit::FloorPlanner::synthesize(&mut prover, circuit, config, constants)?; let (cs, selector_polys) = prover.cs.compress_selectors(prover.selectors.clone()); diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index bbc4ae15b3..e94787b619 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -66,7 +66,7 @@ impl PartialOrd for Column { pub(crate) mod sealed { /// Phase of advice column #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] - pub struct Phase(pub(super) u8); + pub struct Phase(pub(crate) u8); impl Phase { pub fn prev(&self) -> Option { diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index 8d8e60b6d5..bbf0f7fd36 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -190,9 +190,14 @@ pub fn create_proof< AR: Into, { // Ignore assignment of advice column in different phase than current one. + #[cfg(not(feature = "phase-check"))] if self.current_phase != column.column_type().phase { return Ok(()); } + #[cfg(feature = "phase-check")] + if false && self.current_phase.0 < column.column_type().phase.0 { + return Ok(()); + } if !self.usable_rows.contains(&row) { return Err(Error::not_enough_rows_available(self.k)); @@ -275,6 +280,9 @@ pub fn create_proof< }; instances.len() ]; + #[cfg(feature = "phase-check")] + let mut advice_assignments = + vec![vec![domain.empty_lagrange_assigned(); meta.num_advice_columns]; instances.len()]; let mut challenges = HashMap::::with_capacity(meta.num_challenges); let unusable_rows_start = params.n() as usize - (meta.blinding_factors() + 1); @@ -292,8 +300,11 @@ pub fn create_proof< }) .collect::>(); - for ((circuit, advice), instances) in - circuits.iter().zip(advice.iter_mut()).zip(instances) + for (circuit_idx, ((circuit, advice), instances)) in circuits + .iter() + .zip(advice.iter_mut()) + .zip(instances) + .enumerate() { let mut witness = WitnessCollection { k: params.k(), @@ -317,6 +328,22 @@ pub fn create_proof< meta.constants.clone(), )?; + #[cfg(feature = "phase-check")] + { + for (idx, advice_col) in witness.advice.iter().enumerate() { + if pk.vk.cs.advice_column_phase[idx].0 < current_phase.0 { + if advice_assignments[circuit_idx][idx].values != advice_col.values { + log::error!( + "advice column {}(at {:?}) changed when {:?}", + idx, + pk.vk.cs.advice_column_phase[idx], + current_phase + ); + } + } + } + } + let mut advice_values = batch_invert_assigned::( witness .advice @@ -324,6 +351,10 @@ pub fn create_proof< .enumerate() .filter_map(|(column_index, advice)| { if column_indices.contains(&column_index) { + #[cfg(feature = "phase-check")] + { + advice_assignments[circuit_idx][column_index] = advice.clone(); + } Some(advice) } else { None diff --git a/halo2_proofs/src/poly.rs b/halo2_proofs/src/poly.rs index ecf66a6e0b..8d1d80d2a5 100644 --- a/halo2_proofs/src/poly.rs +++ b/halo2_proofs/src/poly.rs @@ -63,7 +63,7 @@ impl Basis for ExtendedLagrangeCoeff {} /// basis. #[derive(Clone, Debug)] pub struct Polynomial { - values: Vec, + pub(crate) values: Vec, _marker: PhantomData, } From c7c72fdbd7a9ebbc77ad641b8ca99dd4a48970da Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Fri, 20 Jan 2023 14:35:02 +0800 Subject: [PATCH 43/62] allow later phase to assign prev phase columns --- halo2_proofs/src/dev.rs | 3 +-- halo2_proofs/src/plonk/prover.rs | 7 +------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index 75847706a0..f2155165b8 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -384,8 +384,7 @@ impl Assignment for MockProver { A: FnOnce() -> AR, AR: Into, { - #[cfg(feature = "phase-check")] - if false && self.current_phase.0 < column.column_type().phase.0 { + if self.current_phase.0 < column.column_type().phase.0 { return Ok(()); } diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index bbf0f7fd36..bd9257c6b3 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -190,12 +190,7 @@ pub fn create_proof< AR: Into, { // Ignore assignment of advice column in different phase than current one. - #[cfg(not(feature = "phase-check"))] - if self.current_phase != column.column_type().phase { - return Ok(()); - } - #[cfg(feature = "phase-check")] - if false && self.current_phase.0 < column.column_type().phase.0 { + if self.current_phase.0 < column.column_type().phase.0 { return Ok(()); } From d984f82ac61a5d05da387fa1aeb935c47b4795d3 Mon Sep 17 00:00:00 2001 From: spherel Date: Sat, 28 Jan 2023 22:11:58 -0600 Subject: [PATCH 44/62] part-wise computation of extended h poly --- halo2_proofs/src/plonk.rs | 8 +- halo2_proofs/src/plonk/evaluation.rs | 443 ++++++++++--------- halo2_proofs/src/plonk/keygen.rs | 32 +- halo2_proofs/src/plonk/permutation.rs | 2 +- halo2_proofs/src/plonk/permutation/keygen.rs | 3 +- halo2_proofs/src/plonk/permutation/prover.rs | 4 +- halo2_proofs/src/poly/domain.rs | 136 ++++++ 7 files changed, 397 insertions(+), 231 deletions(-) diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index f9a6587af6..cc56eb5adc 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -144,12 +144,12 @@ pub struct PinnedVerificationKey<'a, C: CurveAffine> { #[derive(Clone, Debug)] pub struct ProvingKey { vk: VerifyingKey, - l0: Polynomial, - l_last: Polynomial, - l_active_row: Polynomial, + l0: Vec>, + l_last: Vec>, + l_active_row: Vec>, fixed_values: Vec>, fixed_polys: Vec>, - fixed_cosets: Vec>, + fixed_cosets: Vec>>, permutation: permutation::ProvingKey, ev: Evaluator, } diff --git a/halo2_proofs/src/plonk/evaluation.rs b/halo2_proofs/src/plonk/evaluation.rs index f324a4d438..66366902b3 100644 --- a/halo2_proofs/src/plonk/evaluation.rs +++ b/halo2_proofs/src/plonk/evaluation.rs @@ -291,234 +291,261 @@ impl Evaluator { permutations: &[permutation::prover::Committed], ) -> Polynomial { let domain = &pk.vk.domain; - let size = domain.extended_len(); - let rot_scale = 1 << (domain.extended_k() - domain.k()); - let fixed = &pk.fixed_cosets[..]; + let size = 1 << domain.k() as usize; + let rot_scale = 1; let extended_omega = domain.get_extended_omega(); + let omega = domain.get_omega(); let isize = size as i32; let one = C::ScalarExt::one(); - let l0 = &pk.l0; - let l_last = &pk.l_last; - let l_active_row = &pk.l_active_row; let p = &pk.vk.cs.permutation; - // Calculate the advice and instance cosets - let advice: Vec>> = advice_polys + // Calculate the quotient polynomial for each part + let mut current_extended_omega = one; + let value_parts: Vec> = pk + .fixed_cosets .iter() - .map(|advice_polys| { - advice_polys + .enumerate() + .zip(pk.l0.iter()) + .zip(pk.l_last.iter()) + .zip(pk.l_active_row.iter()) + .map(|((((part_idx, fixed), l0), l_last), l_active_row)| { + // Calculate the advice and instance cosets + let advice: Vec>> = advice_polys .iter() - .map(|poly| domain.coeff_to_extended(poly.clone())) - .collect() - }) - .collect(); - let instance: Vec>> = instance_polys - .iter() - .map(|instance_polys| { - instance_polys + .map(|advice_polys| { + advice_polys + .iter() + .map(|poly| { + domain.coeff_to_extended_part(poly.clone(), current_extended_omega) + }) + .collect() + }) + .collect(); + let instance: Vec>> = instance_polys .iter() - .map(|poly| domain.coeff_to_extended(poly.clone())) - .collect() - }) - .collect(); + .map(|instance_polys| { + instance_polys + .iter() + .map(|poly| { + domain.coeff_to_extended_part(poly.clone(), current_extended_omega) + }) + .collect() + }) + .collect(); - let mut values = domain.empty_extended(); + let mut values = domain.empty_lagrange(); - // Core expression evaluations - let num_threads = multicore::current_num_threads(); - for (((advice, instance), lookups), permutation) in advice - .iter() - .zip(instance.iter()) - .zip(lookups.iter()) - .zip(permutations.iter()) - { - // Custom gates - multicore::scope(|scope| { - let chunk_size = (size + num_threads - 1) / num_threads; - for (thread_idx, values) in values.chunks_mut(chunk_size).enumerate() { - let start = thread_idx * chunk_size; - scope.spawn(move |_| { - let mut eval_data = self.custom_gates.instance(); - for (i, value) in values.iter_mut().enumerate() { - let idx = start + i; - *value = self.custom_gates.evaluate( - &mut eval_data, - fixed, - advice, - instance, - challenges, - &beta, - &gamma, - &theta, - &y, - value, - idx, - rot_scale, - isize, - ); + // Core expression evaluations + let num_threads = multicore::current_num_threads(); + for (((advice, instance), lookups), permutation) in advice + .iter() + .zip(instance.iter()) + .zip(lookups.iter()) + .zip(permutations.iter()) + { + // Custom gates + multicore::scope(|scope| { + let chunk_size = (size + num_threads - 1) / num_threads; + for (thread_idx, values) in values.chunks_mut(chunk_size).enumerate() { + let start = thread_idx * chunk_size; + scope.spawn(move |_| { + let mut eval_data = self.custom_gates.instance(); + for (i, value) in values.iter_mut().enumerate() { + let idx = start + i; + *value = self.custom_gates.evaluate( + &mut eval_data, + fixed, + advice, + instance, + challenges, + &beta, + &gamma, + &theta, + &y, + value, + idx, + rot_scale, + isize, + ); + } + }); } }); - } - }); - - // Permutations - let sets = &permutation.sets; - if !sets.is_empty() { - let blinding_factors = pk.vk.cs.blinding_factors(); - let last_rotation = Rotation(-((blinding_factors + 1) as i32)); - let chunk_len = pk.vk.cs.degree() - 2; - let delta_start = beta * &C::Scalar::ZETA; - - let first_set = sets.first().unwrap(); - let last_set = sets.last().unwrap(); - - // Permutation constraints - parallelize(&mut values, |values, start| { - let mut beta_term = extended_omega.pow_vartime(&[start as u64, 0, 0, 0]); - for (i, value) in values.iter_mut().enumerate() { - let idx = start + i; - let r_next = get_rotation_idx(idx, 1, rot_scale, isize); - let r_last = get_rotation_idx(idx, last_rotation.0, rot_scale, isize); - - // Enforce only for the first set. - // l_0(X) * (1 - z_0(X)) = 0 - *value = *value * y - + ((one - first_set.permutation_product_coset[idx]) * l0[idx]); - // Enforce only for the last set. - // l_last(X) * (z_l(X)^2 - z_l(X)) = 0 - *value = *value * y - + ((last_set.permutation_product_coset[idx] - * last_set.permutation_product_coset[idx] - - last_set.permutation_product_coset[idx]) - * l_last[idx]); - // Except for the first set, enforce. - // l_0(X) * (z_i(X) - z_{i-1}(\omega^(last) X)) = 0 - for (set_idx, set) in sets.iter().enumerate() { - if set_idx != 0 { + + // Permutations + let sets = &permutation.sets; + if !sets.is_empty() { + let blinding_factors = pk.vk.cs.blinding_factors(); + let last_rotation = Rotation(-((blinding_factors + 1) as i32)); + let chunk_len = pk.vk.cs.degree() - 2; + let delta_start = beta * &C::Scalar::ZETA; + + let first_set = sets.first().unwrap(); + let last_set = sets.last().unwrap(); + + // Permutation constraints + parallelize(&mut values, |values, start| { + let mut beta_term = current_extended_omega + * omega.pow_vartime(&[start as u64, 0, 0, 0]); + for (i, value) in values.iter_mut().enumerate() { + let idx = start + i; + let r_next = get_rotation_idx(idx, 1, rot_scale, isize); + let r_last = + get_rotation_idx(idx, last_rotation.0, rot_scale, isize); + + // Enforce only for the first set. + // l_0(X) * (1 - z_0(X)) = 0 *value = *value * y - + ((set.permutation_product_coset[idx] - - permutation.sets[set_idx - 1].permutation_product_coset - [r_last]) + + ((one - first_set.permutation_product_coset[part_idx][idx]) * l0[idx]); + // Enforce only for the last set. + // l_last(X) * (z_l(X)^2 - z_l(X)) = 0 + *value = *value * y + + ((last_set.permutation_product_coset[part_idx][idx] + * last_set.permutation_product_coset[part_idx][idx] + - last_set.permutation_product_coset[part_idx][idx]) + * l_last[idx]); + // Except for the first set, enforce. + // l_0(X) * (z_i(X) - z_{i-1}(\omega^(last) X)) = 0 + for (set_idx, set) in sets.iter().enumerate() { + if set_idx != 0 { + *value = *value * y + + ((set.permutation_product_coset[part_idx][idx] + - permutation.sets[set_idx - 1] + .permutation_product_coset[part_idx][r_last]) + * l0[idx]); + } + } + // And for all the sets we enforce: + // (1 - (l_last(X) + l_blind(X))) * ( + // z_i(\omega X) \prod_j (p(X) + \beta s_j(X) + \gamma) + // - z_i(X) \prod_j (p(X) + \delta^j \beta X + \gamma) + // ) + let mut current_delta = delta_start * beta_term; + for ((set, columns), cosets) in sets + .iter() + .zip(p.columns.chunks(chunk_len)) + .zip(pk.permutation.cosets[part_idx].chunks(chunk_len)) + { + let mut left = set.permutation_product_coset[part_idx][r_next]; + for (values, permutation) in columns + .iter() + .map(|&column| match column.column_type() { + Any::Advice(_) => &advice[column.index()], + Any::Fixed => &fixed[column.index()], + Any::Instance => &instance[column.index()], + }) + .zip(cosets.iter()) + { + left *= values[idx] + beta * permutation[idx] + gamma; + } + + let mut right = set.permutation_product_coset[part_idx][idx]; + for values in + columns.iter().map(|&column| match column.column_type() { + Any::Advice(_) => &advice[column.index()], + Any::Fixed => &fixed[column.index()], + Any::Instance => &instance[column.index()], + }) + { + right *= values[idx] + current_delta + gamma; + current_delta *= &C::Scalar::DELTA; + } + + *value = *value * y + ((left - right) * l_active_row[idx]); + } + beta_term *= ω } - } - // And for all the sets we enforce: - // (1 - (l_last(X) + l_blind(X))) * ( - // z_i(\omega X) \prod_j (p(X) + \beta s_j(X) + \gamma) - // - z_i(X) \prod_j (p(X) + \delta^j \beta X + \gamma) - // ) - let mut current_delta = delta_start * beta_term; - for ((set, columns), cosets) in sets - .iter() - .zip(p.columns.chunks(chunk_len)) - .zip(pk.permutation.cosets.chunks(chunk_len)) - { - let mut left = set.permutation_product_coset[r_next]; - for (values, permutation) in columns - .iter() - .map(|&column| match column.column_type() { - Any::Advice(_) => &advice[column.index()], - Any::Fixed => &fixed[column.index()], - Any::Instance => &instance[column.index()], - }) - .zip(cosets.iter()) - { - left *= values[idx] + beta * permutation[idx] + gamma; - } - - let mut right = set.permutation_product_coset[idx]; - for values in columns.iter().map(|&column| match column.column_type() { - Any::Advice(_) => &advice[column.index()], - Any::Fixed => &fixed[column.index()], - Any::Instance => &instance[column.index()], - }) { - right *= values[idx] + current_delta + gamma; - current_delta *= &C::Scalar::DELTA; - } - - *value = *value * y + ((left - right) * l_active_row[idx]); - } - beta_term *= &extended_omega; + }); } - }); - } - // Lookups - for (n, lookup) in lookups.iter().enumerate() { - // Polynomials required for this lookup. - // Calculated here so these only have to be kept in memory for the short time - // they are actually needed. - let product_coset = pk.vk.domain.coeff_to_extended(lookup.product_poly.clone()); - let permuted_input_coset = pk - .vk - .domain - .coeff_to_extended(lookup.permuted_input_poly.clone()); - let permuted_table_coset = pk - .vk - .domain - .coeff_to_extended(lookup.permuted_table_poly.clone()); - - // Lookup constraints - parallelize(&mut values, |values, start| { - let lookup_evaluator = &self.lookups[n]; - let mut eval_data = lookup_evaluator.instance(); - for (i, value) in values.iter_mut().enumerate() { - let idx = start + i; - - let table_value = lookup_evaluator.evaluate( - &mut eval_data, - fixed, - advice, - instance, - challenges, - &beta, - &gamma, - &theta, - &y, - &C::ScalarExt::zero(), - idx, - rot_scale, - isize, + // Lookups + for (n, lookup) in lookups.iter().enumerate() { + // Polynomials required for this lookup. + // Calculated here so these only have to be kept in memory for the short time + // they are actually needed. + let product_coset = pk.vk.domain.coeff_to_extended_part( + lookup.product_poly.clone(), + current_extended_omega, + ); + let permuted_input_coset = pk.vk.domain.coeff_to_extended_part( + lookup.permuted_input_poly.clone(), + current_extended_omega, + ); + let permuted_table_coset = pk.vk.domain.coeff_to_extended_part( + lookup.permuted_table_poly.clone(), + current_extended_omega, ); - let r_next = get_rotation_idx(idx, 1, rot_scale, isize); - let r_prev = get_rotation_idx(idx, -1, rot_scale, isize); - - let a_minus_s = permuted_input_coset[idx] - permuted_table_coset[idx]; - // l_0(X) * (1 - z(X)) = 0 - *value = *value * y + ((one - product_coset[idx]) * l0[idx]); - // l_last(X) * (z(X)^2 - z(X)) = 0 - *value = *value * y - + ((product_coset[idx] * product_coset[idx] - product_coset[idx]) - * l_last[idx]); - // (1 - (l_last(X) + l_blind(X))) * ( - // z(\omega X) (a'(X) + \beta) (s'(X) + \gamma) - // - z(X) (\theta^{m-1} a_0(X) + ... + a_{m-1}(X) + \beta) - // (\theta^{m-1} s_0(X) + ... + s_{m-1}(X) + \gamma) - // ) = 0 - *value = *value * y - + ((product_coset[r_next] - * (permuted_input_coset[idx] + beta) - * (permuted_table_coset[idx] + gamma) - - product_coset[idx] * table_value) - * l_active_row[idx]); - // Check that the first values in the permuted input expression and permuted - // fixed expression are the same. - // l_0(X) * (a'(X) - s'(X)) = 0 - *value = *value * y + (a_minus_s * l0[idx]); - // Check that each value in the permuted lookup input expression is either - // equal to the value above it, or the value at the same index in the - // permuted table expression. - // (1 - (l_last + l_blind)) * (a′(X) − s′(X))â‹…(a′(X) − a′(\omega^{-1} X)) = 0 - *value = *value * y - + (a_minus_s - * (permuted_input_coset[idx] - permuted_input_coset[r_prev]) - * l_active_row[idx]); + // Lookup constraints + parallelize(&mut values, |values, start| { + let lookup_evaluator = &self.lookups[n]; + let mut eval_data = lookup_evaluator.instance(); + for (i, value) in values.iter_mut().enumerate() { + let idx = start + i; + + let table_value = lookup_evaluator.evaluate( + &mut eval_data, + fixed, + advice, + instance, + challenges, + &beta, + &gamma, + &theta, + &y, + &C::ScalarExt::zero(), + idx, + rot_scale, + isize, + ); + + let r_next = get_rotation_idx(idx, 1, rot_scale, isize); + let r_prev = get_rotation_idx(idx, -1, rot_scale, isize); + + let a_minus_s = + permuted_input_coset[idx] - permuted_table_coset[idx]; + // l_0(X) * (1 - z(X)) = 0 + *value = *value * y + ((one - product_coset[idx]) * l0[idx]); + // l_last(X) * (z(X)^2 - z(X)) = 0 + *value = *value * y + + ((product_coset[idx] * product_coset[idx] + - product_coset[idx]) + * l_last[idx]); + // (1 - (l_last(X) + l_blind(X))) * ( + // z(\omega X) (a'(X) + \beta) (s'(X) + \gamma) + // - z(X) (\theta^{m-1} a_0(X) + ... + a_{m-1}(X) + \beta) + // (\theta^{m-1} s_0(X) + ... + s_{m-1}(X) + \gamma) + // ) = 0 + *value = *value * y + + ((product_coset[r_next] + * (permuted_input_coset[idx] + beta) + * (permuted_table_coset[idx] + gamma) + - product_coset[idx] * table_value) + * l_active_row[idx]); + // Check that the first values in the permuted input expression and permuted + // fixed expression are the same. + // l_0(X) * (a'(X) - s'(X)) = 0 + *value = *value * y + (a_minus_s * l0[idx]); + // Check that each value in the permuted lookup input expression is either + // equal to the value above it, or the value at the same index in the + // permuted table expression. + // (1 - (l_last + l_blind)) * (a′(X) − s′(X))â‹…(a′(X) − a′(\omega^{-1} X)) = 0 + *value = *value * y + + (a_minus_s + * (permuted_input_coset[idx] + - permuted_input_coset[r_prev]) + * l_active_row[idx]); + } + }); } - }); - } - } - values + } + current_extended_omega *= extended_omega; + values + }) + .collect(); + + domain.extended_from_lagrange_vec(value_parts) } } diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index 39cef34c0f..85da7d6c51 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -299,10 +299,7 @@ where .map(|poly| vk.domain.lagrange_to_coeff(poly.clone())) .collect(); - let fixed_cosets = fixed_polys - .iter() - .map(|poly| vk.domain.coeff_to_extended(poly.clone())) - .collect(); + let fixed_cosets = vk.domain.batched_coeff_to_extended_parts(&fixed_polys); let permutation_pk = assembly .permutation @@ -313,7 +310,7 @@ where let mut l0 = vk.domain.empty_lagrange(); l0[0] = C::Scalar::one(); let l0 = vk.domain.lagrange_to_coeff(l0); - let l0 = vk.domain.coeff_to_extended(l0); + let l0 = vk.domain.coeff_to_extended_parts(&l0); // Compute l_blind(X) which evaluates to 1 for each blinding factor row // and 0 otherwise over the domain. @@ -322,24 +319,31 @@ where *evaluation = C::Scalar::one(); } let l_blind = vk.domain.lagrange_to_coeff(l_blind); - let l_blind = vk.domain.coeff_to_extended(l_blind); + let l_blind = vk.domain.coeff_to_extended_parts(&l_blind); // Compute l_last(X) which evaluates to 1 on the first inactive row (just // before the blinding factors) and 0 otherwise over the domain let mut l_last = vk.domain.empty_lagrange(); l_last[params.n() as usize - cs.blinding_factors() - 1] = C::Scalar::one(); let l_last = vk.domain.lagrange_to_coeff(l_last); - let l_last = vk.domain.coeff_to_extended(l_last); + let l_last = vk.domain.coeff_to_extended_parts(&l_last); // Compute l_active_row(X) let one = C::Scalar::one(); - let mut l_active_row = vk.domain.empty_extended(); - parallelize(&mut l_active_row, |values, start| { - for (i, value) in values.iter_mut().enumerate() { - let idx = i + start; - *value = one - (l_last[idx] + l_blind[idx]); - } - }); + let l_active_row: Vec> = l_last + .iter() + .zip(l_blind.iter()) + .map(|(l_last, l_blind)| { + let mut l_active_row = vk.domain.empty_lagrange(); + parallelize(&mut l_active_row, |values, start| { + for (i, value) in values.iter_mut().enumerate() { + let idx = i + start; + *value = one - (l_last[idx] + l_blind[idx]); + } + }); + l_active_row + }) + .collect(); // Compute the optimized evaluation data structure let ev = Evaluator::new(&vk.cs); diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index 26a4d805d6..23dcc2b31e 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -90,5 +90,5 @@ impl VerifyingKey { pub(crate) struct ProvingKey { permutations: Vec>, polys: Vec>, - pub(super) cosets: Vec>, + pub(super) cosets: Vec>>, } diff --git a/halo2_proofs/src/plonk/permutation/keygen.rs b/halo2_proofs/src/plonk/permutation/keygen.rs index cdb8cc02f9..58786035f2 100644 --- a/halo2_proofs/src/plonk/permutation/keygen.rs +++ b/halo2_proofs/src/plonk/permutation/keygen.rs @@ -185,7 +185,6 @@ impl Assembly { // Compute permutation polynomials, convert to coset form. let mut permutations = vec![]; let mut polys = vec![]; - let mut cosets = vec![]; for i in 0..p.columns.len() { // Computes the permutation polynomial based on the permutation // description in the assembly. @@ -199,8 +198,8 @@ impl Assembly { permutations.push(permutation_poly.clone()); let poly = domain.lagrange_to_coeff(permutation_poly); polys.push(poly.clone()); - cosets.push(domain.coeff_to_extended(poly)); } + let cosets = domain.batched_coeff_to_extended_parts(&polys); ProvingKey { permutations, polys, diff --git a/halo2_proofs/src/plonk/permutation/prover.rs b/halo2_proofs/src/plonk/permutation/prover.rs index cddc02348a..55112b0386 100644 --- a/halo2_proofs/src/plonk/permutation/prover.rs +++ b/halo2_proofs/src/plonk/permutation/prover.rs @@ -20,7 +20,7 @@ use crate::{ pub(crate) struct CommittedSet { pub(crate) permutation_product_poly: Polynomial, - pub(crate) permutation_product_coset: Polynomial, + pub(crate) permutation_product_coset: Vec>, permutation_product_blind: Blind, } @@ -172,7 +172,7 @@ impl Argument { let z = domain.lagrange_to_coeff(z); let permutation_product_poly = z.clone(); - let permutation_product_coset = domain.coeff_to_extended(z.clone()); + let permutation_product_coset = domain.coeff_to_extended_parts(&z); let permutation_product_commitment = permutation_product_commitment_projective.to_affine(); diff --git a/halo2_proofs/src/poly/domain.rs b/halo2_proofs/src/poly/domain.rs index a753cb859d..c17f63ef26 100644 --- a/halo2_proofs/src/poly/domain.rs +++ b/halo2_proofs/src/poly/domain.rs @@ -165,6 +165,32 @@ impl EvaluationDomain { } } + /// Obtains a polynomial in ExtendedLagrange form when given a vector of + /// Lagrange polynomials with total size `extended_n`; panics if the + /// provided vector is the wrong length. + pub fn extended_from_lagrange_vec( + &self, + values: Vec>, + ) -> Polynomial { + assert_eq!(values.len(), (self.extended_len() >> self.k) as usize); + assert_eq!(values[0].len(), self.n as usize); + + // transpose the values in parallel + let mut transposed = vec![vec![G::group_zero(); values.len()]; self.n as usize]; + values.into_iter().enumerate().for_each(|(i, p)| { + parallelize(&mut transposed, |transposed, start| { + for (transposed, p) in transposed.iter_mut().zip(p.values[start..].iter()) { + transposed[i] = *p; + } + }); + }); + + Polynomial { + values: transposed.into_iter().flatten().collect(), + _marker: PhantomData, + } + } + /// Returns an empty (zero) polynomial in the coefficient basis pub fn empty_coeff(&self) -> Polynomial { Polynomial { @@ -253,6 +279,81 @@ impl EvaluationDomain { } } + /// This takes us from an n-length coefficient vector into parts of the + /// extended evaluation domain. For example, for a polynomial with size n, + /// and an extended domain of size mn, we can compute all parts + /// independently, which are + /// `FFT(f(zeta * X), n)` + /// `FFT(f(zeta * extended_omega * X), n)` + /// ... + /// `FFT(f(zeta * extended_omega^{m-1} * X), n)` + pub fn coeff_to_extended_parts( + &self, + a: &Polynomial, + ) -> Vec> { + assert_eq!(a.values.len(), 1 << self.k); + + let num_parts = self.extended_len() >> self.k; + let mut extended_omega_factor = G::Scalar::one(); + (0..num_parts) + .map(|_| { + let part = self.coeff_to_extended_part(a.clone(), extended_omega_factor); + extended_omega_factor *= self.extended_omega; + part + }) + .collect() + } + + /// This takes us from several n-length coefficient vectors each into parts + /// of the extended evaluation domain. For example, for a polynomial with + /// size n, and an extended domain of size mn, we can compute all parts + /// independently, which are + /// `FFT(f(zeta * X), n)` + /// `FFT(f(zeta * extended_omega * X), n)` + /// ... + /// `FFT(f(zeta * extended_omega^{m-1} * X), n)` + pub fn batched_coeff_to_extended_parts( + &self, + a: &[Polynomial], + ) -> Vec>> { + assert_eq!(a[0].values.len(), 1 << self.k); + + let mut extended_omega_factor = G::Scalar::one(); + let num_parts = self.extended_len() >> self.k; + (0..num_parts) + .map(|_| { + let a_lagrange = a + .iter() + .map(|poly| self.coeff_to_extended_part(poly.clone(), extended_omega_factor)) + .collect(); + extended_omega_factor *= self.extended_omega; + a_lagrange + }) + .collect() + } + + /// This takes us from an n-length coefficient vector into a part of the + /// extended evaluation domain. For example, for a polynomial with size n, + /// and an extended domain of size mn, we can compute one of the m parts + /// separately, which is + /// `FFT(f(zeta * extended_omega_factor * X), n)` + /// where `extended_omega_factor` is `extended_omega^i` with `i` in `[0, m)`. + pub fn coeff_to_extended_part( + &self, + mut a: Polynomial, + extended_omega_factor: G::Scalar, + ) -> Polynomial { + assert_eq!(a.values.len(), 1 << self.k); + + self.distribute_powers(&mut a.values, self.g_coset * extended_omega_factor); + best_fft(&mut a.values, self.omega, self.k); + + Polynomial { + values: a.values, + _marker: PhantomData, + } + } + /// Rotate the extended domain polynomial over the original domain. pub fn rotate_extended( &self, @@ -350,6 +451,19 @@ impl EvaluationDomain { }); } + /// Given a slice of group elements `[a_0, a_1, a_2, ...]`, this returns + /// `[a_0, [c]a_1, [c^2]a_2, [c^3]a_3, [c^4]a_4, ...]`, + /// + fn distribute_powers(&self, a: &mut [G], c: G::Scalar) { + parallelize(a, |a, index| { + let mut c_power = c.pow(&[index as u64, 0, 0, 0]); + for a in a { + a.group_scale(&c_power); + c_power = c_power * c; + } + }); + } + fn ifft(a: &mut [G], omega_inv: G::Scalar, log_n: u32, divisor: G::Scalar) { best_fft(a, omega_inv, log_n); parallelize(a, |a, _| { @@ -555,3 +669,25 @@ fn test_l_i() { assert_eq!(eval_polynomial(&l[(8 - i) % 8][..], x), evaluations[7 - i]); } } + +#[test] +fn test_coeff_to_extended_slice() { + use rand_core::OsRng; + + use crate::arithmetic::eval_polynomial; + use halo2curves::pasta::pallas::Scalar; + let domain = EvaluationDomain::::new(1, 3); + let rng = OsRng; + let mut poly = domain.empty_coeff(); + assert_eq!(poly.len(), 8); + for value in poly.iter_mut() { + *value = Scalar::random(rng); + } + + let want = domain.coeff_to_extended(poly.clone()); + let got = { + let parts = domain.coeff_to_extended_parts(&poly); + domain.extended_from_lagrange_vec(parts) + }; + assert_eq!(want.values, got.values); +} From 3b04a010cb90a8ebe42853d20204c41040006bee Mon Sep 17 00:00:00 2001 From: spherel Date: Sat, 28 Jan 2023 22:11:58 -0600 Subject: [PATCH 45/62] part-wise computation of extended h poly --- halo2_proofs/src/plonk.rs | 8 +- halo2_proofs/src/plonk/evaluation.rs | 443 ++++++++++--------- halo2_proofs/src/plonk/keygen.rs | 32 +- halo2_proofs/src/plonk/permutation.rs | 2 +- halo2_proofs/src/plonk/permutation/keygen.rs | 3 +- halo2_proofs/src/plonk/permutation/prover.rs | 4 +- halo2_proofs/src/poly/domain.rs | 136 ++++++ 7 files changed, 397 insertions(+), 231 deletions(-) diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index 164d68bcff..f7fd2d8896 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -176,12 +176,12 @@ pub struct PinnedVerificationKey<'a, C: CurveAffine> { #[derive(Clone, Debug)] pub struct ProvingKey { vk: VerifyingKey, - l0: Polynomial, - l_last: Polynomial, - l_active_row: Polynomial, + l0: Vec>, + l_last: Vec>, + l_active_row: Vec>, fixed_values: Vec>, fixed_polys: Vec>, - fixed_cosets: Vec>, + fixed_cosets: Vec>>, permutation: permutation::ProvingKey, ev: Evaluator, } diff --git a/halo2_proofs/src/plonk/evaluation.rs b/halo2_proofs/src/plonk/evaluation.rs index f324a4d438..66366902b3 100644 --- a/halo2_proofs/src/plonk/evaluation.rs +++ b/halo2_proofs/src/plonk/evaluation.rs @@ -291,234 +291,261 @@ impl Evaluator { permutations: &[permutation::prover::Committed], ) -> Polynomial { let domain = &pk.vk.domain; - let size = domain.extended_len(); - let rot_scale = 1 << (domain.extended_k() - domain.k()); - let fixed = &pk.fixed_cosets[..]; + let size = 1 << domain.k() as usize; + let rot_scale = 1; let extended_omega = domain.get_extended_omega(); + let omega = domain.get_omega(); let isize = size as i32; let one = C::ScalarExt::one(); - let l0 = &pk.l0; - let l_last = &pk.l_last; - let l_active_row = &pk.l_active_row; let p = &pk.vk.cs.permutation; - // Calculate the advice and instance cosets - let advice: Vec>> = advice_polys + // Calculate the quotient polynomial for each part + let mut current_extended_omega = one; + let value_parts: Vec> = pk + .fixed_cosets .iter() - .map(|advice_polys| { - advice_polys + .enumerate() + .zip(pk.l0.iter()) + .zip(pk.l_last.iter()) + .zip(pk.l_active_row.iter()) + .map(|((((part_idx, fixed), l0), l_last), l_active_row)| { + // Calculate the advice and instance cosets + let advice: Vec>> = advice_polys .iter() - .map(|poly| domain.coeff_to_extended(poly.clone())) - .collect() - }) - .collect(); - let instance: Vec>> = instance_polys - .iter() - .map(|instance_polys| { - instance_polys + .map(|advice_polys| { + advice_polys + .iter() + .map(|poly| { + domain.coeff_to_extended_part(poly.clone(), current_extended_omega) + }) + .collect() + }) + .collect(); + let instance: Vec>> = instance_polys .iter() - .map(|poly| domain.coeff_to_extended(poly.clone())) - .collect() - }) - .collect(); + .map(|instance_polys| { + instance_polys + .iter() + .map(|poly| { + domain.coeff_to_extended_part(poly.clone(), current_extended_omega) + }) + .collect() + }) + .collect(); - let mut values = domain.empty_extended(); + let mut values = domain.empty_lagrange(); - // Core expression evaluations - let num_threads = multicore::current_num_threads(); - for (((advice, instance), lookups), permutation) in advice - .iter() - .zip(instance.iter()) - .zip(lookups.iter()) - .zip(permutations.iter()) - { - // Custom gates - multicore::scope(|scope| { - let chunk_size = (size + num_threads - 1) / num_threads; - for (thread_idx, values) in values.chunks_mut(chunk_size).enumerate() { - let start = thread_idx * chunk_size; - scope.spawn(move |_| { - let mut eval_data = self.custom_gates.instance(); - for (i, value) in values.iter_mut().enumerate() { - let idx = start + i; - *value = self.custom_gates.evaluate( - &mut eval_data, - fixed, - advice, - instance, - challenges, - &beta, - &gamma, - &theta, - &y, - value, - idx, - rot_scale, - isize, - ); + // Core expression evaluations + let num_threads = multicore::current_num_threads(); + for (((advice, instance), lookups), permutation) in advice + .iter() + .zip(instance.iter()) + .zip(lookups.iter()) + .zip(permutations.iter()) + { + // Custom gates + multicore::scope(|scope| { + let chunk_size = (size + num_threads - 1) / num_threads; + for (thread_idx, values) in values.chunks_mut(chunk_size).enumerate() { + let start = thread_idx * chunk_size; + scope.spawn(move |_| { + let mut eval_data = self.custom_gates.instance(); + for (i, value) in values.iter_mut().enumerate() { + let idx = start + i; + *value = self.custom_gates.evaluate( + &mut eval_data, + fixed, + advice, + instance, + challenges, + &beta, + &gamma, + &theta, + &y, + value, + idx, + rot_scale, + isize, + ); + } + }); } }); - } - }); - - // Permutations - let sets = &permutation.sets; - if !sets.is_empty() { - let blinding_factors = pk.vk.cs.blinding_factors(); - let last_rotation = Rotation(-((blinding_factors + 1) as i32)); - let chunk_len = pk.vk.cs.degree() - 2; - let delta_start = beta * &C::Scalar::ZETA; - - let first_set = sets.first().unwrap(); - let last_set = sets.last().unwrap(); - - // Permutation constraints - parallelize(&mut values, |values, start| { - let mut beta_term = extended_omega.pow_vartime(&[start as u64, 0, 0, 0]); - for (i, value) in values.iter_mut().enumerate() { - let idx = start + i; - let r_next = get_rotation_idx(idx, 1, rot_scale, isize); - let r_last = get_rotation_idx(idx, last_rotation.0, rot_scale, isize); - - // Enforce only for the first set. - // l_0(X) * (1 - z_0(X)) = 0 - *value = *value * y - + ((one - first_set.permutation_product_coset[idx]) * l0[idx]); - // Enforce only for the last set. - // l_last(X) * (z_l(X)^2 - z_l(X)) = 0 - *value = *value * y - + ((last_set.permutation_product_coset[idx] - * last_set.permutation_product_coset[idx] - - last_set.permutation_product_coset[idx]) - * l_last[idx]); - // Except for the first set, enforce. - // l_0(X) * (z_i(X) - z_{i-1}(\omega^(last) X)) = 0 - for (set_idx, set) in sets.iter().enumerate() { - if set_idx != 0 { + + // Permutations + let sets = &permutation.sets; + if !sets.is_empty() { + let blinding_factors = pk.vk.cs.blinding_factors(); + let last_rotation = Rotation(-((blinding_factors + 1) as i32)); + let chunk_len = pk.vk.cs.degree() - 2; + let delta_start = beta * &C::Scalar::ZETA; + + let first_set = sets.first().unwrap(); + let last_set = sets.last().unwrap(); + + // Permutation constraints + parallelize(&mut values, |values, start| { + let mut beta_term = current_extended_omega + * omega.pow_vartime(&[start as u64, 0, 0, 0]); + for (i, value) in values.iter_mut().enumerate() { + let idx = start + i; + let r_next = get_rotation_idx(idx, 1, rot_scale, isize); + let r_last = + get_rotation_idx(idx, last_rotation.0, rot_scale, isize); + + // Enforce only for the first set. + // l_0(X) * (1 - z_0(X)) = 0 *value = *value * y - + ((set.permutation_product_coset[idx] - - permutation.sets[set_idx - 1].permutation_product_coset - [r_last]) + + ((one - first_set.permutation_product_coset[part_idx][idx]) * l0[idx]); + // Enforce only for the last set. + // l_last(X) * (z_l(X)^2 - z_l(X)) = 0 + *value = *value * y + + ((last_set.permutation_product_coset[part_idx][idx] + * last_set.permutation_product_coset[part_idx][idx] + - last_set.permutation_product_coset[part_idx][idx]) + * l_last[idx]); + // Except for the first set, enforce. + // l_0(X) * (z_i(X) - z_{i-1}(\omega^(last) X)) = 0 + for (set_idx, set) in sets.iter().enumerate() { + if set_idx != 0 { + *value = *value * y + + ((set.permutation_product_coset[part_idx][idx] + - permutation.sets[set_idx - 1] + .permutation_product_coset[part_idx][r_last]) + * l0[idx]); + } + } + // And for all the sets we enforce: + // (1 - (l_last(X) + l_blind(X))) * ( + // z_i(\omega X) \prod_j (p(X) + \beta s_j(X) + \gamma) + // - z_i(X) \prod_j (p(X) + \delta^j \beta X + \gamma) + // ) + let mut current_delta = delta_start * beta_term; + for ((set, columns), cosets) in sets + .iter() + .zip(p.columns.chunks(chunk_len)) + .zip(pk.permutation.cosets[part_idx].chunks(chunk_len)) + { + let mut left = set.permutation_product_coset[part_idx][r_next]; + for (values, permutation) in columns + .iter() + .map(|&column| match column.column_type() { + Any::Advice(_) => &advice[column.index()], + Any::Fixed => &fixed[column.index()], + Any::Instance => &instance[column.index()], + }) + .zip(cosets.iter()) + { + left *= values[idx] + beta * permutation[idx] + gamma; + } + + let mut right = set.permutation_product_coset[part_idx][idx]; + for values in + columns.iter().map(|&column| match column.column_type() { + Any::Advice(_) => &advice[column.index()], + Any::Fixed => &fixed[column.index()], + Any::Instance => &instance[column.index()], + }) + { + right *= values[idx] + current_delta + gamma; + current_delta *= &C::Scalar::DELTA; + } + + *value = *value * y + ((left - right) * l_active_row[idx]); + } + beta_term *= ω } - } - // And for all the sets we enforce: - // (1 - (l_last(X) + l_blind(X))) * ( - // z_i(\omega X) \prod_j (p(X) + \beta s_j(X) + \gamma) - // - z_i(X) \prod_j (p(X) + \delta^j \beta X + \gamma) - // ) - let mut current_delta = delta_start * beta_term; - for ((set, columns), cosets) in sets - .iter() - .zip(p.columns.chunks(chunk_len)) - .zip(pk.permutation.cosets.chunks(chunk_len)) - { - let mut left = set.permutation_product_coset[r_next]; - for (values, permutation) in columns - .iter() - .map(|&column| match column.column_type() { - Any::Advice(_) => &advice[column.index()], - Any::Fixed => &fixed[column.index()], - Any::Instance => &instance[column.index()], - }) - .zip(cosets.iter()) - { - left *= values[idx] + beta * permutation[idx] + gamma; - } - - let mut right = set.permutation_product_coset[idx]; - for values in columns.iter().map(|&column| match column.column_type() { - Any::Advice(_) => &advice[column.index()], - Any::Fixed => &fixed[column.index()], - Any::Instance => &instance[column.index()], - }) { - right *= values[idx] + current_delta + gamma; - current_delta *= &C::Scalar::DELTA; - } - - *value = *value * y + ((left - right) * l_active_row[idx]); - } - beta_term *= &extended_omega; + }); } - }); - } - // Lookups - for (n, lookup) in lookups.iter().enumerate() { - // Polynomials required for this lookup. - // Calculated here so these only have to be kept in memory for the short time - // they are actually needed. - let product_coset = pk.vk.domain.coeff_to_extended(lookup.product_poly.clone()); - let permuted_input_coset = pk - .vk - .domain - .coeff_to_extended(lookup.permuted_input_poly.clone()); - let permuted_table_coset = pk - .vk - .domain - .coeff_to_extended(lookup.permuted_table_poly.clone()); - - // Lookup constraints - parallelize(&mut values, |values, start| { - let lookup_evaluator = &self.lookups[n]; - let mut eval_data = lookup_evaluator.instance(); - for (i, value) in values.iter_mut().enumerate() { - let idx = start + i; - - let table_value = lookup_evaluator.evaluate( - &mut eval_data, - fixed, - advice, - instance, - challenges, - &beta, - &gamma, - &theta, - &y, - &C::ScalarExt::zero(), - idx, - rot_scale, - isize, + // Lookups + for (n, lookup) in lookups.iter().enumerate() { + // Polynomials required for this lookup. + // Calculated here so these only have to be kept in memory for the short time + // they are actually needed. + let product_coset = pk.vk.domain.coeff_to_extended_part( + lookup.product_poly.clone(), + current_extended_omega, + ); + let permuted_input_coset = pk.vk.domain.coeff_to_extended_part( + lookup.permuted_input_poly.clone(), + current_extended_omega, + ); + let permuted_table_coset = pk.vk.domain.coeff_to_extended_part( + lookup.permuted_table_poly.clone(), + current_extended_omega, ); - let r_next = get_rotation_idx(idx, 1, rot_scale, isize); - let r_prev = get_rotation_idx(idx, -1, rot_scale, isize); - - let a_minus_s = permuted_input_coset[idx] - permuted_table_coset[idx]; - // l_0(X) * (1 - z(X)) = 0 - *value = *value * y + ((one - product_coset[idx]) * l0[idx]); - // l_last(X) * (z(X)^2 - z(X)) = 0 - *value = *value * y - + ((product_coset[idx] * product_coset[idx] - product_coset[idx]) - * l_last[idx]); - // (1 - (l_last(X) + l_blind(X))) * ( - // z(\omega X) (a'(X) + \beta) (s'(X) + \gamma) - // - z(X) (\theta^{m-1} a_0(X) + ... + a_{m-1}(X) + \beta) - // (\theta^{m-1} s_0(X) + ... + s_{m-1}(X) + \gamma) - // ) = 0 - *value = *value * y - + ((product_coset[r_next] - * (permuted_input_coset[idx] + beta) - * (permuted_table_coset[idx] + gamma) - - product_coset[idx] * table_value) - * l_active_row[idx]); - // Check that the first values in the permuted input expression and permuted - // fixed expression are the same. - // l_0(X) * (a'(X) - s'(X)) = 0 - *value = *value * y + (a_minus_s * l0[idx]); - // Check that each value in the permuted lookup input expression is either - // equal to the value above it, or the value at the same index in the - // permuted table expression. - // (1 - (l_last + l_blind)) * (a′(X) − s′(X))â‹…(a′(X) − a′(\omega^{-1} X)) = 0 - *value = *value * y - + (a_minus_s - * (permuted_input_coset[idx] - permuted_input_coset[r_prev]) - * l_active_row[idx]); + // Lookup constraints + parallelize(&mut values, |values, start| { + let lookup_evaluator = &self.lookups[n]; + let mut eval_data = lookup_evaluator.instance(); + for (i, value) in values.iter_mut().enumerate() { + let idx = start + i; + + let table_value = lookup_evaluator.evaluate( + &mut eval_data, + fixed, + advice, + instance, + challenges, + &beta, + &gamma, + &theta, + &y, + &C::ScalarExt::zero(), + idx, + rot_scale, + isize, + ); + + let r_next = get_rotation_idx(idx, 1, rot_scale, isize); + let r_prev = get_rotation_idx(idx, -1, rot_scale, isize); + + let a_minus_s = + permuted_input_coset[idx] - permuted_table_coset[idx]; + // l_0(X) * (1 - z(X)) = 0 + *value = *value * y + ((one - product_coset[idx]) * l0[idx]); + // l_last(X) * (z(X)^2 - z(X)) = 0 + *value = *value * y + + ((product_coset[idx] * product_coset[idx] + - product_coset[idx]) + * l_last[idx]); + // (1 - (l_last(X) + l_blind(X))) * ( + // z(\omega X) (a'(X) + \beta) (s'(X) + \gamma) + // - z(X) (\theta^{m-1} a_0(X) + ... + a_{m-1}(X) + \beta) + // (\theta^{m-1} s_0(X) + ... + s_{m-1}(X) + \gamma) + // ) = 0 + *value = *value * y + + ((product_coset[r_next] + * (permuted_input_coset[idx] + beta) + * (permuted_table_coset[idx] + gamma) + - product_coset[idx] * table_value) + * l_active_row[idx]); + // Check that the first values in the permuted input expression and permuted + // fixed expression are the same. + // l_0(X) * (a'(X) - s'(X)) = 0 + *value = *value * y + (a_minus_s * l0[idx]); + // Check that each value in the permuted lookup input expression is either + // equal to the value above it, or the value at the same index in the + // permuted table expression. + // (1 - (l_last + l_blind)) * (a′(X) − s′(X))â‹…(a′(X) − a′(\omega^{-1} X)) = 0 + *value = *value * y + + (a_minus_s + * (permuted_input_coset[idx] + - permuted_input_coset[r_prev]) + * l_active_row[idx]); + } + }); } - }); - } - } - values + } + current_extended_omega *= extended_omega; + values + }) + .collect(); + + domain.extended_from_lagrange_vec(value_parts) } } diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index e18d9c62d2..65222a92b2 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -338,10 +338,7 @@ where .map(|poly| vk.domain.lagrange_to_coeff(poly.clone())) .collect(); - let fixed_cosets = fixed_polys - .iter() - .map(|poly| vk.domain.coeff_to_extended(poly.clone())) - .collect(); + let fixed_cosets = vk.domain.batched_coeff_to_extended_parts(&fixed_polys); let permutation_pk = assembly .permutation @@ -352,7 +349,7 @@ where let mut l0 = vk.domain.empty_lagrange(); l0[0] = C::Scalar::one(); let l0 = vk.domain.lagrange_to_coeff(l0); - let l0 = vk.domain.coeff_to_extended(l0); + let l0 = vk.domain.coeff_to_extended_parts(&l0); // Compute l_blind(X) which evaluates to 1 for each blinding factor row // and 0 otherwise over the domain. @@ -361,24 +358,31 @@ where *evaluation = C::Scalar::one(); } let l_blind = vk.domain.lagrange_to_coeff(l_blind); - let l_blind = vk.domain.coeff_to_extended(l_blind); + let l_blind = vk.domain.coeff_to_extended_parts(&l_blind); // Compute l_last(X) which evaluates to 1 on the first inactive row (just // before the blinding factors) and 0 otherwise over the domain let mut l_last = vk.domain.empty_lagrange(); l_last[params.n() as usize - cs.blinding_factors() - 1] = C::Scalar::one(); let l_last = vk.domain.lagrange_to_coeff(l_last); - let l_last = vk.domain.coeff_to_extended(l_last); + let l_last = vk.domain.coeff_to_extended_parts(&l_last); // Compute l_active_row(X) let one = C::Scalar::one(); - let mut l_active_row = vk.domain.empty_extended(); - parallelize(&mut l_active_row, |values, start| { - for (i, value) in values.iter_mut().enumerate() { - let idx = i + start; - *value = one - (l_last[idx] + l_blind[idx]); - } - }); + let l_active_row: Vec> = l_last + .iter() + .zip(l_blind.iter()) + .map(|(l_last, l_blind)| { + let mut l_active_row = vk.domain.empty_lagrange(); + parallelize(&mut l_active_row, |values, start| { + for (i, value) in values.iter_mut().enumerate() { + let idx = i + start; + *value = one - (l_last[idx] + l_blind[idx]); + } + }); + l_active_row + }) + .collect(); // Compute the optimized evaluation data structure let ev = Evaluator::new(&vk.cs); diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index 765a1cf975..7ae8a7df2b 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -107,5 +107,5 @@ impl VerifyingKey { pub(crate) struct ProvingKey { permutations: Vec>, polys: Vec>, - pub(super) cosets: Vec>, + pub(super) cosets: Vec>>, } diff --git a/halo2_proofs/src/plonk/permutation/keygen.rs b/halo2_proofs/src/plonk/permutation/keygen.rs index 3b2552f64f..3fbcec4a2c 100644 --- a/halo2_proofs/src/plonk/permutation/keygen.rs +++ b/halo2_proofs/src/plonk/permutation/keygen.rs @@ -191,7 +191,6 @@ impl Assembly { // Compute permutation polynomials, convert to coset form. let mut permutations = vec![]; let mut polys = vec![]; - let mut cosets = vec![]; for i in 0..p.columns.len() { // Computes the permutation polynomial based on the permutation // description in the assembly. @@ -205,8 +204,8 @@ impl Assembly { permutations.push(permutation_poly.clone()); let poly = domain.lagrange_to_coeff(permutation_poly); polys.push(poly.clone()); - cosets.push(domain.coeff_to_extended(poly)); } + let cosets = domain.batched_coeff_to_extended_parts(&polys); ProvingKey { permutations, polys, diff --git a/halo2_proofs/src/plonk/permutation/prover.rs b/halo2_proofs/src/plonk/permutation/prover.rs index cddc02348a..55112b0386 100644 --- a/halo2_proofs/src/plonk/permutation/prover.rs +++ b/halo2_proofs/src/plonk/permutation/prover.rs @@ -20,7 +20,7 @@ use crate::{ pub(crate) struct CommittedSet { pub(crate) permutation_product_poly: Polynomial, - pub(crate) permutation_product_coset: Polynomial, + pub(crate) permutation_product_coset: Vec>, permutation_product_blind: Blind, } @@ -172,7 +172,7 @@ impl Argument { let z = domain.lagrange_to_coeff(z); let permutation_product_poly = z.clone(); - let permutation_product_coset = domain.coeff_to_extended(z.clone()); + let permutation_product_coset = domain.coeff_to_extended_parts(&z); let permutation_product_commitment = permutation_product_commitment_projective.to_affine(); diff --git a/halo2_proofs/src/poly/domain.rs b/halo2_proofs/src/poly/domain.rs index a753cb859d..c17f63ef26 100644 --- a/halo2_proofs/src/poly/domain.rs +++ b/halo2_proofs/src/poly/domain.rs @@ -165,6 +165,32 @@ impl EvaluationDomain { } } + /// Obtains a polynomial in ExtendedLagrange form when given a vector of + /// Lagrange polynomials with total size `extended_n`; panics if the + /// provided vector is the wrong length. + pub fn extended_from_lagrange_vec( + &self, + values: Vec>, + ) -> Polynomial { + assert_eq!(values.len(), (self.extended_len() >> self.k) as usize); + assert_eq!(values[0].len(), self.n as usize); + + // transpose the values in parallel + let mut transposed = vec![vec![G::group_zero(); values.len()]; self.n as usize]; + values.into_iter().enumerate().for_each(|(i, p)| { + parallelize(&mut transposed, |transposed, start| { + for (transposed, p) in transposed.iter_mut().zip(p.values[start..].iter()) { + transposed[i] = *p; + } + }); + }); + + Polynomial { + values: transposed.into_iter().flatten().collect(), + _marker: PhantomData, + } + } + /// Returns an empty (zero) polynomial in the coefficient basis pub fn empty_coeff(&self) -> Polynomial { Polynomial { @@ -253,6 +279,81 @@ impl EvaluationDomain { } } + /// This takes us from an n-length coefficient vector into parts of the + /// extended evaluation domain. For example, for a polynomial with size n, + /// and an extended domain of size mn, we can compute all parts + /// independently, which are + /// `FFT(f(zeta * X), n)` + /// `FFT(f(zeta * extended_omega * X), n)` + /// ... + /// `FFT(f(zeta * extended_omega^{m-1} * X), n)` + pub fn coeff_to_extended_parts( + &self, + a: &Polynomial, + ) -> Vec> { + assert_eq!(a.values.len(), 1 << self.k); + + let num_parts = self.extended_len() >> self.k; + let mut extended_omega_factor = G::Scalar::one(); + (0..num_parts) + .map(|_| { + let part = self.coeff_to_extended_part(a.clone(), extended_omega_factor); + extended_omega_factor *= self.extended_omega; + part + }) + .collect() + } + + /// This takes us from several n-length coefficient vectors each into parts + /// of the extended evaluation domain. For example, for a polynomial with + /// size n, and an extended domain of size mn, we can compute all parts + /// independently, which are + /// `FFT(f(zeta * X), n)` + /// `FFT(f(zeta * extended_omega * X), n)` + /// ... + /// `FFT(f(zeta * extended_omega^{m-1} * X), n)` + pub fn batched_coeff_to_extended_parts( + &self, + a: &[Polynomial], + ) -> Vec>> { + assert_eq!(a[0].values.len(), 1 << self.k); + + let mut extended_omega_factor = G::Scalar::one(); + let num_parts = self.extended_len() >> self.k; + (0..num_parts) + .map(|_| { + let a_lagrange = a + .iter() + .map(|poly| self.coeff_to_extended_part(poly.clone(), extended_omega_factor)) + .collect(); + extended_omega_factor *= self.extended_omega; + a_lagrange + }) + .collect() + } + + /// This takes us from an n-length coefficient vector into a part of the + /// extended evaluation domain. For example, for a polynomial with size n, + /// and an extended domain of size mn, we can compute one of the m parts + /// separately, which is + /// `FFT(f(zeta * extended_omega_factor * X), n)` + /// where `extended_omega_factor` is `extended_omega^i` with `i` in `[0, m)`. + pub fn coeff_to_extended_part( + &self, + mut a: Polynomial, + extended_omega_factor: G::Scalar, + ) -> Polynomial { + assert_eq!(a.values.len(), 1 << self.k); + + self.distribute_powers(&mut a.values, self.g_coset * extended_omega_factor); + best_fft(&mut a.values, self.omega, self.k); + + Polynomial { + values: a.values, + _marker: PhantomData, + } + } + /// Rotate the extended domain polynomial over the original domain. pub fn rotate_extended( &self, @@ -350,6 +451,19 @@ impl EvaluationDomain { }); } + /// Given a slice of group elements `[a_0, a_1, a_2, ...]`, this returns + /// `[a_0, [c]a_1, [c^2]a_2, [c^3]a_3, [c^4]a_4, ...]`, + /// + fn distribute_powers(&self, a: &mut [G], c: G::Scalar) { + parallelize(a, |a, index| { + let mut c_power = c.pow(&[index as u64, 0, 0, 0]); + for a in a { + a.group_scale(&c_power); + c_power = c_power * c; + } + }); + } + fn ifft(a: &mut [G], omega_inv: G::Scalar, log_n: u32, divisor: G::Scalar) { best_fft(a, omega_inv, log_n); parallelize(a, |a, _| { @@ -555,3 +669,25 @@ fn test_l_i() { assert_eq!(eval_polynomial(&l[(8 - i) % 8][..], x), evaluations[7 - i]); } } + +#[test] +fn test_coeff_to_extended_slice() { + use rand_core::OsRng; + + use crate::arithmetic::eval_polynomial; + use halo2curves::pasta::pallas::Scalar; + let domain = EvaluationDomain::::new(1, 3); + let rng = OsRng; + let mut poly = domain.empty_coeff(); + assert_eq!(poly.len(), 8); + for value in poly.iter_mut() { + *value = Scalar::random(rng); + } + + let want = domain.coeff_to_extended(poly.clone()); + let got = { + let parts = domain.coeff_to_extended_parts(&poly); + domain.extended_from_lagrange_vec(parts) + }; + assert_eq!(want.values, got.values); +} From e28317a32cb947f715f2b87ea60bd48f2ebb10e7 Mon Sep 17 00:00:00 2001 From: spherel Date: Sun, 29 Jan 2023 14:10:43 -0600 Subject: [PATCH 46/62] compute fixed_cosets and permutation_(product)_cosets when computing h --- halo2_proofs/src/plonk.rs | 7 +- halo2_proofs/src/plonk/evaluation.rs | 85 ++++++++++++++------ halo2_proofs/src/plonk/keygen.rs | 32 +++----- halo2_proofs/src/plonk/permutation.rs | 3 +- halo2_proofs/src/plonk/permutation/keygen.rs | 6 +- halo2_proofs/src/plonk/permutation/prover.rs | 4 - 6 files changed, 75 insertions(+), 62 deletions(-) diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index f7fd2d8896..3d165fc27c 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -176,12 +176,11 @@ pub struct PinnedVerificationKey<'a, C: CurveAffine> { #[derive(Clone, Debug)] pub struct ProvingKey { vk: VerifyingKey, - l0: Vec>, - l_last: Vec>, - l_active_row: Vec>, + l0: Polynomial, + l_last: Polynomial, + l_active_row: Polynomial, fixed_values: Vec>, fixed_polys: Vec>, - fixed_cosets: Vec>>, permutation: permutation::ProvingKey, ev: Evaluator, } diff --git a/halo2_proofs/src/plonk/evaluation.rs b/halo2_proofs/src/plonk/evaluation.rs index 66366902b3..c9c9a5cbf1 100644 --- a/halo2_proofs/src/plonk/evaluation.rs +++ b/halo2_proofs/src/plonk/evaluation.rs @@ -298,17 +298,24 @@ impl Evaluator { let isize = size as i32; let one = C::ScalarExt::one(); let p = &pk.vk.cs.permutation; + let num_parts = domain.extended_len() >> domain.k(); // Calculate the quotient polynomial for each part let mut current_extended_omega = one; - let value_parts: Vec> = pk - .fixed_cosets - .iter() - .enumerate() - .zip(pk.l0.iter()) - .zip(pk.l_last.iter()) - .zip(pk.l_active_row.iter()) - .map(|((((part_idx, fixed), l0), l_last), l_active_row)| { + let value_parts: Vec> = (0..num_parts) + .map(|_| { + let fixed: Vec> = pk + .fixed_polys + .iter() + .map(|p| domain.coeff_to_extended_part(p.clone(), current_extended_omega)) + .collect(); + let fixed = &fixed[..]; + let l0 = domain.coeff_to_extended_part(pk.l0.clone(), current_extended_omega); + let l_last = + domain.coeff_to_extended_part(pk.l_last.clone(), current_extended_omega); + let l_active_row = + domain.coeff_to_extended_part(pk.l_active_row.clone(), current_extended_omega); + // Calculate the advice and instance cosets let advice: Vec>> = advice_polys .iter() @@ -380,8 +387,30 @@ impl Evaluator { let chunk_len = pk.vk.cs.degree() - 2; let delta_start = beta * &C::Scalar::ZETA; - let first_set = sets.first().unwrap(); - let last_set = sets.last().unwrap(); + let permutation_product_cosets: Vec< + Polynomial, + > = sets + .iter() + .map(|set| { + domain.coeff_to_extended_part( + set.permutation_product_poly.clone(), + current_extended_omega, + ) + }) + .collect(); + let permutation_cosets: Vec> = pk + .permutation + .polys + .iter() + .map(|p| { + domain.coeff_to_extended_part(p.clone(), current_extended_omega) + }) + .collect(); + + let first_set_permutation_product_coset = + permutation_product_cosets.first().unwrap(); + let last_set_permutation_product_coset = + permutation_product_cosets.last().unwrap(); // Permutation constraints parallelize(&mut values, |values, start| { @@ -396,23 +425,23 @@ impl Evaluator { // Enforce only for the first set. // l_0(X) * (1 - z_0(X)) = 0 *value = *value * y - + ((one - first_set.permutation_product_coset[part_idx][idx]) - * l0[idx]); + + ((one - first_set_permutation_product_coset[idx]) * l0[idx]); // Enforce only for the last set. // l_last(X) * (z_l(X)^2 - z_l(X)) = 0 *value = *value * y - + ((last_set.permutation_product_coset[part_idx][idx] - * last_set.permutation_product_coset[part_idx][idx] - - last_set.permutation_product_coset[part_idx][idx]) + + ((last_set_permutation_product_coset[idx] + * last_set_permutation_product_coset[idx] + - last_set_permutation_product_coset[idx]) * l_last[idx]); // Except for the first set, enforce. // l_0(X) * (z_i(X) - z_{i-1}(\omega^(last) X)) = 0 - for (set_idx, set) in sets.iter().enumerate() { + for (set_idx, permutation_product_coset) in + permutation_product_cosets.iter().enumerate() + { if set_idx != 0 { *value = *value * y - + ((set.permutation_product_coset[part_idx][idx] - - permutation.sets[set_idx - 1] - .permutation_product_coset[part_idx][r_last]) + + ((permutation_product_coset[idx] + - permutation_product_cosets[set_idx - 1][r_last]) * l0[idx]); } } @@ -422,12 +451,16 @@ impl Evaluator { // - z_i(X) \prod_j (p(X) + \delta^j \beta X + \gamma) // ) let mut current_delta = delta_start * beta_term; - for ((set, columns), cosets) in sets - .iter() - .zip(p.columns.chunks(chunk_len)) - .zip(pk.permutation.cosets[part_idx].chunks(chunk_len)) + for ( + (columns, permutation_product_coset), + permutation_coset_chunk, + ) in p + .columns + .chunks(chunk_len) + .zip(permutation_product_cosets.iter()) + .zip(permutation_cosets.chunks(chunk_len)) { - let mut left = set.permutation_product_coset[part_idx][r_next]; + let mut left = permutation_product_coset[r_next]; for (values, permutation) in columns .iter() .map(|&column| match column.column_type() { @@ -435,12 +468,12 @@ impl Evaluator { Any::Fixed => &fixed[column.index()], Any::Instance => &instance[column.index()], }) - .zip(cosets.iter()) + .zip(permutation_coset_chunk.iter()) { left *= values[idx] + beta * permutation[idx] + gamma; } - let mut right = set.permutation_product_coset[part_idx][idx]; + let mut right = permutation_product_coset[idx]; for values in columns.iter().map(|&column| match column.column_type() { Any::Advice(_) => &advice[column.index()], diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index 65222a92b2..99bce98b06 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -338,8 +338,6 @@ where .map(|poly| vk.domain.lagrange_to_coeff(poly.clone())) .collect(); - let fixed_cosets = vk.domain.batched_coeff_to_extended_parts(&fixed_polys); - let permutation_pk = assembly .permutation .build_pk(params, &vk.domain, &cs.permutation); @@ -349,7 +347,6 @@ where let mut l0 = vk.domain.empty_lagrange(); l0[0] = C::Scalar::one(); let l0 = vk.domain.lagrange_to_coeff(l0); - let l0 = vk.domain.coeff_to_extended_parts(&l0); // Compute l_blind(X) which evaluates to 1 for each blinding factor row // and 0 otherwise over the domain. @@ -357,32 +354,24 @@ where for evaluation in l_blind[..].iter_mut().rev().take(cs.blinding_factors()) { *evaluation = C::Scalar::one(); } - let l_blind = vk.domain.lagrange_to_coeff(l_blind); - let l_blind = vk.domain.coeff_to_extended_parts(&l_blind); // Compute l_last(X) which evaluates to 1 on the first inactive row (just // before the blinding factors) and 0 otherwise over the domain let mut l_last = vk.domain.empty_lagrange(); l_last[params.n() as usize - cs.blinding_factors() - 1] = C::Scalar::one(); - let l_last = vk.domain.lagrange_to_coeff(l_last); - let l_last = vk.domain.coeff_to_extended_parts(&l_last); // Compute l_active_row(X) let one = C::Scalar::one(); - let l_active_row: Vec> = l_last - .iter() - .zip(l_blind.iter()) - .map(|(l_last, l_blind)| { - let mut l_active_row = vk.domain.empty_lagrange(); - parallelize(&mut l_active_row, |values, start| { - for (i, value) in values.iter_mut().enumerate() { - let idx = i + start; - *value = one - (l_last[idx] + l_blind[idx]); - } - }); - l_active_row - }) - .collect(); + let mut l_active_row = vk.domain.empty_lagrange(); + parallelize(&mut l_active_row, |values, start| { + for (i, value) in values.iter_mut().enumerate() { + let idx = i + start; + *value = one - (l_last[idx] + l_blind[idx]); + } + }); + + let l_last = vk.domain.lagrange_to_coeff(l_last); + let l_active_row = vk.domain.lagrange_to_coeff(l_active_row); // Compute the optimized evaluation data structure let ev = Evaluator::new(&vk.cs); @@ -394,7 +383,6 @@ where l_active_row, fixed_values: fixed, fixed_polys, - fixed_cosets, permutation: permutation_pk, ev, }) diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index 7ae8a7df2b..aff1576009 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -106,6 +106,5 @@ impl VerifyingKey { #[derive(Clone, Debug)] pub(crate) struct ProvingKey { permutations: Vec>, - polys: Vec>, - pub(super) cosets: Vec>>, + pub(super) polys: Vec>, } diff --git a/halo2_proofs/src/plonk/permutation/keygen.rs b/halo2_proofs/src/plonk/permutation/keygen.rs index 3fbcec4a2c..96dd8cfc07 100644 --- a/halo2_proofs/src/plonk/permutation/keygen.rs +++ b/halo2_proofs/src/plonk/permutation/keygen.rs @@ -188,7 +188,7 @@ impl Assembly { } } - // Compute permutation polynomials, convert to coset form. + // Compute permutation polynomials. let mut permutations = vec![]; let mut polys = vec![]; for i in 0..p.columns.len() { @@ -200,16 +200,14 @@ impl Assembly { *p = deltaomega[permuted_i][permuted_j]; } - // Store permutation polynomial and precompute its coset evaluation + // Store permutation polynomial. permutations.push(permutation_poly.clone()); let poly = domain.lagrange_to_coeff(permutation_poly); polys.push(poly.clone()); } - let cosets = domain.batched_coeff_to_extended_parts(&polys); ProvingKey { permutations, polys, - cosets, } } } diff --git a/halo2_proofs/src/plonk/permutation/prover.rs b/halo2_proofs/src/plonk/permutation/prover.rs index 55112b0386..847d2fbd5f 100644 --- a/halo2_proofs/src/plonk/permutation/prover.rs +++ b/halo2_proofs/src/plonk/permutation/prover.rs @@ -20,7 +20,6 @@ use crate::{ pub(crate) struct CommittedSet { pub(crate) permutation_product_poly: Polynomial, - pub(crate) permutation_product_coset: Vec>, permutation_product_blind: Blind, } @@ -172,8 +171,6 @@ impl Argument { let z = domain.lagrange_to_coeff(z); let permutation_product_poly = z.clone(); - let permutation_product_coset = domain.coeff_to_extended_parts(&z); - let permutation_product_commitment = permutation_product_commitment_projective.to_affine(); @@ -182,7 +179,6 @@ impl Argument { sets.push(CommittedSet { permutation_product_poly, - permutation_product_coset, permutation_product_blind, }); } From b533a62e5ad0c0549e7524274867bdaca027364d Mon Sep 17 00:00:00 2001 From: spherel Date: Thu, 2 Feb 2023 13:24:54 -0600 Subject: [PATCH 47/62] add benchmark for coeff_to_extended_parts --- halo2_proofs/src/poly/domain.rs | 40 +++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/halo2_proofs/src/poly/domain.rs b/halo2_proofs/src/poly/domain.rs index c17f63ef26..2923474112 100644 --- a/halo2_proofs/src/poly/domain.rs +++ b/halo2_proofs/src/poly/domain.rs @@ -456,7 +456,7 @@ impl EvaluationDomain { /// fn distribute_powers(&self, a: &mut [G], c: G::Scalar) { parallelize(a, |a, index| { - let mut c_power = c.pow(&[index as u64, 0, 0, 0]); + let mut c_power = c.pow_vartime(&[index as u64, 0, 0, 0]); for a in a { a.group_scale(&c_power); c_power = c_power * c; @@ -671,11 +671,10 @@ fn test_l_i() { } #[test] -fn test_coeff_to_extended_slice() { +fn test_coeff_to_extended_part() { + use halo2curves::pasta::pallas::Scalar; use rand_core::OsRng; - use crate::arithmetic::eval_polynomial; - use halo2curves::pasta::pallas::Scalar; let domain = EvaluationDomain::::new(1, 3); let rng = OsRng; let mut poly = domain.empty_coeff(); @@ -691,3 +690,36 @@ fn test_coeff_to_extended_slice() { }; assert_eq!(want.values, got.values); } + +#[test] +fn bench_coeff_to_extended_parts() { + use halo2curves::pasta::pallas::Scalar; + use rand_core::OsRng; + use std::time::Instant; + + let k = 20; + let domain = EvaluationDomain::::new(3, k); + let rng = OsRng; + let mut poly1 = domain.empty_coeff(); + assert_eq!(poly1.len(), 1 << k); + + for value in poly1.iter_mut() { + *value = Scalar::random(rng); + } + + let poly2 = poly1.clone(); + + let coeff_to_extended_timer = Instant::now(); + let _ = domain.coeff_to_extended(poly1); + println!( + "domain.coeff_to_extended time: {}s", + coeff_to_extended_timer.elapsed().as_secs_f64() + ); + + let coeff_to_extended_parts_timer = Instant::now(); + let _ = domain.coeff_to_extended_parts(&poly2); + println!( + "domain.coeff_to_extended_parts time: {}s", + coeff_to_extended_parts_timer.elapsed().as_secs_f64() + ); +} From ffd33d77b0a5ae42cd14bf46853cc60c0a091621 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Fri, 3 Feb 2023 19:22:46 +0800 Subject: [PATCH 48/62] fix conflicts; remove Infinity rand poly commitment --- halo2_proofs/src/plonk/keygen.rs | 39 +++++++++++++--------- halo2_proofs/src/plonk/permutation.rs | 7 ++-- halo2_proofs/src/plonk/vanishing/prover.rs | 7 ++-- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index 867f2ce562..ffeac8e4db 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -320,27 +320,36 @@ where )?; let mut fixed = batch_invert_assigned(assembly.fixed); - let (cs, selector_polys) = cs.compress_selectors(assembly.selectors); + let (cs, selector_polys) = cs.compress_selectors(assembly.selectors.clone()); fixed.extend( selector_polys .into_iter() .map(|poly| domain.lagrange_from_vec(poly)), ); - let vk = vk.unwrap_or_else(|| { - let permutation_vk = - assembly - .permutation - .clone() - .build_vk(params, &domain, &cs.permutation); - - let fixed_commitments = fixed - .iter() - .map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine()) - .collect(); - - VerifyingKey::from_parts(domain, fixed_commitments, permutation_vk, cs.clone()) - }); + let vk = match vk { + Some(vk) => vk, + None => { + let permutation_vk = + assembly + .permutation + .clone() + .build_vk(params, &domain, &cs.permutation); + + let fixed_commitments = fixed + .iter() + .map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine()) + .collect(); + + VerifyingKey::from_parts( + domain, + fixed_commitments, + permutation_vk, + cs.clone(), + assembly.selectors.clone(), + ) + } + }; let fixed_polys: Vec<_> = fixed .iter() diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index 4dfc5ccfe9..6912199570 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -149,7 +149,7 @@ where ) -> io::Result<()> { write_polynomial_slice(&self.permutations, writer, format)?; write_polynomial_slice(&self.polys, writer, format)?; - write_polynomial_slice(&self.cosets, writer, format)?; + //write_polynomial_slice(&self.cosets, writer, format)?; Ok(()) } } @@ -157,8 +157,7 @@ where impl ProvingKey { /// Gets the total number of bytes in the serialization of `self` pub(super) fn bytes_length(&self) -> usize { - polynomial_slice_byte_length(&self.permutations) - + polynomial_slice_byte_length(&self.polys) - + polynomial_slice_byte_length(&self.cosets) + polynomial_slice_byte_length(&self.permutations) + polynomial_slice_byte_length(&self.polys) + // + polynomial_slice_byte_length(&self.cosets) } } diff --git a/halo2_proofs/src/plonk/vanishing/prover.rs b/halo2_proofs/src/plonk/vanishing/prover.rs index d85f2988e4..aa43a07c0f 100644 --- a/halo2_proofs/src/plonk/vanishing/prover.rs +++ b/halo2_proofs/src/plonk/vanishing/prover.rs @@ -44,16 +44,17 @@ impl Argument { R: RngCore, T: TranscriptWrite, >( - _params: &P, + params: &P, domain: &EvaluationDomain, mut _rng: R, transcript: &mut T, ) -> Result, Error> { // Sample a random polynomial of degree n - 1 - let random_poly = domain.empty_coeff(); + let random_poly = domain.constant_lagrange(C::Scalar::one()); + let random_poly = domain.lagrange_to_coeff(random_poly); // Sample a random blinding factor let random_blind = Blind(C::Scalar::zero()); - let c = C::identity(); + let c = params.commit(&random_poly, random_blind).to_affine(); // We write the identity point to the transcript which // is the commitment of the zero polynomial. transcript.write_point(c)?; From 68b5aab073559d610fe1a87818cbb2aa39da5a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Nicolas?= Date: Sun, 5 Feb 2023 03:20:35 +0100 Subject: [PATCH 49/62] test/mock-prover-values: MockProver exposes the generated columns to tests --- halo2_proofs/src/dev.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index 381d3c4be6..a020d4c874 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -687,6 +687,14 @@ impl MockProver { Ok(prover) } + pub fn advice_values(&self, column: Column) -> &[CellValue] { + &self.advice[column.index()] + } + + pub fn fixed_values(&self, column: Column) -> &[CellValue] { + &self.fixed[column.index()] + } + /// Returns `Ok(())` if this `MockProver` is satisfied, or a list of errors indicating /// the reasons that the circuit is not satisfied. pub fn verify(&self) -> Result<(), Vec> { From 65fd3775ef501256ff630d274a233aa531b468d7 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 8 Feb 2023 13:37:51 +0800 Subject: [PATCH 50/62] change poseidon repo url --- halo2_proofs/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 6b4060a5c1..261f0e4f29 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -55,7 +55,7 @@ blake2b_simd = "1" sha3 = "0.9.1" subtle = "2.3" cfg-if = "0.1" -poseidon = { git = 'https://github.com/appliedzkp/poseidon.git' } #, branch = 'circuit' } +poseidon = { git = 'https://github.com/privacy-scaling-explorations/poseidon.git' } #, branch = 'circuit' } num-integer = "0.1" num-bigint = { version = "0.4", features = ["rand"] } From df552beed921e9ce932c7980b4a0e623c26d5747 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 8 Feb 2023 13:53:48 +0800 Subject: [PATCH 51/62] make ParamsKZG.n public --- halo2_proofs/src/poly/kzg/commitment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index 90034eceb1..aa86fdc14f 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -22,7 +22,7 @@ use super::msm::MSMKZG; #[derive(Debug, Clone)] pub struct ParamsKZG { pub(crate) k: u32, - pub(crate) n: u64, + pub n: u64, pub(crate) g: Vec, pub g_lagrange: Vec, pub(crate) g2: E::G2Affine, From c9a9ab71afcee06358923351d1775c6a0e9a3fe4 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Wed, 8 Feb 2023 19:00:15 +0800 Subject: [PATCH 52/62] revert instance commitment in gwc; don't store selector values in vk bytes --- halo2_proofs/src/plonk.rs | 16 ++++++++++------ halo2_proofs/src/plonk/keygen.rs | 4 ++-- .../src/poly/kzg/multiopen/gwc/prover.rs | 2 +- .../src/poly/kzg/multiopen/gwc/verifier.rs | 2 +- halo2_proofs/tests/plonk_api.rs | 10 ++++------ 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index 3c6214e361..489af783cf 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -56,7 +56,7 @@ pub struct VerifyingKey { cs_degree: usize, /// The representative of this `VerifyingKey` in transcripts. transcript_repr: C::Scalar, - selectors: Vec>, + //selectors: Vec>, } impl VerifyingKey @@ -79,7 +79,7 @@ where commitment.write(writer, format)?; } self.permutation.write(writer, format)?; - + /* // write self.selectors for selector in &self.selectors { // since `selector` is filled with `bool`, we pack them 8 at a time into bytes and then write @@ -87,6 +87,7 @@ where writer.write_all(&[crate::helpers::pack(bits)])?; } } + */ Ok(()) } @@ -118,6 +119,7 @@ where let permutation = permutation::VerifyingKey::read(reader, &cs.permutation, format)?; + /* // read selectors let selectors: Vec> = vec![vec![false; 1 << k]; cs.num_selectors] .into_iter() @@ -131,13 +133,13 @@ where }) .collect::>()?; let (cs, _) = cs.compress_selectors(selectors.clone()); - + */ Ok(Self::from_parts( domain, fixed_commitments, permutation, cs, - selectors, + //selectors, )) } @@ -161,12 +163,14 @@ impl VerifyingKey { fn bytes_length(&self) -> usize { 8 + (self.fixed_commitments.len() * C::default().to_bytes().as_ref().len()) + self.permutation.bytes_length() + /* + self.selectors.len() * (self .selectors .get(0) .map(|selector| selector.len() / 8 + 1) .unwrap_or(0)) + */ } fn from_parts( @@ -174,7 +178,7 @@ impl VerifyingKey { fixed_commitments: Vec, permutation: permutation::VerifyingKey, cs: ConstraintSystem, - selectors: Vec>, + //selectors: Vec>, ) -> Self { // Compute cached values. let cs_degree = cs.degree(); @@ -187,7 +191,7 @@ impl VerifyingKey { cs_degree, // Temporary, this is not pinned. transcript_repr: C::Scalar::zero(), - selectors, + //selectors, }; let mut hasher = Blake2bParams::new() diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index ffeac8e4db..516665b946 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -254,7 +254,7 @@ where fixed_commitments, permutation_vk, cs, - assembly.selectors, +// assembly.selectors, )) } @@ -346,7 +346,7 @@ where fixed_commitments, permutation_vk, cs.clone(), - assembly.selectors.clone(), +// assembly.selectors.clone(), ) } }; diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs index e7bff84ade..ee8a549a00 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs @@ -32,7 +32,7 @@ where E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { - const QUERY_INSTANCE: bool = false; + const QUERY_INSTANCE: bool = true; fn new(params: &'params ParamsKZG) -> Self { Self { params } diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs index 1ec003d638..22fa139480 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs @@ -39,7 +39,7 @@ where type Guard = GuardKZG<'params, E>; type MSMAccumulator = DualMSM<'params, E>; - const QUERY_INSTANCE: bool = false; + const QUERY_INSTANCE: bool = true; fn new(params: &'params ParamsKZG) -> Self { Self { params } diff --git a/halo2_proofs/tests/plonk_api.rs b/halo2_proofs/tests/plonk_api.rs index 913762c0da..113b93dab8 100644 --- a/halo2_proofs/tests/plonk_api.rs +++ b/halo2_proofs/tests/plonk_api.rs @@ -20,8 +20,6 @@ use halo2_proofs::transcript::{ use rand_core::{OsRng, RngCore}; use std::marker::PhantomData; -#[test] -fn plonk_api() { const K: u32 = 5; /// This represents an advice column at a certain row in the ConstraintSystem @@ -532,6 +530,7 @@ fn plonk_api() { assert!(strategy.finalize()); } + #[test] fn test_plonk_api_gwc() { use halo2_proofs::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; use halo2_proofs::poly::kzg::multiopen::{ProverGWC, VerifierGWC}; @@ -561,6 +560,7 @@ fn plonk_api() { >(verifier_params, pk.get_vk(), &proof[..]); } + #[test] fn test_plonk_api_shplonk() { use halo2_proofs::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; use halo2_proofs::poly::kzg::multiopen::{ProverSHPLONK, VerifierSHPLONK}; @@ -590,6 +590,7 @@ fn plonk_api() { >(verifier_params, pk.get_vk(), &proof[..]); } + #[test] fn test_plonk_api_ipa() { use halo2_proofs::poly::ipa::commitment::{IPACommitmentScheme, ParamsIPA}; use halo2_proofs::poly::ipa::multiopen::{ProverIPA, VerifierIPA}; @@ -1020,7 +1021,4 @@ fn plonk_api() { ); } } - test_plonk_api_ipa(); - test_plonk_api_gwc(); - test_plonk_api_shplonk(); -} + From 49f4c58908095b46b4f0983404c12106b725df4e Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Tue, 14 Feb 2023 16:03:42 +0800 Subject: [PATCH 53/62] reduce logging --- .../src/circuit/floor_planner/single_pass.rs | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index 2283acab64..80174a2c51 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -99,16 +99,24 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a assignment(region.into())?; end_timer!(timer_1st); } - log::debug!("region row_count {}: {}", region_name, shape.row_count()); + let row_count = shape.row_count(); + let log_region_info = row_count >= 40; + if log_region_info { + log::debug!( + "region row_count \"{}\": {}", + region_name, + shape.row_count() + ); + } // Lay out this region. We implement the simplest approach here: position the // region starting at the earliest row for which none of the columns are in use. let mut region_start = 0; for column in &shape.columns { let column_start = self.columns.get(column).cloned().unwrap_or(0); - if column_start != 0 { + if column_start != 0 && log_region_info { log::trace!( - "columns {:?} reused between multi regions. Start: {}. Region: {}", + "columns {:?} reused between multi regions. Start: {}. Region: \"{}\"", column, column_start, region_name @@ -116,7 +124,14 @@ impl<'a, F: Field, CS: Assignment + 'a> Layouter for SingleChipLayouter<'a } region_start = cmp::max(region_start, column_start); } - log::debug!("region{} start: {}", self.regions.len(), region_start); + if log_region_info { + log::debug!( + "region \"{}\", idx {} start {}", + region_name, + self.regions.len(), + region_start + ); + } self.regions.push(region_start.into()); // Update column usage information. From d292643f6f8881b41a7ce3c12e88b1b703f7ec13 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Mon, 20 Feb 2023 10:21:17 +0800 Subject: [PATCH 54/62] keep value.inner private to avoid being misused --- halo2_proofs/src/circuit/value.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/halo2_proofs/src/circuit/value.rs b/halo2_proofs/src/circuit/value.rs index 920b70d330..ca31dffda9 100644 --- a/halo2_proofs/src/circuit/value.rs +++ b/halo2_proofs/src/circuit/value.rs @@ -14,8 +14,7 @@ use crate::plonk::{Assigned, Error}; /// for improved usability. #[derive(Clone, Copy, Debug)] pub struct Value { - /// for adhoc usage... - pub inner: Option, + inner: Option, } impl Default for Value { From 5689a747c6acf9f7316b73dbe5ce4a1b3628c60c Mon Sep 17 00:00:00 2001 From: naure Date: Mon, 20 Feb 2023 14:42:35 +0100 Subject: [PATCH 55/62] test/unwrap_value: escape Value safety in the dev module (#34) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Aurélien Nicolas --- halo2_proofs/src/circuit.rs | 1 + halo2_proofs/src/circuit/value.rs | 7 +++++++ halo2_proofs/src/dev.rs | 2 ++ 3 files changed, 10 insertions(+) diff --git a/halo2_proofs/src/circuit.rs b/halo2_proofs/src/circuit.rs index 254c08ff84..1dc9bd917f 100644 --- a/halo2_proofs/src/circuit.rs +++ b/halo2_proofs/src/circuit.rs @@ -12,6 +12,7 @@ use crate::{ }; mod value; +pub(crate) use value::value_dev; pub use value::Value; pub mod floor_planner; diff --git a/halo2_proofs/src/circuit/value.rs b/halo2_proofs/src/circuit/value.rs index ca31dffda9..1a1bf4f9a2 100644 --- a/halo2_proofs/src/circuit/value.rs +++ b/halo2_proofs/src/circuit/value.rs @@ -701,3 +701,10 @@ impl Value> { } } } + +/// Utilities for tests and dev tools. +pub mod value_dev { + pub fn unwrap_value(v: super::Value) -> T { + v.inner.unwrap() + } +} diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index a020d4c874..cdd1c450b4 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -51,6 +51,8 @@ mod graph; #[cfg_attr(docsrs, doc(cfg(feature = "dev-graph")))] pub use graph::{circuit_dot_graph, layout::CircuitLayout}; +pub use crate::circuit::value_dev::unwrap_value; + #[derive(Debug)] struct Region { /// The name of the region. Not required to be unique. From 3185d065c87d4f5538d49d2018ae32fa292f85cd Mon Sep 17 00:00:00 2001 From: zhenfei Date: Mon, 6 Mar 2023 16:17:22 -0500 Subject: [PATCH 56/62] fix errors after sync with axiom's feat/serde_raw --- halo2_proofs/src/helpers.rs | 49 +++++++++++++++++++ halo2_proofs/src/plonk.rs | 16 +++--- halo2_proofs/src/plonk/keygen.rs | 10 +++- halo2_proofs/src/plonk/permutation.rs | 3 +- halo2_proofs/src/plonk/permutation/keygen.rs | 3 +- .../src/poly/kzg/multiopen/gwc/prover.rs | 2 +- 6 files changed, 70 insertions(+), 13 deletions(-) diff --git a/halo2_proofs/src/helpers.rs b/halo2_proofs/src/helpers.rs index c1ad000d4d..a7aa62de69 100644 --- a/halo2_proofs/src/helpers.rs +++ b/halo2_proofs/src/helpers.rs @@ -1,7 +1,9 @@ use crate::poly::Polynomial; use ff::Field; use ff::PrimeField; +use halo2curves::FieldExt; use halo2curves::{pairing::Engine, serde::SerdeObject, CurveAffine}; +use num_bigint::BigUint; use std::io; /// This enum specifies how various types are serialized and deserialized. @@ -32,6 +34,53 @@ pub(crate) trait CurveRead: CurveAffine { } impl CurveRead for C {} + +pub fn field_to_bn(f: &F) -> BigUint { + BigUint::from_bytes_le(f.to_repr().as_ref()) +} + +/// Input a big integer `bn`, compute a field element `f` +/// such that `f == bn % F::MODULUS`. +pub fn bn_to_field(bn: &BigUint) -> F { + let mut buf = bn.to_bytes_le(); + buf.resize(64, 0u8); + + let mut buf_array = [0u8; 64]; + buf_array.copy_from_slice(buf.as_ref()); + F::from_bytes_wide(&buf_array) +} + +/// Input a base field element `b`, output a scalar field +/// element `s` s.t. `s == b % ScalarField::MODULUS` +pub(crate) fn base_to_scalar(base: &C::Base) -> C::Scalar { + let bn = field_to_bn(base); + // bn_to_field will perform a mod reduction + bn_to_field(&bn) +} + +#[cfg(test)] +mod test { + use super::*; + use halo2curves::bn256::{Fq, G1Affine}; + use rand_core::OsRng; + #[test] + fn test_conversion() { + // random numbers + for _ in 0..100 { + let b = Fq::random(OsRng); + let bi = field_to_bn(&b); + let b_rec = bn_to_field(&bi); + assert_eq!(b, b_rec); + + let s = base_to_scalar::(&b); + let si = field_to_bn(&s); + // TODO: fixme -- this test has a small probability to fail + // because |base field| > |scalar field| + assert_eq!(si, bi); + } + } +} + pub trait SerdeCurveAffine: CurveAffine + SerdeObject { /// Reads an element from the buffer and parses it according to the `format`: /// - `Processed`: Reads a compressed curve element and decompress it diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index cf62adda1f..27134602b3 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -56,7 +56,7 @@ pub struct VerifyingKey { cs_degree: usize, /// The representative of this `VerifyingKey` in transcripts. transcript_repr: C::Scalar, - //selectors: Vec>, + selectors: Vec>, } impl VerifyingKey @@ -86,7 +86,6 @@ where writer.write_all(&[crate::helpers::pack(bits)])?; } } - */ Ok(()) } @@ -118,7 +117,7 @@ where let permutation = permutation::VerifyingKey::read(reader, &cs.permutation, format)?; - /* + // read selectors let selectors: Vec> = vec![vec![false; 1 << k]; cs.num_selectors] .into_iter() @@ -132,13 +131,13 @@ where }) .collect::>()?; let (cs, _) = cs.compress_selectors(selectors.clone()); - */ + Ok(Self::from_parts( domain, fixed_commitments, permutation, cs, - //selectors, + selectors, )) } @@ -177,7 +176,7 @@ impl VerifyingKey { fixed_commitments: Vec, permutation: permutation::VerifyingKey, cs: ConstraintSystem, - //selectors: Vec>, + selectors: Vec>, ) -> Self { // Compute cached values. let cs_degree = cs.degree(); @@ -190,7 +189,7 @@ impl VerifyingKey { cs_degree, // Temporary, this is not pinned. transcript_repr: C::Scalar::zero(), - //selectors, + selectors, }; let mut hasher = Blake2bParams::new() @@ -270,6 +269,7 @@ pub struct ProvingKey { l_active_row: Polynomial, fixed_values: Vec>, fixed_polys: Vec>, + fixed_cosets: Vec>, permutation: permutation::ProvingKey, ev: Evaluator, } @@ -350,7 +350,7 @@ where l_active_row, fixed_values, fixed_polys, - //fixed_cosets, + fixed_cosets, permutation, ev, }) diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index 516665b946..527480b60c 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -254,7 +254,7 @@ where fixed_commitments, permutation_vk, cs, -// assembly.selectors, + assembly.selectors, )) } @@ -346,7 +346,7 @@ where fixed_commitments, permutation_vk, cs.clone(), -// assembly.selectors.clone(), + assembly.selectors.clone(), ) } }; @@ -356,6 +356,11 @@ where .map(|poly| vk.domain.lagrange_to_coeff(poly.clone())) .collect(); + let fixed_cosets = fixed_polys + .iter() + .map(|poly| vk.domain.coeff_to_extended(poly.clone())) + .collect(); + let permutation_pk = assembly .permutation .build_pk(params, &vk.domain, &cs.permutation); @@ -401,6 +406,7 @@ where l_active_row, fixed_values: fixed, fixed_polys, + fixed_cosets, permutation: permutation_pk, ev, }) diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index 057baeb372..a0a20df718 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -123,6 +123,7 @@ impl VerifyingKey { pub(crate) struct ProvingKey { permutations: Vec>, pub(super) polys: Vec>, + pub(super) cosets: Vec>, } impl ProvingKey @@ -137,7 +138,7 @@ where Ok(ProvingKey { permutations, polys, - //cosets, + cosets, }) } diff --git a/halo2_proofs/src/plonk/permutation/keygen.rs b/halo2_proofs/src/plonk/permutation/keygen.rs index 874213d598..c8e3b37f5b 100644 --- a/halo2_proofs/src/plonk/permutation/keygen.rs +++ b/halo2_proofs/src/plonk/permutation/keygen.rs @@ -235,7 +235,8 @@ impl Assembly { ProvingKey { permutations, - polys, + polys, + cosets, } } } diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs index e7bff84ade..ee8a549a00 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs @@ -32,7 +32,7 @@ where E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { - const QUERY_INSTANCE: bool = false; + const QUERY_INSTANCE: bool = true; fn new(params: &'params ParamsKZG) -> Self { Self { params } From f913a1a9fa20b5eecdb16dfd72676f3c379c4582 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Wed, 8 Mar 2023 16:30:57 -0500 Subject: [PATCH 57/62] upgrade to group/ff 0.13.0 --- halo2_proofs/Cargo.toml | 6 +- halo2_proofs/benches/dev_lookup.rs | 2 +- halo2_proofs/benches/plonk.rs | 21 +- halo2_proofs/examples/circuit-layout.rs | 16 +- halo2_proofs/examples/shuffle.rs | 43 +- halo2_proofs/examples/simple-example.rs | 18 +- halo2_proofs/examples/two-chip.rs | 42 +- halo2_proofs/src/arithmetic.rs | 505 +------- halo2_proofs/src/arithmetic/field_fft.rs | 259 ++++ halo2_proofs/src/arithmetic/group_fft.rs | 300 +++++ halo2_proofs/src/arithmetic/multi_exp.rs | 156 +++ halo2_proofs/src/arithmetic/util.rs | 83 ++ halo2_proofs/src/circuit.rs | 11 +- .../src/circuit/floor_planner/single_pass.rs | 11 +- halo2_proofs/src/circuit/floor_planner/v1.rs | 11 +- halo2_proofs/src/dev.rs | 53 +- halo2_proofs/src/dev/failure.rs | 8 +- halo2_proofs/src/dev/util.rs | 25 +- halo2_proofs/src/helpers.rs | 14 +- halo2_proofs/src/plonk.rs | 42 +- halo2_proofs/src/plonk/assigned.rs | 14 +- halo2_proofs/src/plonk/circuit.rs | 9 +- .../src/plonk/circuit/compress_selectors.rs | 12 +- halo2_proofs/src/plonk/evaluation.rs | 24 +- halo2_proofs/src/plonk/keygen.rs | 14 +- halo2_proofs/src/plonk/lookup/prover.rs | 18 +- halo2_proofs/src/plonk/lookup/verifier.rs | 12 +- halo2_proofs/src/plonk/permutation/keygen.rs | 9 +- halo2_proofs/src/plonk/permutation/prover.rs | 9 +- .../src/plonk/permutation/verifier.rs | 11 +- halo2_proofs/src/plonk/prover.rs | 15 +- halo2_proofs/src/plonk/vanishing/prover.rs | 10 +- halo2_proofs/src/plonk/vanishing/verifier.rs | 6 +- halo2_proofs/src/plonk/verifier.rs | 15 +- halo2_proofs/src/plonk/verifier/batch.rs | 6 +- halo2_proofs/src/poly.rs | 13 +- halo2_proofs/src/poly/commitment.rs | 24 +- halo2_proofs/src/poly/domain.rs | 159 +-- halo2_proofs/src/poly/evaluator.rs | 10 +- halo2_proofs/src/poly/ipa/commitment.rs | 10 +- .../src/poly/ipa/commitment/prover.rs | 4 +- .../src/poly/ipa/commitment/verifier.rs | 4 +- halo2_proofs/src/poly/ipa/msm.rs | 2 +- halo2_proofs/src/poly/ipa/multiopen.rs | 11 +- halo2_proofs/src/poly/ipa/multiopen/prover.rs | 6 +- .../src/poly/ipa/multiopen/verifier.rs | 10 +- halo2_proofs/src/poly/ipa/strategy.rs | 4 +- halo2_proofs/src/poly/kzg/commitment.rs | 30 +- halo2_proofs/src/poly/kzg/msm.rs | 18 +- halo2_proofs/src/poly/kzg/multiopen/gwc.rs | 9 +- .../src/poly/kzg/multiopen/gwc/prover.rs | 10 +- .../src/poly/kzg/multiopen/gwc/verifier.rs | 12 +- .../src/poly/kzg/multiopen/shplonk.rs | 18 +- .../src/poly/kzg/multiopen/shplonk/prover.rs | 21 +- .../poly/kzg/multiopen/shplonk/verifier.rs | 19 +- halo2_proofs/src/poly/kzg/strategy.rs | 35 +- halo2_proofs/src/poly/multiopen_test.rs | 2 +- halo2_proofs/src/transcript.rs | 37 +- halo2_proofs/src/transcript/blake2b.rs | 2 +- halo2_proofs/src/transcript/poseidon.rs | 47 +- halo2_proofs/tests/plonk_api.rs | 1093 ++++++++--------- 61 files changed, 1939 insertions(+), 1481 deletions(-) create mode 100644 halo2_proofs/src/arithmetic/field_fft.rs create mode 100644 halo2_proofs/src/arithmetic/group_fft.rs create mode 100644 halo2_proofs/src/arithmetic/multi_exp.rs create mode 100644 halo2_proofs/src/arithmetic/util.rs diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 261f0e4f29..e70f7ce02f 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -46,9 +46,9 @@ harness = false [dependencies] backtrace = { version = "0.3", optional = true } rayon = "1.5.1" -ff = "0.12" -group = "0.12" -halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves.git', tag = "0.3.1" } +ff = "0.13" +group = "0.13" +halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves.git', features = [ "derive_serde" ] } rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" diff --git a/halo2_proofs/benches/dev_lookup.rs b/halo2_proofs/benches/dev_lookup.rs index bb6cfdadbf..80690b4548 100644 --- a/halo2_proofs/benches/dev_lookup.rs +++ b/halo2_proofs/benches/dev_lookup.rs @@ -42,7 +42,7 @@ fn criterion_benchmark(c: &mut Criterion) { meta.lookup("lookup", |meta| { let selector = meta.query_selector(config.selector); - let not_selector = Expression::Constant(F::one()) - selector.clone(); + let not_selector = Expression::Constant(F::ONE) - selector.clone(); let advice = meta.query_advice(config.advice, Rotation::cur()); vec![(selector * advice + not_selector, config.table)] }); diff --git a/halo2_proofs/benches/plonk.rs b/halo2_proofs/benches/plonk.rs index a679961463..c7901c2cd0 100644 --- a/halo2_proofs/benches/plonk.rs +++ b/halo2_proofs/benches/plonk.rs @@ -116,15 +116,10 @@ fn criterion_benchmark(c: &mut Criterion) { || value.unwrap().map(|v| v.2), )?; - region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::zero()))?; - region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::zero()))?; - region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::one()))?; - region.assign_fixed( - || "a * b", - self.config.sm, - 0, - || Value::known(FF::one()), - )?; + region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::ZERO))?; + region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::ZERO))?; + region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "a * b", self.config.sm, 0, || Value::known(FF::ONE))?; Ok((lhs.cell(), rhs.cell(), out.cell())) }, ) @@ -163,14 +158,14 @@ fn criterion_benchmark(c: &mut Criterion) { || value.unwrap().map(|v| v.2), )?; - region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::one()))?; - region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::one()))?; - region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::one()))?; + region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::ONE))?; region.assign_fixed( || "a * b", self.config.sm, 0, - || Value::known(FF::zero()), + || Value::known(FF::ZERO), )?; Ok((lhs.cell(), rhs.cell(), out.cell())) }, diff --git a/halo2_proofs/examples/circuit-layout.rs b/halo2_proofs/examples/circuit-layout.rs index beb99502bd..b1cf7eed27 100644 --- a/halo2_proofs/examples/circuit-layout.rs +++ b/halo2_proofs/examples/circuit-layout.rs @@ -94,10 +94,10 @@ impl StandardCs for StandardPlonk { let out = region.assign_advice(|| "out", self.config.c, 0, || value.unwrap().map(|v| v.2))?; - region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::zero()))?; - region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::zero()))?; - region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::one()))?; - region.assign_fixed(|| "a * b", self.config.sm, 0, || Value::known(FF::one()))?; + region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::ZERO))?; + region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::ZERO))?; + region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "a * b", self.config.sm, 0, || Value::known(FF::ONE))?; Ok((lhs.cell(), rhs.cell(), out.cell())) } fn raw_add(&self, region: &mut Region, mut f: F) -> Result<(Cell, Cell, Cell), Error> @@ -131,10 +131,10 @@ impl StandardCs for StandardPlonk { let out = region.assign_advice(|| "out", self.config.c, 0, || value.unwrap().map(|v| v.2))?; - region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::one()))?; - region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::one()))?; - region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::one()))?; - region.assign_fixed(|| "a * b", self.config.sm, 0, || Value::known(FF::zero()))?; + region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "a * b", self.config.sm, 0, || Value::known(FF::ZERO))?; Ok((lhs.cell(), rhs.cell(), out.cell())) } fn copy(&self, region: &mut Region, left: Cell, right: Cell) -> Result<(), Error> { diff --git a/halo2_proofs/examples/shuffle.rs b/halo2_proofs/examples/shuffle.rs index 1926074371..067cb259fa 100644 --- a/halo2_proofs/examples/shuffle.rs +++ b/halo2_proofs/examples/shuffle.rs @@ -1,6 +1,7 @@ -use ff::BatchInvert; +use ff::PrimeField; +use ff::{BatchInvert, FromUniformBytes, WithSmallOrderMulGroup}; use halo2_proofs::{ - arithmetic::{CurveAffine, FieldExt}, + arithmetic::CurveAffine, circuit::{floor_planner::V1, Layouter, Value}, dev::{metadata, FailureLocation, MockProver, VerifyFailure}, halo2curves::pasta::EqAffine, @@ -21,13 +22,13 @@ use halo2_proofs::{ use rand_core::{OsRng, RngCore}; use std::iter; -fn rand_2d_array( +fn rand_2d_array( rng: &mut R, ) -> [[F; H]; W] { [(); W].map(|_| [(); H].map(|_| F::random(&mut *rng))) } -fn shuffled( +fn shuffled( original: [[F; H]; W], rng: &mut R, ) -> [[F; H]; W] { @@ -56,7 +57,7 @@ struct MyConfig { } impl MyConfig { - fn configure(meta: &mut ConstraintSystem) -> Self { + fn configure(meta: &mut ConstraintSystem) -> Self { let [q_shuffle, q_first, q_last] = [(); 3].map(|_| meta.selector()); // First phase let original = [(); W].map(|_| meta.advice_column_in(FirstPhase)); @@ -68,7 +69,7 @@ impl MyConfig { meta.create_gate("z should start with 1", |meta| { let q_first = meta.query_selector(q_first); let z = meta.query_advice(z, Rotation::cur()); - let one = Expression::Constant(F::one()); + let one = Expression::Constant(F::ONE); vec![q_first * (one - z)] }); @@ -76,7 +77,7 @@ impl MyConfig { meta.create_gate("z should end with 1", |meta| { let q_last = meta.query_selector(q_last); let z = meta.query_advice(z, Rotation::cur()); - let one = Expression::Constant(F::one()); + let one = Expression::Constant(F::ONE); vec![q_last * (one - z)] }); @@ -118,12 +119,12 @@ impl MyConfig { } #[derive(Clone, Default)] -struct MyCircuit { +struct MyCircuit { original: Value<[[F; H]; W]>, shuffled: Value<[[F; H]; W]>, } -impl MyCircuit { +impl MyCircuit { fn rand(rng: &mut R) -> Self { let original = rand_2d_array::(rng); let shuffled = shuffled(original, rng); @@ -135,7 +136,7 @@ impl MyCircuit { } } -impl Circuit for MyCircuit { +impl Circuit for MyCircuit { type Config = MyConfig; type FloorPlanner = V1; @@ -200,9 +201,9 @@ impl Circuit for MyCircuit Circuit for MyCircuit Circuit for MyCircuit>(); #[cfg(feature = "sanity-checks")] - assert_eq!(F::one(), *z.last().unwrap()); + assert_eq!(F::ONE, *z.last().unwrap()); z }, @@ -253,7 +254,11 @@ impl Circuit for MyCircuit( +fn test_mock_prover< + F: PrimeField + WithSmallOrderMulGroup<3> + FromUniformBytes<64> + Ord, + const W: usize, + const H: usize, +>( k: u32, circuit: MyCircuit, expected: Result<(), Vec<(metadata::Constraint, FailureLocation)>>, @@ -284,7 +289,9 @@ fn test_prover( k: u32, circuit: MyCircuit, expected: bool, -) { +) where + C::Scalar: FromUniformBytes<64>, +{ let params = ParamsIPA::::new(k); let vk = keygen_vk(¶ms, &circuit).unwrap(); let pk = keygen_pk(¶ms, vk, &circuit).unwrap(); diff --git a/halo2_proofs/examples/simple-example.rs b/halo2_proofs/examples/simple-example.rs index c5e7a9f282..e2e006dbfa 100644 --- a/halo2_proofs/examples/simple-example.rs +++ b/halo2_proofs/examples/simple-example.rs @@ -1,14 +1,14 @@ use std::marker::PhantomData; +use ff::PrimeField; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Selector}, poly::Rotation, }; // ANCHOR: instructions -trait NumericInstructions: Chip { +trait NumericInstructions: Chip { /// Variable representing a number. type Num; @@ -39,7 +39,7 @@ trait NumericInstructions: Chip { // ANCHOR: chip /// The chip that will implement our instructions! Chips store their own /// config, as well as type markers if necessary. -struct FieldChip { +struct FieldChip { config: FieldConfig, _marker: PhantomData, } @@ -65,7 +65,7 @@ struct FieldConfig { s_mul: Selector, } -impl FieldChip { +impl FieldChip { fn construct(config: >::Config) -> Self { Self { config, @@ -126,7 +126,7 @@ impl FieldChip { // ANCHOR_END: chip-config // ANCHOR: chip-impl -impl Chip for FieldChip { +impl Chip for FieldChip { type Config = FieldConfig; type Loaded = (); @@ -143,9 +143,9 @@ impl Chip for FieldChip { // ANCHOR: instructions-impl /// A variable representing a number. #[derive(Clone)] -struct Number(AssignedCell); +struct Number(AssignedCell); -impl NumericInstructions for FieldChip { +impl NumericInstructions for FieldChip { type Num = Number; fn load_private( @@ -238,13 +238,13 @@ impl NumericInstructions for FieldChip { /// they won't have any value during key generation. During proving, if any of these /// were `None` we would get an error. #[derive(Default)] -struct MyCircuit { +struct MyCircuit { constant: F, a: Value, b: Value, } -impl Circuit for MyCircuit { +impl Circuit for MyCircuit { // Since we are using a single chip for everything, we can just reuse its config. type Config = FieldConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/halo2_proofs/examples/two-chip.rs b/halo2_proofs/examples/two-chip.rs index 61d40f93ca..d2ac2c62b7 100644 --- a/halo2_proofs/examples/two-chip.rs +++ b/halo2_proofs/examples/two-chip.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; +use ff::PrimeField; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance, Selector}, poly::Rotation, @@ -10,9 +10,9 @@ use halo2_proofs::{ // ANCHOR: field-instructions /// A variable representing a number. #[derive(Clone)] -struct Number(AssignedCell); +struct Number(AssignedCell); -trait FieldInstructions: AddInstructions + MulInstructions { +trait FieldInstructions: AddInstructions + MulInstructions { /// Variable representing a number. type Num; @@ -43,7 +43,7 @@ trait FieldInstructions: AddInstructions + MulInstructions { // ANCHOR_END: field-instructions // ANCHOR: add-instructions -trait AddInstructions: Chip { +trait AddInstructions: Chip { /// Variable representing a number. type Num; @@ -58,7 +58,7 @@ trait AddInstructions: Chip { // ANCHOR_END: add-instructions // ANCHOR: mul-instructions -trait MulInstructions: Chip { +trait MulInstructions: Chip { /// Variable representing a number. type Num; @@ -108,28 +108,28 @@ struct MulConfig { // ANCHOR: field-chip /// The top-level chip that will implement the `FieldInstructions`. -struct FieldChip { +struct FieldChip { config: FieldConfig, _marker: PhantomData, } // ANCHOR_END: field-chip // ANCHOR: add-chip -struct AddChip { +struct AddChip { config: AddConfig, _marker: PhantomData, } // ANCHOR END: add-chip // ANCHOR: mul-chip -struct MulChip { +struct MulChip { config: MulConfig, _marker: PhantomData, } // ANCHOR_END: mul-chip // ANCHOR: add-chip-trait-impl -impl Chip for AddChip { +impl Chip for AddChip { type Config = AddConfig; type Loaded = (); @@ -144,7 +144,7 @@ impl Chip for AddChip { // ANCHOR END: add-chip-trait-impl // ANCHOR: add-chip-impl -impl AddChip { +impl AddChip { fn construct(config: >::Config, _loaded: >::Loaded) -> Self { Self { config, @@ -174,7 +174,7 @@ impl AddChip { // ANCHOR END: add-chip-impl // ANCHOR: add-instructions-impl -impl AddInstructions for FieldChip { +impl AddInstructions for FieldChip { type Num = Number; fn add( &self, @@ -189,7 +189,7 @@ impl AddInstructions for FieldChip { } } -impl AddInstructions for AddChip { +impl AddInstructions for AddChip { type Num = Number; fn add( @@ -231,7 +231,7 @@ impl AddInstructions for AddChip { // ANCHOR END: add-instructions-impl // ANCHOR: mul-chip-trait-impl -impl Chip for MulChip { +impl Chip for MulChip { type Config = MulConfig; type Loaded = (); @@ -246,7 +246,7 @@ impl Chip for MulChip { // ANCHOR END: mul-chip-trait-impl // ANCHOR: mul-chip-impl -impl MulChip { +impl MulChip { fn construct(config: >::Config, _loaded: >::Loaded) -> Self { Self { config, @@ -296,7 +296,7 @@ impl MulChip { // ANCHOR_END: mul-chip-impl // ANCHOR: mul-instructions-impl -impl MulInstructions for FieldChip { +impl MulInstructions for FieldChip { type Num = Number; fn mul( &self, @@ -310,7 +310,7 @@ impl MulInstructions for FieldChip { } } -impl MulInstructions for MulChip { +impl MulInstructions for MulChip { type Num = Number; fn mul( @@ -352,7 +352,7 @@ impl MulInstructions for MulChip { // ANCHOR END: mul-instructions-impl // ANCHOR: field-chip-trait-impl -impl Chip for FieldChip { +impl Chip for FieldChip { type Config = FieldConfig; type Loaded = (); @@ -367,7 +367,7 @@ impl Chip for FieldChip { // ANCHOR_END: field-chip-trait-impl // ANCHOR: field-chip-impl -impl FieldChip { +impl FieldChip { fn construct(config: >::Config, _loaded: >::Loaded) -> Self { Self { config, @@ -396,7 +396,7 @@ impl FieldChip { // ANCHOR_END: field-chip-impl // ANCHOR: field-instructions-impl -impl FieldInstructions for FieldChip { +impl FieldInstructions for FieldChip { type Num = Number; fn load_private( @@ -448,13 +448,13 @@ impl FieldInstructions for FieldChip { /// they won't have any value during key generation. During proving, if any of these /// were `Value::unknown()` we would get an error. #[derive(Default)] -struct MyCircuit { +struct MyCircuit { a: Value, b: Value, c: Value, } -impl Circuit for MyCircuit { +impl Circuit for MyCircuit { // Since we are using a single chip for everything, we can just reuse its config. type Config = FieldConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/halo2_proofs/src/arithmetic.rs b/halo2_proofs/src/arithmetic.rs index e3fae5f8bb..52ddb41ddb 100644 --- a/halo2_proofs/src/arithmetic.rs +++ b/halo2_proofs/src/arithmetic.rs @@ -1,455 +1,33 @@ //! This module provides common utilities, traits and structures for group, //! field and polynomial arithmetic. +mod field_fft; +mod group_fft; +mod multi_exp; +mod util; + +pub use field_fft::{best_fft, parallel_fft}; +pub use group_fft::{best_group_fft, g_to_lagrange, parallel_group_fft}; +pub use multi_exp::{best_multiexp, small_multiexp}; +pub use util::{generate_twiddle_lookup_table, parallelize}; + use super::multicore; pub use ff::Field; use group::{ ff::{BatchInvert, PrimeField}, - Curve, Group as _, + Curve, Group, }; -pub use halo2curves::{CurveAffine, CurveExt, FieldExt, Group}; +pub use halo2curves::{CurveAffine, CurveExt}; pub const SPARSE_TWIDDLE_DEGREE: u32 = 10; -fn multiexp_serial(coeffs: &[C::Scalar], bases: &[C], acc: &mut C::Curve) { - let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect(); - - let c = if bases.len() < 4 { - 1 - } else if bases.len() < 32 { - 3 - } else { - (f64::from(bases.len() as u32)).ln().ceil() as usize - }; - - fn get_at(segment: usize, c: usize, bytes: &F::Repr) -> usize { - let skip_bits = segment * c; - let skip_bytes = skip_bits / 8; - - if skip_bytes >= 32 { - return 0; - } - - let mut v = [0; 8]; - for (v, o) in v.iter_mut().zip(bytes.as_ref()[skip_bytes..].iter()) { - *v = *o; - } - - let mut tmp = u64::from_le_bytes(v); - tmp >>= skip_bits - (skip_bytes * 8); - tmp = tmp % (1 << c); - - tmp as usize - } - - let segments = (256 / c) + 1; - - for current_segment in (0..segments).rev() { - for _ in 0..c { - *acc = acc.double(); - } - - #[derive(Clone, Copy)] - enum Bucket { - None, - Affine(C), - Projective(C::Curve), - } - - impl Bucket { - fn add_assign(&mut self, other: &C) { - *self = match *self { - Bucket::None => Bucket::Affine(*other), - Bucket::Affine(a) => Bucket::Projective(a + *other), - Bucket::Projective(mut a) => { - a += *other; - Bucket::Projective(a) - } - } - } - - fn add(self, mut other: C::Curve) -> C::Curve { - match self { - Bucket::None => other, - Bucket::Affine(a) => { - other += a; - other - } - Bucket::Projective(a) => other + &a, - } - } - } - - let mut buckets: Vec> = vec![Bucket::None; (1 << c) - 1]; - - for (coeff, base) in coeffs.iter().zip(bases.iter()) { - let coeff = get_at::(current_segment, c, coeff); - if coeff != 0 { - buckets[coeff - 1].add_assign(base); - } - } - - // Summation by parts - // e.g. 3a + 2b + 1c = a + - // (a) + b + - // ((a) + b) + c - let mut running_sum = C::Curve::identity(); - for exp in buckets.into_iter().rev() { - running_sum = exp.add(running_sum); - *acc = *acc + &running_sum; - } - } -} - -/// Performs a small multi-exponentiation operation. -/// Uses the double-and-add algorithm with doublings shared across points. -pub fn small_multiexp(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve { - let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect(); - let mut acc = C::Curve::identity(); - - // for byte idx - for byte_idx in (0..32).rev() { - // for bit idx - for bit_idx in (0..8).rev() { - acc = acc.double(); - // for each coeff - for coeff_idx in 0..coeffs.len() { - let byte = coeffs[coeff_idx].as_ref()[byte_idx]; - if ((byte >> bit_idx) & 1) != 0 { - acc += bases[coeff_idx]; - } - } - } - } - - acc -} - -/// Performs a multi-exponentiation operation. -/// -/// This function will panic if coeffs and bases have a different length. -/// -/// This will use multithreading if beneficial. -pub fn best_multiexp(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve { - assert_eq!(coeffs.len(), bases.len()); - - let num_threads = multicore::current_num_threads(); - if coeffs.len() > num_threads { - let chunk = coeffs.len() / num_threads; - let num_chunks = coeffs.chunks(chunk).len(); - let mut results = vec![C::Curve::identity(); num_chunks]; - multicore::scope(|scope| { - let chunk = coeffs.len() / num_threads; - - for ((coeffs, bases), acc) in coeffs - .chunks(chunk) - .zip(bases.chunks(chunk)) - .zip(results.iter_mut()) - { - scope.spawn(move |_| { - multiexp_serial(coeffs, bases, acc); - }); - } - }); - results.iter().fold(C::Curve::identity(), |a, b| a + b) - } else { - let mut acc = C::Curve::identity(); - multiexp_serial(coeffs, bases, &mut acc); - acc - } -} - -/// Performs a radix-$2$ Fast-Fourier Transformation (FFT) on a vector of size -/// $n = 2^k$, when provided `log_n` = $k$ and an element of multiplicative -/// order $n$ called `omega` ($\omega$). The result is that the vector `a`, when -/// interpreted as the coefficients of a polynomial of degree $n - 1$, is -/// transformed into the evaluations of this polynomial at each of the $n$ -/// distinct powers of $\omega$. This transformation is invertible by providing -/// $\omega^{-1}$ in place of $\omega$ and dividing each resulting field element -/// by $n$. -/// -/// This will use multithreading if beneficial. -pub fn best_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { - let threads = multicore::current_num_threads(); - let log_split = log2_floor(threads) as usize; - let n = a.len() as usize; - let sub_n = n >> log_split; - let split_m = 1 << log_split; - - if sub_n < split_m { - serial_fft(a, omega, log_n); - } else { - parallel_fft(a, omega, log_n); - } -} - -fn bitreverse(mut n: usize, l: usize) -> usize { - let mut r = 0; - for _ in 0..l { - r = (r << 1) | (n & 1); - n >>= 1; - } - r -} - -fn serial_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { - let n = a.len() as u32; - assert_eq!(n, 1 << log_n); - - for k in 0..n as usize { - let rk = bitreverse(k, log_n as usize); - if k < rk { - a.swap(rk as usize, k as usize); - } - } - - let mut m = 1; - for _ in 0..log_n { - let w_m = omega.pow_vartime(&[u64::from(n / (2 * m)), 0, 0, 0]); - - let mut k = 0; - while k < n { - let mut w = G::Scalar::one(); - for j in 0..m { - let mut t = a[(k + j + m) as usize]; - t.group_scale(&w); - a[(k + j + m) as usize] = a[(k + j) as usize]; - a[(k + j + m) as usize].group_sub(&t); - a[(k + j) as usize].group_add(&t); - w *= &w_m; - } - - k += 2 * m; - } - - m *= 2; - } -} - -fn serial_split_fft( - a: &mut [G], - twiddle_lut: &[G::Scalar], - twiddle_scale: usize, - log_n: u32, -) { - let n = a.len() as u32; - assert_eq!(n, 1 << log_n); - - let mut m = 1; - for _ in 0..log_n { - let omega_idx = twiddle_scale * n as usize / (2 * m as usize); // 1/2, 1/4, 1/8, ... - let low_idx = omega_idx % (1 << SPARSE_TWIDDLE_DEGREE); - let high_idx = omega_idx >> SPARSE_TWIDDLE_DEGREE; - let mut w_m = twiddle_lut[low_idx]; - if high_idx > 0 { - w_m = w_m * twiddle_lut[(1 << SPARSE_TWIDDLE_DEGREE) + high_idx]; - } - - let mut k = 0; - while k < n { - let mut w = G::Scalar::one(); - for j in 0..m { - let mut t = a[(k + j + m) as usize]; - t.group_scale(&w); - a[(k + j + m) as usize] = a[(k + j) as usize]; - a[(k + j + m) as usize].group_sub(&t); - a[(k + j) as usize].group_add(&t); - w *= &w_m; - } - - k += 2 * m; - } - - m *= 2; - } -} - -fn split_radix_fft( - tmp: &mut [G], - a: &[G], - twiddle_lut: &[G::Scalar], - n: usize, - sub_fft_offset: usize, - log_split: usize, -) { - let split_m = 1 << log_split; - let sub_n = n >> log_split; - - // we use out-place bitreverse here, split_m <= num_threads, so the buffer spase is small - // and it's is good for data locality - let mut t1 = vec![G::group_zero(); split_m]; - // if unsafe code is allowed, a 10% performance improvement can be achieved - // let mut t1: Vec = Vec::with_capacity(split_m as usize); - // unsafe{ t1.set_len(split_m as usize); } - for i in 0..split_m { - t1[bitreverse(i, log_split)] = a[(i * sub_n + sub_fft_offset)]; - } - serial_split_fft(&mut t1, twiddle_lut, sub_n, log_split as u32); - - let sparse_degree = SPARSE_TWIDDLE_DEGREE; - let omega_idx = sub_fft_offset as usize; - let low_idx = omega_idx % (1 << sparse_degree); - let high_idx = omega_idx >> sparse_degree; - let mut omega = twiddle_lut[low_idx]; - if high_idx > 0 { - omega = omega * twiddle_lut[(1 << sparse_degree) + high_idx]; - } - let mut w_m = G::Scalar::one(); - for i in 0..split_m { - t1[i].group_scale(&w_m); - tmp[i] = t1[i]; - w_m = w_m * omega; - } -} - -pub fn generate_twiddle_lookup_table( - omega: F, - log_n: u32, - sparse_degree: u32, - with_last_level: bool, -) -> Vec { - let without_last_level = !with_last_level; - let is_lut_len_large = sparse_degree > log_n; - - // dense - if is_lut_len_large { - let mut twiddle_lut = vec![F::zero(); (1 << log_n) as usize]; - parallelize(&mut twiddle_lut, |twiddle_lut, start| { - let mut w_n = omega.pow_vartime(&[start as u64, 0, 0, 0]); - for twiddle_lut in twiddle_lut.iter_mut() { - *twiddle_lut = w_n; - w_n = w_n * omega; - } - }); - return twiddle_lut; - } - - // sparse - let low_degree_lut_len = 1 << sparse_degree; - let high_degree_lut_len = 1 << (log_n - sparse_degree - without_last_level as u32); - let mut twiddle_lut = vec![F::zero(); (low_degree_lut_len + high_degree_lut_len) as usize]; - parallelize( - &mut twiddle_lut[..low_degree_lut_len], - |twiddle_lut, start| { - let mut w_n = omega.pow_vartime(&[start as u64, 0, 0, 0]); - for twiddle_lut in twiddle_lut.iter_mut() { - *twiddle_lut = w_n; - w_n = w_n * omega; - } - }, - ); - let high_degree_omega = omega.pow_vartime(&[(1 << sparse_degree) as u64, 0, 0, 0]); - parallelize( - &mut twiddle_lut[low_degree_lut_len..], - |twiddle_lut, start| { - let mut w_n = high_degree_omega.pow_vartime(&[start as u64, 0, 0, 0]); - for twiddle_lut in twiddle_lut.iter_mut() { - *twiddle_lut = w_n; - w_n = w_n * high_degree_omega; - } - }, - ); - twiddle_lut -} - -pub fn parallel_fft(a: &mut [G], omega: G::Scalar, log_n: u32) { - let n = a.len() as usize; - assert_eq!(n, 1 << log_n); - - let log_split = log2_floor(multicore::current_num_threads()) as usize; - let split_m = 1 << log_split; - let sub_n = n >> log_split as usize; - let twiddle_lut = generate_twiddle_lookup_table(omega, log_n, SPARSE_TWIDDLE_DEGREE, true); - - // split fft - let mut tmp = vec![G::group_zero(); n]; - // if unsafe code is allowed, a 10% performance improvement can be achieved - // let mut tmp: Vec = Vec::with_capacity(n); - // unsafe{ tmp.set_len(n); } - multicore::scope(|scope| { - let a = &*a; - let twiddle_lut = &*twiddle_lut; - for (chunk_idx, tmp) in tmp.chunks_mut(sub_n).enumerate() { - scope.spawn(move |_| { - let split_fft_offset = chunk_idx * sub_n >> log_split; - for (i, tmp) in tmp.chunks_mut(split_m).enumerate() { - let split_fft_offset = split_fft_offset + i; - split_radix_fft(tmp, a, twiddle_lut, n, split_fft_offset, log_split); - } - }); - } - }); - - // shuffle - parallelize(a, |a, start| { - for (idx, a) in a.iter_mut().enumerate() { - let idx = start + idx; - let i = idx / sub_n; - let j = idx % sub_n; - *a = tmp[j * split_m + i]; - } - }); - - // sub fft - let new_omega = omega.pow_vartime(&[split_m as u64, 0, 0, 0]); - multicore::scope(|scope| { - for a in a.chunks_mut(sub_n) { - scope.spawn(move |_| { - serial_fft(a, new_omega, log_n - log_split as u32); - }); - } - }); - - // copy & unshuffle - let mask = (1 << log_split) - 1; - parallelize(&mut tmp, |tmp, start| { - for (idx, tmp) in tmp.iter_mut().enumerate() { - let idx = start + idx; - *tmp = a[idx]; - } - }); - parallelize(a, |a, start| { - for (idx, a) in a.iter_mut().enumerate() { - let idx = start + idx; - *a = tmp[sub_n * (idx & mask) + (idx >> log_split)]; - } - }); -} - -/// Convert coefficient bases group elements to lagrange basis by inverse FFT. -pub fn g_to_lagrange(g_projective: Vec, k: u32) -> Vec { - let n_inv = C::Scalar::TWO_INV.pow_vartime(&[k as u64, 0, 0, 0]); - let mut omega_inv = C::Scalar::ROOT_OF_UNITY_INV; - for _ in k..C::Scalar::S { - omega_inv = omega_inv.square(); - } - - let mut g_lagrange_projective = g_projective; - best_fft(&mut g_lagrange_projective, omega_inv, k); - parallelize(&mut g_lagrange_projective, |g, _| { - for g in g.iter_mut() { - *g *= n_inv; - } - }); - - let mut g_lagrange = vec![C::identity(); 1 << k]; - parallelize(&mut g_lagrange, |g_lagrange, starts| { - C::Curve::batch_normalize( - &g_lagrange_projective[starts..(starts + g_lagrange.len())], - g_lagrange, - ); - }); - - g_lagrange -} - /// This evaluates a provided polynomial (in coefficient form) at `point`. pub fn eval_polynomial(poly: &[F], point: F) -> F { fn evaluate(poly: &[F], point: F) -> F { poly.iter() .rev() - .fold(F::zero(), |acc, coeff| acc * point + coeff) + .fold(F::ZERO, |acc, coeff| acc * point + coeff) } let n = poly.len(); let num_threads = multicore::current_num_threads(); @@ -457,7 +35,7 @@ pub fn eval_polynomial(poly: &[F], point: F) -> F { evaluate(poly, point) } else { let chunk_size = (n + num_threads - 1) / num_threads; - let mut parts = vec![F::zero(); num_threads]; + let mut parts = vec![F::ZERO; num_threads]; multicore::scope(|scope| { for (chunk_idx, (out, poly)) in parts.chunks_mut(1).zip(poly.chunks(chunk_size)).enumerate() @@ -468,7 +46,7 @@ pub fn eval_polynomial(poly: &[F], point: F) -> F { }); } }); - parts.iter().fold(F::zero(), |acc, coeff| acc + coeff) + parts.iter().fold(F::ZERO, |acc, coeff| acc + coeff) } } @@ -479,7 +57,7 @@ pub fn compute_inner_product(a: &[F], b: &[F]) -> F { // TODO: parallelize? assert_eq!(a.len(), b.len()); - let mut acc = F::zero(); + let mut acc = F::ZERO; for (a, b) in a.iter().zip(b.iter()) { acc += (*a) * (*b); } @@ -496,9 +74,9 @@ where b = -b; let a = a.into_iter(); - let mut q = vec![F::zero(); a.len() - 1]; + let mut q = vec![F::ZERO; a.len() - 1]; - let mut tmp = F::zero(); + let mut tmp = F::ZERO; for (q, r) in q.iter_mut().rev().zip(a.rev()) { let mut lead_coeff = *r; lead_coeff.sub_assign(&tmp); @@ -510,27 +88,6 @@ where q } -/// This simple utility function will parallelize an operation that is to be -/// performed over a mutable slice. -pub fn parallelize(v: &mut [T], f: F) { - let n = v.len(); - let num_threads = multicore::current_num_threads(); - let mut chunk = (n as usize) / num_threads; - if chunk < num_threads { - chunk = 1; - } - - multicore::scope(|scope| { - for (chunk_num, v) in v.chunks_mut(chunk).enumerate() { - let f = f.clone(); - scope.spawn(move |_| { - let start = chunk_num * chunk; - f(v, start); - }); - } - }); -} - fn log2_floor(num: usize) -> u32 { assert!(num > 0); @@ -546,7 +103,7 @@ fn log2_floor(num: usize) -> u32 { /// Returns coefficients of an n - 1 degree polynomial given a set of n points /// and their evaluations. This function will panic if two values in `points` /// are the same. -pub fn lagrange_interpolate(points: &[F], evals: &[F]) -> Vec { +pub fn lagrange_interpolate(points: &[F], evals: &[F]) -> Vec { assert_eq!(points.len(), evals.len()); if points.len() == 1 { // Constant polynomial @@ -568,11 +125,11 @@ pub fn lagrange_interpolate(points: &[F], evals: &[F]) -> Vec { // Compute (x_j - x_k)^(-1) for each j != i denoms.iter_mut().flat_map(|v| v.iter_mut()).batch_invert(); - let mut final_poly = vec![F::zero(); points.len()]; + let mut final_poly = vec![F::ZERO; points.len()]; for (j, (denoms, eval)) in denoms.into_iter().zip(evals.iter()).enumerate() { let mut tmp: Vec = Vec::with_capacity(points.len()); let mut product = Vec::with_capacity(points.len() - 1); - tmp.push(F::one()); + tmp.push(F::ONE); for (x_k, denom) in points .iter() .enumerate() @@ -580,11 +137,11 @@ pub fn lagrange_interpolate(points: &[F], evals: &[F]) -> Vec { .map(|a| a.1) .zip(denoms.into_iter()) { - product.resize(tmp.len() + 1, F::zero()); + product.resize(tmp.len() + 1, F::ZERO); for ((a, b), product) in tmp .iter() - .chain(std::iter::once(&F::zero())) - .zip(std::iter::once(&F::zero()).chain(tmp.iter())) + .chain(std::iter::once(&F::ZERO)) + .zip(std::iter::once(&F::ZERO).chain(tmp.iter())) .zip(product.iter_mut()) { *product = *a * (-denom * x_k) + *b * denom; @@ -601,9 +158,9 @@ pub fn lagrange_interpolate(points: &[F], evals: &[F]) -> Vec { } } -pub(crate) fn evaluate_vanishing_polynomial(roots: &[F], z: F) -> F { - fn evaluate(roots: &[F], z: F) -> F { - roots.iter().fold(F::one(), |acc, point| (z - point) * acc) +pub(crate) fn evaluate_vanishing_polynomial(roots: &[F], z: F) -> F { + fn evaluate(roots: &[F], z: F) -> F { + roots.iter().fold(F::ONE, |acc, point| (z - point) * acc) } let n = roots.len(); let num_threads = multicore::current_num_threads(); @@ -611,18 +168,18 @@ pub(crate) fn evaluate_vanishing_polynomial(roots: &[F], z: F) -> F evaluate(roots, z) } else { let chunk_size = (n + num_threads - 1) / num_threads; - let mut parts = vec![F::one(); num_threads]; + let mut parts = vec![F::ONE; num_threads]; multicore::scope(|scope| { for (out, roots) in parts.chunks_mut(1).zip(roots.chunks(chunk_size)) { scope.spawn(move |_| out[0] = evaluate(roots, z)); } }); - parts.iter().fold(F::one(), |acc, part| acc * part) + parts.iter().fold(F::ONE, |acc, part| acc * part) } } -pub(crate) fn powers(base: F) -> impl Iterator { - std::iter::successors(Some(F::one()), move |power| Some(base * power)) +pub(crate) fn powers(base: F) -> impl Iterator { + std::iter::successors(Some(F::ONE), move |power| Some(base * power)) } #[cfg(test)] diff --git a/halo2_proofs/src/arithmetic/field_fft.rs b/halo2_proofs/src/arithmetic/field_fft.rs new file mode 100644 index 0000000000..dcb982a619 --- /dev/null +++ b/halo2_proofs/src/arithmetic/field_fft.rs @@ -0,0 +1,259 @@ +use super::multicore; +use super::util::{bitreverse, parallelize}; +use crate::arithmetic::log2_floor; +pub use ff::Field; +use group::{ + ff::{BatchInvert, PrimeField}, + Curve, Group, +}; + +pub use halo2curves::{CurveAffine, CurveExt}; + +pub const SPARSE_TWIDDLE_DEGREE: u32 = 10; +/// Performs a radix-$2$ Fast-Fourier Transformation (FFT) on a vector of size +/// $n = 2^k$, when provided `log_n` = $k$ and an element of multiplicative +/// order $n$ called `omega` ($\omega$). The result is that the vector `a`, when +/// interpreted as the coefficients of a polynomial of degree $n - 1$, is +/// transformed into the evaluations of this polynomial at each of the $n$ +/// distinct powers of $\omega$. This transformation is invertible by providing +/// $\omega^{-1}$ in place of $\omega$ and dividing each resulting field element +/// by $n$. +/// +/// This will use multithreading if beneficial. +pub fn best_fft(a: &mut [F], omega: F, log_n: u32) { + let threads = multicore::current_num_threads(); + let log_split = log2_floor(threads) as usize; + let n = a.len() as usize; + let sub_n = n >> log_split; + let split_m = 1 << log_split; + + if sub_n < split_m { + serial_fft(a, omega, log_n); + } else { + parallel_fft(a, omega, log_n); + } +} + +fn serial_fft(a: &mut [F], omega: F, log_n: u32) { + let n = a.len() as u32; + assert_eq!(n, 1 << log_n); + + for k in 0..n as usize { + let rk = bitreverse(k, log_n as usize); + if k < rk { + a.swap(rk as usize, k as usize); + } + } + + let mut m = 1; + for _ in 0..log_n { + let w_m = omega.pow_vartime(&[u64::from(n / (2 * m)), 0, 0, 0]); + + let mut k = 0; + while k < n { + let mut w = F::ONE; + for j in 0..m { + let mut t = a[(k + j + m) as usize]; + t.mul_assign(&w); + a[(k + j + m) as usize] = a[(k + j) as usize]; + a[(k + j + m) as usize].sub_assign(&t); + a[(k + j) as usize].add_assign(&t); + w *= &w_m; + } + + k += 2 * m; + } + + m *= 2; + } +} + +fn serial_split_fft( + a: &mut [F], + twiddle_lut: &[F], + twiddle_scale: usize, + log_n: u32, +) { + let n = a.len() as u32; + assert_eq!(n, 1 << log_n); + + let mut m = 1; + for _ in 0..log_n { + let omega_idx = twiddle_scale * n as usize / (2 * m as usize); // 1/2, 1/4, 1/8, ... + let low_idx = omega_idx % (1 << SPARSE_TWIDDLE_DEGREE); + let high_idx = omega_idx >> SPARSE_TWIDDLE_DEGREE; + let mut w_m = twiddle_lut[low_idx]; + if high_idx > 0 { + w_m = w_m * twiddle_lut[(1 << SPARSE_TWIDDLE_DEGREE) + high_idx]; + } + + let mut k = 0; + while k < n { + let mut w = F::ONE; + for j in 0..m { + let mut t = a[(k + j + m) as usize]; + t.mul_assign(&w); + a[(k + j + m) as usize] = a[(k + j) as usize]; + a[(k + j + m) as usize].sub_assign(&t); + a[(k + j) as usize].add_assign(&t); + w *= &w_m; + } + + k += 2 * m; + } + + m *= 2; + } +} + +fn split_radix_fft( + tmp: &mut [F], + a: &[F], + twiddle_lut: &[F], + n: usize, + sub_fft_offset: usize, + log_split: usize, +) { + let split_m = 1 << log_split; + let sub_n = n >> log_split; + + // we use out-place bitreverse here, split_m <= num_threads, so the buffer spase is small + // and it's is good for data locality + let mut t1 = vec![F::ZERO; split_m]; + // if unsafe code is allowed, a 10% performance improvement can be achieved + // let mut t1: Vec = Vec::with_capacity(split_m as usize); + // unsafe{ t1.set_len(split_m as usize); } + for i in 0..split_m { + t1[bitreverse(i, log_split)] = a[(i * sub_n + sub_fft_offset)]; + } + serial_split_fft(&mut t1, twiddle_lut, sub_n, log_split as u32); + + let sparse_degree = SPARSE_TWIDDLE_DEGREE; + let omega_idx = sub_fft_offset as usize; + let low_idx = omega_idx % (1 << sparse_degree); + let high_idx = omega_idx >> sparse_degree; + let mut omega = twiddle_lut[low_idx]; + if high_idx > 0 { + omega = omega * twiddle_lut[(1 << sparse_degree) + high_idx]; + } + let mut w_m = F::ONE; + for i in 0..split_m { + t1[i].mul_assign(&w_m); + tmp[i] = t1[i]; + w_m = w_m * omega; + } +} + +pub fn generate_twiddle_lookup_table( + omega: F, + log_n: u32, + sparse_degree: u32, + with_last_level: bool, +) -> Vec { + let without_last_level = !with_last_level; + let is_lut_len_large = sparse_degree > log_n; + + // dense + if is_lut_len_large { + let mut twiddle_lut = vec![F::ZERO; (1 << log_n) as usize]; + parallelize(&mut twiddle_lut, |twiddle_lut, start| { + let mut w_n = omega.pow_vartime(&[start as u64, 0, 0, 0]); + for twiddle_lut in twiddle_lut.iter_mut() { + *twiddle_lut = w_n; + w_n = w_n * omega; + } + }); + return twiddle_lut; + } + + // sparse + let low_degree_lut_len = 1 << sparse_degree; + let high_degree_lut_len = 1 << (log_n - sparse_degree - without_last_level as u32); + let mut twiddle_lut = vec![F::ZERO; (low_degree_lut_len + high_degree_lut_len) as usize]; + parallelize( + &mut twiddle_lut[..low_degree_lut_len], + |twiddle_lut, start| { + let mut w_n = omega.pow_vartime(&[start as u64, 0, 0, 0]); + for twiddle_lut in twiddle_lut.iter_mut() { + *twiddle_lut = w_n; + w_n = w_n * omega; + } + }, + ); + let high_degree_omega = omega.pow_vartime(&[(1 << sparse_degree) as u64, 0, 0, 0]); + parallelize( + &mut twiddle_lut[low_degree_lut_len..], + |twiddle_lut, start| { + let mut w_n = high_degree_omega.pow_vartime(&[start as u64, 0, 0, 0]); + for twiddle_lut in twiddle_lut.iter_mut() { + *twiddle_lut = w_n; + w_n = w_n * high_degree_omega; + } + }, + ); + twiddle_lut +} + +pub fn parallel_fft(a: &mut [F], omega: F, log_n: u32) { + let n = a.len() as usize; + assert_eq!(n, 1 << log_n); + + let log_split = log2_floor(multicore::current_num_threads()) as usize; + let split_m = 1 << log_split; + let sub_n = n >> log_split as usize; + let twiddle_lut = generate_twiddle_lookup_table(omega, log_n, SPARSE_TWIDDLE_DEGREE, true); + + // split fft + let mut tmp = vec![F::ZERO; n]; + // if unsafe code is allowed, a 10% performance improvement can be achieved + // let mut tmp: Vec = Vec::with_capacity(n); + // unsafe{ tmp.set_len(n); } + multicore::scope(|scope| { + let a = &*a; + let twiddle_lut = &*twiddle_lut; + for (chunk_idx, tmp) in tmp.chunks_mut(sub_n).enumerate() { + scope.spawn(move |_| { + let split_fft_offset = chunk_idx * sub_n >> log_split; + for (i, tmp) in tmp.chunks_mut(split_m).enumerate() { + let split_fft_offset = split_fft_offset + i; + split_radix_fft(tmp, a, twiddle_lut, n, split_fft_offset, log_split); + } + }); + } + }); + + // shuffle + parallelize(a, |a, start| { + for (idx, a) in a.iter_mut().enumerate() { + let idx = start + idx; + let i = idx / sub_n; + let j = idx % sub_n; + *a = tmp[j * split_m + i]; + } + }); + + // sub fft + let new_omega = omega.pow_vartime(&[split_m as u64, 0, 0, 0]); + multicore::scope(|scope| { + for a in a.chunks_mut(sub_n) { + scope.spawn(move |_| { + serial_fft(a, new_omega, log_n - log_split as u32); + }); + } + }); + + // copy & unshuffle + let mask = (1 << log_split) - 1; + parallelize(&mut tmp, |tmp, start| { + for (idx, tmp) in tmp.iter_mut().enumerate() { + let idx = start + idx; + *tmp = a[idx]; + } + }); + parallelize(a, |a, start| { + for (idx, a) in a.iter_mut().enumerate() { + let idx = start + idx; + *a = tmp[sub_n * (idx & mask) + (idx >> log_split)]; + } + }); +} diff --git a/halo2_proofs/src/arithmetic/group_fft.rs b/halo2_proofs/src/arithmetic/group_fft.rs new file mode 100644 index 0000000000..de51f5b998 --- /dev/null +++ b/halo2_proofs/src/arithmetic/group_fft.rs @@ -0,0 +1,300 @@ +use crate::arithmetic::{log2_floor, util::bitreverse}; + +use super::{multicore, util::parallelize}; +pub use ff::Field; +use group::{ + ff::{BatchInvert, PrimeField}, + Curve, Group, +}; + +pub use halo2curves::{CurveAffine, CurveExt}; + +pub const SPARSE_TWIDDLE_DEGREE: u32 = 10; +/// Performs a radix-$2$ Fast-Fourier Transformation (FFT) on a vector of size +/// $n = 2^k$, when provided `log_n` = $k$ and an element of multiplicative +/// order $n$ called `omega` ($\omega$). The result is that the vector `a`, when +/// interpreted as the coefficients of a polynomial of degree $n - 1$, is +/// transformed into the evaluations of this polynomial at each of the $n$ +/// distinct powers of $\omega$. This transformation is invertible by providing +/// $\omega^{-1}$ in place of $\omega$ and dividing each resulting field element +/// by $n$. +/// +/// This will use multithreading if beneficial. +pub fn best_group_fft(a: &mut [G], omega: G::Scalar, log_n: u32) +where + G: Group, + G::Scalar: PrimeField, +{ + let threads = multicore::current_num_threads(); + let log_split = log2_floor(threads) as usize; + let n = a.len() as usize; + let sub_n = n >> log_split; + let split_m = 1 << log_split; + + if sub_n < split_m { + serial_fft(a, omega, log_n); + } else { + parallel_group_fft(a, omega, log_n); + } +} + +fn serial_fft(a: &mut [G], omega: G::Scalar, log_n: u32) +where + G: Group, + G::Scalar: PrimeField, +{ + let n = a.len() as u32; + assert_eq!(n, 1 << log_n); + + for k in 0..n as usize { + let rk = bitreverse(k, log_n as usize); + if k < rk { + a.swap(rk as usize, k as usize); + } + } + + let mut m = 1; + for _ in 0..log_n { + let w_m = omega.pow_vartime(&[u64::from(n / (2 * m)), 0, 0, 0]); + + let mut k = 0; + while k < n { + let mut w = G::Scalar::ONE; + for j in 0..m { + let mut t = a[(k + j + m) as usize]; + t.mul_assign(&w); + a[(k + j + m) as usize] = a[(k + j) as usize]; + a[(k + j + m) as usize].sub_assign(&t); + a[(k + j) as usize].add_assign(&t); + w *= &w_m; + } + + k += 2 * m; + } + + m *= 2; + } +} + +fn serial_split_fft(a: &mut [G], twiddle_lut: &[G::Scalar], twiddle_scale: usize, log_n: u32) +where + G: Group, + G::Scalar: PrimeField, +{ + let n = a.len() as u32; + assert_eq!(n, 1 << log_n); + + let mut m = 1; + for _ in 0..log_n { + let omega_idx = twiddle_scale * n as usize / (2 * m as usize); // 1/2, 1/4, 1/8, ... + let low_idx = omega_idx % (1 << SPARSE_TWIDDLE_DEGREE); + let high_idx = omega_idx >> SPARSE_TWIDDLE_DEGREE; + let mut w_m = twiddle_lut[low_idx]; + if high_idx > 0 { + w_m = w_m * twiddle_lut[(1 << SPARSE_TWIDDLE_DEGREE) + high_idx]; + } + + let mut k = 0; + while k < n { + let mut w = G::Scalar::ONE; + for j in 0..m { + let mut t = a[(k + j + m) as usize]; + t.mul_assign(&w); + a[(k + j + m) as usize] = a[(k + j) as usize]; + a[(k + j + m) as usize].sub_assign(&t); + a[(k + j) as usize].add_assign(&t); + w *= &w_m; + } + + k += 2 * m; + } + + m *= 2; + } +} + +fn split_radix_fft( + tmp: &mut [G], + a: &[G], + twiddle_lut: &[G::Scalar], + n: usize, + sub_fft_offset: usize, + log_split: usize, +) where + G: Group, + G::Scalar: PrimeField, +{ + let split_m = 1 << log_split; + let sub_n = n >> log_split; + + // we use out-place bitreverse here, split_m <= num_threads, so the buffer spase is small + // and it's is good for data locality + let mut t1 = vec![G::identity(); split_m]; + // if unsafe code is allowed, a 10% performance improvement can be achieved + // let mut t1: Vec = Vec::with_capacity(split_m as usize); + // unsafe{ t1.set_len(split_m as usize); } + for i in 0..split_m { + t1[bitreverse(i, log_split)] = a[(i * sub_n + sub_fft_offset)]; + } + serial_split_fft(&mut t1, twiddle_lut, sub_n, log_split as u32); + + let sparse_degree = SPARSE_TWIDDLE_DEGREE; + let omega_idx = sub_fft_offset as usize; + let low_idx = omega_idx % (1 << sparse_degree); + let high_idx = omega_idx >> sparse_degree; + let mut omega = twiddle_lut[low_idx]; + if high_idx > 0 { + omega = omega * twiddle_lut[(1 << sparse_degree) + high_idx]; + } + let mut w_m = G::Scalar::ONE; + for i in 0..split_m { + t1[i].mul_assign(&w_m); + tmp[i] = t1[i]; + w_m = w_m * omega; + } +} + +pub fn generate_twiddle_lookup_table( + omega: F, + log_n: u32, + sparse_degree: u32, + with_last_level: bool, +) -> Vec { + let without_last_level = !with_last_level; + let is_lut_len_large = sparse_degree > log_n; + + // dense + if is_lut_len_large { + let mut twiddle_lut = vec![F::ZERO; (1 << log_n) as usize]; + parallelize(&mut twiddle_lut, |twiddle_lut, start| { + let mut w_n = omega.pow_vartime(&[start as u64, 0, 0, 0]); + for twiddle_lut in twiddle_lut.iter_mut() { + *twiddle_lut = w_n; + w_n = w_n * omega; + } + }); + return twiddle_lut; + } + + // sparse + let low_degree_lut_len = 1 << sparse_degree; + let high_degree_lut_len = 1 << (log_n - sparse_degree - without_last_level as u32); + let mut twiddle_lut = vec![F::ZERO; (low_degree_lut_len + high_degree_lut_len) as usize]; + parallelize( + &mut twiddle_lut[..low_degree_lut_len], + |twiddle_lut, start| { + let mut w_n = omega.pow_vartime(&[start as u64, 0, 0, 0]); + for twiddle_lut in twiddle_lut.iter_mut() { + *twiddle_lut = w_n; + w_n = w_n * omega; + } + }, + ); + let high_degree_omega = omega.pow_vartime(&[(1 << sparse_degree) as u64, 0, 0, 0]); + parallelize( + &mut twiddle_lut[low_degree_lut_len..], + |twiddle_lut, start| { + let mut w_n = high_degree_omega.pow_vartime(&[start as u64, 0, 0, 0]); + for twiddle_lut in twiddle_lut.iter_mut() { + *twiddle_lut = w_n; + w_n = w_n * high_degree_omega; + } + }, + ); + twiddle_lut +} + +pub fn parallel_group_fft(a: &mut [G], omega: G::Scalar, log_n: u32) +where + G: Group, + G::Scalar: PrimeField, +{ + let n = a.len() as usize; + assert_eq!(n, 1 << log_n); + + let log_split = log2_floor(multicore::current_num_threads()) as usize; + let split_m = 1 << log_split; + let sub_n = n >> log_split as usize; + let twiddle_lut = generate_twiddle_lookup_table(omega, log_n, SPARSE_TWIDDLE_DEGREE, true); + + // split fft + let mut tmp = vec![G::identity(); n]; + // if unsafe code is allowed, a 10% performance improvement can be achieved + // let mut tmp: Vec = Vec::with_capacity(n); + // unsafe{ tmp.set_len(n); } + multicore::scope(|scope| { + let a = &*a; + let twiddle_lut = &*twiddle_lut; + for (chunk_idx, tmp) in tmp.chunks_mut(sub_n).enumerate() { + scope.spawn(move |_| { + let split_fft_offset = chunk_idx * sub_n >> log_split; + for (i, tmp) in tmp.chunks_mut(split_m).enumerate() { + let split_fft_offset = split_fft_offset + i; + split_radix_fft(tmp, a, twiddle_lut, n, split_fft_offset, log_split); + } + }); + } + }); + + // shuffle + parallelize(a, |a, start| { + for (idx, a) in a.iter_mut().enumerate() { + let idx = start + idx; + let i = idx / sub_n; + let j = idx % sub_n; + *a = tmp[j * split_m + i]; + } + }); + + // sub fft + let new_omega = omega.pow_vartime(&[split_m as u64, 0, 0, 0]); + multicore::scope(|scope| { + for a in a.chunks_mut(sub_n) { + scope.spawn(move |_| { + serial_fft(a, new_omega, log_n - log_split as u32); + }); + } + }); + + // copy & unshuffle + let mask = (1 << log_split) - 1; + parallelize(&mut tmp, |tmp, start| { + for (idx, tmp) in tmp.iter_mut().enumerate() { + let idx = start + idx; + *tmp = a[idx]; + } + }); + parallelize(a, |a, start| { + for (idx, a) in a.iter_mut().enumerate() { + let idx = start + idx; + *a = tmp[sub_n * (idx & mask) + (idx >> log_split)]; + } + }); +} + +/// Convert coefficient bases group elements to lagrange basis by inverse FFT. +pub fn g_to_lagrange(g_projective: Vec, k: u32) -> Vec { + let n_inv = C::Scalar::TWO_INV.pow_vartime(&[k as u64, 0, 0, 0]); + let mut omega_inv = C::Scalar::ROOT_OF_UNITY_INV; + for _ in k..C::Scalar::S { + omega_inv = omega_inv.square(); + } + + let mut g_lagrange_projective = g_projective; + best_group_fft(&mut g_lagrange_projective, omega_inv, k); + parallelize(&mut g_lagrange_projective, |g, _| { + for g in g.iter_mut() { + *g *= n_inv; + } + }); + + let mut g_lagrange = vec![C::identity(); 1 << k]; + parallelize(&mut g_lagrange, |g_lagrange, starts| { + C::Curve::batch_normalize( + &g_lagrange_projective[starts..(starts + g_lagrange.len())], + g_lagrange, + ); + }); + + g_lagrange +} diff --git a/halo2_proofs/src/arithmetic/multi_exp.rs b/halo2_proofs/src/arithmetic/multi_exp.rs new file mode 100644 index 0000000000..f2967ce712 --- /dev/null +++ b/halo2_proofs/src/arithmetic/multi_exp.rs @@ -0,0 +1,156 @@ +use super::multicore; +pub use ff::Field; +use group::{ + ff::{BatchInvert, PrimeField}, + Curve, Group, +}; + +pub use halo2curves::{CurveAffine, CurveExt}; + +fn multiexp_serial(coeffs: &[C::Scalar], bases: &[C], acc: &mut C::Curve) { + let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect(); + + let c = if bases.len() < 4 { + 1 + } else if bases.len() < 32 { + 3 + } else { + (f64::from(bases.len() as u32)).ln().ceil() as usize + }; + + fn get_at(segment: usize, c: usize, bytes: &F::Repr) -> usize { + let skip_bits = segment * c; + let skip_bytes = skip_bits / 8; + + if skip_bytes >= 32 { + return 0; + } + + let mut v = [0; 8]; + for (v, o) in v.iter_mut().zip(bytes.as_ref()[skip_bytes..].iter()) { + *v = *o; + } + + let mut tmp = u64::from_le_bytes(v); + tmp >>= skip_bits - (skip_bytes * 8); + tmp = tmp % (1 << c); + + tmp as usize + } + + let segments = (256 / c) + 1; + + for current_segment in (0..segments).rev() { + for _ in 0..c { + *acc = acc.double(); + } + + #[derive(Clone, Copy)] + enum Bucket { + None, + Affine(C), + Projective(C::Curve), + } + + impl Bucket { + fn add_assign(&mut self, other: &C) { + *self = match *self { + Bucket::None => Bucket::Affine(*other), + Bucket::Affine(a) => Bucket::Projective(a + *other), + Bucket::Projective(mut a) => { + a += *other; + Bucket::Projective(a) + } + } + } + + fn add(self, mut other: C::Curve) -> C::Curve { + match self { + Bucket::None => other, + Bucket::Affine(a) => { + other += a; + other + } + Bucket::Projective(a) => other + &a, + } + } + } + + let mut buckets: Vec> = vec![Bucket::None; (1 << c) - 1]; + + for (coeff, base) in coeffs.iter().zip(bases.iter()) { + let coeff = get_at::(current_segment, c, coeff); + if coeff != 0 { + buckets[coeff - 1].add_assign(base); + } + } + + // Summation by parts + // e.g. 3a + 2b + 1c = a + + // (a) + b + + // ((a) + b) + c + let mut running_sum = C::Curve::identity(); + for exp in buckets.into_iter().rev() { + running_sum = exp.add(running_sum); + *acc = *acc + &running_sum; + } + } +} + +/// Performs a small multi-exponentiation operation. +/// Uses the double-and-add algorithm with doublings shared across points. +pub fn small_multiexp(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve { + let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect(); + let mut acc = C::Curve::identity(); + + // for byte idx + for byte_idx in (0..32).rev() { + // for bit idx + for bit_idx in (0..8).rev() { + acc = acc.double(); + // for each coeff + for coeff_idx in 0..coeffs.len() { + let byte = coeffs[coeff_idx].as_ref()[byte_idx]; + if ((byte >> bit_idx) & 1) != 0 { + acc += bases[coeff_idx]; + } + } + } + } + + acc +} + +/// Performs a multi-exponentiation operation. +/// +/// This function will panic if coeffs and bases have a different length. +/// +/// This will use multithreading if beneficial. +pub fn best_multiexp(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve { + assert_eq!(coeffs.len(), bases.len()); + + let num_threads = multicore::current_num_threads(); + if coeffs.len() > num_threads { + let chunk = coeffs.len() / num_threads; + let num_chunks = coeffs.chunks(chunk).len(); + let mut results = vec![C::Curve::identity(); num_chunks]; + multicore::scope(|scope| { + let chunk = coeffs.len() / num_threads; + + for ((coeffs, bases), acc) in coeffs + .chunks(chunk) + .zip(bases.chunks(chunk)) + .zip(results.iter_mut()) + { + scope.spawn(move |_| { + multiexp_serial(coeffs, bases, acc); + }); + } + }); + results.iter().fold(C::Curve::identity(), |a, b| a + b) + } else { + let mut acc = C::Curve::identity(); + multiexp_serial(coeffs, bases, &mut acc); + acc + } +} diff --git a/halo2_proofs/src/arithmetic/util.rs b/halo2_proofs/src/arithmetic/util.rs new file mode 100644 index 0000000000..c4da0758d5 --- /dev/null +++ b/halo2_proofs/src/arithmetic/util.rs @@ -0,0 +1,83 @@ +use ff::Field; + +use crate::multicore; + +pub(super) fn bitreverse(mut n: usize, l: usize) -> usize { + let mut r = 0; + for _ in 0..l { + r = (r << 1) | (n & 1); + n >>= 1; + } + r +} + +/// This simple utility function will parallelize an operation that is to be +/// performed over a mutable slice. +pub fn parallelize(v: &mut [T], f: F) { + let n = v.len(); + let num_threads = multicore::current_num_threads(); + let mut chunk = (n as usize) / num_threads; + if chunk < num_threads { + chunk = 1; + } + + multicore::scope(|scope| { + for (chunk_num, v) in v.chunks_mut(chunk).enumerate() { + let f = f.clone(); + scope.spawn(move |_| { + let start = chunk_num * chunk; + f(v, start); + }); + } + }); +} + +pub fn generate_twiddle_lookup_table( + omega: F, + log_n: u32, + sparse_degree: u32, + with_last_level: bool, +) -> Vec { + let without_last_level = !with_last_level; + let is_lut_len_large = sparse_degree > log_n; + + // dense + if is_lut_len_large { + let mut twiddle_lut = vec![F::ZERO; (1 << log_n) as usize]; + parallelize(&mut twiddle_lut, |twiddle_lut, start| { + let mut w_n = omega.pow_vartime(&[start as u64, 0, 0, 0]); + for twiddle_lut in twiddle_lut.iter_mut() { + *twiddle_lut = w_n; + w_n = w_n * omega; + } + }); + return twiddle_lut; + } + + // sparse + let low_degree_lut_len = 1 << sparse_degree; + let high_degree_lut_len = 1 << (log_n - sparse_degree - without_last_level as u32); + let mut twiddle_lut = vec![F::ZERO; (low_degree_lut_len + high_degree_lut_len) as usize]; + parallelize( + &mut twiddle_lut[..low_degree_lut_len], + |twiddle_lut, start| { + let mut w_n = omega.pow_vartime(&[start as u64, 0, 0, 0]); + for twiddle_lut in twiddle_lut.iter_mut() { + *twiddle_lut = w_n; + w_n = w_n * omega; + } + }, + ); + let high_degree_omega = omega.pow_vartime(&[(1 << sparse_degree) as u64, 0, 0, 0]); + parallelize( + &mut twiddle_lut[low_degree_lut_len..], + |twiddle_lut, start| { + let mut w_n = high_degree_omega.pow_vartime(&[start as u64, 0, 0, 0]); + for twiddle_lut in twiddle_lut.iter_mut() { + *twiddle_lut = w_n; + w_n = w_n * high_degree_omega; + } + }, + ); + twiddle_lut +} diff --git a/halo2_proofs/src/circuit.rs b/halo2_proofs/src/circuit.rs index 1dc9bd917f..58e988a990 100644 --- a/halo2_proofs/src/circuit.rs +++ b/halo2_proofs/src/circuit.rs @@ -2,13 +2,10 @@ use std::{convert::TryInto, fmt, marker::PhantomData}; -use ff::Field; +use ff::{Field, PrimeField}; -use crate::{ - arithmetic::FieldExt, - plonk::{ - Advice, Any, Assigned, Challenge, Column, Error, Fixed, Instance, Selector, TableColumn, - }, +use crate::plonk::{ + Advice, Any, Assigned, Challenge, Column, Error, Fixed, Instance, Selector, TableColumn, }; mod value; @@ -28,7 +25,7 @@ pub mod layouter; /// The chip also loads any fixed configuration needed at synthesis time /// using its own implementation of `load`, and stores it in [`Chip::Loaded`]. /// This can be accessed via [`Chip::loaded`]. -pub trait Chip: Sized { +pub trait Chip: Sized { /// A type that holds the configuration for this chip, and any other state it may need /// during circuit synthesis, that can be derived during [`Circuit::configure`]. /// diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index 80174a2c51..f658413185 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -503,13 +503,13 @@ impl<'r, 'a, F: Field, CS: Assignment + 'a> TableLayouter #[cfg(test)] mod tests { - use halo2curves::pasta::vesta; - use super::SimpleFloorPlanner; use crate::{ dev::MockProver, plonk::{Advice, Circuit, Column, Error}, }; + use ff::Field; + use halo2curves::pasta::vesta; #[test] fn not_enough_columns_for_constants() { @@ -535,12 +535,7 @@ mod tests { layouter.assign_region( || "assign constant", |mut region| { - region.assign_advice_from_constant( - || "one", - config, - 0, - vesta::Scalar::one(), - ) + region.assign_advice_from_constant(|| "one", config, 0, vesta::Scalar::ONE) }, )?; diff --git a/halo2_proofs/src/circuit/floor_planner/v1.rs b/halo2_proofs/src/circuit/floor_planner/v1.rs index dbe0a71dc1..1b41839923 100644 --- a/halo2_proofs/src/circuit/floor_planner/v1.rs +++ b/halo2_proofs/src/circuit/floor_planner/v1.rs @@ -518,12 +518,12 @@ impl<'r, 'a, F: Field, CS: Assignment + 'a> RegionLayouter for V1Region<'r #[cfg(test)] mod tests { - use halo2curves::pasta::vesta; - use crate::{ dev::MockProver, plonk::{Advice, Circuit, Column, Error}, }; + use ff::Field; + use halo2curves::pasta::vesta; #[test] fn not_enough_columns_for_constants() { @@ -549,12 +549,7 @@ mod tests { layouter.assign_region( || "assign constant", |mut region| { - region.assign_advice_from_constant( - || "one", - config, - 0, - vesta::Scalar::one(), - ) + region.assign_advice_from_constant(|| "one", config, 0, vesta::Scalar::ONE) }, )?; diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index cdd1c450b4..c8b8656aef 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -9,13 +9,16 @@ use std::time::{Duration, Instant}; use blake2b_simd::blake2b; use ff::Field; +use ff::FromUniformBytes; +use ff::PrimeField; +use ff::WithSmallOrderMulGroup; +use group::Group; use crate::plonk::permutation::keygen::Assembly; use crate::plonk::sealed::SealedPhase; use crate::plonk::FirstPhase; use crate::plonk::ThirdPhase; use crate::{ - arithmetic::{FieldExt, Group}, circuit, plonk::{ permutation, Advice, Any, Assigned, Assignment, Challenge, Circuit, Column, ColumnType, @@ -91,7 +94,7 @@ impl Region { /// The value of a particular cell within the circuit. #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum CellValue { +pub enum CellValue + Field> { /// An unassigned cell. Unassigned, /// A cell that has been assigned a value. @@ -102,23 +105,23 @@ pub enum CellValue { /// A value within an expression. #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)] -enum Value { +enum Value> { Real(F), Poison, } -impl From> for Value { +impl + Field> From> for Value { fn from(value: CellValue) -> Self { match value { // Cells that haven't been explicitly assigned to, default to zero. - CellValue::Unassigned => Value::Real(F::zero()), + CellValue::Unassigned => Value::Real(F::ZERO), CellValue::Assigned(v) => Value::Real(v), CellValue::Poison(_) => Value::Poison, } } } -impl Neg for Value { +impl + Field> Neg for Value { type Output = Self; fn neg(self) -> Self::Output { @@ -129,7 +132,7 @@ impl Neg for Value { } } -impl Add for Value { +impl + Field> Add for Value { type Output = Self; fn add(self, rhs: Self) -> Self::Output { @@ -140,7 +143,7 @@ impl Add for Value { } } -impl Mul for Value { +impl + Field> Mul for Value { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { @@ -151,14 +154,14 @@ impl Mul for Value { (Value::Real(x), Value::Poison) | (Value::Poison, Value::Real(x)) if x.is_zero_vartime() => { - Value::Real(F::zero()) + Value::Real(F::ZERO) } _ => Value::Poison, } } } -impl Mul for Value { +impl + Field> Mul for Value { type Output = Self; fn mul(self, rhs: F) -> Self::Output { @@ -166,7 +169,7 @@ impl Mul for Value { Value::Real(lhs) => Value::Real(lhs * rhs), // If poison is multiplied by zero, then we treat the poison as unconstrained // and we don't propagate it. - Value::Poison if rhs.is_zero_vartime() => Value::Real(F::zero()), + Value::Poison if rhs.is_zero_vartime() => Value::Real(F::ZERO), _ => Value::Poison, } } @@ -184,12 +187,12 @@ impl Mul for Value { /// /// ``` /// use halo2_proofs::{ -/// arithmetic::FieldExt, /// circuit::{Layouter, SimpleFloorPlanner, Value}, /// dev::{FailureLocation, MockProver, VerifyFailure}, /// plonk::{Advice, Any, Circuit, Column, ConstraintSystem, Error, Selector}, /// poly::Rotation, /// }; +/// use ff::PrimeField; /// use halo2curves::pasta::Fp; /// const K: u32 = 5; /// @@ -207,7 +210,7 @@ impl Mul for Value { /// b: Value, /// } /// -/// impl Circuit for MyCircuit { +/// impl Circuit for MyCircuit { /// type Config = MyConfig; /// type FloorPlanner = SimpleFloorPlanner; /// @@ -286,7 +289,7 @@ impl Mul for Value { /// )); /// ``` #[derive(Debug)] -pub struct MockProver { +pub struct MockProver + Field> { k: u32, n: u32, cs: ConstraintSystem, @@ -301,7 +304,7 @@ pub struct MockProver { fixed: Vec>>, // The advice cells in the circuit, arranged as [column][row]. pub(crate) advice: Vec>>, - advice_prev: Vec>>, + _advice_prev: Vec>>, // The instance cells in the circuit, arranged as [column][row]. instance: Vec>, @@ -317,7 +320,7 @@ pub struct MockProver { current_phase: crate::plonk::sealed::Phase, } -impl Assignment for MockProver { +impl> Assignment for MockProver { fn enter_region(&mut self, name: N) where NR: Into, @@ -536,7 +539,7 @@ impl Assignment for MockProver { } } -impl MockProver { +impl + FromUniformBytes<64> + Ord> MockProver { /// Runs a synthetic keygen-and-prove operation on the given circuit, collecting data /// about the constraints and their assignments. pub fn run>( @@ -565,7 +568,7 @@ impl MockProver { return Err(Error::InstanceTooLarge); } - instance.resize(n, F::zero()); + instance.resize(n, F::ZERO); Ok(instance) }) .collect::, _>>()?; @@ -595,7 +598,7 @@ impl MockProver { let mut hash: [u8; 64] = blake2b(b"Halo2-MockProver").as_bytes().try_into().unwrap(); iter::repeat_with(|| { hash = blake2b(&hash).as_bytes().try_into().unwrap(); - F::from_bytes_wide(&hash) + F::from_uniform_bytes(&hash) }) .take(cs.num_challenges) .collect() @@ -616,7 +619,7 @@ impl MockProver { current_region: None, fixed: fixed.clone(), advice: advice.clone(), - advice_prev: last_advice.clone(), + _advice_prev: last_advice.clone(), instance: instance.clone(), selectors: selectors.clone(), challenges: cur_challenges.clone(), @@ -666,7 +669,7 @@ impl MockProver { current_region: None, fixed, advice, - advice_prev: vec![], + _advice_prev: vec![], instance, selectors, challenges: challenges.clone(), @@ -802,7 +805,7 @@ impl MockProver { &|a, b| a + b, &|a, b| a * b, &|a, scalar| a * scalar, - &Value::Real(F::zero()), + &Value::Real(F::ZERO), ) { Value::Real(x) if x.is_zero_vartime() => None, Value::Real(_) => Some(VerifyFailure::ConstraintNotSatisfied { @@ -887,7 +890,7 @@ impl MockProver { &|a, b| a + b, &|a, b| a * b, &|a, scalar| a * scalar, - &Value::Real(F::zero()), + &Value::Real(F::ZERO), ) }; @@ -1175,7 +1178,7 @@ impl MockProver { &|a, b| a + b, &|a, b| a * b, &|a, scalar| a * scalar, - &Value::Real(F::zero()), + &Value::Real(F::ZERO), ) { Value::Real(x) if x.is_zero_vartime() => None, Value::Real(_) => Some(VerifyFailure::ConstraintNotSatisfied { @@ -1253,7 +1256,7 @@ impl MockProver { &|a, b| a + b, &|a, b| a * b, &|a, scalar| a * scalar, - &Value::Real(F::zero()), + &Value::Real(F::ZERO), ) }; diff --git a/halo2_proofs/src/dev/failure.rs b/halo2_proofs/src/dev/failure.rs index d5a68c09d8..e90b42f29f 100644 --- a/halo2_proofs/src/dev/failure.rs +++ b/halo2_proofs/src/dev/failure.rs @@ -1,8 +1,8 @@ use std::collections::{BTreeMap, HashSet}; use std::fmt::{self, Debug}; +use ff::{PrimeField, WithSmallOrderMulGroup}; use group::ff::Field; -use halo2curves::FieldExt; use super::metadata::{DebugColumn, DebugVirtualCell}; use super::MockProver; @@ -444,7 +444,7 @@ fn render_constraint_not_satisfied( /// | x0 = 0x5 /// | x1 = 1 /// ``` -fn render_lookup( +fn render_lookup>( prover: &MockProver, name: &str, lookup_index: usize, @@ -510,7 +510,7 @@ fn render_lookup( ) }); - fn cell_value<'a, F: FieldExt, Q: Into + Copy>( + fn cell_value<'a, F: PrimeField + WithSmallOrderMulGroup<3>, Q: Into + Copy>( load: impl Fn(Q) -> Value + 'a, ) -> impl Fn(Q) -> BTreeMap + 'a { move |query| { @@ -614,7 +614,7 @@ fn render_lookup( impl VerifyFailure { /// Emits this failure in pretty-printed format to stderr. - pub(super) fn emit(&self, prover: &MockProver) { + pub(super) fn emit>(&self, prover: &MockProver) { match self { Self::CellNotAssigned { gate, diff --git a/halo2_proofs/src/dev/util.rs b/halo2_proofs/src/dev/util.rs index a4dbfe5a40..3200844bdb 100644 --- a/halo2_proofs/src/dev/util.rs +++ b/halo2_proofs/src/dev/util.rs @@ -1,7 +1,8 @@ use std::collections::BTreeMap; +use ff::PrimeField; +use ff::WithSmallOrderMulGroup; use group::ff::Field; -use halo2curves::FieldExt; use super::{metadata, CellValue, Value}; use crate::{ @@ -59,9 +60,9 @@ impl From for AnyQuery { pub(super) fn format_value(v: F) -> String { if v.is_zero_vartime() { "0".into() - } else if v == F::one() { + } else if v == F::ONE { "1".into() - } else if v == -F::one() { + } else if v == -F::ONE { "-1".into() } else { // Format value as hex. @@ -73,7 +74,12 @@ pub(super) fn format_value(v: F) -> String { } } -pub(super) fn load<'a, F: FieldExt, T: ColumnType, Q: Into + Copy>( +pub(super) fn load< + 'a, + F: PrimeField + WithSmallOrderMulGroup<3>, + T: ColumnType, + Q: Into + Copy, +>( n: i32, row: i32, queries: &'a [(Column, Rotation)], @@ -86,7 +92,12 @@ pub(super) fn load<'a, F: FieldExt, T: ColumnType, Q: Into + Copy>( } } -pub(super) fn load_instance<'a, F: FieldExt, T: ColumnType, Q: Into + Copy>( +pub(super) fn load_instance< + 'a, + F: PrimeField + WithSmallOrderMulGroup<3>, + T: ColumnType, + Q: Into + Copy, +>( n: i32, row: i32, queries: &'a [(Column, Rotation)], @@ -99,7 +110,7 @@ pub(super) fn load_instance<'a, F: FieldExt, T: ColumnType, Q: Into + } } -fn cell_value<'a, F: FieldExt, Q: Into + Copy>( +fn cell_value<'a, F: PrimeField + WithSmallOrderMulGroup<3>, Q: Into + Copy>( virtual_cells: &'a [VirtualCell], load: impl Fn(Q) -> Value + 'a, ) -> impl Fn(Q) -> BTreeMap + 'a { @@ -132,7 +143,7 @@ fn cell_value<'a, F: FieldExt, Q: Into + Copy>( } } -pub(super) fn cell_values<'a, F: FieldExt>( +pub(super) fn cell_values<'a, F: PrimeField + WithSmallOrderMulGroup<3>>( gate: &Gate, poly: &Expression, load_fixed: impl Fn(FixedQuery) -> Value + 'a, diff --git a/halo2_proofs/src/helpers.rs b/halo2_proofs/src/helpers.rs index a7aa62de69..7d549556b1 100644 --- a/halo2_proofs/src/helpers.rs +++ b/halo2_proofs/src/helpers.rs @@ -1,7 +1,7 @@ use crate::poly::Polynomial; use ff::Field; +use ff::FromUniformBytes; use ff::PrimeField; -use halo2curves::FieldExt; use halo2curves::{pairing::Engine, serde::SerdeObject, CurveAffine}; use num_bigint::BigUint; use std::io; @@ -34,25 +34,27 @@ pub(crate) trait CurveRead: CurveAffine { } impl CurveRead for C {} - -pub fn field_to_bn(f: &F) -> BigUint { +pub fn field_to_bn(f: &F) -> BigUint { BigUint::from_bytes_le(f.to_repr().as_ref()) } /// Input a big integer `bn`, compute a field element `f` /// such that `f == bn % F::MODULUS`. -pub fn bn_to_field(bn: &BigUint) -> F { +pub fn bn_to_field>(bn: &BigUint) -> F { let mut buf = bn.to_bytes_le(); buf.resize(64, 0u8); let mut buf_array = [0u8; 64]; buf_array.copy_from_slice(buf.as_ref()); - F::from_bytes_wide(&buf_array) + F::from_uniform_bytes(&buf_array) } /// Input a base field element `b`, output a scalar field /// element `s` s.t. `s == b % ScalarField::MODULUS` -pub(crate) fn base_to_scalar(base: &C::Base) -> C::Scalar { +pub(crate) fn base_to_scalar(base: &C::Base) -> C::Scalar +where + C::ScalarExt: FromUniformBytes<64>, +{ let bn = field_to_bn(base); // bn_to_field will perform a mod reduction bn_to_field(&bn) diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index 27134602b3..4e584b98a3 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -6,11 +6,12 @@ //! [plonk]: https://eprint.iacr.org/2019/953 use blake2b_simd::Params as Blake2bParams; -use ff::PrimeField; +use ff::{FromUniformBytes, PrimeField}; use group::ff::Field; use halo2curves::pairing::Engine; +use halo2curves::CurveAffineExt; -use crate::arithmetic::{CurveAffine, FieldExt}; +use crate::arithmetic::CurveAffine; use crate::helpers::{ polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice, SerdeCurveAffine, SerdePrimeField, @@ -61,7 +62,7 @@ pub struct VerifyingKey { impl VerifyingKey where - C::Scalar: SerdePrimeField, + C::Scalar: SerdePrimeField + FromUniformBytes<64>, { /// Writes a verifying key to a buffer. /// @@ -117,7 +118,6 @@ where let permutation = permutation::VerifyingKey::read(reader, &cs.permutation, format)?; - // read selectors let selectors: Vec> = vec![vec![false; 1 << k]; cs.num_selectors] .into_iter() @@ -131,7 +131,7 @@ where }) .collect::>()?; let (cs, _) = cs.compress_selectors(selectors.clone()); - + Ok(Self::from_parts( domain, fixed_commitments, @@ -157,18 +157,21 @@ where } } -impl VerifyingKey { +impl VerifyingKey +where + C::Scalar: FromUniformBytes<64>, +{ fn bytes_length(&self) -> usize { 8 + (self.fixed_commitments.len() * C::default().to_bytes().as_ref().len()) + self.permutation.bytes_length() - /* - + self.selectors.len() - * (self - .selectors - .get(0) - .map(|selector| selector.len() / 8 + 1) - .unwrap_or(0)) - */ + /* + + self.selectors.len() + * (self + .selectors + .get(0) + .map(|selector| selector.len() / 8 + 1) + .unwrap_or(0)) + */ } fn from_parts( @@ -188,7 +191,7 @@ impl VerifyingKey { cs, cs_degree, // Temporary, this is not pinned. - transcript_repr: C::Scalar::zero(), + transcript_repr: C::Scalar::ZERO, selectors, }; @@ -203,7 +206,7 @@ impl VerifyingKey { hasher.update(s.as_bytes()); // Hash in final Blake2bState - vk.transcript_repr = C::Scalar::from_bytes_wide(hasher.finalize().as_array()); + vk.transcript_repr = C::Scalar::from_uniform_bytes(hasher.finalize().as_array()); vk } @@ -274,7 +277,10 @@ pub struct ProvingKey { ev: Evaluator, } -impl ProvingKey { +impl ProvingKey +where + C::Scalar: FromUniformBytes<64>, +{ /// Get the underlying [`VerifyingKey`]. pub fn get_vk(&self) -> &VerifyingKey { &self.vk @@ -295,7 +301,7 @@ impl ProvingKey { impl ProvingKey where - C::Scalar: SerdePrimeField, + C::Scalar: SerdePrimeField + FromUniformBytes<64>, { /// Writes a proving key to a buffer. /// diff --git a/halo2_proofs/src/plonk/assigned.rs b/halo2_proofs/src/plonk/assigned.rs index 7524291e4c..46d527b915 100644 --- a/halo2_proofs/src/plonk/assigned.rs +++ b/halo2_proofs/src/plonk/assigned.rs @@ -280,7 +280,7 @@ impl Assigned { /// Returns the numerator. pub fn numerator(&self) -> F { match self { - Self::Zero => F::zero(), + Self::Zero => F::ZERO, Self::Trivial(x) => *x, Self::Rational(numerator, _) => *numerator, } @@ -341,7 +341,7 @@ impl Assigned { pub fn invert(&self) -> Self { match self { Self::Zero => Self::Zero, - Self::Trivial(x) => Self::Rational(F::one(), *x), + Self::Trivial(x) => Self::Rational(F::ONE, *x), Self::Rational(numerator, denominator) => Self::Rational(*denominator, *numerator), } } @@ -352,13 +352,13 @@ impl Assigned { /// If the denominator is zero, this returns zero. pub fn evaluate(self) -> F { match self { - Self::Zero => F::zero(), + Self::Zero => F::ZERO, Self::Trivial(x) => x, Self::Rational(numerator, denominator) => { - if denominator == F::one() { + if denominator == F::ONE { numerator } else { - numerator * denominator.invert().unwrap_or(F::zero()) + numerator * denominator.invert().unwrap_or(F::ZERO) } } } @@ -451,7 +451,7 @@ mod proptests { }; use group::ff::Field; - use halo2curves::{pasta::Fp, FieldExt}; + use halo2curves::pasta::Fp; use proptest::{collection::vec, prelude::*, sample::select}; use super::Assigned; @@ -477,7 +477,7 @@ mod proptests { } fn inv0(&self) -> Self { - self.invert().unwrap_or(F::zero()) + self.invert().unwrap_or(F::ZERO) } } diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index d591c46cce..9e17d5b5c2 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -348,11 +348,10 @@ impl TryFrom> for Column { /// row when required: /// ``` /// use halo2_proofs::{ -/// arithmetic::FieldExt, /// circuit::{Chip, Layouter, Value}, /// plonk::{Advice, Column, Error, Selector}, /// }; -/// # use ff::Field; +/// use ff::{Field, PrimeField}; /// # use halo2_proofs::plonk::Fixed; /// /// struct Config { @@ -361,12 +360,12 @@ impl TryFrom> for Column { /// s: Selector, /// } /// -/// fn circuit_logic>(chip: C, mut layouter: impl Layouter) -> Result<(), Error> { +/// fn circuit_logic>(chip: C, mut layouter: impl Layouter) -> Result<(), Error> { /// let config = chip.config(); /// # let config: Config = todo!(); /// layouter.assign_region(|| "bar", |mut region| { -/// region.assign_advice(|| "a", config.a, 0, || Value::known(F::one()))?; -/// region.assign_advice(|| "a", config.b, 1, || Value::known(F::one()))?; +/// region.assign_advice(|| "a", config.a, 0, || Value::known(F::ONE))?; +/// region.assign_advice(|| "a", config.b, 1, || Value::known(F::ONE))?; /// config.s.enable(&mut region, 1) /// })?; /// Ok(()) diff --git a/halo2_proofs/src/plonk/circuit/compress_selectors.rs b/halo2_proofs/src/plonk/circuit/compress_selectors.rs index b6807e1163..3de6b4dfc2 100644 --- a/halo2_proofs/src/plonk/circuit/compress_selectors.rs +++ b/halo2_proofs/src/plonk/circuit/compress_selectors.rs @@ -79,7 +79,7 @@ where let combination_assignment = selector .activations .iter() - .map(|b| if *b { F::one() } else { F::zero() }) + .map(|b| if *b { F::ONE } else { F::ZERO }) .collect::>(); let combination_index = combination_assignments.len(); combination_assignments.push(combination_assignment); @@ -177,12 +177,12 @@ where } // Now, compute the selector and combination assignments. - let mut combination_assignment = vec![F::zero(); n]; + let mut combination_assignment = vec![F::ZERO; n]; let combination_len = combination.len(); let combination_index = combination_assignments.len(); let query = allocate_fixed_column(); - let mut assigned_root = F::one(); + let mut assigned_root = F::ONE; selector_assignments.extend(combination.into_iter().map(|selector| { // Compute the expression for substitution. This produces an expression of the // form @@ -192,12 +192,12 @@ where // `assigned_root`. In particular, rows set to 0 correspond to all selectors // being disabled. let mut expression = query.clone(); - let mut root = F::one(); + let mut root = F::ONE; for _ in 0..combination_len { if root != assigned_root { expression = expression * (Expression::Constant(root) - query.clone()); } - root += F::one(); + root += F::ONE; } // Update the combination assignment @@ -212,7 +212,7 @@ where } } - assigned_root += F::one(); + assigned_root += F::ONE; SelectorAssignment { selector: selector.selector, diff --git a/halo2_proofs/src/plonk/evaluation.rs b/halo2_proofs/src/plonk/evaluation.rs index c9c9a5cbf1..00e9981202 100644 --- a/halo2_proofs/src/plonk/evaluation.rs +++ b/halo2_proofs/src/plonk/evaluation.rs @@ -4,13 +4,15 @@ use crate::plonk::permutation::Argument; use crate::plonk::{lookup, permutation, AdviceQuery, Any, FixedQuery, InstanceQuery, ProvingKey}; use crate::poly::Basis; use crate::{ - arithmetic::{eval_polynomial, parallelize, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, parallelize, CurveAffine}, poly::{ commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, ProverQuery, Rotation, }, transcript::{EncodedChallenge, TranscriptWrite}, }; +use ff::PrimeField; +use ff::WithSmallOrderMulGroup; use group::prime::PrimeCurve; use group::{ ff::{BatchInvert, Field}, @@ -296,7 +298,7 @@ impl Evaluator { let extended_omega = domain.get_extended_omega(); let omega = domain.get_omega(); let isize = size as i32; - let one = C::ScalarExt::one(); + let one = C::ScalarExt::ONE; let p = &pk.vk.cs.permutation; let num_parts = domain.extended_len() >> domain.k(); @@ -527,7 +529,7 @@ impl Evaluator { &gamma, &theta, &y, - &C::ScalarExt::zero(), + &C::ScalarExt::ZERO, idx, rot_scale, isize, @@ -587,8 +589,8 @@ impl Default for GraphEvaluator { Self { // Fixed positions to allow easy access constants: vec![ - C::ScalarExt::zero(), - C::ScalarExt::one(), + C::ScalarExt::ZERO, + C::ScalarExt::ONE, C::ScalarExt::from(2u64), ], rotations: Vec::new(), @@ -736,9 +738,9 @@ impl GraphEvaluator { } } Expression::Scaled(a, f) => { - if *f == C::ScalarExt::zero() { + if *f == C::ScalarExt::ZERO { ValueSource::Constant(0) - } else if *f == C::ScalarExt::one() { + } else if *f == C::ScalarExt::ONE { self.add_expression(a) } else { let cst = self.add_constant(f); @@ -752,7 +754,7 @@ impl GraphEvaluator { /// Creates a new evaluation structure pub fn instance(&self) -> EvaluationData { EvaluationData { - intermediates: vec![C::ScalarExt::zero(); self.num_intermediates], + intermediates: vec![C::ScalarExt::ZERO; self.num_intermediates], rotations: vec![0usize; self.rotations.len()], } } @@ -800,13 +802,13 @@ impl GraphEvaluator { if let Some(calc) = self.calculations.last() { data.intermediates[calc.target] } else { - C::ScalarExt::zero() + C::ScalarExt::ZERO } } } /// Simple evaluation of an expression -pub fn evaluate( +pub fn evaluate( expression: &Expression, size: usize, rot_scale: i32, @@ -815,7 +817,7 @@ pub fn evaluate( instance: &[Polynomial], challenges: &[F], ) -> Vec { - let mut values = vec![F::zero(); size]; + let mut values = vec![F::ZERO; size]; let isize = size as i32; parallelize(&mut values, |values, start| { for (i, value) in values.iter_mut().enumerate() { diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index 527480b60c..ad67668015 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -2,7 +2,7 @@ use std::ops::Range; -use ff::Field; +use ff::{Field, FromUniformBytes}; use group::Curve; use super::{ @@ -206,6 +206,7 @@ pub fn keygen_vk<'params, C, P, ConcreteCircuit>( ) -> Result, Error> where C: CurveAffine, + C::Scalar: FromUniformBytes<64>, P: Params<'params, C>, ConcreteCircuit: Circuit, { @@ -265,6 +266,7 @@ pub fn keygen_pk2<'params, C, P, ConcreteCircuit>( ) -> Result, Error> where C: CurveAffine, + C::Scalar: FromUniformBytes<64>, P: Params<'params, C>, ConcreteCircuit: Circuit, { @@ -279,6 +281,7 @@ pub fn keygen_pk<'params, C, P, ConcreteCircuit>( ) -> Result, Error> where C: CurveAffine, + C::Scalar: FromUniformBytes<64>, P: Params<'params, C>, ConcreteCircuit: Circuit, { @@ -293,6 +296,7 @@ pub fn keygen_pk_impl<'params, C, P, ConcreteCircuit>( ) -> Result, Error> where C: CurveAffine, + C::Scalar: FromUniformBytes<64>, P: Params<'params, C>, ConcreteCircuit: Circuit, { @@ -368,23 +372,23 @@ where // Compute l_0(X) // TODO: this can be done more efficiently let mut l0 = vk.domain.empty_lagrange(); - l0[0] = C::Scalar::one(); + l0[0] = C::Scalar::ONE; let l0 = vk.domain.lagrange_to_coeff(l0); // Compute l_blind(X) which evaluates to 1 for each blinding factor row // and 0 otherwise over the domain. let mut l_blind = vk.domain.empty_lagrange(); for evaluation in l_blind[..].iter_mut().rev().take(cs.blinding_factors()) { - *evaluation = C::Scalar::one(); + *evaluation = C::Scalar::ONE; } // Compute l_last(X) which evaluates to 1 on the first inactive row (just // before the blinding factors) and 0 otherwise over the domain let mut l_last = vk.domain.empty_lagrange(); - l_last[params.n() as usize - cs.blinding_factors() - 1] = C::Scalar::one(); + l_last[params.n() as usize - cs.blinding_factors() - 1] = C::Scalar::ONE; // Compute l_active_row(X) - let one = C::Scalar::one(); + let one = C::Scalar::ONE; let mut l_active_row = vk.domain.empty_lagrange(); parallelize(&mut l_active_row, |values, start| { for (i, value) in values.iter_mut().enumerate() { diff --git a/halo2_proofs/src/plonk/lookup/prover.rs b/halo2_proofs/src/plonk/lookup/prover.rs index f5d87d061e..703fa61a62 100644 --- a/halo2_proofs/src/plonk/lookup/prover.rs +++ b/halo2_proofs/src/plonk/lookup/prover.rs @@ -5,7 +5,7 @@ use super::super::{ use super::Argument; use crate::plonk::evaluation::evaluate; use crate::{ - arithmetic::{eval_polynomial, parallelize, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, parallelize, CurveAffine}, poly::{ commitment::{Blind, Params}, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, ProverQuery, @@ -13,6 +13,8 @@ use crate::{ }, transcript::{EncodedChallenge, TranscriptWrite}, }; +use ff::{PrimeField, WithSmallOrderMulGroup}; +use group::prime::PrimeCurveAffine; use group::{ ff::{BatchInvert, Field}, Curve, @@ -51,7 +53,7 @@ pub(in crate::plonk) struct Evaluated { constructed: Committed, } -impl Argument { +impl> Argument { /// Given a Lookup with input expressions [A_0, A_1, ..., A_{m-1}] and table expressions /// [S_0, S_1, ..., S_{m-1}], this method /// - constructs A_compressed = \theta^{m-1} A_0 + theta^{m-2} A_1 + ... + \theta A_{m-2} + A_{m-1} @@ -191,7 +193,7 @@ impl Permuted { // s_j(X) is the jth table expression in this lookup, // s'(X) is the compression of the permuted table expressions, // and i is the ith row of the expression. - let mut lookup_product = vec![C::Scalar::zero(); params.n() as usize]; + let mut lookup_product = vec![C::Scalar::ZERO; params.n() as usize]; // Denominator uses the permuted input expression and permuted table expression parallelize(&mut lookup_product, |lookup_product, start| { for ((lookup_product, permuted_input_value), permuted_table_value) in lookup_product @@ -234,9 +236,9 @@ impl Permuted { // Compute the evaluations of the lookup product polynomial // over our domain, starting with z[0] = 1 - let z = iter::once(C::Scalar::one()) + let z = iter::once(C::Scalar::ONE) .chain(lookup_product) - .scan(C::Scalar::one(), |state, cur| { + .scan(C::Scalar::ONE, |state, cur| { *state *= &cur; Some(*state) }) @@ -257,7 +259,7 @@ impl Permuted { let u = (params.n() as usize) - (blinding_factors + 1); // l_0(X) * (1 - z(X)) = 0 - assert_eq!(z[0], C::Scalar::one()); + assert_eq!(z[0], C::Scalar::ONE); // z(\omega X) (a'(X) + \beta) (s'(X) + \gamma) // - z(X) (\theta^{m-1} a_0(X) + ... + a_{m-1}(X) + \beta) (\theta^{m-1} s_0(X) + ... + s_{m-1}(X) + \gamma) @@ -284,7 +286,7 @@ impl Permuted { // l_last(X) * (z(X)^2 - z(X)) = 0 // Assertion will fail only when soundness is broken, in which // case this z[u] value will be zero. (bad!) - assert_eq!(z[u], C::Scalar::one()); + assert_eq!(z[u], C::Scalar::ONE); } let product_blind = Blind(C::Scalar::random(rng)); @@ -413,7 +415,7 @@ fn permute_expression_pair<'params, C: CurveAffine, P: Params<'params, C>, R: Rn *acc.entry(*coeff).or_insert(0) += 1; acc }); - let mut permuted_table_coeffs = vec![C::Scalar::zero(); usable_rows]; + let mut permuted_table_coeffs = vec![C::Scalar::ZERO; usable_rows]; let mut repeated_input_rows = permuted_input_expression .iter() diff --git a/halo2_proofs/src/plonk/lookup/verifier.rs b/halo2_proofs/src/plonk/lookup/verifier.rs index add4e592c9..afc99f8127 100644 --- a/halo2_proofs/src/plonk/lookup/verifier.rs +++ b/halo2_proofs/src/plonk/lookup/verifier.rs @@ -5,12 +5,12 @@ use super::super::{ }; use super::Argument; use crate::{ - arithmetic::{CurveAffine, FieldExt}, + arithmetic::CurveAffine, plonk::{Error, VerifyingKey}, poly::{commitment::MSM, Rotation, VerifierQuery}, transcript::{EncodedChallenge, TranscriptRead}, }; -use ff::Field; +use ff::{Field, PrimeField}; #[derive(Debug)] pub struct PermutationCommitments { @@ -34,7 +34,7 @@ pub struct Evaluated { pub permuted_table_eval: C::Scalar, } -impl Argument { +impl Argument { pub fn read_permuted_commitments< C: CurveAffine, E: EncodedChallenge, @@ -104,7 +104,7 @@ impl Evaluated { instance_evals: &[C::Scalar], challenges: &[C::Scalar], ) -> impl Iterator + 'a { - let active_rows = C::Scalar::one() - (l_last + l_blind); + let active_rows = C::Scalar::ONE - (l_last + l_blind); let product_expression = || { // z(\omega X) (a'(X) + \beta) (s'(X) + \gamma) @@ -130,7 +130,7 @@ impl Evaluated { &|a, scalar| a * &scalar, ) }) - .fold(C::Scalar::zero(), |acc, eval| acc * &*theta + &eval) + .fold(C::Scalar::ZERO, |acc, eval| acc * &*theta + &eval) }; let right = self.product_eval * &(compress_expressions(&argument.input_expressions) + &*beta) @@ -142,7 +142,7 @@ impl Evaluated { std::iter::empty() .chain( // l_0(X) * (1 - z'(X)) = 0 - Some(l_0 * &(C::Scalar::one() - &self.product_eval)), + Some(l_0 * &(C::Scalar::ONE - &self.product_eval)), ) .chain( // l_last(X) * (z(X)^2 - z(X)) = 0 diff --git a/halo2_proofs/src/plonk/permutation/keygen.rs b/halo2_proofs/src/plonk/permutation/keygen.rs index c8e3b37f5b..0a541f5164 100644 --- a/halo2_proofs/src/plonk/permutation/keygen.rs +++ b/halo2_proofs/src/plonk/permutation/keygen.rs @@ -3,13 +3,14 @@ use group::Curve; use super::{Argument, ProvingKey, VerifyingKey}; use crate::{ - arithmetic::{parallelize, CurveAffine, FieldExt}, + arithmetic::{parallelize, CurveAffine}, plonk::{Any, Column, Error}, poly::{ commitment::{Blind, CommitmentScheme, Params}, EvaluationDomain, }, }; +use ff::PrimeField; /// Struct that accumulates all the necessary data in order to construct the permutation argument. #[derive(Debug, Clone, PartialEq, Eq)] @@ -109,7 +110,7 @@ impl Assembly { p: &Argument, ) -> VerifyingKey { // Compute [omega^0, omega^1, ..., omega^{params.n - 1}] - let mut omega_powers = vec![C::Scalar::zero(); params.n() as usize]; + let mut omega_powers = vec![C::Scalar::ZERO; params.n() as usize]; { let omega = domain.get_omega(); parallelize(&mut omega_powers, |o, start| { @@ -171,7 +172,7 @@ impl Assembly { p: &Argument, ) -> ProvingKey { // Compute [omega^0, omega^1, ..., omega^{params.n - 1}] - let mut omega_powers = vec![C::Scalar::zero(); params.n() as usize]; + let mut omega_powers = vec![C::Scalar::ZERO; params.n() as usize]; { let omega = domain.get_omega(); parallelize(&mut omega_powers, |o, start| { @@ -235,7 +236,7 @@ impl Assembly { ProvingKey { permutations, - polys, + polys, cosets, } } diff --git a/halo2_proofs/src/plonk/permutation/prover.rs b/halo2_proofs/src/plonk/permutation/prover.rs index 847d2fbd5f..bba2b73688 100644 --- a/halo2_proofs/src/plonk/permutation/prover.rs +++ b/halo2_proofs/src/plonk/permutation/prover.rs @@ -1,3 +1,4 @@ +use ff::PrimeField; use group::{ ff::{BatchInvert, Field}, Curve, @@ -8,7 +9,7 @@ use std::iter::{self, ExactSizeIterator}; use super::super::{circuit::Any, ChallengeBeta, ChallengeGamma, ChallengeX}; use super::{Argument, ProvingKey}; use crate::{ - arithmetic::{eval_polynomial, parallelize, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, parallelize, CurveAffine}, plonk::{self, Error}, poly::{ self, @@ -72,10 +73,10 @@ impl Argument { let blinding_factors = pk.vk.cs.blinding_factors(); // Each column gets its own delta power. - let mut deltaomega = C::Scalar::one(); + let mut deltaomega = C::Scalar::ONE; // Track the "last" value from the previous column set - let mut last_z = C::Scalar::one(); + let mut last_z = C::Scalar::ONE; let mut sets = vec![]; @@ -92,7 +93,7 @@ impl Argument { // where p_j(X) is the jth column in this permutation, // and i is the ith row of the column. - let mut modified_values = vec![C::Scalar::one(); params.n() as usize]; + let mut modified_values = vec![C::Scalar::ONE; params.n() as usize]; // Iterate over each column of the permutation for (&column, permuted_column_values) in columns.iter().zip(permutations.iter()) { diff --git a/halo2_proofs/src/plonk/permutation/verifier.rs b/halo2_proofs/src/plonk/permutation/verifier.rs index b892d1720d..3ee0443f53 100644 --- a/halo2_proofs/src/plonk/permutation/verifier.rs +++ b/halo2_proofs/src/plonk/permutation/verifier.rs @@ -4,11 +4,12 @@ use std::iter; use super::super::{circuit::Any, ChallengeBeta, ChallengeGamma, ChallengeX}; use super::{Argument, VerifyingKey}; use crate::{ - arithmetic::{CurveAffine, FieldExt}, + arithmetic::CurveAffine, plonk::{self, Error}, poly::{commitment::MSM, Rotation, VerifierQuery}, transcript::{EncodedChallenge, TranscriptRead}, }; +use ff::PrimeField; #[derive(Debug)] pub struct Committed { @@ -123,9 +124,9 @@ impl Evaluated { // Enforce only for the first set. // l_0(X) * (1 - z_0(X)) = 0 .chain( - self.sets.first().map(|first_set| { - l_0 * &(C::Scalar::one() - &first_set.permutation_product_eval) - }), + self.sets + .first() + .map(|first_set| l_0 * &(C::Scalar::ONE - &first_set.permutation_product_eval)), ) // Enforce only for the last set. // l_last(X) * (z_l(X)^2 - z_l(X)) = 0 @@ -198,7 +199,7 @@ impl Evaluated { current_delta *= &C::Scalar::DELTA; } - (left - &right) * (C::Scalar::one() - &(l_last + &l_blind)) + (left - &right) * (C::Scalar::ONE - &(l_last + &l_blind)) }), ) } diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index 1f50679772..45e580bbe3 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -1,4 +1,4 @@ -use ff::Field; +use ff::{Field, FromUniformBytes}; use group::Curve; use halo2curves::CurveExt; use rand_core::RngCore; @@ -19,7 +19,7 @@ use super::{ ChallengeY, Error, Expression, ProvingKey, }; use crate::{ - arithmetic::{eval_polynomial, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, CurveAffine}, circuit::Value, plonk::Assigned, poly::{ @@ -53,7 +53,10 @@ pub fn create_proof< instances: &[&[&[Scheme::Scalar]]], mut rng: R, transcript: &mut T, -) -> Result<(), Error> { +) -> Result<(), Error> +where + Scheme::Scalar: FromUniformBytes<64>, +{ for instance in instances.iter() { if instance.len() != pk.vk.cs.num_instance_columns { return Err(Error::InvalidInstances); @@ -309,7 +312,7 @@ pub fn create_proof< }) .collect::>(); - for (circuit_idx, ((circuit, advice), instances)) in circuits + for (_circuit_idx, ((circuit, advice), instances)) in circuits .iter() .zip(advice.iter_mut()) .zip(instances) @@ -376,10 +379,10 @@ pub fn create_proof< for advice_values in &mut advice_values { //for cell in &mut advice_values[unusable_rows_start..] { //*cell = C::Scalar::random(&mut rng); - //*cell = C::Scalar::one(); + //*cell = C::Scalar::ONE; //} let idx = advice_values.len() - 1; - advice_values[idx] = Scheme::Scalar::one(); + advice_values[idx] = Scheme::Scalar::ONE; } // Compute commitments to advice column polynomials diff --git a/halo2_proofs/src/plonk/vanishing/prover.rs b/halo2_proofs/src/plonk/vanishing/prover.rs index aa43a07c0f..d394b8c0de 100644 --- a/halo2_proofs/src/plonk/vanishing/prover.rs +++ b/halo2_proofs/src/plonk/vanishing/prover.rs @@ -6,7 +6,7 @@ use rand_core::RngCore; use super::Argument; use crate::{ - arithmetic::{eval_polynomial, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, CurveAffine}, plonk::{ChallengeX, ChallengeY, Error}, poly::{ self, @@ -50,10 +50,10 @@ impl Argument { transcript: &mut T, ) -> Result, Error> { // Sample a random polynomial of degree n - 1 - let random_poly = domain.constant_lagrange(C::Scalar::one()); + let random_poly = domain.constant_lagrange(C::Scalar::ONE); let random_poly = domain.lagrange_to_coeff(random_poly); // Sample a random blinding factor - let random_blind = Blind(C::Scalar::zero()); + let random_blind = Blind(C::Scalar::ZERO); let c = params.commit(&random_poly, random_blind).to_affine(); // We write the identity point to the transcript which // is the commitment of the zero polynomial. @@ -139,9 +139,7 @@ impl Constructed { .h_blinds .iter() .rev() - .fold(Blind(C::Scalar::zero()), |acc, eval| { - acc * Blind(xn) + *eval - }); + .fold(Blind(C::Scalar::ZERO), |acc, eval| acc * Blind(xn) + *eval); let random_eval = eval_polynomial(&self.committed.random_poly, *x); transcript.write_scalar(random_eval)?; diff --git a/halo2_proofs/src/plonk/vanishing/verifier.rs b/halo2_proofs/src/plonk/vanishing/verifier.rs index 3570dee6c1..0881dfb2c0 100644 --- a/halo2_proofs/src/plonk/vanishing/verifier.rs +++ b/halo2_proofs/src/plonk/vanishing/verifier.rs @@ -94,8 +94,8 @@ impl PartiallyEvaluated { y: ChallengeY, xn: C::Scalar, ) -> Evaluated { - let expected_h_eval = expressions.fold(C::Scalar::zero(), |h_eval, v| h_eval * &*y + &v); - let expected_h_eval = expected_h_eval * ((xn - C::Scalar::one()).invert().unwrap()); + let expected_h_eval = expressions.fold(C::Scalar::ZERO, |h_eval, v| h_eval * &*y + &v); + let expected_h_eval = expected_h_eval * ((xn - C::Scalar::ONE).invert().unwrap()); let h_commitment = self.h_commitments @@ -104,7 +104,7 @@ impl PartiallyEvaluated { .fold(params.empty_msm(), |mut acc, commitment| { acc.scale(xn); let commitment: C::CurveExt = (*commitment).into(); - acc.append_term(C::Scalar::one(), commitment); + acc.append_term(C::Scalar::ONE, commitment); acc }); diff --git a/halo2_proofs/src/plonk/verifier.rs b/halo2_proofs/src/plonk/verifier.rs index e6a2327e7b..32fd638c86 100644 --- a/halo2_proofs/src/plonk/verifier.rs +++ b/halo2_proofs/src/plonk/verifier.rs @@ -1,4 +1,4 @@ -use ff::Field; +use ff::{Field, FromUniformBytes}; use group::Curve; use rand_core::RngCore; use std::iter; @@ -7,7 +7,7 @@ use super::{ vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, ChallengeY, Error, VerifyingKey, }; -use crate::arithmetic::{compute_inner_product, CurveAffine, FieldExt}; +use crate::arithmetic::{compute_inner_product, CurveAffine}; use crate::poly::commitment::{CommitmentScheme, Verifier}; use crate::poly::VerificationStrategy; use crate::poly::{ @@ -37,7 +37,10 @@ pub fn verify_proof< strategy: Strategy, instances: &[&[&[Scheme::Scalar]]], transcript: &mut T, -) -> Result { +) -> Result +where + Scheme::Scalar: FromUniformBytes<64>, +{ // Check that instances matches the expected number of instance columns for instances in instances.iter() { if instances.len() != vk.cs.num_instance_columns { @@ -56,7 +59,7 @@ pub fn verify_proof< return Err(Error::InstanceTooLarge); } let mut poly = instance.to_vec(); - poly.resize(params.n() as usize, Scheme::Scalar::zero()); + poly.resize(params.n() as usize, Scheme::Scalar::ZERO); let poly = vk.domain.lagrange_from_vec(poly); Ok(params.commit_lagrange(&poly, Blind::default()).to_affine()) @@ -94,7 +97,7 @@ pub fn verify_proof< let (advice_commitments, challenges) = { let mut advice_commitments = vec![vec![Scheme::Curve::default(); vk.cs.num_advice_columns]; num_proofs]; - let mut challenges = vec![Scheme::Scalar::zero(); vk.cs.num_challenges]; + let mut challenges = vec![Scheme::Scalar::ZERO; vk.cs.num_challenges]; for current_phase in vk.cs.phases() { for advice_commitments in advice_commitments.iter_mut() { @@ -253,7 +256,7 @@ pub fn verify_proof< let l_last = l_evals[0]; let l_blind: Scheme::Scalar = l_evals[1..(1 + blinding_factors)] .iter() - .fold(Scheme::Scalar::zero(), |acc, eval| acc + eval); + .fold(Scheme::Scalar::ZERO, |acc, eval| acc + eval); let l_0 = l_evals[1 + blinding_factors]; // Compute the expected value of h(x) diff --git a/halo2_proofs/src/plonk/verifier/batch.rs b/halo2_proofs/src/plonk/verifier/batch.rs index f07ba4141f..04e08be4af 100644 --- a/halo2_proofs/src/plonk/verifier/batch.rs +++ b/halo2_proofs/src/plonk/verifier/batch.rs @@ -1,5 +1,6 @@ use std::{io, marker::PhantomData}; +use ff::FromUniformBytes; use group::ff::Field; use halo2curves::CurveAffine; use rand_core::{OsRng, RngCore}; @@ -67,7 +68,10 @@ pub struct BatchVerifier { items: Vec>, } -impl BatchVerifier { +impl BatchVerifier +where + C::Scalar: FromUniformBytes<64>, +{ /// Constructs a new batch verifier. pub fn new() -> Self { Self { items: vec![] } diff --git a/halo2_proofs/src/poly.rs b/halo2_proofs/src/poly.rs index f72bb58e3c..70c99a83a1 100644 --- a/halo2_proofs/src/poly.rs +++ b/halo2_proofs/src/poly.rs @@ -9,7 +9,6 @@ use crate::SerdeFormat; use ff::PrimeField; use group::ff::{BatchInvert, Field}; -use halo2curves::FieldExt; use std::fmt::Debug; use std::io; use std::marker::PhantomData; @@ -177,7 +176,7 @@ impl Polynomial { } } -pub(crate) fn batch_invert_assigned( +pub(crate) fn batch_invert_assigned( assigned: Vec, LagrangeCoeff>>, ) -> Vec> { let mut assigned_denominators: Vec<_> = assigned @@ -202,9 +201,7 @@ pub(crate) fn batch_invert_assigned( assigned .iter() .zip(assigned_denominators.into_iter()) - .map(|(poly, inv_denoms)| { - poly.invert(inv_denoms.into_iter().map(|d| d.unwrap_or_else(F::one))) - }) + .map(|(poly, inv_denoms)| poly.invert(inv_denoms.into_iter().map(|d| d.unwrap_or(F::ONE)))) .collect() } @@ -274,13 +271,13 @@ impl Mul for Polynomial { type Output = Polynomial; fn mul(mut self, rhs: F) -> Polynomial { - if rhs == F::zero() { + if rhs == F::ZERO { return Polynomial { - values: vec![F::zero(); self.len()], + values: vec![F::ZERO; self.len()], _marker: PhantomData, }; } - if rhs == F::one() { + if rhs == F::ONE { return self; } diff --git a/halo2_proofs/src/poly/commitment.rs b/halo2_proofs/src/poly/commitment.rs index e82515cfff..6517df5ec1 100644 --- a/halo2_proofs/src/poly/commitment.rs +++ b/halo2_proofs/src/poly/commitment.rs @@ -5,9 +5,9 @@ use super::{ }; use crate::poly::Error; use crate::transcript::{EncodedChallenge, TranscriptRead, TranscriptWrite}; -use ff::Field; +use ff::{Field, PrimeField, WithSmallOrderMulGroup}; use group::Curve; -use halo2curves::{CurveAffine, CurveExt, FieldExt}; +use halo2curves::{CurveAffine, CurveExt}; use rand_core::RngCore; use std::{ fmt::Debug, @@ -18,7 +18,7 @@ use std::{ /// Defines components of a commitment scheme. pub trait CommitmentScheme { /// Application field of this commitment scheme - type Scalar: FieldExt + halo2curves::Group; + type Scalar: PrimeField + WithSmallOrderMulGroup<3>; /// Elliptic curve used to commit the application and witnesses type Curve: CurveAffine; @@ -192,20 +192,20 @@ pub trait Verifier<'params, Scheme: CommitmentScheme> { #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub struct Blind(pub F); -impl Default for Blind { +impl Default for Blind { fn default() -> Self { - Blind(F::one()) + Blind(F::ONE) } } -impl Blind { +impl Blind { /// Given `rng` creates new blinding scalar pub fn new(rng: &mut R) -> Self { Blind(F::random(rng)) } } -impl Add for Blind { +impl Add for Blind { type Output = Self; fn add(self, rhs: Blind) -> Self { @@ -213,7 +213,7 @@ impl Add for Blind { } } -impl Mul for Blind { +impl Mul for Blind { type Output = Self; fn mul(self, rhs: Blind) -> Self { @@ -221,25 +221,25 @@ impl Mul for Blind { } } -impl AddAssign for Blind { +impl AddAssign for Blind { fn add_assign(&mut self, rhs: Blind) { self.0 += rhs.0; } } -impl MulAssign for Blind { +impl MulAssign for Blind { fn mul_assign(&mut self, rhs: Blind) { self.0 *= rhs.0; } } -impl AddAssign for Blind { +impl AddAssign for Blind { fn add_assign(&mut self, rhs: F) { self.0 += rhs; } } -impl MulAssign for Blind { +impl MulAssign for Blind { fn mul_assign(&mut self, rhs: F) { self.0 *= rhs; } diff --git a/halo2_proofs/src/poly/domain.rs b/halo2_proofs/src/poly/domain.rs index 2923474112..e2884f3d25 100644 --- a/halo2_proofs/src/poly/domain.rs +++ b/halo2_proofs/src/poly/domain.rs @@ -2,13 +2,17 @@ //! domain that is of a suitable size for the application. use crate::{ - arithmetic::{best_fft, parallelize, FieldExt, Group}, + arithmetic::{best_fft, parallelize}, plonk::Assigned, }; use super::{Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, Rotation}; -use group::ff::{BatchInvert, Field, PrimeField}; +use ff::WithSmallOrderMulGroup; +use group::{ + ff::{BatchInvert, Field, PrimeField}, + Group, +}; use std::marker::PhantomData; @@ -16,24 +20,24 @@ use std::marker::PhantomData; /// performing operations on an evaluation domain of size $2^k$ and an extended /// domain of size $2^{k} * j$ with $j \neq 0$. #[derive(Clone, Debug)] -pub struct EvaluationDomain { +pub struct EvaluationDomain> { n: u64, k: u32, extended_k: u32, - omega: G::Scalar, - omega_inv: G::Scalar, - extended_omega: G::Scalar, - extended_omega_inv: G::Scalar, - g_coset: G::Scalar, - g_coset_inv: G::Scalar, + omega: F, + omega_inv: F, + extended_omega: F, + extended_omega_inv: F, + g_coset: F, + g_coset_inv: F, quotient_poly_degree: u64, - ifft_divisor: G::Scalar, - extended_ifft_divisor: G::Scalar, - t_evaluations: Vec, - barycentric_weight: G::Scalar, + ifft_divisor: F, + extended_ifft_divisor: F, + t_evaluations: Vec, + barycentric_weight: F, } -impl EvaluationDomain { +impl> EvaluationDomain { /// This constructs a new evaluation domain object based on the provided /// values $j, k$. pub fn new(j: u32, k: u32) -> Self { @@ -51,12 +55,12 @@ impl EvaluationDomain { extended_k += 1; } - let mut extended_omega = G::Scalar::root_of_unity(); + let mut extended_omega = F::ROOT_OF_UNITY; // Get extended_omega, the 2^{extended_k}'th root of unity // The loop computes extended_omega = omega^{2 ^ (S - extended_k)} // Notice that extended_omega ^ {2 ^ extended_k} = omega ^ {2^S} = 1. - for _ in extended_k..G::Scalar::S { + for _ in extended_k..F::S { extended_omega = extended_omega.square(); } let extended_omega = extended_omega; @@ -78,14 +82,14 @@ impl EvaluationDomain { // already. // The coset evaluation domain is: // zeta {1, extended_omega, extended_omega^2, ..., extended_omega^{(2^extended_k) - 1}} - let g_coset = G::Scalar::ZETA; + let g_coset = F::ZETA; let g_coset_inv = g_coset.square(); let mut t_evaluations = Vec::with_capacity(1 << (extended_k - k)); { // Compute the evaluations of t(X) = X^n - 1 in the coset evaluation domain. // We don't have to compute all of them, because it will repeat. - let orig = G::Scalar::ZETA.pow_vartime(&[n as u64, 0, 0, 0]); + let orig = F::ZETA.pow_vartime(&[n as u64, 0, 0, 0]); let step = extended_omega.pow_vartime(&[n as u64, 0, 0, 0]); let mut cur = orig; loop { @@ -99,19 +103,19 @@ impl EvaluationDomain { // Subtract 1 from each to give us t_evaluations[i] = t(zeta * extended_omega^i) for coeff in &mut t_evaluations { - *coeff -= &G::Scalar::one(); + *coeff -= &F::ONE; } // Invert, because we're dividing by this polynomial. // We invert in a batch, below. } - let mut ifft_divisor = G::Scalar::from(1 << k); // Inversion computed later - let mut extended_ifft_divisor = G::Scalar::from(1 << extended_k); // Inversion computed later + let mut ifft_divisor = F::from(1 << k); // Inversion computed later + let mut extended_ifft_divisor = F::from(1 << extended_k); // Inversion computed later // The barycentric weight of 1 over the evaluation domain // 1 / \prod_{i != 0} (1 - omega^i) - let mut barycentric_weight = G::Scalar::from(n); // Inversion computed later + let mut barycentric_weight = F::from(n); // Inversion computed later // Compute batch inversion t_evaluations @@ -144,7 +148,7 @@ impl EvaluationDomain { /// Obtains a polynomial in Lagrange form when given a vector of Lagrange /// coefficients of size `n`; panics if the provided vector is the wrong /// length. - pub fn lagrange_from_vec(&self, values: Vec) -> Polynomial { + pub fn lagrange_from_vec(&self, values: Vec) -> Polynomial { assert_eq!(values.len(), self.n as usize); Polynomial { @@ -156,7 +160,7 @@ impl EvaluationDomain { /// Obtains a polynomial in coefficient form when given a vector of /// coefficients of size `n`; panics if the provided vector is the wrong /// length. - pub fn coeff_from_vec(&self, values: Vec) -> Polynomial { + pub fn coeff_from_vec(&self, values: Vec) -> Polynomial { assert_eq!(values.len(), self.n as usize); Polynomial { @@ -170,13 +174,13 @@ impl EvaluationDomain { /// provided vector is the wrong length. pub fn extended_from_lagrange_vec( &self, - values: Vec>, - ) -> Polynomial { + values: Vec>, + ) -> Polynomial { assert_eq!(values.len(), (self.extended_len() >> self.k) as usize); assert_eq!(values[0].len(), self.n as usize); // transpose the values in parallel - let mut transposed = vec![vec![G::group_zero(); values.len()]; self.n as usize]; + let mut transposed = vec![vec![F::ZERO; values.len()]; self.n as usize]; values.into_iter().enumerate().for_each(|(i, p)| { parallelize(&mut transposed, |transposed, start| { for (transposed, p) in transposed.iter_mut().zip(p.values[start..].iter()) { @@ -192,35 +196,32 @@ impl EvaluationDomain { } /// Returns an empty (zero) polynomial in the coefficient basis - pub fn empty_coeff(&self) -> Polynomial { + pub fn empty_coeff(&self) -> Polynomial { Polynomial { - values: vec![G::group_zero(); self.n as usize], + values: vec![F::ZERO; self.n as usize], _marker: PhantomData, } } /// Returns an empty (zero) polynomial in the Lagrange coefficient basis - pub fn empty_lagrange(&self) -> Polynomial { + pub fn empty_lagrange(&self) -> Polynomial { Polynomial { - values: vec![G::group_zero(); self.n as usize], + values: vec![F::ZERO; self.n as usize], _marker: PhantomData, } } /// Returns an empty (zero) polynomial in the Lagrange coefficient basis, with /// deferred inversions. - pub(crate) fn empty_lagrange_assigned(&self) -> Polynomial, LagrangeCoeff> - where - G: Field, - { + pub(crate) fn empty_lagrange_assigned(&self) -> Polynomial, LagrangeCoeff> { Polynomial { - values: vec![G::group_zero().into(); self.n as usize], + values: vec![F::ZERO.into(); self.n as usize], _marker: PhantomData, } } /// Returns a constant polynomial in the Lagrange coefficient basis - pub fn constant_lagrange(&self, scalar: G) -> Polynomial { + pub fn constant_lagrange(&self, scalar: F) -> Polynomial { Polynomial { values: vec![scalar; self.n as usize], _marker: PhantomData, @@ -229,16 +230,16 @@ impl EvaluationDomain { /// Returns an empty (zero) polynomial in the extended Lagrange coefficient /// basis - pub fn empty_extended(&self) -> Polynomial { + pub fn empty_extended(&self) -> Polynomial { Polynomial { - values: vec![G::group_zero(); self.extended_len()], + values: vec![F::ZERO; self.extended_len()], _marker: PhantomData, } } /// Returns a constant polynomial in the extended Lagrange coefficient /// basis - pub fn constant_extended(&self, scalar: G) -> Polynomial { + pub fn constant_extended(&self, scalar: F) -> Polynomial { Polynomial { values: vec![scalar; self.extended_len()], _marker: PhantomData, @@ -249,7 +250,7 @@ impl EvaluationDomain { /// /// This function will panic if the provided vector is not the correct /// length. - pub fn lagrange_to_coeff(&self, mut a: Polynomial) -> Polynomial { + pub fn lagrange_to_coeff(&self, mut a: Polynomial) -> Polynomial { assert_eq!(a.values.len(), 1 << self.k); // Perform inverse FFT to obtain the polynomial in coefficient form @@ -265,12 +266,12 @@ impl EvaluationDomain { /// evaluation domain, rotating by `rotation` if desired. pub fn coeff_to_extended( &self, - mut a: Polynomial, - ) -> Polynomial { + mut a: Polynomial, + ) -> Polynomial { assert_eq!(a.values.len(), 1 << self.k); self.distribute_powers_zeta(&mut a.values, true); - a.values.resize(self.extended_len(), G::group_zero()); + a.values.resize(self.extended_len(), F::ZERO); best_fft(&mut a.values, self.extended_omega, self.extended_k); Polynomial { @@ -289,12 +290,12 @@ impl EvaluationDomain { /// `FFT(f(zeta * extended_omega^{m-1} * X), n)` pub fn coeff_to_extended_parts( &self, - a: &Polynomial, - ) -> Vec> { + a: &Polynomial, + ) -> Vec> { assert_eq!(a.values.len(), 1 << self.k); let num_parts = self.extended_len() >> self.k; - let mut extended_omega_factor = G::Scalar::one(); + let mut extended_omega_factor = F::ONE; (0..num_parts) .map(|_| { let part = self.coeff_to_extended_part(a.clone(), extended_omega_factor); @@ -314,11 +315,11 @@ impl EvaluationDomain { /// `FFT(f(zeta * extended_omega^{m-1} * X), n)` pub fn batched_coeff_to_extended_parts( &self, - a: &[Polynomial], - ) -> Vec>> { + a: &[Polynomial], + ) -> Vec>> { assert_eq!(a[0].values.len(), 1 << self.k); - let mut extended_omega_factor = G::Scalar::one(); + let mut extended_omega_factor = F::ONE; let num_parts = self.extended_len() >> self.k; (0..num_parts) .map(|_| { @@ -340,9 +341,9 @@ impl EvaluationDomain { /// where `extended_omega_factor` is `extended_omega^i` with `i` in `[0, m)`. pub fn coeff_to_extended_part( &self, - mut a: Polynomial, - extended_omega_factor: G::Scalar, - ) -> Polynomial { + mut a: Polynomial, + extended_omega_factor: F, + ) -> Polynomial { assert_eq!(a.values.len(), 1 << self.k); self.distribute_powers(&mut a.values, self.g_coset * extended_omega_factor); @@ -357,9 +358,9 @@ impl EvaluationDomain { /// Rotate the extended domain polynomial over the original domain. pub fn rotate_extended( &self, - poly: &Polynomial, + poly: &Polynomial, rotation: Rotation, - ) -> Polynomial { + ) -> Polynomial { let new_rotation = ((1 << (self.extended_k - self.k)) * rotation.0.abs()) as usize; let mut poly = poly.clone(); @@ -379,7 +380,7 @@ impl EvaluationDomain { /// This function will panic if the provided vector is not the correct /// length. // TODO/FIXME: caller should be responsible for truncating - pub fn extended_to_coeff(&self, mut a: Polynomial) -> Vec { + pub fn extended_to_coeff(&self, mut a: Polynomial) -> Vec { assert_eq!(a.values.len(), self.extended_len()); // Inverse FFT @@ -407,15 +408,15 @@ impl EvaluationDomain { /// polynomial of the $2^k$ size domain. pub fn divide_by_vanishing_poly( &self, - mut a: Polynomial, - ) -> Polynomial { + mut a: Polynomial, + ) -> Polynomial { assert_eq!(a.values.len(), self.extended_len()); // Divide to obtain the quotient polynomial in the coset evaluation // domain. parallelize(&mut a.values, |h, mut index| { for h in h { - h.group_scale(&self.t_evaluations[index % self.t_evaluations.len()]); + h.mul_assign(&self.t_evaluations[index % self.t_evaluations.len()]); index += 1; } }); @@ -433,7 +434,7 @@ impl EvaluationDomain { /// /// `into_coset` should be set to `true` when moving into the coset, /// and `false` when moving out. This toggles the choice of `zeta`. - fn distribute_powers_zeta(&self, a: &mut [G], into_coset: bool) { + fn distribute_powers_zeta(&self, a: &mut [F], into_coset: bool) { let coset_powers = if into_coset { [self.g_coset, self.g_coset_inv] } else { @@ -444,7 +445,7 @@ impl EvaluationDomain { // Distribute powers to move into/from coset let i = index % (coset_powers.len() + 1); if i != 0 { - a.group_scale(&coset_powers[i - 1]); + a.mul_assign(&coset_powers[i - 1]); } index += 1; } @@ -454,22 +455,22 @@ impl EvaluationDomain { /// Given a slice of group elements `[a_0, a_1, a_2, ...]`, this returns /// `[a_0, [c]a_1, [c^2]a_2, [c^3]a_3, [c^4]a_4, ...]`, /// - fn distribute_powers(&self, a: &mut [G], c: G::Scalar) { + fn distribute_powers(&self, a: &mut [F], c: F) { parallelize(a, |a, index| { let mut c_power = c.pow_vartime(&[index as u64, 0, 0, 0]); for a in a { - a.group_scale(&c_power); + a.mul_assign(&c_power); c_power = c_power * c; } }); } - fn ifft(a: &mut [G], omega_inv: G::Scalar, log_n: u32, divisor: G::Scalar) { + fn ifft(a: &mut [F], omega_inv: F, log_n: u32, divisor: F) { best_fft(a, omega_inv, log_n); parallelize(a, |a, _| { for a in a { // Finish iFFT - a.group_scale(&divisor); + a.mul_assign(&divisor); } }); } @@ -490,24 +491,24 @@ impl EvaluationDomain { } /// Get $\omega$, the generator of the $2^k$ order multiplicative subgroup. - pub fn get_omega(&self) -> G::Scalar { + pub fn get_omega(&self) -> F { self.omega } /// Get $\omega^{-1}$, the inverse of the generator of the $2^k$ order /// multiplicative subgroup. - pub fn get_omega_inv(&self) -> G::Scalar { + pub fn get_omega_inv(&self) -> F { self.omega_inv } /// Get the generator of the extended domain's multiplicative subgroup. - pub fn get_extended_omega(&self) -> G::Scalar { + pub fn get_extended_omega(&self) -> F { self.extended_omega } /// Multiplies a value by some power of $\omega$, essentially rotating over /// the domain. - pub fn rotate_omega(&self, value: G::Scalar, rotation: Rotation) -> G::Scalar { + pub fn rotate_omega(&self, value: F, rotation: Rotation) -> F { let mut point = value; if rotation.0 >= 0 { point *= &self.get_omega().pow_vartime(&[rotation.0 as u64]); @@ -548,23 +549,23 @@ impl EvaluationDomain { /// which is the barycentric weight of $\omega^i$. pub fn l_i_range + Clone>( &self, - x: G::Scalar, - xn: G::Scalar, + x: F, + xn: F, rotations: I, - ) -> Vec { + ) -> Vec { let mut results; { let rotations = rotations.clone().into_iter(); results = Vec::with_capacity(rotations.size_hint().1.unwrap_or(0)); for rotation in rotations { let rotation = Rotation(rotation); - let result = x - self.rotate_omega(G::Scalar::one(), rotation); + let result = x - self.rotate_omega(F::ONE, rotation); results.push(result); } results.iter_mut().batch_invert(); } - let common = (xn - G::Scalar::one()) * self.barycentric_weight; + let common = (xn - F::ONE) * self.barycentric_weight; for (rotation, result) in rotations.into_iter().zip(results.iter_mut()) { let rotation = Rotation(rotation); *result = self.rotate_omega(*result * common, rotation); @@ -581,7 +582,7 @@ impl EvaluationDomain { /// Obtain a pinned version of this evaluation domain; a structure with the /// minimal parameters needed to determine the rest of the evaluation /// domain. - pub fn pinned(&self) -> PinnedEvaluationDomain<'_, G> { + pub fn pinned(&self) -> PinnedEvaluationDomain<'_, F> { PinnedEvaluationDomain { k: &self.k, extended_k: &self.extended_k, @@ -593,10 +594,10 @@ impl EvaluationDomain { /// Represents the minimal parameters that determine an `EvaluationDomain`. #[allow(dead_code)] #[derive(Debug)] -pub struct PinnedEvaluationDomain<'a, G: Group> { +pub struct PinnedEvaluationDomain<'a, F: PrimeField> { k: &'a u32, extended_k: &'a u32, - omega: &'a G::Scalar, + omega: &'a F, } #[test] @@ -654,8 +655,8 @@ fn test_l_i() { points.push(domain.omega.pow(&[i, 0, 0, 0])); } for i in 0..8 { - let mut l_i = vec![Scalar::zero(); 8]; - l_i[i] = Scalar::one(); + let mut l_i = vec![Scalar::ZERO; 8]; + l_i[i] = Scalar::ONE; let l_i = lagrange_interpolate(&points[..], &l_i[..]); l.push(l_i); } diff --git a/halo2_proofs/src/poly/evaluator.rs b/halo2_proofs/src/poly/evaluator.rs index d1ba853c47..ea3e24ddf1 100644 --- a/halo2_proofs/src/poly/evaluator.rs +++ b/halo2_proofs/src/poly/evaluator.rs @@ -230,7 +230,7 @@ impl Evaluator { lhs } Ast::DistributePowers(terms, base) => terms.iter().fold( - B::constant_term(ctx.poly_len, ctx.chunk_size, ctx.chunk_index, F::zero()), + B::constant_term(ctx.poly_len, ctx.chunk_size, ctx.chunk_index, F::ZERO), |mut acc, term| { let term = recurse(term, ctx); for (acc, term) in acc.iter_mut().zip(term) { @@ -347,7 +347,7 @@ impl From> for Ast { impl Ast { pub(crate) fn one() -> Self { - Self::ConstantTerm(F::one()) + Self::ConstantTerm(F::ONE) } } @@ -355,7 +355,7 @@ impl Neg for Ast { type Output = Ast; fn neg(self) -> Self::Output { - Ast::Scale(Arc::new(self), -F::one()) + Ast::Scale(Arc::new(self), -F::ONE) } } @@ -521,7 +521,7 @@ impl BasisOps for Coeff { chunk_index: usize, scalar: F, ) -> Vec { - let mut chunk = vec![F::zero(); cmp::min(chunk_size, poly_len - chunk_size * chunk_index)]; + let mut chunk = vec![F::ZERO; cmp::min(chunk_size, poly_len - chunk_size * chunk_index)]; if chunk_index == 0 { chunk[0] = scalar; } @@ -535,7 +535,7 @@ impl BasisOps for Coeff { chunk_index: usize, scalar: F, ) -> Vec { - let mut chunk = vec![F::zero(); cmp::min(chunk_size, poly_len - chunk_size * chunk_index)]; + let mut chunk = vec![F::ZERO; cmp::min(chunk_size, poly_len - chunk_size * chunk_index)]; // If the chunk size is 1 (e.g. if we have a small k and many threads), then the // linear coefficient is the second chunk. Otherwise, the chunk size is greater // than one, and the linear coefficient is the second element of the first chunk. diff --git a/halo2_proofs/src/poly/ipa/commitment.rs b/halo2_proofs/src/poly/ipa/commitment.rs index 9060e8315c..461c0d4b26 100644 --- a/halo2_proofs/src/poly/ipa/commitment.rs +++ b/halo2_proofs/src/poly/ipa/commitment.rs @@ -4,7 +4,7 @@ //! [halo]: https://eprint.iacr.org/2019/1021 use crate::arithmetic::{ - best_fft, best_multiexp, g_to_lagrange, parallelize, CurveAffine, CurveExt, FieldExt, Group, + best_fft, best_multiexp, g_to_lagrange, parallelize, CurveAffine, CurveExt, }; use crate::helpers::CurveRead; use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, ParamsVerifier, MSM}; @@ -234,9 +234,7 @@ impl<'params, C: CurveAffine> ParamsProver<'params, C> for ParamsIPA { #[cfg(test)] mod test { - use crate::arithmetic::{ - best_fft, best_multiexp, parallelize, CurveAffine, CurveExt, FieldExt, Group, - }; + use crate::arithmetic::{best_fft, best_multiexp, parallelize, CurveAffine, CurveExt}; use crate::helpers::CurveRead; use crate::poly::commitment::ParamsProver; use crate::poly::commitment::{Blind, CommitmentScheme, Params, MSM}; @@ -309,7 +307,7 @@ mod test { use rand_core::OsRng; use super::super::commitment::{Blind, Params}; - use crate::arithmetic::{eval_polynomial, FieldExt}; + use crate::arithmetic::eval_polynomial; use crate::halo2curves::pasta::{EpAffine, Fq}; use crate::poly::EvaluationDomain; use crate::transcript::{ @@ -363,7 +361,7 @@ mod test { assert_eq!(v, v_prime); let mut commitment_msm = MSMIPA::new(¶ms); - commitment_msm.append_term(Field::one(), p.into()); + commitment_msm.append_term(Field::ONE, p.into()); let guard = verify_proof(¶ms, commitment_msm, &mut transcript, *x, v).unwrap(); let ch_verifier = transcript.squeeze_challenge(); diff --git a/halo2_proofs/src/poly/ipa/commitment/prover.rs b/halo2_proofs/src/poly/ipa/commitment/prover.rs index 3b22b31b36..d176987c96 100644 --- a/halo2_proofs/src/poly/ipa/commitment/prover.rs +++ b/halo2_proofs/src/poly/ipa/commitment/prover.rs @@ -3,7 +3,7 @@ use rand_core::RngCore; use super::{Params, ParamsIPA}; use crate::arithmetic::{ - best_multiexp, compute_inner_product, eval_polynomial, parallelize, CurveAffine, FieldExt, + best_multiexp, compute_inner_product, eval_polynomial, parallelize, CurveAffine, }; use crate::poly::commitment::ParamsProver; @@ -87,7 +87,7 @@ pub fn create_proof< // `p_prime` and `b` is the evaluation of the polynomial at `x_3`. let mut b = Vec::with_capacity(1 << params.k); { - let mut cur = C::Scalar::one(); + let mut cur = C::Scalar::ONE; for _ in 0..(1 << params.k) { b.push(cur); cur *= &x_3; diff --git a/halo2_proofs/src/poly/ipa/commitment/verifier.rs b/halo2_proofs/src/poly/ipa/commitment/verifier.rs index b3b30e0b4b..0b60842899 100644 --- a/halo2_proofs/src/poly/ipa/commitment/verifier.rs +++ b/halo2_proofs/src/poly/ipa/commitment/verifier.rs @@ -96,10 +96,10 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge, T: Transcri /// Computes $\prod\limits_{i=0}^{k-1} (1 + u_{k - 1 - i} x^{2^i})$. fn compute_b(x: F, u: &[F]) -> F { - let mut tmp = F::one(); + let mut tmp = F::ONE; let mut cur = x; for u_j in u.iter().rev() { - tmp *= F::one() + &(*u_j * &cur); + tmp *= F::ONE + &(*u_j * &cur); cur *= cur; } tmp diff --git a/halo2_proofs/src/poly/ipa/msm.rs b/halo2_proofs/src/poly/ipa/msm.rs index 63f994b46e..3316e25337 100644 --- a/halo2_proofs/src/poly/ipa/msm.rs +++ b/halo2_proofs/src/poly/ipa/msm.rs @@ -191,7 +191,7 @@ impl<'a, C: CurveAffine> MSMIPA<'a, C> { if let Some(g_scalars) = self.g_scalars.as_mut() { g_scalars[0] += &constant; } else { - let mut g_scalars = vec![C::Scalar::zero(); self.params.n as usize]; + let mut g_scalars = vec![C::Scalar::ZERO; self.params.n as usize]; g_scalars[0] += &constant; self.g_scalars = Some(g_scalars); } diff --git a/halo2_proofs/src/poly/ipa/multiopen.rs b/halo2_proofs/src/poly/ipa/multiopen.rs index b724139a8f..4aa6bd0de4 100644 --- a/halo2_proofs/src/poly/ipa/multiopen.rs +++ b/halo2_proofs/src/poly/ipa/multiopen.rs @@ -6,15 +6,12 @@ use std::collections::{BTreeMap, BTreeSet}; use super::*; -use crate::{ - arithmetic::{CurveAffine, FieldExt}, - poly::query::Query, - transcript::ChallengeScalar, -}; +use crate::{arithmetic::CurveAffine, poly::query::Query, transcript::ChallengeScalar}; mod prover; mod verifier; +use ff::PrimeField; pub use prover::ProverIPA; pub use verifier::VerifierIPA; @@ -63,7 +60,9 @@ type IntermediateSets = ( Vec>, ); -fn construct_intermediate_sets>(queries: I) -> IntermediateSets +fn construct_intermediate_sets>( + queries: I, +) -> IntermediateSets where I: IntoIterator + Clone, { diff --git a/halo2_proofs/src/poly/ipa/multiopen/prover.rs b/halo2_proofs/src/poly/ipa/multiopen/prover.rs index bba038c93a..6d65e7ae64 100644 --- a/halo2_proofs/src/poly/ipa/multiopen/prover.rs +++ b/halo2_proofs/src/poly/ipa/multiopen/prover.rs @@ -1,7 +1,7 @@ use super::{ construct_intermediate_sets, ChallengeX1, ChallengeX2, ChallengeX3, ChallengeX4, Query, }; -use crate::arithmetic::{eval_polynomial, kate_division, CurveAffine, FieldExt}; +use crate::arithmetic::{eval_polynomial, kate_division, CurveAffine}; use crate::poly::commitment::ParamsProver; use crate::poly::commitment::{Blind, Params, Prover}; use crate::poly::ipa::commitment::{self, IPACommitmentScheme, ParamsIPA}; @@ -47,7 +47,7 @@ impl<'params, C: CurveAffine> Prover<'params, IPACommitmentScheme> for Prover // Collapse openings at same point sets together into single openings using // x_1 challenge. let mut q_polys: Vec>> = vec![None; point_sets.len()]; - let mut q_blinds = vec![Blind(C::Scalar::zero()); point_sets.len()]; + let mut q_blinds = vec![Blind(C::Scalar::ZERO); point_sets.len()]; { let mut accumulate = |set_idx: usize, @@ -80,7 +80,7 @@ impl<'params, C: CurveAffine> Prover<'params, IPACommitmentScheme> for Prover .fold(poly.clone().unwrap().values, |poly, point| { kate_division(&poly, *point) }); - poly.resize(self.params.n as usize, C::Scalar::zero()); + poly.resize(self.params.n as usize, C::Scalar::ZERO); let poly = Polynomial { values: poly, _marker: PhantomData, diff --git a/halo2_proofs/src/poly/ipa/multiopen/verifier.rs b/halo2_proofs/src/poly/ipa/multiopen/verifier.rs index ff4c7626f6..391f89e15b 100644 --- a/halo2_proofs/src/poly/ipa/multiopen/verifier.rs +++ b/halo2_proofs/src/poly/ipa/multiopen/verifier.rs @@ -8,7 +8,7 @@ use rand_core::RngCore; use super::{ construct_intermediate_sets, ChallengeX1, ChallengeX2, ChallengeX3, ChallengeX4, Query, }; -use crate::arithmetic::{eval_polynomial, lagrange_interpolate, CurveAffine, FieldExt}; +use crate::arithmetic::{eval_polynomial, lagrange_interpolate, CurveAffine}; use crate::poly::commitment::{Params, Verifier, MSM}; use crate::poly::ipa::commitment::{IPACommitmentScheme, ParamsIPA, ParamsVerifierIPA}; use crate::poly::ipa::msm::MSMIPA; @@ -63,7 +63,7 @@ impl<'params, C: CurveAffine> Verifier<'params, IPACommitmentScheme> // while the inner vec corresponds to the points in a particular set. let mut q_eval_sets = Vec::with_capacity(point_sets.len()); for point_set in point_sets.iter() { - q_eval_sets.push(vec![C::Scalar::zero(); point_set.len()]); + q_eval_sets.push(vec![C::Scalar::ZERO; point_set.len()]); } { let mut accumulate = |set_idx: usize, @@ -72,7 +72,7 @@ impl<'params, C: CurveAffine> Verifier<'params, IPACommitmentScheme> q_commitments[set_idx].scale(*x_1); match new_commitment { CommitmentReference::Commitment(c) => { - q_commitments[set_idx].append_term(C::Scalar::one(), (*c).into()); + q_commitments[set_idx].append_term(C::Scalar::ONE, (*c).into()); } CommitmentReference::MSM(msm) => { q_commitments[set_idx].add_msm(msm); @@ -116,7 +116,7 @@ impl<'params, C: CurveAffine> Verifier<'params, IPACommitmentScheme> .zip(q_eval_sets.iter()) .zip(u.iter()) .fold( - C::Scalar::zero(), + C::Scalar::ZERO, |msm_eval, ((points, evals), proof_eval)| { let r_poly = lagrange_interpolate(points, evals); let r_eval = eval_polynomial(&r_poly, *x_3); @@ -132,7 +132,7 @@ impl<'params, C: CurveAffine> Verifier<'params, IPACommitmentScheme> let x_4: ChallengeX4<_> = transcript.squeeze_challenge_scalar(); // Compute the final commitment that has to be opened - msm.append_term(C::Scalar::one(), q_prime_commitment.into()); + msm.append_term(C::Scalar::ONE, q_prime_commitment.into()); let (msm, v) = q_commitments.into_iter().zip(u.iter()).fold( (msm, msm_eval), |(mut msm, msm_eval), (q_commitment, q_eval)| { diff --git a/halo2_proofs/src/poly/ipa/strategy.rs b/halo2_proofs/src/poly/ipa/strategy.rs index 6f3b4b7228..c8d385f90c 100644 --- a/halo2_proofs/src/poly/ipa/strategy.rs +++ b/halo2_proofs/src/poly/ipa/strategy.rs @@ -70,7 +70,7 @@ impl<'params, C: CurveAffine> GuardIPA<'params, C> { /// Computes G = ⟨s, params.g⟩ pub fn compute_g(&self) -> C { - let s = compute_s(&self.u, C::Scalar::one()); + let s = compute_s(&self.u, C::Scalar::ONE); best_multiexp(&s, &self.msm.params.g).to_affine() } @@ -160,7 +160,7 @@ impl<'params, C: CurveAffine> /// Computes the coefficients of $g(X) = \prod\limits_{i=0}^{k-1} (1 + u_{k - 1 - i} X^{2^i})$. fn compute_s(u: &[F], init: F) -> Vec { assert!(!u.is_empty()); - let mut v = vec![F::zero(); 1 << u.len()]; + let mut v = vec![F::ZERO; 1 << u.len()]; v[0] = init; for (len, u_j) in u.iter().rev().enumerate().map(|(i, u_j)| (1 << i, u_j)) { diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index aa86fdc14f..6076ee7673 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -1,12 +1,12 @@ use crate::arithmetic::{ - best_fft, best_multiexp, g_to_lagrange, parallelize, CurveAffine, CurveExt, FieldExt, Group, + best_fft, best_multiexp, g_to_lagrange, parallelize, CurveAffine, CurveExt, }; use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, ParamsVerifier, MSM}; use crate::poly::{Coeff, LagrangeCoeff, Polynomial}; use crate::SerdeFormat; -use ff::{Field, PrimeField}; +use ff::{Field, PrimeField, WithSmallOrderMulGroup}; use group::{prime::PrimeCurveAffine, Curve, Group as _}; use halo2curves::pairing::Engine; use rand_core::{OsRng, RngCore}; @@ -20,7 +20,10 @@ use super::msm::MSMKZG; /// These are the public parameters for the polynomial commitment scheme. #[derive(Debug, Clone)] -pub struct ParamsKZG { +pub struct ParamsKZG +where + E::Scalar: PrimeField, +{ pub(crate) k: u32, pub n: u64, pub(crate) g: Vec, @@ -37,6 +40,7 @@ pub struct KZGCommitmentScheme { impl CommitmentScheme for KZGCommitmentScheme where + E::Scalar: WithSmallOrderMulGroup<3>, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { @@ -55,7 +59,10 @@ where } } -impl ParamsKZG { +impl ParamsKZG +where + E::Scalar: PrimeField, +{ /// Initializes parameters for the curve, draws toxic secret from given rng. /// MUST NOT be used in production. pub fn setup(k: u32, rng: R) -> Self { @@ -80,7 +87,7 @@ impl ParamsKZG { // Calculate g = [G1, [s] G1, [s^2] G1, ..., [s^(n-1)] G1] in parallel. let g1 = E::G1Affine::generator(); - let mut g_projective = vec![E::G1::group_zero(); n as usize]; + let mut g_projective = vec![E::G1::identity(); n as usize]; parallelize(&mut g_projective, |g, start| { let mut current_g: E::G1 = g1.into(); current_g *= s.pow_vartime(&[start as u64]); @@ -98,14 +105,14 @@ impl ParamsKZG { g }; - let mut g_lagrange_projective = vec![E::G1::group_zero(); n as usize]; + let mut g_lagrange_projective = vec![E::G1::identity(); n as usize]; let mut root = E::Scalar::ROOT_OF_UNITY_INV.invert().unwrap(); for _ in k..E::Scalar::S { root = root.square(); } let n_inv = Option::::from(E::Scalar::from(n).invert()) .expect("inversion should be ok for n = 1< = ParamsKZG; impl<'params, E: Engine + Debug> Params<'params, E::G1Affine> for ParamsKZG where + E::Scalar: PrimeField, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { @@ -316,6 +324,7 @@ where impl<'params, E: Engine + Debug> ParamsVerifier<'params, E::G1Affine> for ParamsKZG where + E::Scalar: PrimeField, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { @@ -323,6 +332,7 @@ where impl<'params, E: Engine + Debug> ParamsProver<'params, E::G1Affine> for ParamsKZG where + E::Scalar: PrimeField, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { @@ -352,9 +362,7 @@ where #[cfg(test)] mod test { - use crate::arithmetic::{ - best_fft, best_multiexp, parallelize, CurveAffine, CurveExt, FieldExt, Group, - }; + use crate::arithmetic::{best_fft, best_multiexp, parallelize, CurveAffine, CurveExt}; use crate::poly::commitment::ParamsProver; use crate::poly::commitment::{Blind, CommitmentScheme, Params, MSM}; use crate::poly::kzg::commitment::{ParamsKZG, ParamsVerifierKZG}; @@ -403,7 +411,7 @@ mod test { use rand_core::OsRng; use super::super::commitment::{Blind, Params}; - use crate::arithmetic::{eval_polynomial, FieldExt}; + use crate::arithmetic::eval_polynomial; use crate::halo2curves::bn256::{Bn256, Fr}; use crate::poly::EvaluationDomain; diff --git a/halo2_proofs/src/poly/kzg/msm.rs b/halo2_proofs/src/poly/kzg/msm.rs index 6cc90a5103..ae410424c8 100644 --- a/halo2_proofs/src/poly/kzg/msm.rs +++ b/halo2_proofs/src/poly/kzg/msm.rs @@ -5,6 +5,7 @@ use crate::{ arithmetic::{best_multiexp, parallelize, CurveAffine}, poly::commitment::MSM, }; +use ff::PrimeField; use group::{Curve, Group}; use halo2curves::pairing::{Engine, MillerLoopResult, MultiMillerLoop}; @@ -27,7 +28,7 @@ impl MSMKZG { /// Prepares all scalars in the MSM to linear combination pub fn combine_with_base(&mut self, base: E::Scalar) { use ff::Field; - let mut acc = E::Scalar::one(); + let mut acc = E::Scalar::ONE; if !self.scalars.is_empty() { for scalar in self.scalars.iter_mut().rev() { *scalar *= &acc; @@ -111,7 +112,10 @@ impl PreMSM { } } -impl<'params, E: MultiMillerLoop + Debug> From<&'params ParamsKZG> for DualMSM<'params, E> { +impl<'params, E: MultiMillerLoop + Debug> From<&'params ParamsKZG> for DualMSM<'params, E> +where + E::Scalar: PrimeField, +{ fn from(params: &'params ParamsKZG) -> Self { DualMSM::new(params) } @@ -119,13 +123,19 @@ impl<'params, E: MultiMillerLoop + Debug> From<&'params ParamsKZG> for DualMS /// Two channel MSM accumulator #[derive(Debug, Clone)] -pub struct DualMSM<'a, E: Engine> { +pub struct DualMSM<'a, E: Engine> +where + E::Scalar: PrimeField, +{ pub(crate) params: &'a ParamsKZG, pub(crate) left: MSMKZG, pub(crate) right: MSMKZG, } -impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E> { +impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E> +where + E::Scalar: PrimeField, +{ /// Create a new two channel MSM accumulator instance pub fn new(params: &'a ParamsKZG) -> Self { Self { diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc.rs index 4869238ae7..a5b22244f2 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc.rs @@ -1,11 +1,12 @@ mod prover; mod verifier; +use ff::PrimeField; pub use prover::ProverGWC; pub use verifier::VerifierGWC; use crate::{ - arithmetic::{eval_polynomial, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, CurveAffine}, poly::{ commitment::{Params, ParamsVerifier}, query::Query, @@ -27,13 +28,15 @@ type ChallengeU = ChallengeScalar; struct V {} type ChallengeV = ChallengeScalar; -struct CommitmentData> { +struct CommitmentData> { queries: Vec, point: F, _marker: PhantomData, } -fn construct_intermediate_sets>(queries: I) -> Vec> +fn construct_intermediate_sets>( + queries: I, +) -> Vec> where I: IntoIterator + Clone, { diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs index ee8a549a00..da3d7bf07c 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs @@ -1,5 +1,5 @@ use super::{construct_intermediate_sets, ChallengeV, Query}; -use crate::arithmetic::{eval_polynomial, kate_division, powers, CurveAffine, FieldExt}; +use crate::arithmetic::{eval_polynomial, kate_division, powers, CurveAffine}; use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::ParamsProver; use crate::poly::commitment::Prover; @@ -12,7 +12,7 @@ use crate::poly::{ }; use crate::transcript::{EncodedChallenge, TranscriptWrite}; -use ff::Field; +use ff::{Field, PrimeField, WithSmallOrderMulGroup}; use group::Curve; use halo2curves::pairing::Engine; use rand_core::RngCore; @@ -22,13 +22,17 @@ use std::marker::PhantomData; /// Concrete KZG prover with GWC variant #[derive(Debug)] -pub struct ProverGWC<'params, E: Engine> { +pub struct ProverGWC<'params, E: Engine> +where + E::Scalar: PrimeField, +{ params: &'params ParamsKZG, } /// Create a multi-opening proof impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme> for ProverGWC<'params, E> where + E::Scalar: PrimeField + Ord + WithSmallOrderMulGroup<3>, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs index 22fa139480..6da691b7be 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs @@ -3,7 +3,7 @@ use std::io::Read; use std::marker::PhantomData; use super::{construct_intermediate_sets, ChallengeU, ChallengeV}; -use crate::arithmetic::{eval_polynomial, lagrange_interpolate, powers, CurveAffine, FieldExt}; +use crate::arithmetic::{eval_polynomial, lagrange_interpolate, powers, CurveAffine}; use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::Verifier; use crate::poly::commitment::MSM; @@ -19,20 +19,24 @@ use crate::poly::{ }; use crate::transcript::{EncodedChallenge, TranscriptRead}; -use ff::Field; +use ff::{Field, PrimeField, WithSmallOrderMulGroup}; use group::Group; use halo2curves::pairing::{Engine, MillerLoopResult, MultiMillerLoop}; use rand_core::OsRng; #[derive(Debug)] /// Concrete KZG verifier with GWC variant -pub struct VerifierGWC<'params, E: Engine> { +pub struct VerifierGWC<'params, E: Engine> +where + E::Scalar: PrimeField, +{ params: &'params ParamsKZG, } impl<'params, E> Verifier<'params, KZGCommitmentScheme> for VerifierGWC<'params, E> where E: MultiMillerLoop + Debug, + E::Scalar: PrimeField + WithSmallOrderMulGroup<3>, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { @@ -70,7 +74,7 @@ where let u: ChallengeU<_> = transcript.squeeze_challenge_scalar(); let mut commitment_multi = MSMKZG::::new(); - let mut eval_multi = E::Scalar::zero(); + let mut eval_multi = E::Scalar::ZERO; let mut witness = MSMKZG::::new(); let mut witness_with_aux = MSMKZG::::new(); diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs index 0b1a2492b1..d60c8f1c03 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs @@ -1,11 +1,12 @@ mod prover; mod verifier; +use ff::PrimeField; pub use prover::ProverSHPLONK; pub use verifier::VerifierSHPLONK; use crate::{ - arithmetic::{eval_polynomial, lagrange_interpolate, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, lagrange_interpolate, CurveAffine}, poly::{query::Query, Coeff, Polynomial}, transcript::ChallengeScalar, }; @@ -29,9 +30,9 @@ struct Y {} type ChallengeY = ChallengeScalar; #[derive(Debug, Clone, PartialEq)] -struct Commitment((T, Vec)); +struct Commitment((T, Vec)); -impl Commitment { +impl Commitment { fn get(&self) -> T { self.0 .0.clone() } @@ -42,18 +43,18 @@ impl Commitment { } #[derive(Debug, Clone, PartialEq)] -struct RotationSet { +struct RotationSet { commitments: Vec>, points: Vec, } #[derive(Debug, PartialEq)] -struct IntermediateSets> { +struct IntermediateSets> { rotation_sets: Vec>, super_point_set: BTreeSet, } -fn construct_intermediate_sets>( +fn construct_intermediate_sets>( queries: I, ) -> IntermediateSets where @@ -148,6 +149,7 @@ where #[cfg(test)] mod proptests { + use ff::FromUniformBytes; use proptest::{ collection::vec, prelude::*, @@ -157,7 +159,7 @@ mod proptests { use super::{construct_intermediate_sets, Commitment, IntermediateSets}; use crate::poly::Rotation; - use halo2curves::{pasta::Fp, FieldExt}; + use halo2curves::pasta::Fp; use std::collections::BTreeMap; use std::convert::TryFrom; @@ -190,7 +192,7 @@ mod proptests { fn arb_point()( bytes in vec(any::(), 64) ) -> Fp { - Fp::from_bytes_wide(&<[u8; 64]>::try_from(bytes).unwrap()) + Fp::from_uniform_bytes(&<[u8; 64]>::try_from(bytes).unwrap()) } } diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs index 3206364b8f..4d5a9ed900 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs @@ -3,7 +3,7 @@ use super::{ }; use crate::arithmetic::{ eval_polynomial, evaluate_vanishing_polynomial, kate_division, lagrange_interpolate, - parallelize, powers, CurveAffine, FieldExt, + parallelize, powers, CurveAffine, }; use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::{Blind, ParamsProver, Prover}; @@ -13,7 +13,7 @@ use crate::poly::Rotation; use crate::poly::{commitment::Params, Coeff, Polynomial}; use crate::transcript::{EncodedChallenge, TranscriptWrite}; -use ff::Field; +use ff::{Field, PrimeField, WithSmallOrderMulGroup}; use group::Curve; use halo2curves::pairing::Engine; use rand_core::RngCore; @@ -23,7 +23,7 @@ use std::io::{self, Write}; use std::marker::PhantomData; use std::ops::MulAssign; -fn div_by_vanishing(poly: Polynomial, roots: &[F]) -> Vec { +fn div_by_vanishing(poly: Polynomial, roots: &[F]) -> Vec { let poly = roots .iter() .fold(poly.values, |poly, point| kate_division(&poly, *point)); @@ -90,11 +90,17 @@ impl<'a, C: CurveAffine> RotationSet> { /// Concrete KZG prover with SHPLONK variant #[derive(Debug)] -pub struct ProverSHPLONK<'a, E: Engine> { +pub struct ProverSHPLONK<'a, E: Engine> +where + E::Scalar: PrimeField, +{ params: &'a ParamsKZG, } -impl<'a, E: Engine> ProverSHPLONK<'a, E> { +impl<'a, E: Engine> ProverSHPLONK<'a, E> +where + E::Scalar: PrimeField, +{ /// Given parameters creates new prover instance pub fn new(params: &'a ParamsKZG) -> Self { Self { params } @@ -105,6 +111,7 @@ impl<'a, E: Engine> ProverSHPLONK<'a, E> { impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme> for ProverSHPLONK<'params, E> where + E::Scalar: PrimeField + Ord + WithSmallOrderMulGroup<3>, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { @@ -162,7 +169,7 @@ where // Q_i(X) = N_i(X) / Z_i(X) where // Z_i(X) = (x - r_i_0) * (x - r_i_1) * ... let mut poly = div_by_vanishing(n_x, points); - poly.resize(self.params.n as usize, E::Scalar::zero()); + poly.resize(self.params.n as usize, E::Scalar::ZERO); Polynomial { values: poly, @@ -261,7 +268,7 @@ where #[cfg(debug_assertions)] { let must_be_zero = eval_polynomial(&l_x.values[..], *u); - assert_eq!(must_be_zero, E::Scalar::zero()); + assert_eq!(must_be_zero, E::Scalar::ZERO); } let mut h_x = div_by_vanishing(l_x, &[*u]); diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs index 11ffa880ef..69183c1eb2 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs @@ -5,7 +5,6 @@ use super::ChallengeY; use super::{construct_intermediate_sets, ChallengeU, ChallengeV}; use crate::arithmetic::{ eval_polynomial, evaluate_vanishing_polynomial, lagrange_interpolate, powers, CurveAffine, - FieldExt, }; use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::Verifier; @@ -22,7 +21,7 @@ use crate::poly::{ Error, }; use crate::transcript::{EncodedChallenge, TranscriptRead}; -use ff::Field; +use ff::{Field, PrimeField, WithSmallOrderMulGroup}; use group::Group; use halo2curves::pairing::{Engine, MillerLoopResult, MultiMillerLoop}; use rand_core::OsRng; @@ -30,13 +29,17 @@ use std::ops::MulAssign; /// Concrete KZG multiopen verifier with SHPLONK variant #[derive(Debug)] -pub struct VerifierSHPLONK<'params, E: Engine> { +pub struct VerifierSHPLONK<'params, E: Engine> +where + E::Scalar: PrimeField, +{ params: &'params ParamsKZG, } impl<'params, E> Verifier<'params, KZGCommitmentScheme> for VerifierSHPLONK<'params, E> where E: MultiMillerLoop + Debug, + E::Scalar: PrimeField + Ord + WithSmallOrderMulGroup<3>, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { @@ -77,8 +80,8 @@ where let u: ChallengeU<_> = transcript.squeeze_challenge_scalar(); let h2 = transcript.read_point().map_err(|_| Error::SamplingError)?; - let (mut z_0_diff_inverse, mut z_0) = (E::Scalar::zero(), E::Scalar::zero()); - let (mut outer_msm, mut r_outer_acc) = (PreMSM::::new(), E::Scalar::zero()); + let (mut z_0_diff_inverse, mut z_0) = (E::Scalar::ZERO, E::Scalar::ZERO); + let (mut outer_msm, mut r_outer_acc) = (PreMSM::::new(), E::Scalar::ZERO); for (i, (rotation_set, power_of_v)) in rotation_sets.iter().zip(powers(*v)).enumerate() { let diffs: Vec = super_point_set .iter() @@ -91,7 +94,7 @@ where if i == 0 { z_0 = evaluate_vanishing_polynomial(&rotation_set.points[..], *u); z_0_diff_inverse = z_diff_i.invert().unwrap(); - z_diff_i = E::Scalar::one(); + z_diff_i = E::Scalar::ONE; } else { z_diff_i.mul_assign(z_0_diff_inverse); } @@ -137,9 +140,7 @@ where outer_msm.append_term(-z_0, h1.into()); outer_msm.append_term(*u, h2.into()); - msm_accumulator - .left - .append_term(E::Scalar::one(), h2.into()); + msm_accumulator.left.append_term(E::Scalar::ONE, h2.into()); msm_accumulator.right.add_msm(&outer_msm); diff --git a/halo2_proofs/src/poly/kzg/strategy.rs b/halo2_proofs/src/poly/kzg/strategy.rs index ca4b4fb18a..9fc4d1c2fa 100644 --- a/halo2_proofs/src/poly/kzg/strategy.rs +++ b/halo2_proofs/src/poly/kzg/strategy.rs @@ -15,7 +15,7 @@ use crate::{ }, transcript::{EncodedChallenge, TranscriptRead}, }; -use ff::Field; +use ff::{Field, PrimeField, WithSmallOrderMulGroup}; use group::Group; use halo2curves::{ pairing::{Engine, MillerLoopResult, MultiMillerLoop}, @@ -25,7 +25,10 @@ use rand_core::OsRng; /// Wrapper for linear verification accumulator #[derive(Debug, Clone)] -pub struct GuardKZG<'params, E: MultiMillerLoop + Debug> { +pub struct GuardKZG<'params, E: MultiMillerLoop + Debug> +where + E::Scalar: PrimeField, +{ pub(crate) msm_accumulator: DualMSM<'params, E>, } @@ -33,6 +36,7 @@ pub struct GuardKZG<'params, E: MultiMillerLoop + Debug> { impl<'params, E> Guard> for GuardKZG<'params, E> where E: MultiMillerLoop + Debug, + E::Scalar: WithSmallOrderMulGroup<3>, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { @@ -40,7 +44,10 @@ where } /// KZG specific operations -impl<'params, E: MultiMillerLoop + Debug> GuardKZG<'params, E> { +impl<'params, E: MultiMillerLoop + Debug> GuardKZG<'params, E> +where + E::Scalar: PrimeField, +{ pub(crate) fn new(msm_accumulator: DualMSM<'params, E>) -> Self { Self { msm_accumulator } } @@ -48,11 +55,17 @@ impl<'params, E: MultiMillerLoop + Debug> GuardKZG<'params, E> { /// A verifier that checks multiple proofs in a batch #[derive(Clone, Debug)] -pub struct AccumulatorStrategy<'params, E: Engine> { +pub struct AccumulatorStrategy<'params, E: Engine> +where + E::Scalar: PrimeField, +{ pub(crate) msm_accumulator: DualMSM<'params, E>, } -impl<'params, E: MultiMillerLoop + Debug> AccumulatorStrategy<'params, E> { +impl<'params, E: MultiMillerLoop + Debug> AccumulatorStrategy<'params, E> +where + E::Scalar: PrimeField, +{ /// Constructs an empty batch verifier pub fn new(params: &'params ParamsKZG) -> Self { AccumulatorStrategy { @@ -68,11 +81,17 @@ impl<'params, E: MultiMillerLoop + Debug> AccumulatorStrategy<'params, E> { /// A verifier that checks a single proof #[derive(Clone, Debug)] -pub struct SingleStrategy<'params, E: Engine> { +pub struct SingleStrategy<'params, E: Engine> +where + E::Scalar: PrimeField, +{ pub(crate) msm: DualMSM<'params, E>, } -impl<'params, E: MultiMillerLoop + Debug> SingleStrategy<'params, E> { +impl<'params, E: MultiMillerLoop + Debug> SingleStrategy<'params, E> +where + E::Scalar: PrimeField, +{ /// Constructs an empty batch verifier pub fn new(params: &'params ParamsKZG) -> Self { SingleStrategy { @@ -92,6 +111,7 @@ impl< >, > VerificationStrategy<'params, KZGCommitmentScheme, V> for AccumulatorStrategy<'params, E> where + E::Scalar: WithSmallOrderMulGroup<3>, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { @@ -130,6 +150,7 @@ impl< >, > VerificationStrategy<'params, KZGCommitmentScheme, V> for SingleStrategy<'params, E> where + E::Scalar: WithSmallOrderMulGroup<3>, E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { diff --git a/halo2_proofs/src/poly/multiopen_test.rs b/halo2_proofs/src/poly/multiopen_test.rs index 8dd563b15a..fa447a1a1f 100644 --- a/halo2_proofs/src/poly/multiopen_test.rs +++ b/halo2_proofs/src/poly/multiopen_test.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod test { - use crate::arithmetic::{eval_polynomial, FieldExt}; + use crate::arithmetic::eval_polynomial; use crate::plonk::Error; use crate::poly::commitment::ParamsProver; use crate::poly::commitment::{Blind, ParamsVerifier, MSM}; diff --git a/halo2_proofs/src/transcript.rs b/halo2_proofs/src/transcript.rs index 8907f9779d..f2bf2997ea 100644 --- a/halo2_proofs/src/transcript.rs +++ b/halo2_proofs/src/transcript.rs @@ -2,11 +2,12 @@ //! transcripts. use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; +use ff::FromUniformBytes; use group::ff::PrimeField; use sha3::{Digest, Keccak256}; use std::convert::TryInto; -use halo2curves::{Coordinates, CurveAffine, FieldExt}; +use halo2curves::{Coordinates, CurveAffine}; use std::io::{self, Read, Write}; use std::marker::PhantomData; @@ -119,6 +120,8 @@ pub struct Keccak256Read> { impl TranscriptReadBuffer> for Blake2bRead> +where + C::Scalar: FromUniformBytes<64>, { /// Initialize a transcript given an input buffer. fn init(reader: R) -> Self { @@ -135,6 +138,8 @@ impl TranscriptReadBuffer> impl TranscriptReadBuffer> for Keccak256Read> +where + C::Scalar: FromUniformBytes<64>, { /// Initialize a transcript given an input buffer. fn init(reader: R) -> Self { @@ -150,6 +155,8 @@ impl TranscriptReadBuffer> impl TranscriptRead> for Blake2bRead> +where + C::Scalar: FromUniformBytes<64>, { fn read_point(&mut self) -> io::Result { let mut compressed = C::Repr::default(); @@ -179,6 +186,8 @@ impl TranscriptRead> impl TranscriptRead> for Keccak256Read> +where + C::Scalar: FromUniformBytes<64>, { fn read_point(&mut self) -> io::Result { let mut compressed = C::Repr::default(); @@ -206,8 +215,9 @@ impl TranscriptRead> } } -impl Transcript> - for Blake2bRead> +impl Transcript> for Blake2bRead> +where + C::Scalar: FromUniformBytes<64>, { fn squeeze_challenge(&mut self) -> Challenge255 { self.state.update(&[BLAKE2B_PREFIX_CHALLENGE]); @@ -240,6 +250,8 @@ impl Transcript> impl Transcript> for Keccak256Read> +where + C::Scalar: FromUniformBytes<64>, { fn squeeze_challenge(&mut self) -> Challenge255 { self.state.update(&[KECCAK256_PREFIX_CHALLENGE]); @@ -298,6 +310,8 @@ pub struct Keccak256Write> { impl TranscriptWriterBuffer> for Blake2bWrite> +where + C::Scalar: FromUniformBytes<64>, { /// Initialize a transcript given an output buffer. fn init(writer: W) -> Self { @@ -319,6 +333,8 @@ impl TranscriptWriterBuffer> impl TranscriptWriterBuffer> for Keccak256Write> +where + C::Scalar: FromUniformBytes<64>, { /// Initialize a transcript given an output buffer. fn init(writer: W) -> Self { @@ -340,6 +356,8 @@ impl TranscriptWriterBuffer> impl TranscriptWrite> for Blake2bWrite> +where + C::Scalar: FromUniformBytes<64>, { fn write_point(&mut self, point: C) -> io::Result<()> { self.common_point(point)?; @@ -355,6 +373,8 @@ impl TranscriptWrite> impl TranscriptWrite> for Keccak256Write> +where + C::Scalar: FromUniformBytes<64>, { fn write_point(&mut self, point: C) -> io::Result<()> { self.common_point(point)?; @@ -370,6 +390,8 @@ impl TranscriptWrite> impl Transcript> for Blake2bWrite> +where + C::Scalar: FromUniformBytes<64>, { fn squeeze_challenge(&mut self) -> Challenge255 { self.state.update(&[BLAKE2B_PREFIX_CHALLENGE]); @@ -402,6 +424,8 @@ impl Transcript> impl Transcript> for Keccak256Write> +where + C::Scalar: FromUniformBytes<64>, { fn squeeze_challenge(&mut self) -> Challenge255 { self.state.update(&[KECCAK256_PREFIX_CHALLENGE]); @@ -496,12 +520,15 @@ impl std::ops::Deref for Challenge255 { } } -impl EncodedChallenge for Challenge255 { +impl EncodedChallenge for Challenge255 +where + C::Scalar: FromUniformBytes<64>, +{ type Input = [u8; 64]; fn new(challenge_input: &[u8; 64]) -> Self { Challenge255( - C::Scalar::from_bytes_wide(challenge_input) + C::Scalar::from_uniform_bytes(challenge_input) .to_repr() .as_ref() .try_into() diff --git a/halo2_proofs/src/transcript/blake2b.rs b/halo2_proofs/src/transcript/blake2b.rs index 99954e6efd..aae177ee35 100644 --- a/halo2_proofs/src/transcript/blake2b.rs +++ b/halo2_proofs/src/transcript/blake2b.rs @@ -70,7 +70,7 @@ impl TranscriptRead> Some(p) => p, // TODO: check that this is actually safe to push an // identity point to the transcript - None => C::Scalar::zero(), + None => C::Scalar::ZERO, }; self.common_scalar(scalar)?; diff --git a/halo2_proofs/src/transcript/poseidon.rs b/halo2_proofs/src/transcript/poseidon.rs index d9da18a440..0d4f0935ec 100644 --- a/halo2_proofs/src/transcript/poseidon.rs +++ b/halo2_proofs/src/transcript/poseidon.rs @@ -1,8 +1,9 @@ use super::{Challenge255, EncodedChallenge, Transcript, TranscriptRead, TranscriptWrite}; use crate::helpers::base_to_scalar; -use ff::Field; +use ff::{Field, FromUniformBytes}; use group::ff::PrimeField; -use halo2curves::{Coordinates, CurveAffine, FieldExt}; +use halo2curves::serde::SerdeObject; +use halo2curves::{Coordinates, CurveAffine}; use num_bigint::BigUint; use poseidon::Poseidon; use std::convert::TryInto; @@ -21,7 +22,10 @@ pub struct PoseidonRead> { } /// TODO -impl> PoseidonRead { +impl> PoseidonRead +where + C::Scalar: FromUniformBytes<64> + SerdeObject, +{ /// Initialize a transcript given an input buffer. pub fn init(reader: R) -> Self { PoseidonRead { @@ -34,6 +38,8 @@ impl> PoseidonRead { impl TranscriptRead> for PoseidonRead> +where + C::Scalar: FromUniformBytes<64> + SerdeObject, { fn read_point(&mut self) -> io::Result { let mut compressed = C::Repr::default(); @@ -64,8 +70,9 @@ impl TranscriptRead> } } -impl Transcript> - for PoseidonRead> +impl Transcript> for PoseidonRead> +where + C::Scalar: FromUniformBytes<64> + SerdeObject, { fn squeeze_challenge(&mut self) -> Challenge255 { //self.state.update(&[PREFIX_SQUEEZE]); @@ -100,13 +107,25 @@ impl Transcript> } /// TODO #[derive(Debug, Clone)] -pub struct PoseidonWrite> { +pub struct PoseidonWrite +where + W: Write, + C: CurveAffine, + E: EncodedChallenge, + C::ScalarExt: FromUniformBytes<64>, +{ state: Poseidon, writer: W, _marker: PhantomData<(C, E)>, } -impl> PoseidonWrite { +impl PoseidonWrite +where + W: Write, + C: CurveAffine, + E: EncodedChallenge, + C::ScalarExt: FromUniformBytes<64> + SerdeObject, +{ /// Initialize a transcript given an output buffer. pub fn init(writer: W) -> Self { PoseidonWrite { @@ -123,8 +142,11 @@ impl> PoseidonWrite { } } -impl TranscriptWrite> - for PoseidonWrite> +impl TranscriptWrite> for PoseidonWrite> +where + W: Write, + C: CurveAffine, + C::ScalarExt: FromUniformBytes<64> + SerdeObject, { fn write_point(&mut self, point: C) -> io::Result<()> { self.common_point(point)?; @@ -138,8 +160,11 @@ impl TranscriptWrite> } } -impl Transcript> - for PoseidonWrite> +impl Transcript> for PoseidonWrite> +where + W: Write, + C: CurveAffine, + C::ScalarExt: FromUniformBytes<64> + SerdeObject, { fn squeeze_challenge(&mut self) -> Challenge255 { //self.state.update(&[PREFIX_SQUEEZE]); diff --git a/halo2_proofs/tests/plonk_api.rs b/halo2_proofs/tests/plonk_api.rs index 113b93dab8..1b47f219d7 100644 --- a/halo2_proofs/tests/plonk_api.rs +++ b/halo2_proofs/tests/plonk_api.rs @@ -2,7 +2,10 @@ #![allow(clippy::op_ref)] use assert_matches::assert_matches; -use halo2_proofs::arithmetic::{Field, FieldExt}; +use ff::FromUniformBytes; +use ff::PrimeField; +use ff::WithSmallOrderMulGroup; +use halo2_proofs::arithmetic::Field; use halo2_proofs::circuit::{Cell, Layouter, SimpleFloorPlanner, Value}; use halo2_proofs::dev::MockProver; use halo2_proofs::plonk::{ @@ -20,400 +23,363 @@ use halo2_proofs::transcript::{ use rand_core::{OsRng, RngCore}; use std::marker::PhantomData; - const K: u32 = 5; - - /// This represents an advice column at a certain row in the ConstraintSystem - #[derive(Copy, Clone, Debug)] - pub struct Variable(Column, usize); - - #[derive(Clone)] - struct PlonkConfig { - a: Column, - b: Column, - c: Column, - d: Column, - e: Column, - - sa: Column, - sb: Column, - sc: Column, - sm: Column, - sp: Column, - sl: TableColumn, +const K: u32 = 5; + +/// This represents an advice column at a certain row in the ConstraintSystem +#[derive(Copy, Clone, Debug)] +pub struct Variable(Column, usize); + +#[derive(Clone)] +struct PlonkConfig { + a: Column, + b: Column, + c: Column, + d: Column, + e: Column, + + sa: Column, + sb: Column, + sc: Column, + sm: Column, + sp: Column, + sl: TableColumn, +} + +#[allow(clippy::type_complexity)] +trait StandardCs { + fn raw_multiply( + &self, + layouter: &mut impl Layouter, + f: F, + ) -> Result<(Cell, Cell, Cell), Error> + where + F: FnMut() -> Value<(Assigned, Assigned, Assigned)>; + fn raw_add( + &self, + layouter: &mut impl Layouter, + f: F, + ) -> Result<(Cell, Cell, Cell), Error> + where + F: FnMut() -> Value<(Assigned, Assigned, Assigned)>; + fn copy(&self, layouter: &mut impl Layouter, a: Cell, b: Cell) -> Result<(), Error>; + fn public_input(&self, layouter: &mut impl Layouter, f: F) -> Result + where + F: FnMut() -> Value; + fn lookup_table(&self, layouter: &mut impl Layouter, values: &[FF]) -> Result<(), Error>; +} + +#[derive(Clone)] +struct MyCircuit { + a: Value, + lookup_table: Vec, +} + +struct StandardPlonk { + config: PlonkConfig, + _marker: PhantomData, +} + +impl StandardPlonk { + fn new(config: PlonkConfig) -> Self { + StandardPlonk { + config, + _marker: PhantomData, + } } - - #[allow(clippy::type_complexity)] - trait StandardCs { - fn raw_multiply( - &self, - layouter: &mut impl Layouter, - f: F, - ) -> Result<(Cell, Cell, Cell), Error> - where - F: FnMut() -> Value<(Assigned, Assigned, Assigned)>; - fn raw_add( - &self, - layouter: &mut impl Layouter, - f: F, - ) -> Result<(Cell, Cell, Cell), Error> - where - F: FnMut() -> Value<(Assigned, Assigned, Assigned)>; - fn copy(&self, layouter: &mut impl Layouter, a: Cell, b: Cell) -> Result<(), Error>; - fn public_input(&self, layouter: &mut impl Layouter, f: F) -> Result - where - F: FnMut() -> Value; - fn lookup_table( - &self, - layouter: &mut impl Layouter, - values: &[FF], - ) -> Result<(), Error>; +} + +impl StandardCs for StandardPlonk { + fn raw_multiply( + &self, + layouter: &mut impl Layouter, + mut f: F, + ) -> Result<(Cell, Cell, Cell), Error> + where + F: FnMut() -> Value<(Assigned, Assigned, Assigned)>, + { + layouter.assign_region( + || "raw_multiply", + |mut region| { + let mut value = None; + let lhs = region.assign_advice( + || "lhs", + self.config.a, + 0, + || { + value = Some(f()); + value.unwrap().map(|v| v.0) + }, + )?; + region.assign_advice( + || "lhs^4", + self.config.d, + 0, + || value.unwrap().map(|v| v.0).square().square(), + )?; + let rhs = region.assign_advice( + || "rhs", + self.config.b, + 0, + || value.unwrap().map(|v| v.1), + )?; + region.assign_advice( + || "rhs^4", + self.config.e, + 0, + || value.unwrap().map(|v| v.1).square().square(), + )?; + let out = region.assign_advice( + || "out", + self.config.c, + 0, + || value.unwrap().map(|v| v.2), + )?; + + region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::ZERO))?; + region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::ZERO))?; + region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "a * b", self.config.sm, 0, || Value::known(FF::ONE))?; + Ok((lhs.cell(), rhs.cell(), out.cell())) + }, + ) } - - #[derive(Clone)] - struct MyCircuit { - a: Value, - lookup_table: Vec, + fn raw_add( + &self, + layouter: &mut impl Layouter, + mut f: F, + ) -> Result<(Cell, Cell, Cell), Error> + where + F: FnMut() -> Value<(Assigned, Assigned, Assigned)>, + { + layouter.assign_region( + || "raw_add", + |mut region| { + let mut value = None; + let lhs = region.assign_advice( + || "lhs", + self.config.a, + 0, + || { + value = Some(f()); + value.unwrap().map(|v| v.0) + }, + )?; + region.assign_advice( + || "lhs^4", + self.config.d, + 0, + || value.unwrap().map(|v| v.0).square().square(), + )?; + let rhs = region.assign_advice( + || "rhs", + self.config.b, + 0, + || value.unwrap().map(|v| v.1), + )?; + region.assign_advice( + || "rhs^4", + self.config.e, + 0, + || value.unwrap().map(|v| v.1).square().square(), + )?; + let out = region.assign_advice( + || "out", + self.config.c, + 0, + || value.unwrap().map(|v| v.2), + )?; + + region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::ONE))?; + region.assign_fixed(|| "a * b", self.config.sm, 0, || Value::known(FF::ZERO))?; + Ok((lhs.cell(), rhs.cell(), out.cell())) + }, + ) } - - struct StandardPlonk { - config: PlonkConfig, - _marker: PhantomData, + fn copy(&self, layouter: &mut impl Layouter, left: Cell, right: Cell) -> Result<(), Error> { + layouter.assign_region( + || "copy", + |mut region| { + region.constrain_equal(left, right)?; + region.constrain_equal(left, right) + }, + ) } - - impl StandardPlonk { - fn new(config: PlonkConfig) -> Self { - StandardPlonk { - config, - _marker: PhantomData, - } - } + fn public_input(&self, layouter: &mut impl Layouter, mut f: F) -> Result + where + F: FnMut() -> Value, + { + layouter.assign_region( + || "public_input", + |mut region| { + let value = region.assign_advice(|| "value", self.config.a, 0, &mut f)?; + region.assign_fixed(|| "public", self.config.sp, 0, || Value::known(FF::ONE))?; + + Ok(value.cell()) + }, + ) } - - impl StandardCs for StandardPlonk { - fn raw_multiply( - &self, - layouter: &mut impl Layouter, - mut f: F, - ) -> Result<(Cell, Cell, Cell), Error> - where - F: FnMut() -> Value<(Assigned, Assigned, Assigned)>, - { - layouter.assign_region( - || "raw_multiply", - |mut region| { - let mut value = None; - let lhs = region.assign_advice( - || "lhs", - self.config.a, - 0, - || { - value = Some(f()); - value.unwrap().map(|v| v.0) - }, - )?; - region.assign_advice( - || "lhs^4", - self.config.d, - 0, - || value.unwrap().map(|v| v.0).square().square(), - )?; - let rhs = region.assign_advice( - || "rhs", - self.config.b, - 0, - || value.unwrap().map(|v| v.1), - )?; - region.assign_advice( - || "rhs^4", - self.config.e, - 0, - || value.unwrap().map(|v| v.1).square().square(), - )?; - let out = region.assign_advice( - || "out", - self.config.c, - 0, - || value.unwrap().map(|v| v.2), + fn lookup_table(&self, layouter: &mut impl Layouter, values: &[FF]) -> Result<(), Error> { + layouter.assign_table( + || "", + |mut table| { + for (index, &value) in values.iter().enumerate() { + table.assign_cell( + || "table col", + self.config.sl, + index, + || Value::known(value), )?; + } + Ok(()) + }, + )?; + Ok(()) + } +} - region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::zero()))?; - region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::zero()))?; - region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::one()))?; - region.assign_fixed( - || "a * b", - self.config.sm, - 0, - || Value::known(FF::one()), - )?; - Ok((lhs.cell(), rhs.cell(), out.cell())) - }, - ) - } - fn raw_add( - &self, - layouter: &mut impl Layouter, - mut f: F, - ) -> Result<(Cell, Cell, Cell), Error> - where - F: FnMut() -> Value<(Assigned, Assigned, Assigned)>, - { - layouter.assign_region( - || "raw_add", - |mut region| { - let mut value = None; - let lhs = region.assign_advice( - || "lhs", - self.config.a, - 0, - || { - value = Some(f()); - value.unwrap().map(|v| v.0) - }, - )?; - region.assign_advice( - || "lhs^4", - self.config.d, - 0, - || value.unwrap().map(|v| v.0).square().square(), - )?; - let rhs = region.assign_advice( - || "rhs", - self.config.b, - 0, - || value.unwrap().map(|v| v.1), - )?; - region.assign_advice( - || "rhs^4", - self.config.e, - 0, - || value.unwrap().map(|v| v.1).square().square(), - )?; - let out = region.assign_advice( - || "out", - self.config.c, - 0, - || value.unwrap().map(|v| v.2), - )?; +impl Circuit for MyCircuit { + type Config = PlonkConfig; + type FloorPlanner = SimpleFloorPlanner; - region.assign_fixed(|| "a", self.config.sa, 0, || Value::known(FF::one()))?; - region.assign_fixed(|| "b", self.config.sb, 0, || Value::known(FF::one()))?; - region.assign_fixed(|| "c", self.config.sc, 0, || Value::known(FF::one()))?; - region.assign_fixed( - || "a * b", - self.config.sm, - 0, - || Value::known(FF::zero()), - )?; - Ok((lhs.cell(), rhs.cell(), out.cell())) - }, - ) - } - fn copy( - &self, - layouter: &mut impl Layouter, - left: Cell, - right: Cell, - ) -> Result<(), Error> { - layouter.assign_region( - || "copy", - |mut region| { - region.constrain_equal(left, right)?; - region.constrain_equal(left, right) - }, - ) + fn without_witnesses(&self) -> Self { + Self { + a: Value::unknown(), + lookup_table: self.lookup_table.clone(), } - fn public_input(&self, layouter: &mut impl Layouter, mut f: F) -> Result - where - F: FnMut() -> Value, - { - layouter.assign_region( - || "public_input", - |mut region| { - let value = region.assign_advice(|| "value", self.config.a, 0, &mut f)?; - region.assign_fixed( - || "public", - self.config.sp, - 0, - || Value::known(FF::one()), - )?; + } - Ok(value.cell()) - }, - ) - } - fn lookup_table( - &self, - layouter: &mut impl Layouter, - values: &[FF], - ) -> Result<(), Error> { - layouter.assign_table( - || "", - |mut table| { - for (index, &value) in values.iter().enumerate() { - table.assign_cell( - || "table col", - self.config.sl, - index, - || Value::known(value), - )?; - } - Ok(()) - }, - )?; - Ok(()) + fn configure(meta: &mut ConstraintSystem) -> PlonkConfig { + let e = meta.advice_column(); + let a = meta.advice_column(); + let b = meta.advice_column(); + let sf = meta.fixed_column(); + let c = meta.advice_column(); + let d = meta.advice_column(); + let p = meta.instance_column(); + + meta.enable_equality(a); + meta.enable_equality(b); + meta.enable_equality(c); + + let sm = meta.fixed_column(); + let sa = meta.fixed_column(); + let sb = meta.fixed_column(); + let sc = meta.fixed_column(); + let sp = meta.fixed_column(); + let sl = meta.lookup_table_column(); + + /* + * A B ... sl + * [ + * instance 0 ... 0 + * a a ... 0 + * a a^2 ... 0 + * a a ... 0 + * a a^2 ... 0 + * ... ... ... ... + * ... ... ... instance + * ... ... ... a + * ... ... ... a + * ... ... ... 0 + * ] + */ + + meta.lookup("lookup", |meta| { + let a_ = meta.query_any(a, Rotation::cur()); + vec![(a_, sl)] + }); + + meta.create_gate("Combined add-mult", |meta| { + let d = meta.query_advice(d, Rotation::next()); + let a = meta.query_advice(a, Rotation::cur()); + let sf = meta.query_fixed(sf, Rotation::cur()); + let e = meta.query_advice(e, Rotation::prev()); + let b = meta.query_advice(b, Rotation::cur()); + let c = meta.query_advice(c, Rotation::cur()); + + let sa = meta.query_fixed(sa, Rotation::cur()); + let sb = meta.query_fixed(sb, Rotation::cur()); + let sc = meta.query_fixed(sc, Rotation::cur()); + let sm = meta.query_fixed(sm, Rotation::cur()); + + vec![a.clone() * sa + b.clone() * sb + a * b * sm - (c * sc) + sf * (d * e)] + }); + + meta.create_gate("Public input", |meta| { + let a = meta.query_advice(a, Rotation::cur()); + let p = meta.query_instance(p, Rotation::cur()); + let sp = meta.query_fixed(sp, Rotation::cur()); + + vec![sp * (a - p)] + }); + + meta.enable_equality(sf); + meta.enable_equality(e); + meta.enable_equality(d); + meta.enable_equality(p); + meta.enable_equality(sm); + meta.enable_equality(sa); + meta.enable_equality(sb); + meta.enable_equality(sc); + meta.enable_equality(sp); + + PlonkConfig { + a, + b, + c, + d, + e, + sa, + sb, + sc, + sm, + sp, + sl, } } - impl Circuit for MyCircuit { - type Config = PlonkConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self { - a: Value::unknown(), - lookup_table: self.lookup_table.clone(), - } + fn synthesize(&self, config: PlonkConfig, mut layouter: impl Layouter) -> Result<(), Error> { + let cs = StandardPlonk::new(config); + + let _ = cs.public_input(&mut layouter, || Value::known(F::ONE + F::ONE))?; + + for _ in 0..10 { + let a: Value> = self.a.into(); + let mut a_squared = Value::unknown(); + let (a0, _, c0) = cs.raw_multiply(&mut layouter, || { + a_squared = a.square(); + a.zip(a_squared).map(|(a, a_squared)| (a, a, a_squared)) + })?; + let (a1, b1, _) = cs.raw_add(&mut layouter, || { + let fin = a_squared + a; + a.zip(a_squared) + .zip(fin) + .map(|((a, a_squared), fin)| (a, a_squared, fin)) + })?; + cs.copy(&mut layouter, a0, a1)?; + cs.copy(&mut layouter, b1, c0)?; } - fn configure(meta: &mut ConstraintSystem) -> PlonkConfig { - let e = meta.advice_column(); - let a = meta.advice_column(); - let b = meta.advice_column(); - let sf = meta.fixed_column(); - let c = meta.advice_column(); - let d = meta.advice_column(); - let p = meta.instance_column(); - - meta.enable_equality(a); - meta.enable_equality(b); - meta.enable_equality(c); - - let sm = meta.fixed_column(); - let sa = meta.fixed_column(); - let sb = meta.fixed_column(); - let sc = meta.fixed_column(); - let sp = meta.fixed_column(); - let sl = meta.lookup_table_column(); - - /* - * A B ... sl - * [ - * instance 0 ... 0 - * a a ... 0 - * a a^2 ... 0 - * a a ... 0 - * a a^2 ... 0 - * ... ... ... ... - * ... ... ... instance - * ... ... ... a - * ... ... ... a - * ... ... ... 0 - * ] - */ - - meta.lookup("lookup", |meta| { - let a_ = meta.query_any(a, Rotation::cur()); - vec![(a_, sl)] - }); - - meta.create_gate("Combined add-mult", |meta| { - let d = meta.query_advice(d, Rotation::next()); - let a = meta.query_advice(a, Rotation::cur()); - let sf = meta.query_fixed(sf, Rotation::cur()); - let e = meta.query_advice(e, Rotation::prev()); - let b = meta.query_advice(b, Rotation::cur()); - let c = meta.query_advice(c, Rotation::cur()); - - let sa = meta.query_fixed(sa, Rotation::cur()); - let sb = meta.query_fixed(sb, Rotation::cur()); - let sc = meta.query_fixed(sc, Rotation::cur()); - let sm = meta.query_fixed(sm, Rotation::cur()); - - vec![a.clone() * sa + b.clone() * sb + a * b * sm - (c * sc) + sf * (d * e)] - }); - - meta.create_gate("Public input", |meta| { - let a = meta.query_advice(a, Rotation::cur()); - let p = meta.query_instance(p, Rotation::cur()); - let sp = meta.query_fixed(sp, Rotation::cur()); - - vec![sp * (a - p)] - }); - - meta.enable_equality(sf); - meta.enable_equality(e); - meta.enable_equality(d); - meta.enable_equality(p); - meta.enable_equality(sm); - meta.enable_equality(sa); - meta.enable_equality(sb); - meta.enable_equality(sc); - meta.enable_equality(sp); - - PlonkConfig { - a, - b, - c, - d, - e, - sa, - sb, - sc, - sm, - sp, - sl, - } - } + cs.lookup_table(&mut layouter, &self.lookup_table)?; - fn synthesize( - &self, - config: PlonkConfig, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let cs = StandardPlonk::new(config); - - let _ = cs.public_input(&mut layouter, || Value::known(F::one() + F::one()))?; - - for _ in 0..10 { - let a: Value> = self.a.into(); - let mut a_squared = Value::unknown(); - let (a0, _, c0) = cs.raw_multiply(&mut layouter, || { - a_squared = a.square(); - a.zip(a_squared).map(|(a, a_squared)| (a, a, a_squared)) - })?; - let (a1, b1, _) = cs.raw_add(&mut layouter, || { - let fin = a_squared + a; - a.zip(a_squared) - .zip(fin) - .map(|((a, a_squared), fin)| (a, a_squared, fin)) - })?; - cs.copy(&mut layouter, a0, a1)?; - cs.copy(&mut layouter, b1, c0)?; - } - - cs.lookup_table(&mut layouter, &self.lookup_table)?; - - Ok(()) - } + Ok(()) } - - macro_rules! common { - ($scheme:ident) => {{ - let a = <$scheme as CommitmentScheme>::Scalar::from(2834758237) - * <$scheme as CommitmentScheme>::Scalar::ZETA; - let instance = <$scheme as CommitmentScheme>::Scalar::one() - + <$scheme as CommitmentScheme>::Scalar::one(); - let lookup_table = vec![ - instance, - a, - a, - <$scheme as CommitmentScheme>::Scalar::zero(), - ]; - (a, instance, lookup_table) - }}; - } - - macro_rules! bad_keys { +} + +macro_rules! common { + ($scheme:ident) => {{ + let a = <$scheme as CommitmentScheme>::Scalar::from(2834758237) + * <$scheme as CommitmentScheme>::Scalar::ZETA; + let instance = + <$scheme as CommitmentScheme>::Scalar::ONE + <$scheme as CommitmentScheme>::Scalar::ONE; + let lookup_table = vec![instance, a, a, <$scheme as CommitmentScheme>::Scalar::ZERO]; + (a, instance, lookup_table) + }}; +} + +macro_rules! bad_keys { ($scheme:ident) => {{ let (_, _, lookup_table) = common!($scheme); let empty_circuit: MyCircuit<<$scheme as CommitmentScheme>::Scalar> = MyCircuit { @@ -443,188 +409,190 @@ use std::marker::PhantomData; }}; } - fn keygen( - params: &Scheme::ParamsProver, - ) -> ProvingKey { - let (_, _, lookup_table) = common!(Scheme); - let empty_circuit: MyCircuit = MyCircuit { - a: Value::unknown(), - lookup_table, - }; - - // Initialize the proving key - let vk = keygen_vk(params, &empty_circuit).expect("keygen_vk should not fail"); - - keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail") - } - - fn create_proof< - 'params, - Scheme: CommitmentScheme, - P: Prover<'params, Scheme>, - E: EncodedChallenge, - R: RngCore, - T: TranscriptWriterBuffer, Scheme::Curve, E>, - >( - rng: R, - params: &'params Scheme::ParamsProver, - pk: &ProvingKey, - ) -> Vec { - let (a, instance, lookup_table) = common!(Scheme); - - let circuit: MyCircuit = MyCircuit { - a: Value::known(a), - lookup_table, - }; - - let mut transcript = T::init(vec![]); - - create_plonk_proof::( - params, - pk, - &[circuit.clone(), circuit.clone()], - &[&[&[instance]], &[&[instance]]], - rng, - &mut transcript, - ) - .expect("proof generation should not fail"); - - // Check this circuit is satisfied. - let prover = match MockProver::run(K, &circuit, vec![vec![instance]]) { - Ok(prover) => prover, - Err(e) => panic!("{:?}", e), - }; - assert_eq!(prover.verify(), Ok(())); - - transcript.finalize() - } - - fn verify_proof< - 'a, - 'params, - Scheme: CommitmentScheme, - V: Verifier<'params, Scheme>, - E: EncodedChallenge, - T: TranscriptReadBuffer<&'a [u8], Scheme::Curve, E>, - Strategy: VerificationStrategy<'params, Scheme, V, Output = Strategy>, - >( - params_verifier: &'params Scheme::ParamsVerifier, - vk: &VerifyingKey, - proof: &'a [u8], - ) { - let (_, instance, _) = common!(Scheme); - let pubinputs = vec![instance]; - - let mut transcript = T::init(proof); - - let strategy = Strategy::new(params_verifier); - let strategy = verify_plonk_proof( - params_verifier, - vk, - strategy, - &[&[&pubinputs[..]], &[&pubinputs[..]]], - &mut transcript, - ) - .unwrap(); - - assert!(strategy.finalize()); - } - - #[test] - fn test_plonk_api_gwc() { - use halo2_proofs::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; - use halo2_proofs::poly::kzg::multiopen::{ProverGWC, VerifierGWC}; - use halo2_proofs::poly::kzg::strategy::AccumulatorStrategy; - use halo2curves::bn256::Bn256; - - type Scheme = KZGCommitmentScheme; - bad_keys!(Scheme); - - let params = ParamsKZG::::new(K); - let rng = OsRng; - - let pk = keygen::>(¶ms); - - let proof = create_proof::<_, ProverGWC<_>, _, _, Blake2bWrite<_, _, Challenge255<_>>>( - rng, ¶ms, &pk, - ); - - let verifier_params = params.verifier_params(); - - verify_proof::< - _, - VerifierGWC<_>, - _, - Blake2bRead<_, _, Challenge255<_>>, - AccumulatorStrategy<_>, - >(verifier_params, pk.get_vk(), &proof[..]); - } - - #[test] - fn test_plonk_api_shplonk() { - use halo2_proofs::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; - use halo2_proofs::poly::kzg::multiopen::{ProverSHPLONK, VerifierSHPLONK}; - use halo2_proofs::poly::kzg::strategy::AccumulatorStrategy; - use halo2curves::bn256::Bn256; - - type Scheme = KZGCommitmentScheme; - bad_keys!(Scheme); - - let params = ParamsKZG::::new(K); - let rng = OsRng; - - let pk = keygen::>(¶ms); - - let proof = create_proof::<_, ProverSHPLONK<_>, _, _, Blake2bWrite<_, _, Challenge255<_>>>( - rng, ¶ms, &pk, - ); - - let verifier_params = params.verifier_params(); - - verify_proof::< - _, - VerifierSHPLONK<_>, - _, - Blake2bRead<_, _, Challenge255<_>>, - AccumulatorStrategy<_>, - >(verifier_params, pk.get_vk(), &proof[..]); - } - - #[test] - fn test_plonk_api_ipa() { - use halo2_proofs::poly::ipa::commitment::{IPACommitmentScheme, ParamsIPA}; - use halo2_proofs::poly::ipa::multiopen::{ProverIPA, VerifierIPA}; - use halo2_proofs::poly::ipa::strategy::AccumulatorStrategy; - use halo2curves::pasta::EqAffine; - - type Scheme = IPACommitmentScheme; - bad_keys!(Scheme); - - let params = ParamsIPA::::new(K); - let rng = OsRng; - - let pk = keygen::>(¶ms); - - let proof = create_proof::<_, ProverIPA<_>, _, _, Blake2bWrite<_, _, Challenge255<_>>>( - rng, ¶ms, &pk, - ); - - let verifier_params = params.verifier_params(); - - verify_proof::< - _, - VerifierIPA<_>, - _, - Blake2bRead<_, _, Challenge255<_>>, - AccumulatorStrategy<_>, - >(verifier_params, pk.get_vk(), &proof[..]); - - // Check that the verification key has not changed unexpectedly - { - //panic!("{:#?}", pk.get_vk().pinned()); - assert_eq!( - format!("{:#?}", pk.get_vk().pinned()), - r#####"PinnedVerificationKey { +fn keygen(params: &Scheme::ParamsProver) -> ProvingKey +where + Scheme::Scalar: FromUniformBytes<64>, +{ + let (_, _, lookup_table) = common!(Scheme); + let empty_circuit: MyCircuit = MyCircuit { + a: Value::unknown(), + lookup_table, + }; + + // Initialize the proving key + let vk = keygen_vk(params, &empty_circuit).expect("keygen_vk should not fail"); + + keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail") +} + +fn create_proof< + 'params, + Scheme: CommitmentScheme, + P: Prover<'params, Scheme>, + E: EncodedChallenge, + R: RngCore, + T: TranscriptWriterBuffer, Scheme::Curve, E>, +>( + rng: R, + params: &'params Scheme::ParamsProver, + pk: &ProvingKey, +) -> Vec +where + Scheme::Scalar: FromUniformBytes<64> + WithSmallOrderMulGroup<3> + Ord, +{ + let (a, instance, lookup_table) = common!(Scheme); + + let circuit: MyCircuit = MyCircuit { + a: Value::known(a), + lookup_table, + }; + + let mut transcript = T::init(vec![]); + + create_plonk_proof::( + params, + pk, + &[circuit.clone(), circuit.clone()], + &[&[&[instance]], &[&[instance]]], + rng, + &mut transcript, + ) + .expect("proof generation should not fail"); + + // Check this circuit is satisfied. + let prover = match MockProver::run(K, &circuit, vec![vec![instance]]) { + Ok(prover) => prover, + Err(e) => panic!("{:?}", e), + }; + assert_eq!(prover.verify(), Ok(())); + + transcript.finalize() +} + +fn verify_proof< + 'a, + 'params, + Scheme: CommitmentScheme, + V: Verifier<'params, Scheme>, + E: EncodedChallenge, + T: TranscriptReadBuffer<&'a [u8], Scheme::Curve, E>, + Strategy: VerificationStrategy<'params, Scheme, V, Output = Strategy>, +>( + params_verifier: &'params Scheme::ParamsVerifier, + vk: &VerifyingKey, + proof: &'a [u8], +) where + Scheme::Scalar: FromUniformBytes<64> + WithSmallOrderMulGroup<3> + Ord, +{ + let (_, instance, _) = common!(Scheme); + let pubinputs = vec![instance]; + + let mut transcript = T::init(proof); + + let strategy = Strategy::new(params_verifier); + let strategy = verify_plonk_proof( + params_verifier, + vk, + strategy, + &[&[&pubinputs[..]], &[&pubinputs[..]]], + &mut transcript, + ) + .unwrap(); + + assert!(strategy.finalize()); +} + +#[test] +fn test_plonk_api_gwc() { + use halo2_proofs::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; + use halo2_proofs::poly::kzg::multiopen::{ProverGWC, VerifierGWC}; + use halo2_proofs::poly::kzg::strategy::AccumulatorStrategy; + use halo2curves::bn256::Bn256; + + type Scheme = KZGCommitmentScheme; + bad_keys!(Scheme); + + let params = ParamsKZG::::new(K); + let rng = OsRng; + + let pk = keygen::>(¶ms); + + let proof = create_proof::<_, ProverGWC<_>, _, _, Blake2bWrite<_, _, Challenge255<_>>>( + rng, ¶ms, &pk, + ); + + let verifier_params = params.verifier_params(); + + verify_proof::<_, VerifierGWC<_>, _, Blake2bRead<_, _, Challenge255<_>>, AccumulatorStrategy<_>>( + verifier_params, + pk.get_vk(), + &proof[..], + ); +} + +#[test] +fn test_plonk_api_shplonk() { + use halo2_proofs::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; + use halo2_proofs::poly::kzg::multiopen::{ProverSHPLONK, VerifierSHPLONK}; + use halo2_proofs::poly::kzg::strategy::AccumulatorStrategy; + use halo2curves::bn256::Bn256; + + type Scheme = KZGCommitmentScheme; + bad_keys!(Scheme); + + let params = ParamsKZG::::new(K); + let rng = OsRng; + + let pk = keygen::>(¶ms); + + let proof = create_proof::<_, ProverSHPLONK<_>, _, _, Blake2bWrite<_, _, Challenge255<_>>>( + rng, ¶ms, &pk, + ); + + let verifier_params = params.verifier_params(); + + verify_proof::< + _, + VerifierSHPLONK<_>, + _, + Blake2bRead<_, _, Challenge255<_>>, + AccumulatorStrategy<_>, + >(verifier_params, pk.get_vk(), &proof[..]); +} + +#[test] +fn test_plonk_api_ipa() { + use halo2_proofs::poly::ipa::commitment::{IPACommitmentScheme, ParamsIPA}; + use halo2_proofs::poly::ipa::multiopen::{ProverIPA, VerifierIPA}; + use halo2_proofs::poly::ipa::strategy::AccumulatorStrategy; + use halo2curves::pasta::EqAffine; + + type Scheme = IPACommitmentScheme; + bad_keys!(Scheme); + + let params = ParamsIPA::::new(K); + let rng = OsRng; + + let pk = keygen::>(¶ms); + + let proof = create_proof::<_, ProverIPA<_>, _, _, Blake2bWrite<_, _, Challenge255<_>>>( + rng, ¶ms, &pk, + ); + + let verifier_params = params.verifier_params(); + + verify_proof::<_, VerifierIPA<_>, _, Blake2bRead<_, _, Challenge255<_>>, AccumulatorStrategy<_>>( + verifier_params, + pk.get_vk(), + &proof[..], + ); + + // Check that the verification key has not changed unexpectedly + { + //panic!("{:#?}", pk.get_vk().pinned()); + assert_eq!( + format!("{:#?}", pk.get_vk().pinned()), + r#####"PinnedVerificationKey { base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", domain: PinnedEvaluationDomain { @@ -1018,7 +986,6 @@ use std::marker::PhantomData; ], }, }"##### - ); - } + ); } - +} From 4fdb7da31d1801001cc8c46bbc869b78c6fdca1d Mon Sep 17 00:00:00 2001 From: zhenfei Date: Wed, 8 Mar 2023 17:15:33 -0500 Subject: [PATCH 58/62] upgrade to group/ff 0.13.0 for halo2_gadgets --- Cargo.toml | 5 ++ halo2_gadgets/Cargo.toml | 3 - halo2_gadgets/benches/poseidon.rs | 4 +- halo2_gadgets/benches/primitives.rs | 4 +- halo2_gadgets/benches/sha256.rs | 2 +- halo2_gadgets/src/ecc.rs | 6 +- halo2_gadgets/src/ecc/chip.rs | 6 +- halo2_gadgets/src/ecc/chip/add.rs | 9 +- halo2_gadgets/src/ecc/chip/add_incomplete.rs | 6 +- halo2_gadgets/src/ecc/chip/constants.rs | 22 ++--- halo2_gadgets/src/ecc/chip/mul.rs | 23 +++-- halo2_gadgets/src/ecc/chip/mul/complete.rs | 2 +- halo2_gadgets/src/ecc/chip/mul/incomplete.rs | 3 +- halo2_gadgets/src/ecc/chip/mul/overflow.rs | 5 +- halo2_gadgets/src/ecc/chip/mul_fixed.rs | 10 +-- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 10 +-- .../src/ecc/chip/mul_fixed/full_width.rs | 22 +++-- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 19 +++-- halo2_gadgets/src/ecc/chip/witness_point.rs | 6 +- halo2_gadgets/src/poseidon.rs | 33 ++++---- halo2_gadgets/src/poseidon/pow5.rs | 53 ++++++------ halo2_gadgets/src/poseidon/primitives.rs | 84 +++++++++++++------ halo2_gadgets/src/poseidon/primitives/fp.rs | 2 +- halo2_gadgets/src/poseidon/primitives/fq.rs | 2 +- .../src/poseidon/primitives/grain.rs | 14 ++-- halo2_gadgets/src/poseidon/primitives/mds.rs | 12 +-- .../src/poseidon/primitives/p128pow5t3.rs | 16 ++-- halo2_gadgets/src/sha256.rs | 15 ++-- halo2_gadgets/src/sha256/table16.rs | 4 +- .../src/sha256/table16/compression.rs | 4 +- .../table16/compression/compression_gates.rs | 36 ++++---- .../table16/compression/compression_util.rs | 2 +- .../table16/compression/subregion_digest.rs | 2 +- .../table16/compression/subregion_initial.rs | 2 +- .../table16/compression/subregion_main.rs | 2 +- halo2_gadgets/src/sha256/table16/gates.rs | 20 ++--- .../src/sha256/table16/message_schedule.rs | 4 +- .../message_schedule/schedule_gates.rs | 21 ++--- .../table16/message_schedule/schedule_util.rs | 2 +- .../table16/message_schedule/subregion1.rs | 2 +- .../table16/message_schedule/subregion2.rs | 2 +- .../table16/message_schedule/subregion3.rs | 2 +- .../src/sha256/table16/spread_table.rs | 83 +++++++++--------- halo2_gadgets/src/sinsemilla.rs | 14 ++-- halo2_gadgets/src/sinsemilla/chip.rs | 2 +- .../src/sinsemilla/chip/generator_table.rs | 3 +- .../src/sinsemilla/chip/hash_to_point.rs | 20 ++--- halo2_gadgets/src/sinsemilla/merkle.rs | 6 +- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 6 +- halo2_gadgets/src/sinsemilla/message.rs | 18 ++-- halo2_gadgets/src/sinsemilla/primitives.rs | 10 +-- .../src/sinsemilla/primitives/addition.rs | 4 +- .../src/sinsemilla/primitives/sinsemilla_s.rs | 2 +- halo2_gadgets/src/utilities.rs | 32 +++---- halo2_gadgets/src/utilities/cond_swap.rs | 21 ++--- .../src/utilities/decompose_running_sum.rs | 21 +++-- .../src/utilities/lookup_range_check.rs | 37 ++++---- halo2_proofs/benches/dev_lookup.rs | 6 +- halo2_proofs/benches/plonk.rs | 16 ++-- halo2_proofs/src/lib.rs | 4 + halo2_proofs/src/transcript/blake2b.rs | 4 +- 61 files changed, 430 insertions(+), 382 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b7878ae843..65a7b5dc94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,8 @@ members = [ "halo2_gadgets", "halo2_proofs", ] + + + +[patch."https://github.com/privacy-scaling-explorations/poseidon.git"] +poseidon = { git = "https://github.com/scroll-tech/poseidon.git", branch = "halo2-ecc-snark-verifier-0220" } \ No newline at end of file diff --git a/halo2_gadgets/Cargo.toml b/halo2_gadgets/Cargo.toml index 6025ef7297..f0d86c7553 100644 --- a/halo2_gadgets/Cargo.toml +++ b/halo2_gadgets/Cargo.toml @@ -24,11 +24,8 @@ rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"] [dependencies] arrayvec = "0.7.0" bitvec = "1" -ff = "0.12" -group = "0.12" halo2_proofs = { version = "0.2", path = "../halo2_proofs" } lazy_static = "1" -halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves', tag = '0.3.0' } proptest = { version = "1.0.0", optional = true } rand = "0.8" subtle = "2.3" diff --git a/halo2_gadgets/benches/poseidon.rs b/halo2_gadgets/benches/poseidon.rs index e8cfa08714..715f91e312 100644 --- a/halo2_gadgets/benches/poseidon.rs +++ b/halo2_gadgets/benches/poseidon.rs @@ -1,4 +1,5 @@ -use ff::Field; +use halo2_proofs::curves::pasta::{pallas, vesta, EqAffine, Fp}; +use halo2_proofs::ff::Field; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, plonk::{ @@ -18,7 +19,6 @@ use halo2_proofs::{ Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }, }; -use halo2curves::pasta::{pallas, vesta, EqAffine, Fp}; use halo2_gadgets::poseidon::{ primitives::{self as poseidon, ConstantLength, Spec}, diff --git a/halo2_gadgets/benches/primitives.rs b/halo2_gadgets/benches/primitives.rs index 5397efce05..6f6058cc78 100644 --- a/halo2_gadgets/benches/primitives.rs +++ b/halo2_gadgets/benches/primitives.rs @@ -1,11 +1,11 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; -use ff::Field; use halo2_gadgets::{ poseidon::primitives::{self as poseidon, ConstantLength, P128Pow5T3}, sinsemilla::primitives as sinsemilla, }; +use halo2_proofs::ff::Field; -use halo2curves::pasta::pallas; +use halo2_proofs::curves::pasta::pallas; #[cfg(unix)] use pprof::criterion::{Output, PProfProfiler}; use rand::{rngs::OsRng, Rng}; diff --git a/halo2_gadgets/benches/sha256.rs b/halo2_gadgets/benches/sha256.rs index 670956cb0d..fbb694ab15 100644 --- a/halo2_gadgets/benches/sha256.rs +++ b/halo2_gadgets/benches/sha256.rs @@ -1,10 +1,10 @@ +use halo2_proofs::curves::pasta::{pallas, EqAffine}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ConstraintSystem, Error}, poly::commitment::Params, transcript::{Blake2bRead, Blake2bWrite, Challenge255}, }; -use halo2curves::pasta::{pallas, EqAffine}; use rand::rngs::OsRng; use std::{ diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 08f34b15f2..4df13272ad 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -577,15 +577,15 @@ impl> FixedPointShort { #[cfg(test)] pub(crate) mod tests { - use ff::PrimeField; - use group::{prime::PrimeCurveAffine, Curve, Group}; + use halo2_proofs::ff::PrimeField; + use halo2_proofs::group::{prime::PrimeCurveAffine, Curve, Group}; + use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; - use halo2curves::pasta::pallas; use lazy_static::lazy_static; use super::{ diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 466234e6b7..09c29c893c 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -7,13 +7,13 @@ use crate::{ }; use arrayvec::ArrayVec; -use ff::PrimeField; -use group::prime::PrimeCurveAffine; +use halo2_proofs::curves::{pasta::pallas, CurveAffine}; +use halo2_proofs::ff::PrimeField; +use halo2_proofs::group::prime::PrimeCurveAffine; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{Advice, Assigned, Column, ConstraintSystem, Error, Fixed}, }; -use halo2curves::{pasta::pallas, CurveAffine}; use std::convert::TryInto; diff --git a/halo2_gadgets/src/ecc/chip/add.rs b/halo2_gadgets/src/ecc/chip/add.rs index 9f24d0d7dd..6f75783be6 100644 --- a/halo2_gadgets/src/ecc/chip/add.rs +++ b/halo2_gadgets/src/ecc/chip/add.rs @@ -1,10 +1,11 @@ use super::EccPoint; +use halo2_proofs::curves::pasta::pallas; +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ circuit::Region, plonk::{Advice, Assigned, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, poly::Rotation, }; -use halo2curves::{pasta::pallas, FieldExt}; use std::collections::HashSet; #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -323,7 +324,7 @@ impl Config { #[cfg(test)] // Check that the correct sum is obtained. { - use group::Curve; + use halo2_proofs::group::Curve; let p = p.point(); let q = q.point(); @@ -341,12 +342,12 @@ impl Config { #[cfg(test)] pub mod tests { - use group::{prime::PrimeCurveAffine, Curve}; + use halo2_proofs::curves::{pasta::pallas, CurveExt}; + use halo2_proofs::group::{prime::PrimeCurveAffine, Curve}; use halo2_proofs::{ circuit::{Layouter, Value}, plonk::Error, }; - use halo2curves::{pasta::pallas, CurveExt}; use crate::ecc::{chip::EccPoint, EccInstructions, NonIdentityPoint}; diff --git a/halo2_gadgets/src/ecc/chip/add_incomplete.rs b/halo2_gadgets/src/ecc/chip/add_incomplete.rs index a28391c9e1..b952bd5e4e 100644 --- a/halo2_gadgets/src/ecc/chip/add_incomplete.rs +++ b/halo2_gadgets/src/ecc/chip/add_incomplete.rs @@ -1,12 +1,12 @@ use std::collections::HashSet; use super::NonIdentityEccPoint; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::Region, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector}, poly::Rotation, }; -use halo2curves::pasta::pallas; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { @@ -147,12 +147,12 @@ impl Config { #[cfg(test)] pub mod tests { - use group::Curve; + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::group::Curve; use halo2_proofs::{ circuit::{Layouter, Value}, plonk::Error, }; - use halo2curves::pasta::pallas; use crate::ecc::{EccInstructions, NonIdentityPoint}; diff --git a/halo2_gadgets/src/ecc/chip/constants.rs b/halo2_gadgets/src/ecc/chip/constants.rs index cecbbae99a..3e26b8d040 100644 --- a/halo2_gadgets/src/ecc/chip/constants.rs +++ b/halo2_gadgets/src/ecc/chip/constants.rs @@ -1,12 +1,12 @@ //! Constants required for the ECC chip. use arrayvec::ArrayVec; -use group::{ +use halo2_proofs::arithmetic::lagrange_interpolate; +use halo2_proofs::curves::{pasta::pallas, CurveAffine}; +use halo2_proofs::group::{ ff::{Field, PrimeField}, Curve, }; -use halo2_proofs::arithmetic::lagrange_interpolate; -use halo2curves::{pasta::pallas, CurveAffine, FieldExt}; /// Window size for fixed-base scalar multiplication pub const FIXED_BASE_WINDOW_SIZE: usize = 3; @@ -61,7 +61,7 @@ fn compute_window_table(base: C, num_windows: usize) -> Vec<[C; // Generate window table entries for the last window, w = `num_windows - 1`. // For the last window, we compute [k * (2^3)^w - sum]B, where sum is defined // as sum = \sum_{j = 0}^{`num_windows - 2`} 2^{3j+1} - let sum = (0..(num_windows - 1)).fold(C::Scalar::zero(), |acc, j| { + let sum = (0..(num_windows - 1)).fold(C::Scalar::ZERO, |acc, j| { acc + C::Scalar::from(2).pow(&[FIXED_BASE_WINDOW_SIZE as u64 * j as u64 + 1, 0, 0, 0]) }); window_table.push( @@ -181,7 +181,7 @@ pub fn test_lagrange_coeffs(base: C, num_windows: usize) { .rev() .cloned() .reduce(|acc, coeff| acc * x + coeff) - .unwrap_or_else(C::Base::zero) + .unwrap_or(C::Base::ZERO) } let lagrange_coeffs = compute_lagrange_coeffs(base, num_windows); @@ -213,7 +213,7 @@ pub fn test_lagrange_coeffs(base: C, num_windows: usize) { // Compute the actual x-coordinate of the multiple [k * (8^84) - offset]B, // where offset = \sum_{j = 0}^{83} 2^{3j+1} - let offset = (0..(num_windows - 1)).fold(C::Scalar::zero(), |acc, w| { + let offset = (0..(num_windows - 1)).fold(C::Scalar::ZERO, |acc, w| { acc + C::Scalar::from(2).pow(&[FIXED_BASE_WINDOW_SIZE as u64 * w as u64 + 1, 0, 0, 0]) }); let scalar = C::Scalar::from(bits as u64) @@ -229,11 +229,11 @@ pub fn test_lagrange_coeffs(base: C, num_windows: usize) { #[cfg(test)] mod tests { - use group::{ff::Field, Curve, Group}; - use halo2curves::{pasta::pallas, CurveAffine, FieldExt}; - use proptest::prelude::*; - use super::{compute_window_table, find_zs_and_us, test_lagrange_coeffs, H, NUM_WINDOWS}; + use halo2_proofs::curves::{pasta::pallas, CurveAffine}; + use halo2_proofs::ff::FromUniformBytes; + use halo2_proofs::group::{ff::Field, Curve, Group}; + use proptest::prelude::*; prop_compose! { /// Generate an arbitrary Pallas point. @@ -241,7 +241,7 @@ mod tests { // Instead of rejecting out-of-range bytes, let's reduce them. let mut buf = [0; 64]; buf[..32].copy_from_slice(&bytes); - let scalar = pallas::Scalar::from_bytes_wide(&buf); + let scalar = pallas::Scalar::from_uniform_bytes(&buf); pallas::Point::generator() * scalar } } diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 26c705a17c..57b62c7496 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -8,16 +8,15 @@ use std::{ ops::{Deref, Range}, }; -use ff::PrimeField; +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{AssignedCell, Layouter, Region, Value}, plonk::{Advice, Assigned, Column, ConstraintSystem, Constraints, Error, Selector}, poly::Rotation, }; use uint::construct_uint; -use halo2curves::pasta::pallas; +use halo2_proofs::curves::pasta::pallas; mod complete; pub(super) mod incomplete; @@ -261,7 +260,7 @@ impl Config { #[cfg(test)] // Check that the correct multiple is obtained. { - use group::Curve; + use halo2_proofs::group::Curve; let base = base.point(); let alpha = alpha @@ -389,8 +388,8 @@ impl Config { #[derive(Clone, Debug)] // `x`-coordinate of the accumulator. -struct X(AssignedCell, F>); -impl Deref for X { +struct X(AssignedCell, F>); +impl Deref for X { type Target = AssignedCell, F>; fn deref(&self) -> &Self::Target { @@ -400,8 +399,8 @@ impl Deref for X { #[derive(Clone, Debug)] // `y`-coordinate of the accumulator. -struct Y(AssignedCell, F>); -impl Deref for Y { +struct Y(AssignedCell, F>); +impl Deref for Y { type Target = AssignedCell, F>; fn deref(&self) -> &Self::Target { @@ -411,8 +410,8 @@ impl Deref for Y { #[derive(Clone, Debug)] // Cumulative sum `z` used to decompose the scalar. -struct Z(AssignedCell); -impl Deref for Z { +struct Z(AssignedCell); +impl Deref for Z { type Target = AssignedCell; fn deref(&self) -> &Self::Target { @@ -461,7 +460,8 @@ fn decompose_for_scalar_mul(scalar: Value<&pallas::Base>) -> Vec> { #[cfg(test)] pub mod tests { - use group::{ + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::group::{ ff::{Field, PrimeField}, Curve, }; @@ -469,7 +469,6 @@ pub mod tests { circuit::{Chip, Layouter, Value}, plonk::Error, }; - use halo2curves::pasta::pallas; use rand::rngs::OsRng; use crate::{ diff --git a/halo2_gadgets/src/ecc/chip/mul/complete.rs b/halo2_gadgets/src/ecc/chip/mul/complete.rs index d23294d2fb..fabbcc06b4 100644 --- a/halo2_gadgets/src/ecc/chip/mul/complete.rs +++ b/halo2_gadgets/src/ecc/chip/mul/complete.rs @@ -8,7 +8,7 @@ use halo2_proofs::{ poly::Rotation, }; -use halo2curves::pasta::pallas; +use halo2_proofs::curves::pasta::pallas; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Config { diff --git a/halo2_gadgets/src/ecc/chip/mul/incomplete.rs b/halo2_gadgets/src/ecc/chip/mul/incomplete.rs index bfe51c7e2e..eec9c716a4 100644 --- a/halo2_gadgets/src/ecc/chip/mul/incomplete.rs +++ b/halo2_gadgets/src/ecc/chip/mul/incomplete.rs @@ -1,6 +1,8 @@ use super::super::NonIdentityEccPoint; use super::{X, Y, Z}; use crate::utilities::bool_check; +use halo2_proofs::curves::pasta::pallas; +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ circuit::{Region, Value}, plonk::{ @@ -8,7 +10,6 @@ use halo2_proofs::{ }, poly::Rotation, }; -use halo2curves::{pasta::pallas, FieldExt}; /// A helper struct for implementing single-row double-and-add using incomplete addition. #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/halo2_gadgets/src/ecc/chip/mul/overflow.rs b/halo2_gadgets/src/ecc/chip/mul/overflow.rs index 0d7bd69692..e74619de74 100644 --- a/halo2_gadgets/src/ecc/chip/mul/overflow.rs +++ b/halo2_gadgets/src/ecc/chip/mul/overflow.rs @@ -2,16 +2,15 @@ use super::{T_Q, Z}; use crate::{ sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::LookupRangeCheckConfig, }; - use halo2_proofs::circuit::AssignedCell; +use halo2_proofs::curves::pasta::pallas; +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ circuit::Layouter, plonk::{Advice, Assigned, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, poly::Rotation, }; -use halo2curves::{pasta::pallas, FieldExt}; - use std::iter; #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed.rs b/halo2_gadgets/src/ecc/chip/mul_fixed.rs index 909dd171d3..27d50c4be8 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed.rs @@ -4,9 +4,9 @@ use super::{ }; use crate::utilities::decompose_running_sum::RunningSumConfig; -use std::marker::PhantomData; - -use group::{ +use halo2_proofs::arithmetic::Field; +use halo2_proofs::curves::{pasta::pallas, CurveAffine}; +use halo2_proofs::group::{ ff::{PrimeField, PrimeFieldBits}, Curve, }; @@ -18,8 +18,8 @@ use halo2_proofs::{ }, poly::Rotation, }; -use halo2curves::{pasta::pallas, CurveAffine, FieldExt}; use lazy_static::lazy_static; +use std::marker::PhantomData; pub mod base_field_elem; pub mod full_width; @@ -388,7 +388,7 @@ impl> Config { let k_usize = scalar.windows_usize()[NUM_WINDOWS - 1]; // offset_acc = \sum_{j = 0}^{NUM_WINDOWS - 2} 2^{FIXED_BASE_WINDOW_SIZE*j + 1} - let offset_acc = (0..(NUM_WINDOWS - 1)).fold(pallas::Scalar::zero(), |acc, w| { + let offset_acc = (0..(NUM_WINDOWS - 1)).fold(pallas::Scalar::ZERO, |acc, w| { acc + (*TWO_SCALAR).pow(&[FIXED_BASE_WINDOW_SIZE as u64 * w as u64 + 1, 0, 0, 0]) }); diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 08fd34e313..91e84c082d 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -7,13 +7,13 @@ use crate::{ utilities::{bitrange_subset, lookup_range_check::LookupRangeCheckConfig, range_check}, }; -use group::ff::PrimeField; +use halo2_proofs::curves::pasta::pallas; +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ circuit::{AssignedCell, Layouter}, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, poly::Rotation, }; -use halo2curves::{pasta::pallas, FieldExt}; use std::convert::TryInto; @@ -218,7 +218,7 @@ impl> Config { // Check that the correct multiple is obtained. { use super::super::FixedPoint; - use group::Curve; + use halo2_proofs::group::Curve; let scalar = &scalar .base_field_elem() @@ -377,7 +377,8 @@ impl> Config { #[cfg(test)] pub mod tests { - use group::{ + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::group::{ ff::{Field, PrimeField}, Curve, }; @@ -385,7 +386,6 @@ pub mod tests { circuit::{Chip, Layouter, Value}, plonk::Error, }; - use halo2curves::pasta::pallas; use rand::rngs::OsRng; use crate::{ diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs index b82620c283..7c21b3cb58 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs @@ -2,13 +2,13 @@ use super::super::{EccPoint, EccScalarFixed, FixedPoints, FIXED_BASE_WINDOW_SIZE use crate::utilities::{decompose_word, range_check}; use arrayvec::ArrayVec; -use ff::PrimeField; +use halo2_proofs::curves::pasta::pallas; +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ circuit::{AssignedCell, Layouter, Region, Value}, plonk::{ConstraintSystem, Constraints, Error, Selector}, poly::Rotation, }; -use halo2curves::pasta::pallas; #[derive(Clone, Debug, Eq, PartialEq)] pub struct Config> { @@ -163,7 +163,7 @@ impl> Config { // Check that the correct multiple is obtained. { use super::super::FixedPoint; - use group::Curve; + use halo2_proofs::group::Curve; let real_mul = scalar.value.map(|scalar| base.generator() * scalar); let result = result.point(); @@ -179,12 +179,12 @@ impl> Config { #[cfg(test)] pub mod tests { - use group::{ff::Field, Curve}; + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::group::{ff::Field, Curve}; use halo2_proofs::{ circuit::{Layouter, Value}, plonk::Error, }; - use halo2curves::pasta::pallas; use rand::rngs::OsRng; use crate::ecc::{ @@ -256,11 +256,9 @@ pub mod tests { { const LAST_DOUBLING: &str = "1333333333333333333333333333333333333333333333333333333333333333333333333333333333334"; let h = pallas::Scalar::from(H as u64); - let scalar_fixed = LAST_DOUBLING - .chars() - .fold(pallas::Scalar::zero(), |acc, c| { - acc * &h + &pallas::Scalar::from(c.to_digit(8).unwrap() as u64) - }); + let scalar_fixed = LAST_DOUBLING.chars().fold(pallas::Scalar::ZERO, |acc, c| { + acc * &h + &pallas::Scalar::from(c.to_digit(8).unwrap() as u64) + }); let by = ScalarFixed::new( chip.clone(), layouter.namespace(|| LAST_DOUBLING), @@ -280,7 +278,7 @@ pub mod tests { // [0]B should return (0,0) since it uses complete addition // on the last step. { - let scalar_fixed = pallas::Scalar::zero(); + let scalar_fixed = pallas::Scalar::ZERO; let zero = ScalarFixed::new( chip.clone(), layouter.namespace(|| "0"), @@ -295,7 +293,7 @@ pub mod tests { // [-1]B is the largest scalar field element. { - let scalar_fixed = -pallas::Scalar::one(); + let scalar_fixed = -pallas::Scalar::ONE; let neg_1 = ScalarFixed::new( chip.clone(), layouter.namespace(|| "-1"), diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 844d88d134..124aeceda7 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -3,12 +3,12 @@ use std::convert::TryInto; use super::super::{EccPoint, EccScalarFixedShort, FixedPoints, L_SCALAR_SHORT, NUM_WINDOWS_SHORT}; use crate::{ecc::chip::MagnitudeSign, utilities::bool_check}; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Layouter, Region}, plonk::{ConstraintSystem, Constraints, Error, Expression, Selector}, poly::Rotation, }; -use halo2curves::pasta::pallas; #[derive(Clone, Debug, Eq, PartialEq)] pub struct Config> { @@ -209,7 +209,7 @@ impl> Config { // tested at the circuit-level. { use super::super::FixedPoint; - use group::{ff::PrimeField, Curve}; + use halo2_proofs::group::{ff::PrimeField, Curve}; scalar .magnitude @@ -228,9 +228,9 @@ impl> Config { let magnitude = pallas::Scalar::from_repr(magnitude.to_repr()).unwrap(); let sign = if sign == &&pallas::Base::one() { - pallas::Scalar::one() + pallas::Scalar::ONE } else { - -pallas::Scalar::one() + -pallas::Scalar::ONE }; magnitude * sign @@ -248,13 +248,14 @@ impl> Config { #[cfg(test)] pub mod tests { - use group::{ff::PrimeField, Curve}; + use halo2_proofs::arithmetic::Field; + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::group::{ff::PrimeField, Curve}; use halo2_proofs::{ arithmetic::CurveAffine, circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{Any, Error}, }; - use halo2curves::{pasta::pallas, FieldExt}; use crate::{ ecc::{ @@ -359,9 +360,9 @@ pub mod tests { let scalar = { let magnitude = pallas::Scalar::from_repr(magnitude.to_repr()).unwrap(); let sign = if *sign == pallas::Base::one() { - pallas::Scalar::one() + pallas::Scalar::ONE } else { - -pallas::Scalar::one() + -pallas::Scalar::ONE }; magnitude * sign }; @@ -499,7 +500,7 @@ pub mod tests { // Copied from halo2_proofs::dev::util fn format_value(v: pallas::Base) -> String { - use ff::Field; + use halo2_proofs::ff::Field; if v.is_zero_vartime() { "0".into() } else if v == pallas::Base::one() { diff --git a/halo2_gadgets/src/ecc/chip/witness_point.rs b/halo2_gadgets/src/ecc/chip/witness_point.rs index ef83bbde54..01eab1fac8 100644 --- a/halo2_gadgets/src/ecc/chip/witness_point.rs +++ b/halo2_gadgets/src/ecc/chip/witness_point.rs @@ -1,7 +1,8 @@ use super::{EccPoint, NonIdentityEccPoint}; -use group::prime::PrimeCurveAffine; +use halo2_proofs::group::prime::PrimeCurveAffine; +use halo2_proofs::curves::{pasta::pallas, CurveAffine}; use halo2_proofs::{ circuit::{AssignedCell, Region, Value}, plonk::{ @@ -10,7 +11,6 @@ use halo2_proofs::{ }, poly::Rotation, }; -use halo2curves::{pasta::pallas, CurveAffine}; type Coordinates = ( AssignedCell, pallas::Base>, @@ -152,7 +152,7 @@ impl Config { #[cfg(test)] pub mod tests { use halo2_proofs::circuit::Layouter; - use halo2curves::pasta::pallas; + use halo2_proofs::curves::pasta::pallas; use super::*; use crate::ecc::{EccInstructions, NonIdentityPoint}; diff --git a/halo2_gadgets/src/poseidon.rs b/halo2_gadgets/src/poseidon.rs index 1350075146..4b133c2671 100644 --- a/halo2_gadgets/src/poseidon.rs +++ b/halo2_gadgets/src/poseidon.rs @@ -4,9 +4,10 @@ use std::convert::TryInto; use std::fmt; use std::marker::PhantomData; -use group::ff::Field; +use halo2_proofs::ff::Field; +use halo2_proofs::ff::FromUniformBytes; +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{AssignedCell, Chip, Layouter}, plonk::Error, }; @@ -27,8 +28,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: PrimeField + Ord + FromUniformBytes<64>, + 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>; @@ -45,7 +50,7 @@ pub trait PoseidonInstructions, const T: usize, /// /// [`Hash`]: self::Hash pub trait PoseidonSpongeInstructions< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, S: Spec, D: Domain, const T: usize, @@ -71,7 +76,7 @@ pub trait PoseidonSpongeInstructions< /// A word over which the Poseidon permutation operates. #[derive(Debug)] pub struct Word< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, PoseidonChip: PoseidonInstructions, S: Spec, const T: usize, @@ -81,7 +86,7 @@ pub struct Word< } impl< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, PoseidonChip: PoseidonInstructions, S: Spec, const T: usize, @@ -100,7 +105,7 @@ impl< } fn poseidon_sponge< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -122,7 +127,7 @@ fn poseidon_sponge< /// A Poseidon sponge. #[derive(Debug)] pub struct Sponge< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, PoseidonChip: PoseidonSpongeInstructions, S: Spec, M: SpongeMode, @@ -137,7 +142,7 @@ pub struct Sponge< } impl< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -210,7 +215,7 @@ impl< } impl< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -241,7 +246,7 @@ impl< /// A Poseidon hash function, built around a sponge. #[derive(Debug)] pub struct Hash< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -252,7 +257,7 @@ pub struct Hash< } impl< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, @@ -267,7 +272,7 @@ impl< } impl< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, PoseidonChip: PoseidonSpongeInstructions, T, RATE>, S: Spec, const T: usize, diff --git a/halo2_gadgets/src/poseidon/pow5.rs b/halo2_gadgets/src/poseidon/pow5.rs index 7b9862e5b6..14d12c800d 100644 --- a/halo2_gadgets/src/poseidon/pow5.rs +++ b/halo2_gadgets/src/poseidon/pow5.rs @@ -1,14 +1,13 @@ -use std::convert::TryInto; -use std::iter; - +use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{AssignedCell, Cell, Chip, Layouter, Region, Value}, plonk::{ Advice, Any, Column, ConstraintSystem, Constraints, Error, Expression, Fixed, Selector, }, poly::Rotation, }; +use std::convert::TryInto; +use std::iter; use super::{ primitives::{Absorbing, Domain, Mds, Spec, Squeezing, State}, @@ -18,7 +17,7 @@ use crate::utilities::Var; /// 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], @@ -40,11 +39,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, const WIDTH: usize, const RATE: usize> + Pow5Chip +{ /// Configures this chip for use in a circuit. /// /// # Side-effects @@ -209,7 +210,7 @@ impl Pow5Chip Chip for Pow5Chip { +impl Chip for Pow5Chip { type Config = Pow5Config; type Loaded = (); @@ -222,8 +223,12 @@ impl Chip for Pow5Chip, const WIDTH: usize, const RATE: usize> - PoseidonInstructions for Pow5Chip +impl< + F: PrimeField + Ord + FromUniformBytes<64>, + S: Spec, + const WIDTH: usize, + const RATE: usize, + > PoseidonInstructions for Pow5Chip { type Word = StateWord; @@ -273,7 +278,7 @@ impl, const WIDTH: usize, const RATE: usize } impl< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, S: Spec, D: Domain, const WIDTH: usize, @@ -302,7 +307,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())?; @@ -372,7 +377,7 @@ impl< .get(i) .map(|word| word.0.value().cloned()) // The capacity element is never altered by the input. - .unwrap_or_else(|| Value::known(F::zero())); + .unwrap_or_else(|| Value::known(F::ZERO)); region .assign_advice( || format!("load output_{}", i), @@ -403,21 +408,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() } @@ -428,9 +433,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, @@ -450,7 +455,7 @@ impl Pow5State { r.as_ref().map(|r| { r.iter() .enumerate() - .fold(F::zero(), |acc, (j, r_j)| acc + m_i[j] * r_j) + .fold(F::ZERO, |acc, (j, r_j)| acc + m_i[j] * r_j) }) }); @@ -491,7 +496,7 @@ impl Pow5State { r.as_ref().map(|r| { m_i.iter() .zip(r.iter()) - .fold(F::zero(), |acc, (m_ij, r_j)| acc + *m_ij * r_j) + .fold(F::ZERO, |acc, (m_ij, r_j)| acc + *m_ij * r_j) }) }) .collect(); @@ -524,7 +529,7 @@ impl Pow5State { r_mid.as_ref().map(|r| { m_i.iter() .zip(r.iter()) - .fold(F::zero(), |acc, (m_ij, r_j)| acc + *m_ij * r_j) + .fold(F::ZERO, |acc, (m_ij, r_j)| acc + *m_ij * r_j) }) }) .collect(); @@ -594,13 +599,13 @@ impl Pow5State { #[cfg(test)] mod tests { - use group::ff::{Field, PrimeField}; + use halo2_proofs::curves::pasta::{pallas, Fp}; + use halo2_proofs::group::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; - use halo2curves::pasta::{pallas, Fp}; use rand::rngs::OsRng; use super::{PoseidonInstructions, Pow5Chip, Pow5Config, StateWord}; diff --git a/halo2_gadgets/src/poseidon/primitives.rs b/halo2_gadgets/src/poseidon/primitives.rs index 4d7d5b038a..61ef04ac1c 100644 --- a/halo2_gadgets/src/poseidon/primitives.rs +++ b/halo2_gadgets/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; @@ -30,7 +31,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, const T: usize, const RATE: usize>: + fmt::Debug +{ /// The number of full rounds for this specification. /// /// This must be an even number. @@ -58,7 +61,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())) @@ -76,7 +79,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: PrimeField + Ord + FromUniformBytes<64>, + S: Spec, + const T: usize, + const RATE: usize, +>( state: &mut State, mds: &Mds, round_constants: &[[F; T]], @@ -85,7 +93,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 { @@ -123,7 +131,12 @@ pub(crate) fn permute, const T: usize, const RA }); } -fn poseidon_sponge, const T: usize, const RATE: usize>( +fn poseidon_sponge< + F: PrimeField + Ord + FromUniformBytes<64>, + S: Spec, + const T: usize, + const RATE: usize, +>( state: &mut State, input: Option<&Absorbing>, mds_matrix: &Mds, @@ -180,7 +193,7 @@ impl Absorbing { /// A Poseidon sponge. pub(crate) struct Sponge< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, S: Spec, M: SpongeMode, const T: usize, @@ -193,15 +206,19 @@ pub(crate) struct Sponge< _marker: PhantomData, } -impl, const T: usize, const RATE: usize> - Sponge, T, RATE> +impl< + F: PrimeField + Ord + FromUniformBytes<64>, + S: Spec, + const T: usize, + const RATE: usize, + > Sponge, T, RATE> { /// Constructs a new sponge for the given Poseidon specification. pub(crate) fn new(initial_capacity_element: F) -> Self { 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] = initial_capacity_element; Sponge { @@ -251,8 +268,12 @@ impl, const T: usize, const RATE: usize> } } -impl, const T: usize, const RATE: usize> - Sponge, T, RATE> +impl< + F: PrimeField + Ord + FromUniformBytes<64>, + S: Spec, + const T: usize, + const RATE: usize, + > Sponge, T, RATE> { /// Squeezes an element from the sponge. pub(crate) fn squeeze(&mut self) -> F { @@ -275,7 +296,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; @@ -295,7 +316,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 { @@ -315,13 +336,13 @@ 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) } } /// A Poseidon hash function, built around a sponge. pub struct Hash< - F: FieldExt, + F: PrimeField + Ord + FromUniformBytes<64>, S: Spec, D: Domain, const T: usize, @@ -331,8 +352,13 @@ pub struct Hash< _domain: PhantomData, } -impl, D: Domain, const T: usize, const RATE: usize> - fmt::Debug for Hash +impl< + F: PrimeField + Ord + FromUniformBytes<64>, + 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") @@ -345,8 +371,13 @@ impl, D: Domain, const T: usize, const } } -impl, D: Domain, const T: usize, const RATE: usize> - Hash +impl< + F: PrimeField + Ord + FromUniformBytes<64>, + S: Spec, + D: Domain, + const T: usize, + const RATE: usize, + > Hash { /// Initializes a new hasher. pub fn init() -> Self { @@ -357,8 +388,13 @@ impl, D: Domain, const T: usize, const } } -impl, const T: usize, const RATE: usize, const L: usize> - Hash, T, RATE> +impl< + F: PrimeField + Ord + FromUniformBytes<64>, + 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 { @@ -374,9 +410,9 @@ impl, const T: usize, const RATE: usize, const #[cfg(test)] mod tests { - use halo2curves::{pasta::pallas, FieldExt}; - use super::{permute, ConstantLength, Hash, P128Pow5T3 as OrchardNullifier, Spec}; + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::ff::PrimeField; #[test] fn orchard_spec_equivalence() { diff --git a/halo2_gadgets/src/poseidon/primitives/fp.rs b/halo2_gadgets/src/poseidon/primitives/fp.rs index 38b38937fb..adc8ed8d92 100644 --- a/halo2_gadgets/src/poseidon/primitives/fp.rs +++ b/halo2_gadgets/src/poseidon/primitives/fp.rs @@ -6,7 +6,7 @@ //! ```text //! $ sage generate_parameters_grain.sage 1 0 255 3 8 56 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001 //! ``` -use halo2curves::pasta::pallas; +use halo2_proofs::curves::pasta::pallas; // Number of round constants: 192 // Round constants for GF(p): diff --git a/halo2_gadgets/src/poseidon/primitives/fq.rs b/halo2_gadgets/src/poseidon/primitives/fq.rs index 3629318adc..f9b43c9f82 100644 --- a/halo2_gadgets/src/poseidon/primitives/fq.rs +++ b/halo2_gadgets/src/poseidon/primitives/fq.rs @@ -6,7 +6,7 @@ //! ```text //! sage generate_parameters_grain.sage 1 0 255 3 8 56 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 //! ``` -use halo2curves::pasta::vesta; +use halo2_proofs::curves::pasta::vesta; // Number of round constants: 192 // Round constants for GF(p): diff --git a/halo2_gadgets/src/poseidon/primitives/grain.rs b/halo2_gadgets/src/poseidon/primitives/grain.rs index f3cf94f761..46c264d0d9 100644 --- a/halo2_gadgets/src/poseidon/primitives/grain.rs +++ b/halo2_gadgets/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, PrimeField}; const STATE: usize = 80; @@ -43,13 +43,13 @@ impl SboxType { } } -pub(super) struct Grain { +pub(super) struct Grain { state: BitArr!(for 80, in u8, Msb0), next_bit: usize, _field: PhantomData, } -impl Grain { +impl> 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> Iterator for Grain { type Item = bool; fn next(&mut self) -> Option { @@ -181,7 +181,7 @@ impl Iterator for Grain { #[cfg(test)] mod tests { - use halo2curves::pasta::Fp; + use halo2_proofs::curves::pasta::Fp; use super::{Grain, SboxType}; diff --git a/halo2_gadgets/src/poseidon/primitives/mds.rs b/halo2_gadgets/src/poseidon/primitives/mds.rs index fb809e3a79..8374d5805b 100644 --- a/halo2_gadgets/src/poseidon/primitives/mds.rs +++ b/halo2_gadgets/src/poseidon/primitives/mds.rs @@ -1,8 +1,8 @@ -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use super::{grain::Grain, Mds}; -pub(super) fn generate_mds( +pub(super) fn generate_mds, 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 { @@ -98,7 +98,7 @@ pub(super) fn generate_mds( #[cfg(test)] mod tests { - use halo2curves::pasta::Fp; + use halo2_proofs::curves::pasta::Fp; use super::{generate_mds, Grain}; diff --git a/halo2_gadgets/src/poseidon/primitives/p128pow5t3.rs b/halo2_gadgets/src/poseidon/primitives/p128pow5t3.rs index 379c399b4e..e6134608e0 100644 --- a/halo2_gadgets/src/poseidon/primitives/p128pow5t3.rs +++ b/halo2_gadgets/src/poseidon/primitives/p128pow5t3.rs @@ -1,5 +1,5 @@ use halo2_proofs::arithmetic::Field; -use halo2curves::pasta::{pallas::Base as Fp, vesta::Base as Fq}; +use halo2_proofs::curves::pasta::{pallas::Base as Fp, vesta::Base as Fq}; use super::{Mds, Spec}; @@ -66,11 +66,9 @@ impl Spec for P128Pow5T3 { #[cfg(test)] mod tests { - use ff::PrimeField; + use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use std::marker::PhantomData; - use halo2curves::FieldExt; - use super::{ super::{fp, fq}, Fp, Fq, @@ -80,15 +78,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); - 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 } @@ -108,7 +108,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/halo2_gadgets/src/sha256.rs b/halo2_gadgets/src/sha256.rs index 19a658df3a..2e08ed1369 100644 --- a/halo2_gadgets/src/sha256.rs +++ b/halo2_gadgets/src/sha256.rs @@ -2,15 +2,14 @@ //! //! [SHA-256]: https://tools.ietf.org/html/rfc6234 -use std::cmp::min; -use std::convert::TryInto; -use std::fmt; - +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{Chip, Layouter}, plonk::Error, }; +use std::cmp::min; +use std::convert::TryInto; +use std::fmt; mod table16; @@ -22,7 +21,7 @@ pub const BLOCK_SIZE: usize = 16; const DIGEST_SIZE: usize = 8; /// The set of circuit instructions required to use the [`Sha256`] gadget. -pub trait Sha256Instructions: Chip { +pub trait Sha256Instructions: Chip { /// Variable representing the SHA-256 internal state. type State: Clone + fmt::Debug; /// Variable representing a 32-bit word of the input block to the SHA-256 compression @@ -63,14 +62,14 @@ pub struct Sha256Digest([BlockWord; DIGEST_SIZE]); /// A gadget that constrains a SHA-256 invocation. It supports input at a granularity of /// 32 bits. #[derive(Debug)] -pub struct Sha256> { +pub struct Sha256> { chip: CS, state: CS::State, cur_block: Vec, length: usize, } -impl> Sha256 { +impl> Sha256 { /// Create a new hasher instance. pub fn new(chip: Sha256Chip, mut layouter: impl Layouter) -> Result { let state = chip.initialization_vector(&mut layouter)?; diff --git a/halo2_gadgets/src/sha256/table16.rs b/halo2_gadgets/src/sha256/table16.rs index c4919158bc..3167f85473 100644 --- a/halo2_gadgets/src/sha256/table16.rs +++ b/halo2_gadgets/src/sha256/table16.rs @@ -2,11 +2,11 @@ use std::convert::TryInto; use std::marker::PhantomData; use super::Sha256Instructions; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Region, Value}, plonk::{Advice, Any, Assigned, Column, ConstraintSystem, Error}, }; -use halo2curves::pasta::pallas; mod compression; mod gates; @@ -454,11 +454,11 @@ trait Table16Assignment { mod tests { use super::super::{Sha256, BLOCK_SIZE}; use super::{message_schedule::msg_schedule_test_input, Table16Chip, Table16Config}; + use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, plonk::{Circuit, ConstraintSystem, Error}, }; - use halo2curves::pasta::pallas; #[test] fn print_sha256_circuit() { diff --git a/halo2_gadgets/src/sha256/table16/compression.rs b/halo2_gadgets/src/sha256/table16/compression.rs index 62deb42937..a07bad6cd1 100644 --- a/halo2_gadgets/src/sha256/table16/compression.rs +++ b/halo2_gadgets/src/sha256/table16/compression.rs @@ -3,12 +3,12 @@ use super::{ util::{i2lebsp, lebs2ip}, AssignedBits, BlockWord, SpreadInputs, SpreadVar, Table16Assignment, ROUNDS, STATE, }; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Layouter, Value}, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; use std::ops::Range; @@ -940,12 +940,12 @@ mod tests { use super::super::{ super::BLOCK_SIZE, msg_schedule_test_input, BlockWord, Table16Chip, Table16Config, IV, }; + use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; - use halo2curves::pasta::pallas; #[test] fn compress() { diff --git a/halo2_gadgets/src/sha256/table16/compression/compression_gates.rs b/halo2_gadgets/src/sha256/table16/compression/compression_gates.rs index e22a10210c..bb94fd747b 100644 --- a/halo2_gadgets/src/sha256/table16/compression/compression_gates.rs +++ b/halo2_gadgets/src/sha256/table16/compression/compression_gates.rs @@ -1,15 +1,15 @@ use super::super::{util::*, Gate}; use halo2_proofs::{ - arithmetic::FieldExt, + ff::PrimeField, plonk::{Constraint, Constraints, Expression}, }; use std::marker::PhantomData; -pub struct CompressionGate(PhantomData); +pub struct CompressionGate(PhantomData); -impl CompressionGate { +impl CompressionGate { fn ones() -> Expression { - Expression::Constant(F::one()) + Expression::Constant(F::ONE) } // Decompose `A,B,C,D` words @@ -59,16 +59,16 @@ impl CompressionGate { + c_mid * F::from(1 << 16) + c_hi * F::from(1 << 19) + d * F::from(1 << 22) - + word_lo * (-F::one()) - + word_hi * F::from(1 << 16) * (-F::one()); + + word_lo * (-F::ONE) + + word_hi * F::from(1 << 16) * (-F::ONE); let spread_check = spread_a + spread_b * F::from(1 << 4) + spread_c_lo * F::from(1 << 26) + spread_c_mid * F::from(1 << 32) + spread_c_hi * F::from(1 << 38) + spread_d * F::from(1 << 44) - + spread_word_lo * (-F::one()) - + spread_word_hi * F::from(1 << 32) * (-F::one()); + + spread_word_lo * (-F::ONE) + + spread_word_hi * F::from(1 << 32) * (-F::ONE); Constraints::with_selector( s_decompose_abcd, @@ -130,16 +130,16 @@ impl CompressionGate { + b_hi * F::from(1 << 8) + c * F::from(1 << 11) + d * F::from(1 << 25) - + word_lo * (-F::one()) - + word_hi * F::from(1 << 16) * (-F::one()); + + word_lo * (-F::ONE) + + word_hi * F::from(1 << 16) * (-F::ONE); let spread_check = spread_a_lo + spread_a_hi * F::from(1 << 6) + spread_b_lo * F::from(1 << 12) + spread_b_hi * F::from(1 << 16) + spread_c * F::from(1 << 22) + spread_d * F::from(1 << 50) - + spread_word_lo * (-F::one()) - + spread_word_hi * F::from(1 << 32) * (-F::one()); + + spread_word_lo * (-F::ONE) + + spread_word_hi * F::from(1 << 32) * (-F::ONE); Constraints::with_selector( s_decompose_efgh, @@ -189,7 +189,7 @@ impl CompressionGate { + spread_c_mid * F::from(1 << 52) + spread_c_hi * F::from(1 << 58); let xor = xor_0 + xor_1 + xor_2; - let check = spread_witness + (xor * -F::one()); + let check = spread_witness + (xor * -F::ONE); Some(("s_upper_sigma_0", s_upper_sigma_0 * check)) } @@ -233,7 +233,7 @@ impl CompressionGate { + spread_b_hi * F::from(1 << 30) + spread_c * F::from(1 << 36); let xor = xor_0 + xor_1 + xor_2; - let check = spread_witness + (xor * -F::one()); + let check = spread_witness + (xor * -F::ONE); Some(("s_upper_sigma_1", s_upper_sigma_1 * check)) } @@ -259,7 +259,7 @@ impl CompressionGate { let rhs_odd = spread_p0_odd + spread_p1_odd * F::from(1 << 32); let rhs = rhs_even + rhs_odd * F::from(2); - let check = lhs + rhs * -F::one(); + let check = lhs + rhs * -F::ONE; Some(("s_ch", s_ch * check)) } @@ -284,11 +284,11 @@ impl CompressionGate { impl Iterator)>, > { let neg_check = { - let evens = Self::ones() * F::from(MASK_EVEN_32 as u64); + let evens = SelF::ONEs() * F::from(MASK_EVEN_32 as u64); // evens - spread_e_lo = spread_e_neg_lo - let lo_check = spread_e_neg_lo.clone() + spread_e_lo + (evens.clone() * (-F::one())); + let lo_check = spread_e_neg_lo.clone() + spread_e_lo + (evens.clone() * (-F::ONE)); // evens - spread_e_hi = spread_e_neg_hi - let hi_check = spread_e_neg_hi.clone() + spread_e_hi + (evens * (-F::one())); + let hi_check = spread_e_neg_hi.clone() + spread_e_hi + (evens * (-F::ONE)); std::iter::empty() .chain(Some(("lo_check", lo_check))) diff --git a/halo2_gadgets/src/sha256/table16/compression/compression_util.rs b/halo2_gadgets/src/sha256/table16/compression/compression_util.rs index 324fe8f695..51ec7a9009 100644 --- a/halo2_gadgets/src/sha256/table16/compression/compression_util.rs +++ b/halo2_gadgets/src/sha256/table16/compression/compression_util.rs @@ -5,11 +5,11 @@ use super::{ use crate::sha256::table16::{ util::*, AssignedBits, SpreadVar, SpreadWord, StateWord, Table16Assignment, }; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Region, Value}, plonk::{Advice, Column, Error}, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; // Test vector 'abc' diff --git a/halo2_gadgets/src/sha256/table16/compression/subregion_digest.rs b/halo2_gadgets/src/sha256/table16/compression/subregion_digest.rs index aa30f80af7..e0810154bb 100644 --- a/halo2_gadgets/src/sha256/table16/compression/subregion_digest.rs +++ b/halo2_gadgets/src/sha256/table16/compression/subregion_digest.rs @@ -1,10 +1,10 @@ use super::super::{super::DIGEST_SIZE, BlockWord, RoundWordDense}; use super::{compression_util::*, CompressionConfig, State}; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Region, Value}, plonk::{Advice, Column, Error}, }; -use halo2curves::pasta::pallas; impl CompressionConfig { #[allow(clippy::many_single_char_names)] diff --git a/halo2_gadgets/src/sha256/table16/compression/subregion_initial.rs b/halo2_gadgets/src/sha256/table16/compression/subregion_initial.rs index a487dc0c87..269acd7028 100644 --- a/halo2_gadgets/src/sha256/table16/compression/subregion_initial.rs +++ b/halo2_gadgets/src/sha256/table16/compression/subregion_initial.rs @@ -1,11 +1,11 @@ use super::super::{RoundWord, StateWord, STATE}; use super::{compression_util::*, CompressionConfig, State}; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; impl CompressionConfig { #[allow(clippy::many_single_char_names)] diff --git a/halo2_gadgets/src/sha256/table16/compression/subregion_main.rs b/halo2_gadgets/src/sha256/table16/compression/subregion_main.rs index bda188a866..1e204369de 100644 --- a/halo2_gadgets/src/sha256/table16/compression/subregion_main.rs +++ b/halo2_gadgets/src/sha256/table16/compression/subregion_main.rs @@ -1,7 +1,7 @@ use super::super::{AssignedBits, RoundWord, RoundWordA, RoundWordE, StateWord, ROUND_CONSTANTS}; use super::{compression_util::*, CompressionConfig, State}; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{circuit::Region, plonk::Error}; -use halo2curves::pasta::pallas; impl CompressionConfig { #[allow(clippy::many_single_char_names)] diff --git a/halo2_gadgets/src/sha256/table16/gates.rs b/halo2_gadgets/src/sha256/table16/gates.rs index 4f268092db..3de43aee79 100644 --- a/halo2_gadgets/src/sha256/table16/gates.rs +++ b/halo2_gadgets/src/sha256/table16/gates.rs @@ -1,10 +1,10 @@ -use halo2_proofs::{arithmetic::FieldExt, plonk::Expression}; +use halo2_proofs::{ff::PrimeField, plonk::Expression}; -pub struct Gate(pub Expression); +pub struct Gate(pub Expression); -impl Gate { +impl Gate { fn ones() -> Expression { - Expression::Constant(F::one()) + Expression::Constant(F::ONE) } // Helper gates @@ -28,11 +28,11 @@ impl Gate { let factor = factorial((deg - 1) as u64); let numerator = |var: Expression, eval: u32, idx: u64| { - let mut expr = Self::ones(); + let mut expr = SelF::ONEs(); for i in 0..deg { let i = i as u64; if i != idx { - expr = expr * (Self::ones() * (-F::one()) * F::from(i) + var.clone()); + expr = expr * (SelF::ONEs() * (-F::ONE) * F::from(i) + var.clone()); } } expr * F::from(u64::from(eval)) @@ -46,13 +46,13 @@ impl Gate { } } if denom < 0 { - -F::one() * F::from(factor / (-denom as u64)) + -F::ONE * F::from(factor / (-denom as u64)) } else { F::from(factor / (denom as u64)) } }; - let mut expr = Self::ones() * F::zero(); + let mut expr = SelF::ONEs() * F::ZERO; for ((idx, _), eval) in points.iter().enumerate().zip(evals.iter()) { expr = expr + numerator(var.clone(), *eval, idx as u64) * denominator(idx as i32) } @@ -61,9 +61,9 @@ impl Gate { } pub fn range_check(value: Expression, lower_range: u64, upper_range: u64) -> Expression { - let mut expr = Self::ones(); + let mut expr = SelF::ONEs(); for i in lower_range..(upper_range + 1) { - expr = expr * (Self::ones() * (-F::one()) * F::from(i) + value.clone()) + expr = expr * (SelF::ONEs() * (-F::ONE) * F::from(i) + value.clone()) } expr } diff --git a/halo2_gadgets/src/sha256/table16/message_schedule.rs b/halo2_gadgets/src/sha256/table16/message_schedule.rs index 690e086c49..51db80a0af 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule.rs @@ -1,12 +1,12 @@ use std::convert::TryInto; use super::{super::BLOCK_SIZE, AssignedBits, BlockWord, SpreadInputs, Table16Assignment, ROUNDS}; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::Layouter, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; -use halo2curves::pasta::pallas; mod schedule_gates; mod schedule_util; @@ -397,12 +397,12 @@ mod tests { super::BLOCK_SIZE, util::lebs2ip, BlockWord, SpreadTableChip, Table16Chip, Table16Config, }; use super::schedule_util::*; + use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; - use halo2curves::pasta::pallas; #[test] fn message_schedule() { diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/schedule_gates.rs b/halo2_gadgets/src/sha256/table16/message_schedule/schedule_gates.rs index fab51bd373..d3e9e8f980 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/schedule_gates.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/schedule_gates.rs @@ -1,10 +1,10 @@ use super::super::Gate; -use halo2_proofs::{arithmetic::FieldExt, plonk::Expression}; +use halo2_proofs::{ff::PrimeField, plonk::Expression}; use std::marker::PhantomData; -pub struct ScheduleGate(PhantomData); +pub struct ScheduleGate(PhantomData); -impl ScheduleGate { +impl ScheduleGate { /// s_word for W_16 to W_63 #[allow(clippy::too_many_arguments)] pub fn s_word( @@ -25,8 +25,8 @@ impl ScheduleGate { let word_check = lo + hi * F::from(1 << 16) - + (carry.clone() * F::from(1 << 32) * (-F::one())) - + (word * (-F::one())); + + (carry.clone() * F::from(1 << 32) * (-F::ONE)) + + (word * (-F::ONE)); let carry_check = Gate::range_check(carry, 0, 3); [("word_check", word_check), ("carry_check", carry_check)] @@ -58,11 +58,8 @@ impl ScheduleGate { tag_d: Expression, word: Expression, ) -> impl Iterator)> { - let decompose_check = a - + b * F::from(1 << 3) - + c * F::from(1 << 7) - + d * F::from(1 << 18) - + word * (-F::one()); + let decompose_check = + a + b * F::from(1 << 3) + c * F::from(1 << 7) + d * F::from(1 << 18) + word * (-F::ONE); let range_check_tag_c = Gate::range_check(tag_c, 0, 2); let range_check_tag_d = Gate::range_check(tag_d, 0, 4); @@ -99,7 +96,7 @@ impl ScheduleGate { + e * F::from(1 << 17) + f * F::from(1 << 18) + g * F::from(1 << 19) - + word * (-F::one()); + + word * (-F::ONE); let range_check_tag_d = Gate::range_check(tag_d, 0, 0); let range_check_tag_g = Gate::range_check(tag_g, 0, 3); @@ -129,7 +126,7 @@ impl ScheduleGate { + b * F::from(1 << 10) + c * F::from(1 << 17) + d * F::from(1 << 19) - + word * (-F::one()); + + word * (-F::ONE); let range_check_tag_a = Gate::range_check(tag_a, 0, 1); let range_check_tag_d = Gate::range_check(tag_d, 0, 3); diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs b/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs index 79a9fa2621..08c3b9c48d 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs @@ -1,10 +1,10 @@ use super::super::AssignedBits; use super::MessageScheduleConfig; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; #[cfg(test)] use super::super::{super::BLOCK_SIZE, BlockWord, ROUNDS}; diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs b/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs index 947c9dda2a..1643a62fa0 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs @@ -1,10 +1,10 @@ use super::super::{util::*, AssignedBits, BlockWord, SpreadVar, SpreadWord, Table16Assignment}; use super::{schedule_util::*, MessageScheduleConfig}; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; // A word in subregion 1 diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs b/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs index 43e96c934f..ca536f2987 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs @@ -1,10 +1,10 @@ use super::super::{util::*, AssignedBits, Bits, SpreadVar, SpreadWord, Table16Assignment}; use super::{schedule_util::*, MessageScheduleConfig, MessageWord}; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; /// A word in subregion 2 diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/subregion3.rs b/halo2_gadgets/src/sha256/table16/message_schedule/subregion3.rs index b23046e42e..fecc69d3a9 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/subregion3.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/subregion3.rs @@ -1,10 +1,10 @@ use super::super::{util::*, AssignedBits, Bits, SpreadVar, SpreadWord, Table16Assignment}; use super::{schedule_util::*, MessageScheduleConfig, MessageWord}; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; // A word in subregion 3 diff --git a/halo2_gadgets/src/sha256/table16/spread_table.rs b/halo2_gadgets/src/sha256/table16/spread_table.rs index 3e1488e9ac..ba7b8a54ce 100644 --- a/halo2_gadgets/src/sha256/table16/spread_table.rs +++ b/halo2_gadgets/src/sha256/table16/spread_table.rs @@ -1,11 +1,11 @@ use super::{util::*, AssignedBits}; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{Chip, Layouter, Region, Value}, + ff::PrimeField, plonk::{Advice, Column, ConstraintSystem, Error, TableColumn}, poly::Rotation, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; use std::marker::PhantomData; @@ -153,12 +153,12 @@ pub(super) struct SpreadTableConfig { } #[derive(Clone, Debug)] -pub(super) struct SpreadTableChip { +pub(super) struct SpreadTableChip { config: SpreadTableConfig, _marker: PhantomData, } -impl Chip for SpreadTableChip { +impl Chip for SpreadTableChip { type Config = SpreadTableConfig; type Loaded = (); @@ -171,7 +171,7 @@ impl Chip for SpreadTableChip { } } -impl SpreadTableChip { +impl SpreadTableChip { pub fn configure( meta: &mut ConstraintSystem, input_tag: Column, @@ -250,35 +250,32 @@ impl SpreadTableChip { } impl SpreadTableConfig { - fn generate() -> impl Iterator { - (1..=(1 << 16)).scan( - (F::zero(), F::zero(), F::zero()), - |(tag, dense, spread), i| { - // We computed this table row in the previous iteration. - let res = (*tag, *dense, *spread); - - // i holds the zero-indexed row number for the next table row. - match i { - BITS_7 | BITS_10 | BITS_11 | BITS_13 | BITS_14 => *tag += F::one(), - _ => (), - } - *dense += F::one(); - if i & 1 == 0 { - // On even-numbered rows we recompute the spread. - *spread = F::zero(); - for b in 0..16 { - if (i >> b) & 1 != 0 { - *spread += F::from(1 << (2 * b)); - } + fn generate() -> impl Iterator { + (1..=(1 << 16)).scan((F::ZERO, F::ZERO, F::ZERO), |(tag, dense, spread), i| { + // We computed this table row in the previous iteration. + let res = (*tag, *dense, *spread); + + // i holds the zero-indexed row number for the next table row. + match i { + BITS_7 | BITS_10 | BITS_11 | BITS_13 | BITS_14 => *tag += F::ONE, + _ => (), + } + *dense += F::ONE; + if i & 1 == 0 { + // On even-numbered rows we recompute the spread. + *spread = F::ZERO; + for b in 0..16 { + if (i >> b) & 1 != 0 { + *spread += F::from(1 << (2 * b)); } - } else { - // On odd-numbered rows we add one. - *spread += F::one(); } + } else { + // On odd-numbered rows we add one. + *spread += F::ONE; + } - Some(res) - }, - ) + Some(res) + }) } } @@ -287,13 +284,13 @@ mod tests { use super::{get_tag, SpreadTableChip, SpreadTableConfig}; use rand::Rng; + use halo2_proofs::curves::pasta::Fp; use halo2_proofs::{ - arithmetic::FieldExt, + arithmetic::PrimeField, circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, plonk::{Advice, Circuit, Column, ConstraintSystem, Error}, }; - use halo2curves::pasta::Fp; #[test] fn lookup_table() { @@ -303,7 +300,7 @@ mod tests { struct MyCircuit {} - impl Circuit for MyCircuit { + impl Circuit for MyCircuit { type Config = SpreadTableConfig; type FloorPlanner = SimpleFloorPlanner; @@ -354,20 +351,20 @@ mod tests { }; // Test the first few small values. - add_row(F::zero(), F::from(0b000), F::from(0b000000))?; - add_row(F::zero(), F::from(0b001), F::from(0b000001))?; - add_row(F::zero(), F::from(0b010), F::from(0b000100))?; - add_row(F::zero(), F::from(0b011), F::from(0b000101))?; - add_row(F::zero(), F::from(0b100), F::from(0b010000))?; - add_row(F::zero(), F::from(0b101), F::from(0b010001))?; + add_row(F::ZERO, F::from(0b000), F::from(0b000000))?; + add_row(F::ZERO, F::from(0b001), F::from(0b000001))?; + add_row(F::ZERO, F::from(0b010), F::from(0b000100))?; + add_row(F::ZERO, F::from(0b011), F::from(0b000101))?; + add_row(F::ZERO, F::from(0b100), F::from(0b010000))?; + add_row(F::ZERO, F::from(0b101), F::from(0b010001))?; // Test the tag boundaries: // 7-bit - add_row(F::zero(), F::from(0b1111111), F::from(0b01010101010101))?; - add_row(F::one(), F::from(0b10000000), F::from(0b0100000000000000))?; + add_row(F::ZERO, F::from(0b1111111), F::from(0b01010101010101))?; + add_row(F::ONE, F::from(0b10000000), F::from(0b0100000000000000))?; // - 10-bit add_row( - F::one(), + F::ONE, F::from(0b1111111111), F::from(0b01010101010101010101), )?; diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 3cec450ea1..8fe65dd18e 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -5,12 +5,12 @@ use crate::{ ecc::{self, EccInstructions, FixedPoints}, utilities::{FieldValue, RangeConstrained, Var}, }; -use group::ff::{Field, PrimeField}; +use halo2_proofs::curves::CurveAffine; +use halo2_proofs::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{Layouter, Value}, plonk::Error, }; -use halo2curves::CurveAffine; use std::fmt::Debug; pub mod chip; @@ -203,9 +203,9 @@ where let to_base_field = |bits: &[Value]| -> Value { let bits: Value> = bits.iter().cloned().collect(); bits.map(|bits| { - bits.into_iter().rev().fold(C::Base::zero(), |acc, bit| { + bits.into_iter().rev().fold(C::Base::ZERO, |acc, bit| { if bit { - acc.double() + C::Base::one() + acc.double() + C::Base::ONE } else { acc.double() } @@ -243,7 +243,7 @@ where subpieces: impl IntoIterator>>, ) -> Result { let (field_elem, total_bits) = subpieces.into_iter().fold( - (Value::known(C::Base::zero()), 0), + (Value::known(C::Base::ZERO), 0), |(acc, bits), subpiece| { assert!(bits < 64); let subpiece_shifted = subpiece @@ -477,8 +477,8 @@ pub(crate) mod tests { }, }; - use group::{ff::Field, Curve}; - use halo2curves::pasta::pallas; + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::group::{ff::Field, Curve}; use lazy_static::lazy_static; use std::convert::TryInto; diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index a6788e55e1..996d6973ee 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -13,6 +13,7 @@ use crate::{ }; use std::marker::PhantomData; +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{ @@ -21,7 +22,6 @@ use halo2_proofs::{ }, poly::Rotation, }; -use halo2curves::pasta::pallas; mod generator_table; use generator_table::GeneratorTableConfig; diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index a653c13b35..94f7c71b51 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -6,7 +6,8 @@ use halo2_proofs::{ use super::{CommitDomains, FixedPoints, HashDomains}; use crate::sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}; -use halo2curves::{pasta::pallas, FieldExt}; +use halo2_proofs::curves::pasta::pallas; +use halo2_proofs::ff::PrimeField; /// Table containing independent generators S[0..2^k] #[derive(Eq, PartialEq, Copy, Clone, Debug)] diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 70eab6b86d..c7d0d4f517 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -10,8 +10,8 @@ use halo2_proofs::{ plonk::{Assigned, Error}, }; -use group::ff::{PrimeField, PrimeFieldBits}; -use halo2curves::{pasta::pallas, CurveAffine, FieldExt}; +use halo2_proofs::curves::{pasta::pallas, CurveAffine}; +use halo2_proofs::ff::{PrimeField, PrimeFieldBits}; use std::ops::Deref; @@ -126,8 +126,8 @@ where { use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; - use group::{prime::PrimeCurveAffine, Curve}; - use halo2curves::CurveExt; + use halo2_proofs::curves::CurveExt; + use halo2_proofs::group::{prime::PrimeCurveAffine, Curve}; let field_elems: Value> = message .iter() @@ -376,15 +376,15 @@ where } /// The x-coordinate of the accumulator in a Sinsemilla hash instance. -struct X(AssignedCell, F>); +struct X(AssignedCell, F>); -impl From, F>> for X { +impl From, F>> for X { fn from(cell_value: AssignedCell, F>) -> Self { X(cell_value) } } -impl Deref for X { +impl Deref for X { type Target = AssignedCell, F>; fn deref(&self) -> &AssignedCell, F> { @@ -397,15 +397,15 @@ impl Deref for X { /// This is never actually witnessed until the last round, since it /// can be derived from other variables. Thus it only exists as a field /// element, not a `CellValue`. -struct Y(Value>); +struct Y(Value>); -impl From>> for Y { +impl From>> for Y { fn from(value: Value>) -> Self { Y(value) } } -impl Deref for Y { +impl Deref for Y { type Target = Value>; fn deref(&self) -> &Value> { diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index a9ae781d5c..5dbf1cf707 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -1,10 +1,10 @@ //! Gadgets for implementing a Merkle tree with Sinsemilla. +use halo2_proofs::curves::CurveAffine; use halo2_proofs::{ circuit::{Chip, Layouter, Value}, plonk::Error, }; -use halo2curves::CurveAffine; use super::{HashDomains, SinsemillaInstructions}; @@ -187,13 +187,13 @@ pub mod tests { utilities::{i2lebsp, lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, }; - use group::ff::{Field, PrimeField, PrimeFieldBits}; + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::group::ff::{Field, PrimeField, PrimeFieldBits}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; - use halo2curves::pasta::pallas; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 97da766d0c..76447327b4 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -1,11 +1,11 @@ //! Chip implementing a Merkle hash using Sinsemilla as the hash function. +use halo2_proofs::curves::pasta::pallas; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector}, poly::Rotation, }; -use halo2curves::{pasta::pallas, FieldExt}; use super::MerkleInstructions; @@ -24,7 +24,7 @@ use crate::{ }, }, }; -use group::ff::PrimeField; +use halo2_proofs::ff::PrimeField; /// Configuration for the `MerkleChip` implementation. #[derive(Clone, Debug, PartialEq, Eq)] @@ -380,7 +380,7 @@ where { use crate::{sinsemilla::primitives::HashDomain, utilities::i2lebsp}; - use group::ff::PrimeFieldBits; + use halo2_proofs::group::ff::PrimeFieldBits; left.value() .zip(right.value()) diff --git a/halo2_gadgets/src/sinsemilla/message.rs b/halo2_gadgets/src/sinsemilla/message.rs index 6bb72e2f1e..504481604c 100644 --- a/halo2_gadgets/src/sinsemilla/message.rs +++ b/halo2_gadgets/src/sinsemilla/message.rs @@ -1,16 +1,14 @@ //! Gadget and chips for the Sinsemilla hash function. -use ff::PrimeFieldBits; -use halo2_proofs::{ - arithmetic::FieldExt, - circuit::{AssignedCell, Cell, Value}, -}; +use halo2_proofs::circuit::{AssignedCell, Cell, Value}; +use halo2_proofs::ff::PrimeField; +use halo2_proofs::ff::PrimeFieldBits; use std::fmt::Debug; /// A [`Message`] composed of several [`MessagePiece`]s. #[derive(Clone, Debug)] -pub struct Message(Vec>); +pub struct Message(Vec>); -impl +impl From>> for Message { fn from(pieces: Vec>) -> Self { @@ -20,7 +18,7 @@ impl } } -impl std::ops::Deref +impl std::ops::Deref for Message { type Target = [MessagePiece]; @@ -35,13 +33,13 @@ impl std:: /// The piece must fit within a base field element, which means its length /// cannot exceed the base field's `NUM_BITS`. #[derive(Clone, Debug)] -pub struct MessagePiece { +pub struct MessagePiece { cell_value: AssignedCell, /// The number of K-bit words in this message piece. num_words: usize, } -impl MessagePiece { +impl MessagePiece { pub fn new(cell_value: AssignedCell, num_words: usize) -> Self { assert!(num_words * K < F::NUM_BITS as usize); Self { diff --git a/halo2_gadgets/src/sinsemilla/primitives.rs b/halo2_gadgets/src/sinsemilla/primitives.rs index fd2e4aea72..227f18cc7e 100644 --- a/halo2_gadgets/src/sinsemilla/primitives.rs +++ b/halo2_gadgets/src/sinsemilla/primitives.rs @@ -1,8 +1,8 @@ //! Implementation of Sinsemilla outside the circuit. -use group::{Curve, Wnaf}; use halo2_proofs::arithmetic::{CurveAffine, CurveExt}; -use halo2curves::pasta::pallas; +use halo2_proofs::curves::pasta::pallas; +use halo2_proofs::group::{Curve, Wnaf}; use subtle::CtOption; mod addition; @@ -245,7 +245,7 @@ impl CommitDomain { #[cfg(test)] mod tests { use super::{Pad, K}; - use halo2curves::{pasta::pallas, CurveExt}; + use halo2_proofs::curves::{pasta::pallas, CurveExt}; #[test] fn pad() { @@ -291,8 +291,8 @@ mod tests { #[test] fn sinsemilla_s() { use super::sinsemilla_s::SINSEMILLA_S; - use group::Curve; - use halo2curves::CurveAffine; + use halo2_proofs::curves::CurveAffine; + use halo2_proofs::group::Curve; let hasher = pallas::Point::hash_to_curve(super::S_PERSONALIZATION); diff --git a/halo2_gadgets/src/sinsemilla/primitives/addition.rs b/halo2_gadgets/src/sinsemilla/primitives/addition.rs index 9d4574dca1..6c0d8873ee 100644 --- a/halo2_gadgets/src/sinsemilla/primitives/addition.rs +++ b/halo2_gadgets/src/sinsemilla/primitives/addition.rs @@ -1,7 +1,7 @@ use std::ops::Add; -use group::{cofactor::CofactorCurveAffine, Group}; -use halo2curves::pasta::pallas; +use halo2_proofs::curves::pasta::pallas; +use halo2_proofs::group::{cofactor::CofactorCurveAffine, Group}; use subtle::{ConstantTimeEq, CtOption}; /// P ∪ {⊥} diff --git a/halo2_gadgets/src/sinsemilla/primitives/sinsemilla_s.rs b/halo2_gadgets/src/sinsemilla/primitives/sinsemilla_s.rs index c72fe5841f..050fce3ff5 100644 --- a/halo2_gadgets/src/sinsemilla/primitives/sinsemilla_s.rs +++ b/halo2_gadgets/src/sinsemilla/primitives/sinsemilla_s.rs @@ -1,5 +1,5 @@ use super::K; -use halo2curves::pasta::pallas; +use halo2_proofs::curves::pasta::pallas; /// The precomputed bases for the [Sinsemilla hash function][concretesinsemillahash]. /// diff --git a/halo2_gadgets/src/utilities.rs b/halo2_gadgets/src/utilities.rs index fa50f7e8e8..ec93930993 100644 --- a/halo2_gadgets/src/utilities.rs +++ b/halo2_gadgets/src/utilities.rs @@ -1,11 +1,10 @@ //! Utility gadgets. -use ff::{Field, PrimeFieldBits}; +use halo2_proofs::ff::{Field, PrimeField, PrimeFieldBits}; use halo2_proofs::{ circuit::{AssignedCell, Cell, Layouter, Value}, plonk::{Advice, Column, Error, Expression}, }; -use halo2curves::FieldExt; use std::marker::PhantomData; use std::ops::Range; @@ -32,7 +31,7 @@ impl FieldValue for AssignedCell { } /// 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; @@ -40,7 +39,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() } @@ -51,7 +50,7 @@ impl Var for AssignedCell { } /// Trait for utilities used across circuits. -pub trait UtilitiesInstructions { +pub trait UtilitiesInstructions { /// Variable in the circuit. type Var: Var; @@ -130,15 +129,19 @@ impl RangeConstrained> { } /// Checks that an expression is either 1 or 0. -pub fn bool_check(value: Expression) -> Expression { +pub fn bool_check(value: Expression) -> Expression { range_check(value, 2) } /// If `a` then `b`, else `c`. Returns (a * b) + (1 - a) * c. /// /// `a` must be a boolean-constrained expression. -pub fn ternary(a: Expression, b: Expression, c: Expression) -> Expression { - let one_minus_a = Expression::Constant(F::one()) - a.clone(); +pub fn ternary( + a: Expression, + b: Expression, + c: Expression, +) -> Expression { + let one_minus_a = Expression::Constant(F::ONE) - a.clone(); a * b + one_minus_a * c } @@ -156,9 +159,9 @@ pub fn bitrange_subset(field_elem: &F, bitrange: Range .skip(bitrange.start) .take(bitrange.end - bitrange.start) .rev() - .fold(F::zero(), |acc, bit| { + .fold(F::ZERO, |acc, bit| { if bit { - acc.double() + F::one() + acc.double() + F::ONE } else { acc.double() } @@ -167,7 +170,7 @@ pub fn bitrange_subset(field_elem: &F, bitrange: Range /// Check that an expression is in the small range [0..range), /// i.e. 0 ≤ word < range. -pub fn range_check(word: Expression, range: usize) -> Expression { +pub fn range_check(word: Expression, range: usize) -> Expression { (1..range).fold(word.clone(), |acc, i| { acc * (Expression::Constant(F::from(i as u64)) - word.clone()) }) @@ -240,14 +243,15 @@ pub fn i2lebsp(int: u64) -> [bool; NUM_BITS] { #[cfg(test)] mod tests { use super::*; - use group::ff::{Field, PrimeField}; + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::ff::FromUniformBytes; + use halo2_proofs::group::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, dev::{FailureLocation, MockProver, VerifyFailure}, plonk::{Any, Circuit, ConstraintSystem, Constraints, Error, Selector}, poly::Rotation, }; - use halo2curves::{pasta::pallas, FieldExt}; use proptest::prelude::*; use rand::rngs::OsRng; use std::convert::TryInto; @@ -420,7 +424,7 @@ mod tests { // Instead of rejecting out-of-range bytes, let's reduce them. let mut buf = [0; 64]; buf[..32].copy_from_slice(&bytes); - pallas::Scalar::from_bytes_wide(&buf) + pallas::Scalar::from_uniform_bytes(&buf) } } diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 9dc1afa3ef..ab8dae67f5 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -1,16 +1,16 @@ //! Gadget and chip for a conditional swap utility. use super::{bool_check, ternary, UtilitiesInstructions}; +use halo2_proofs::ff::PrimeField; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector}, poly::Rotation, }; -use halo2curves::FieldExt; use std::marker::PhantomData; /// Instructions for a conditional swap gadget. -pub trait CondSwapInstructions: UtilitiesInstructions { +pub trait CondSwapInstructions: UtilitiesInstructions { #[allow(clippy::type_complexity)] /// Given an input pair (a,b) and a `swap` boolean flag, returns /// (b,a) if `swap` is set, else (a,b) if `swap` is not set. @@ -32,7 +32,7 @@ pub struct CondSwapChip { _marker: PhantomData, } -impl Chip for CondSwapChip { +impl Chip for CondSwapChip { type Config = CondSwapConfig; type Loaded = (); @@ -63,11 +63,11 @@ impl CondSwapConfig { } } -impl UtilitiesInstructions for CondSwapChip { +impl UtilitiesInstructions for CondSwapChip { type Var = AssignedCell; } -impl CondSwapInstructions for CondSwapChip { +impl CondSwapInstructions for CondSwapChip { #[allow(clippy::type_complexity)] fn swap( &self, @@ -122,7 +122,7 @@ impl CondSwapInstructions for CondSwapChip { } } -impl CondSwapChip { +impl CondSwapChip { /// Configures this chip for use in a circuit. /// /// # Side-effects @@ -195,25 +195,26 @@ impl CondSwapChip { mod tests { use super::super::UtilitiesInstructions; use super::{CondSwapChip, CondSwapConfig, CondSwapInstructions}; - use group::ff::Field; + use halo2_proofs::curves::pasta::pallas::Base; + use halo2_proofs::ff::PrimeField; + use halo2_proofs::group::ff::Field; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; - use halo2curves::{pasta::pallas::Base, FieldExt}; use rand::rngs::OsRng; #[test] fn cond_swap() { #[derive(Default)] - struct MyCircuit { + struct MyCircuit { a: Value, b: Value, swap: Value, } - impl Circuit for MyCircuit { + impl Circuit for MyCircuit { type Config = CondSwapConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/halo2_gadgets/src/utilities/decompose_running_sum.rs b/halo2_gadgets/src/utilities/decompose_running_sum.rs index 89508f176c..3afd417e74 100644 --- a/halo2_gadgets/src/utilities/decompose_running_sum.rs +++ b/halo2_gadgets/src/utilities/decompose_running_sum.rs @@ -22,7 +22,7 @@ //! This means that $2^K$ has to be at most `degree_bound - 1` in order for //! the range check constraint to stay within the degree bound. -use ff::PrimeFieldBits; +use halo2_proofs::ff::{PrimeField, PrimeFieldBits}; use halo2_proofs::{ circuit::{AssignedCell, Region, Value}, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector}, @@ -30,13 +30,12 @@ use halo2_proofs::{ }; use super::range_check; -use halo2curves::FieldExt; use std::marker::PhantomData; /// The running sum $[z_0, ..., z_W]$. If created in strict mode, $z_W = 0$. #[derive(Debug)] -pub struct RunningSum(Vec>); -impl std::ops::Deref for RunningSum { +pub struct RunningSum(Vec>); +impl std::ops::Deref for RunningSum { type Target = Vec>; fn deref(&self) -> &Vec> { @@ -46,13 +45,13 @@ impl std::ops::Deref for RunningSum { /// Configuration that provides methods for running sum decomposition. #[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub struct RunningSumConfig { +pub struct RunningSumConfig { q_range_check: Selector, z: Column, _marker: PhantomData, } -impl +impl RunningSumConfig { /// Returns the q_range_check selector of this [`RunningSumConfig`]. @@ -200,7 +199,7 @@ impl if strict { // Constrain the final running sum output to be zero. - region.constrain_constant(zs.last().unwrap().cell(), F::zero())?; + region.constrain_constant(zs.last().unwrap().cell(), F::ZERO)?; } Ok(RunningSum(zs)) @@ -210,13 +209,13 @@ impl #[cfg(test)] mod tests { use super::*; - use group::ff::{Field, PrimeField}; + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::group::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, dev::{FailureLocation, MockProver, VerifyFailure}, plonk::{Any, Circuit, ConstraintSystem, Error}, }; - use halo2curves::{pasta::pallas, FieldExt}; use rand::rngs::OsRng; use crate::ecc::chip::{ @@ -228,7 +227,7 @@ mod tests { #[test] fn test_running_sum() { struct MyCircuit< - F: FieldExt + PrimeFieldBits, + F: PrimeField + PrimeFieldBits, const WORD_NUM_BITS: usize, const WINDOW_NUM_BITS: usize, const NUM_WINDOWS: usize, @@ -238,7 +237,7 @@ mod tests { } impl< - F: FieldExt + PrimeFieldBits, + F: PrimeField + PrimeFieldBits, const WORD_NUM_BITS: usize, const WINDOW_NUM_BITS: usize, const NUM_WINDOWS: usize, diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index f97654c38b..d7a9d69e0a 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -1,6 +1,8 @@ //! Make use of a K-bit lookup table to decompose a field element into K-bit //! words. +use halo2_proofs::ff::PrimeField; +use halo2_proofs::ff::PrimeFieldBits; use halo2_proofs::{ circuit::{AssignedCell, Layouter, Region}, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector, TableColumn}, @@ -8,14 +10,12 @@ use halo2_proofs::{ }; use std::{convert::TryInto, marker::PhantomData}; -use ff::PrimeFieldBits; - use super::*; /// The running sum $[z_0, ..., z_W]$. If created in strict mode, $z_W = 0$. #[derive(Debug)] -pub struct RunningSum(Vec>); -impl std::ops::Deref for RunningSum { +pub struct RunningSum(Vec>); +impl std::ops::Deref for RunningSum { type Target = Vec>; fn deref(&self) -> &Vec> { @@ -23,7 +23,7 @@ impl std::ops::Deref for RunningSum { } } -impl RangeConstrained> { +impl RangeConstrained> { /// Witnesses a subset of the bits in `value` and constrains them to be the correct /// number of bits. /// @@ -56,7 +56,7 @@ impl RangeConstrained> { /// Configuration that provides methods for a lookup range check. #[derive(Eq, PartialEq, Debug, Clone, Copy)] -pub struct LookupRangeCheckConfig { +pub struct LookupRangeCheckConfig { q_lookup: Selector, q_running: Selector, q_bitshift: Selector, @@ -65,7 +65,7 @@ pub struct LookupRangeCheckConfig _marker: PhantomData, } -impl LookupRangeCheckConfig { +impl LookupRangeCheckConfig { /// The `running_sum` advice column breaks the field element into `K`-bit /// words. It is used to construct the input expression to the lookup /// argument. @@ -118,7 +118,7 @@ impl LookupRangeCheckConfig // In the short range check, the word is directly witnessed. let short_lookup = { let short_word = z_cur; - let q_short = Expression::Constant(F::one()) - q_running; + let q_short = Expression::Constant(F::ONE) - q_running; q_short * short_word }; @@ -285,7 +285,7 @@ impl LookupRangeCheckConfig if strict { // Constrain the final `z` to be zero. - region.constrain_constant(zs.last().unwrap().cell(), F::zero())?; + region.constrain_constant(zs.last().unwrap().cell(), F::ZERO)?; } Ok(RunningSum(zs)) @@ -389,25 +389,26 @@ mod tests { use super::super::lebs2ip; use crate::sinsemilla::primitives::K; - use ff::{Field, PrimeFieldBits}; + use halo2_proofs::curves::pasta::pallas; + use halo2_proofs::ff::{Field, PrimeFieldBits}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::{FailureLocation, MockProver, VerifyFailure}, + ff::PrimeField, plonk::{Circuit, ConstraintSystem, Error}, }; - use halo2curves::{pasta::pallas, FieldExt}; use std::{convert::TryInto, marker::PhantomData}; #[test] fn lookup_range_check() { #[derive(Clone, Copy)] - struct MyCircuit { + struct MyCircuit { num_words: usize, _marker: PhantomData, } - impl Circuit for MyCircuit { + impl Circuit for MyCircuit { type Config = LookupRangeCheckConfig; type FloorPlanner = SimpleFloorPlanner; @@ -434,11 +435,11 @@ mod tests { // Lookup constraining element to be no longer than num_words * K bits. let elements_and_expected_final_zs = [ - (F::from((1 << (self.num_words * K)) - 1), F::zero(), true), // a word that is within self.num_words * K bits long - (F::from(1 << (self.num_words * K)), F::one(), false), // a word that is just over self.num_words * K bits long + (F::from((1 << (self.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long + (F::from(1 << (self.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long ]; - fn expected_zs( + fn expected_zs( element: F, num_words: usize, ) -> Vec { @@ -498,12 +499,12 @@ mod tests { #[test] fn short_range_check() { - struct MyCircuit { + struct MyCircuit { element: Value, num_bits: usize, } - impl Circuit for MyCircuit { + impl Circuit for MyCircuit { type Config = LookupRangeCheckConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/halo2_proofs/benches/dev_lookup.rs b/halo2_proofs/benches/dev_lookup.rs index 80690b4548..37a57800f5 100644 --- a/halo2_proofs/benches/dev_lookup.rs +++ b/halo2_proofs/benches/dev_lookup.rs @@ -1,7 +1,7 @@ #[macro_use] extern crate criterion; -use halo2_proofs::arithmetic::FieldExt; +use ff::PrimeField; use halo2_proofs::circuit::{Layouter, SimpleFloorPlanner, Value}; use halo2_proofs::dev::MockProver; use halo2_proofs::plonk::*; @@ -14,7 +14,7 @@ use criterion::{BenchmarkId, Criterion}; fn criterion_benchmark(c: &mut Criterion) { #[derive(Clone, Default)] - struct MyCircuit { + struct MyCircuit { _marker: PhantomData, } @@ -25,7 +25,7 @@ fn criterion_benchmark(c: &mut Criterion) { advice: Column, } - impl Circuit for MyCircuit { + impl Circuit for MyCircuit { type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/halo2_proofs/benches/plonk.rs b/halo2_proofs/benches/plonk.rs index c7901c2cd0..e4659e53b8 100644 --- a/halo2_proofs/benches/plonk.rs +++ b/halo2_proofs/benches/plonk.rs @@ -1,8 +1,8 @@ #[macro_use] extern crate criterion; -use group::ff::Field; -use halo2_proofs::arithmetic::FieldExt; +use ff::Field; +use ff::PrimeField; use halo2_proofs::circuit::{Cell, Layouter, SimpleFloorPlanner, Value}; use halo2_proofs::plonk::*; use halo2_proofs::poly::{commitment::ParamsProver, Rotation}; @@ -43,7 +43,7 @@ fn criterion_benchmark(c: &mut Criterion) { sm: Column, } - trait StandardCs { + trait StandardCs { fn raw_multiply( &self, layouter: &mut impl Layouter, @@ -62,17 +62,17 @@ fn criterion_benchmark(c: &mut Criterion) { } #[derive(Clone)] - struct MyCircuit { + struct MyCircuit { a: Value, k: u32, } - struct StandardPlonk { + struct StandardPlonk { config: PlonkConfig, _marker: PhantomData, } - impl StandardPlonk { + impl StandardPlonk { fn new(config: PlonkConfig) -> Self { StandardPlonk { config, @@ -81,7 +81,7 @@ fn criterion_benchmark(c: &mut Criterion) { } } - impl StandardCs for StandardPlonk { + impl StandardCs for StandardPlonk { fn raw_multiply( &self, layouter: &mut impl Layouter, @@ -181,7 +181,7 @@ fn criterion_benchmark(c: &mut Criterion) { } } - impl Circuit for MyCircuit { + impl Circuit for MyCircuit { type Config = PlonkConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/halo2_proofs/src/lib.rs b/halo2_proofs/src/lib.rs index e577a8c076..4abf110da2 100644 --- a/halo2_proofs/src/lib.rs +++ b/halo2_proofs/src/lib.rs @@ -35,3 +35,7 @@ pub mod transcript; pub mod dev; mod helpers; pub use helpers::SerdeFormat; + +pub use ff; +pub use group; +pub use halo2curves as curves; diff --git a/halo2_proofs/src/transcript/blake2b.rs b/halo2_proofs/src/transcript/blake2b.rs index aae177ee35..d76a4dea39 100644 --- a/halo2_proofs/src/transcript/blake2b.rs +++ b/halo2_proofs/src/transcript/blake2b.rs @@ -103,7 +103,7 @@ impl Transcript> } None => { // Infinity point - self.state.update(C::Base::zero().to_repr().as_ref()); + self.state.update(C::Base::ZERO.to_repr().as_ref()); self.state.update(C::Base::from(5).to_repr().as_ref()); } } @@ -185,7 +185,7 @@ impl Transcript> } None => { // Infinity point - self.state.update(C::Base::zero().to_repr().as_ref()); + self.state.update(C::Base::ZERO.to_repr().as_ref()); self.state.update(C::Base::from(5).to_repr().as_ref()); } } From 401e2183dff392f255dc85c6eba0072526ef032a Mon Sep 17 00:00:00 2001 From: zhenfei Date: Wed, 8 Mar 2023 17:45:57 -0500 Subject: [PATCH 59/62] fix clippy --- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 1 + halo2_proofs/src/arithmetic/field_fft.rs | 2 +- halo2_proofs/src/arithmetic/group_fft.rs | 2 +- halo2_proofs/src/dev.rs | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 124aeceda7..1e8808b8ec 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -209,6 +209,7 @@ impl> Config { // tested at the circuit-level. { use super::super::FixedPoint; + use halo2_proofs::ff::Field; use halo2_proofs::group::{ff::PrimeField, Curve}; scalar diff --git a/halo2_proofs/src/arithmetic/field_fft.rs b/halo2_proofs/src/arithmetic/field_fft.rs index dcb982a619..5c5eebaf89 100644 --- a/halo2_proofs/src/arithmetic/field_fft.rs +++ b/halo2_proofs/src/arithmetic/field_fft.rs @@ -213,7 +213,7 @@ pub fn parallel_fft(a: &mut [F], omega: F, log_n: u32) { let twiddle_lut = &*twiddle_lut; for (chunk_idx, tmp) in tmp.chunks_mut(sub_n).enumerate() { scope.spawn(move |_| { - let split_fft_offset = chunk_idx * sub_n >> log_split; + let split_fft_offset = (chunk_idx * sub_n) >> log_split; for (i, tmp) in tmp.chunks_mut(split_m).enumerate() { let split_fft_offset = split_fft_offset + i; split_radix_fft(tmp, a, twiddle_lut, n, split_fft_offset, log_split); diff --git a/halo2_proofs/src/arithmetic/group_fft.rs b/halo2_proofs/src/arithmetic/group_fft.rs index de51f5b998..dc6ba067f0 100644 --- a/halo2_proofs/src/arithmetic/group_fft.rs +++ b/halo2_proofs/src/arithmetic/group_fft.rs @@ -227,7 +227,7 @@ where let twiddle_lut = &*twiddle_lut; for (chunk_idx, tmp) in tmp.chunks_mut(sub_n).enumerate() { scope.spawn(move |_| { - let split_fft_offset = chunk_idx * sub_n >> log_split; + let split_fft_offset = (chunk_idx * sub_n) >> log_split; for (i, tmp) in tmp.chunks_mut(split_m).enumerate() { let split_fft_offset = split_fft_offset + i; split_radix_fft(tmp, a, twiddle_lut, n, split_fft_offset, log_split); diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index c8b8656aef..71a92c57fb 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -672,7 +672,7 @@ impl + FromUniformBytes<64> + Ord> Moc _advice_prev: vec![], instance, selectors, - challenges: challenges.clone(), + challenges, permutation, usable_rows: 0..usable_rows, current_phase: ThirdPhase.to_sealed(), From 0ea1a1e2ff5266aa466044cb59dfa1e27097f0b0 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Mon, 13 Mar 2023 09:30:14 -0400 Subject: [PATCH 60/62] remove ff and group as dependencies --- Cargo.toml | 11 +++++++++-- halo2_proofs/Cargo.toml | 4 +--- halo2_proofs/benches/arithmetic.rs | 2 +- halo2_proofs/benches/dev_lookup.rs | 2 +- halo2_proofs/benches/fft.rs | 2 +- halo2_proofs/benches/plonk.rs | 4 ++-- halo2_proofs/examples/circuit-layout.rs | 2 +- halo2_proofs/examples/cost-model.rs | 4 ++-- halo2_proofs/examples/serialization.rs | 2 +- halo2_proofs/examples/shuffle.rs | 4 ++-- halo2_proofs/examples/simple-example.rs | 2 +- halo2_proofs/examples/two-chip.rs | 4 ++-- halo2_proofs/src/arithmetic.rs | 8 +++----- halo2_proofs/src/arithmetic/field_fft.rs | 4 ++-- halo2_proofs/src/arithmetic/group_fft.rs | 4 ++-- halo2_proofs/src/arithmetic/multi_exp.rs | 4 ++-- halo2_proofs/src/arithmetic/util.rs | 2 +- halo2_proofs/src/circuit.rs | 2 +- .../src/circuit/floor_planner/single_pass.rs | 4 ++-- halo2_proofs/src/circuit/floor_planner/v1.rs | 4 ++-- halo2_proofs/src/circuit/layouter.rs | 2 +- halo2_proofs/src/circuit/value.rs | 2 +- halo2_proofs/src/dev.rs | 12 ++++++------ halo2_proofs/src/dev/cost.rs | 4 ++-- halo2_proofs/src/dev/failure.rs | 4 ++-- halo2_proofs/src/dev/failure/emitter.rs | 2 +- halo2_proofs/src/dev/gates.rs | 4 ++-- halo2_proofs/src/dev/graph.rs | 2 +- halo2_proofs/src/dev/graph/layout.rs | 2 +- halo2_proofs/src/dev/util.rs | 6 +++--- halo2_proofs/src/helpers.rs | 6 +++--- halo2_proofs/src/lib.rs | 4 ++-- halo2_proofs/src/plonk.rs | 4 ++-- halo2_proofs/src/plonk/assigned.rs | 4 ++-- halo2_proofs/src/plonk/circuit.rs | 4 ++-- halo2_proofs/src/plonk/circuit/compress_selectors.rs | 2 +- halo2_proofs/src/plonk/evaluation.rs | 8 ++++---- halo2_proofs/src/plonk/keygen.rs | 4 ++-- halo2_proofs/src/plonk/lookup.rs | 2 +- halo2_proofs/src/plonk/lookup/prover.rs | 6 +++--- halo2_proofs/src/plonk/lookup/verifier.rs | 2 +- halo2_proofs/src/plonk/permutation.rs | 2 +- halo2_proofs/src/plonk/permutation/keygen.rs | 6 +++--- halo2_proofs/src/plonk/permutation/prover.rs | 4 ++-- halo2_proofs/src/plonk/permutation/verifier.rs | 4 ++-- halo2_proofs/src/plonk/prover.rs | 6 +++--- halo2_proofs/src/plonk/vanishing/prover.rs | 4 ++-- halo2_proofs/src/plonk/vanishing/verifier.rs | 2 +- halo2_proofs/src/plonk/verifier.rs | 4 ++-- halo2_proofs/src/plonk/verifier/batch.rs | 4 ++-- halo2_proofs/src/poly.rs | 4 ++-- halo2_proofs/src/poly/commitment.rs | 4 ++-- halo2_proofs/src/poly/domain.rs | 4 ++-- halo2_proofs/src/poly/evaluator.rs | 2 +- halo2_proofs/src/poly/ipa/commitment.rs | 10 +++++----- halo2_proofs/src/poly/ipa/commitment/prover.rs | 4 ++-- halo2_proofs/src/poly/ipa/commitment/verifier.rs | 2 +- halo2_proofs/src/poly/ipa/msm.rs | 8 ++++---- halo2_proofs/src/poly/ipa/multiopen.rs | 2 +- halo2_proofs/src/poly/ipa/multiopen/prover.rs | 4 ++-- halo2_proofs/src/poly/ipa/multiopen/verifier.rs | 2 +- halo2_proofs/src/poly/ipa/strategy.rs | 4 ++-- halo2_proofs/src/poly/kzg/commitment.rs | 12 ++++++------ halo2_proofs/src/poly/kzg/msm.rs | 10 +++++----- halo2_proofs/src/poly/kzg/multiopen/gwc.rs | 2 +- halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs | 4 ++-- halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs | 4 ++-- halo2_proofs/src/poly/kzg/multiopen/shplonk.rs | 4 ++-- .../src/poly/kzg/multiopen/shplonk/prover.rs | 4 ++-- .../src/poly/kzg/multiopen/shplonk/verifier.rs | 4 ++-- halo2_proofs/src/poly/kzg/strategy.rs | 4 ++-- halo2_proofs/src/poly/multiopen.rs | 10 +++++----- halo2_proofs/src/poly/multiopen_test.rs | 4 ++-- halo2_proofs/src/poly/query.rs | 2 +- halo2_proofs/src/transcript.rs | 4 ++-- halo2_proofs/src/transcript/blake2b.rs | 4 ++-- halo2_proofs/src/transcript/mod.rs.bak | 4 ++-- halo2_proofs/src/transcript/poseidon.rs | 4 ++-- halo2_proofs/tests/plonk_api.rs | 6 +++--- 79 files changed, 168 insertions(+), 165 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 65a7b5dc94..359fb2339b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,13 @@ members = [ ] - +# 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" } \ No newline at end of file +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" } \ No newline at end of file diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index e70f7ce02f..dab20c4c62 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -46,8 +46,6 @@ harness = false [dependencies] backtrace = { version = "0.3", optional = true } rayon = "1.5.1" -ff = "0.13" -group = "0.13" halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves.git', features = [ "derive_serde" ] } rand_core = { version = "0.6", default-features = false } tracing = "0.1" @@ -55,7 +53,7 @@ blake2b_simd = "1" sha3 = "0.9.1" subtle = "2.3" cfg-if = "0.1" -poseidon = { git = 'https://github.com/privacy-scaling-explorations/poseidon.git' } #, branch = 'circuit' } +poseidon = { git = 'https://github.com/privacy-scaling-explorations/poseidon.git' } num-integer = "0.1" num-bigint = { version = "0.4", features = ["rand"] } diff --git a/halo2_proofs/benches/arithmetic.rs b/halo2_proofs/benches/arithmetic.rs index 4ae88af137..0f5695bcc3 100644 --- a/halo2_proofs/benches/arithmetic.rs +++ b/halo2_proofs/benches/arithmetic.rs @@ -3,7 +3,7 @@ extern crate criterion; use crate::arithmetic::small_multiexp; use crate::halo2curves::pasta::{EqAffine, Fp}; -use group::ff::Field; +use halo2curves::ff::Field; use halo2_proofs::*; use halo2_proofs::poly::{commitment::ParamsProver, ipa::commitment::ParamsIPA}; diff --git a/halo2_proofs/benches/dev_lookup.rs b/halo2_proofs/benches/dev_lookup.rs index 37a57800f5..74ab31f02b 100644 --- a/halo2_proofs/benches/dev_lookup.rs +++ b/halo2_proofs/benches/dev_lookup.rs @@ -1,7 +1,7 @@ #[macro_use] extern crate criterion; -use ff::PrimeField; +use halo2curves::ff::PrimeField; use halo2_proofs::circuit::{Layouter, SimpleFloorPlanner, Value}; use halo2_proofs::dev::MockProver; use halo2_proofs::plonk::*; diff --git a/halo2_proofs/benches/fft.rs b/halo2_proofs/benches/fft.rs index 0de72a0380..40c6b35b39 100644 --- a/halo2_proofs/benches/fft.rs +++ b/halo2_proofs/benches/fft.rs @@ -2,7 +2,7 @@ extern crate criterion; use crate::arithmetic::best_fft; -use group::ff::Field; +use halo2curves::ff::Field; use halo2_proofs::*; use halo2curves::pasta::Fp; diff --git a/halo2_proofs/benches/plonk.rs b/halo2_proofs/benches/plonk.rs index e4659e53b8..cbbee900bc 100644 --- a/halo2_proofs/benches/plonk.rs +++ b/halo2_proofs/benches/plonk.rs @@ -1,8 +1,8 @@ #[macro_use] extern crate criterion; -use ff::Field; -use ff::PrimeField; +use halo2curves::ff::Field; +use halo2curves::ff::PrimeField; use halo2_proofs::circuit::{Cell, Layouter, SimpleFloorPlanner, Value}; use halo2_proofs::plonk::*; use halo2_proofs::poly::{commitment::ParamsProver, Rotation}; diff --git a/halo2_proofs/examples/circuit-layout.rs b/halo2_proofs/examples/circuit-layout.rs index b1cf7eed27..29a7533c9c 100644 --- a/halo2_proofs/examples/circuit-layout.rs +++ b/halo2_proofs/examples/circuit-layout.rs @@ -1,4 +1,4 @@ -use ff::Field; +use halo2curves::ff::Field; use halo2_proofs::{ arithmetic::FieldExt, circuit::{Cell, Layouter, Region, SimpleFloorPlanner, Value}, diff --git a/halo2_proofs/examples/cost-model.rs b/halo2_proofs/examples/cost-model.rs index 100f047fac..eba20ff959 100644 --- a/halo2_proofs/examples/cost-model.rs +++ b/halo2_proofs/examples/cost-model.rs @@ -5,8 +5,8 @@ use std::{ time::{Duration, Instant}, }; -use ff::Field; -use group::{Curve, Group}; +use halo2curves::ff::Field; +use halo2curves::group::{Curve, Group}; use gumdrop::Options; use halo2_proofs::arithmetic::best_multiexp; use halo2curves::pasta::pallas; diff --git a/halo2_proofs/examples/serialization.rs b/halo2_proofs/examples/serialization.rs index 91ed5464e4..c8a792d7fa 100644 --- a/halo2_proofs/examples/serialization.rs +++ b/halo2_proofs/examples/serialization.rs @@ -3,7 +3,7 @@ use std::{ io::{BufReader, BufWriter, Write}, }; -use ff::Field; +use halo2curves::ff::Field; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, plonk::{ diff --git a/halo2_proofs/examples/shuffle.rs b/halo2_proofs/examples/shuffle.rs index 067cb259fa..f4f64a03bf 100644 --- a/halo2_proofs/examples/shuffle.rs +++ b/halo2_proofs/examples/shuffle.rs @@ -1,5 +1,5 @@ -use ff::PrimeField; -use ff::{BatchInvert, FromUniformBytes, WithSmallOrderMulGroup}; +use halo2curves::ff::PrimeField; +use halo2curves::ff::{BatchInvert, FromUniformBytes, WithSmallOrderMulGroup}; use halo2_proofs::{ arithmetic::CurveAffine, circuit::{floor_planner::V1, Layouter, Value}, diff --git a/halo2_proofs/examples/simple-example.rs b/halo2_proofs/examples/simple-example.rs index e2e006dbfa..166b94e4e8 100644 --- a/halo2_proofs/examples/simple-example.rs +++ b/halo2_proofs/examples/simple-example.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use ff::PrimeField; +use halo2curves::ff::PrimeField; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Selector}, diff --git a/halo2_proofs/examples/two-chip.rs b/halo2_proofs/examples/two-chip.rs index d2ac2c62b7..57f5929346 100644 --- a/halo2_proofs/examples/two-chip.rs +++ b/halo2_proofs/examples/two-chip.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use ff::PrimeField; +use halo2curves::ff::PrimeField; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance, Selector}, @@ -496,7 +496,7 @@ impl Circuit for MyCircuit { #[allow(clippy::many_single_char_names)] fn main() { - use group::ff::Field; + use halo2curves::ff::Field; use halo2_proofs::dev::MockProver; use halo2curves::pasta::Fp; use rand_core::OsRng; diff --git a/halo2_proofs/src/arithmetic.rs b/halo2_proofs/src/arithmetic.rs index 52ddb41ddb..2006dc0743 100644 --- a/halo2_proofs/src/arithmetic.rs +++ b/halo2_proofs/src/arithmetic.rs @@ -12,11 +12,9 @@ pub use multi_exp::{best_multiexp, small_multiexp}; pub use util::{generate_twiddle_lookup_table, parallelize}; use super::multicore; -pub use ff::Field; -use group::{ - ff::{BatchInvert, PrimeField}, - Curve, Group, -}; +pub use halo2curves::ff::Field; +use halo2curves::ff::{BatchInvert, PrimeField}; +use halo2curves::group::{Curve, Group}; pub use halo2curves::{CurveAffine, CurveExt}; diff --git a/halo2_proofs/src/arithmetic/field_fft.rs b/halo2_proofs/src/arithmetic/field_fft.rs index 5c5eebaf89..74f9c79baa 100644 --- a/halo2_proofs/src/arithmetic/field_fft.rs +++ b/halo2_proofs/src/arithmetic/field_fft.rs @@ -1,8 +1,8 @@ use super::multicore; use super::util::{bitreverse, parallelize}; use crate::arithmetic::log2_floor; -pub use ff::Field; -use group::{ +pub use halo2curves::ff::Field; +use halo2curves::group::{ ff::{BatchInvert, PrimeField}, Curve, Group, }; diff --git a/halo2_proofs/src/arithmetic/group_fft.rs b/halo2_proofs/src/arithmetic/group_fft.rs index dc6ba067f0..6d2ce4247d 100644 --- a/halo2_proofs/src/arithmetic/group_fft.rs +++ b/halo2_proofs/src/arithmetic/group_fft.rs @@ -1,8 +1,8 @@ use crate::arithmetic::{log2_floor, util::bitreverse}; use super::{multicore, util::parallelize}; -pub use ff::Field; -use group::{ +pub use halo2curves::ff::Field; +use halo2curves::group::{ ff::{BatchInvert, PrimeField}, Curve, Group, }; diff --git a/halo2_proofs/src/arithmetic/multi_exp.rs b/halo2_proofs/src/arithmetic/multi_exp.rs index f2967ce712..9760947a42 100644 --- a/halo2_proofs/src/arithmetic/multi_exp.rs +++ b/halo2_proofs/src/arithmetic/multi_exp.rs @@ -1,6 +1,6 @@ use super::multicore; -pub use ff::Field; -use group::{ +pub use halo2curves::ff::Field; +use halo2curves::group::{ ff::{BatchInvert, PrimeField}, Curve, Group, }; diff --git a/halo2_proofs/src/arithmetic/util.rs b/halo2_proofs/src/arithmetic/util.rs index c4da0758d5..cb9f816a32 100644 --- a/halo2_proofs/src/arithmetic/util.rs +++ b/halo2_proofs/src/arithmetic/util.rs @@ -1,4 +1,4 @@ -use ff::Field; +use halo2curves::ff::Field; use crate::multicore; diff --git a/halo2_proofs/src/circuit.rs b/halo2_proofs/src/circuit.rs index 58e988a990..0a8f086fb0 100644 --- a/halo2_proofs/src/circuit.rs +++ b/halo2_proofs/src/circuit.rs @@ -2,7 +2,7 @@ use std::{convert::TryInto, fmt, marker::PhantomData}; -use ff::{Field, PrimeField}; +use halo2curves::ff::{Field, PrimeField}; use crate::plonk::{ Advice, Any, Assigned, Challenge, Column, Error, Fixed, Instance, Selector, TableColumn, diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index f658413185..105eb8d012 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use std::fmt; use std::marker::PhantomData; -use ff::Field; +use halo2curves::ff::Field; use ark_std::{end_timer, start_timer}; @@ -508,7 +508,7 @@ mod tests { dev::MockProver, plonk::{Advice, Circuit, Column, Error}, }; - use ff::Field; + use halo2curves::ff::Field; use halo2curves::pasta::vesta; #[test] diff --git a/halo2_proofs/src/circuit/floor_planner/v1.rs b/halo2_proofs/src/circuit/floor_planner/v1.rs index 1b41839923..4f579ba8d4 100644 --- a/halo2_proofs/src/circuit/floor_planner/v1.rs +++ b/halo2_proofs/src/circuit/floor_planner/v1.rs @@ -1,6 +1,6 @@ use std::fmt; -use ff::Field; +use halo2curves::ff::Field; use crate::{ circuit::{ @@ -522,7 +522,7 @@ mod tests { dev::MockProver, plonk::{Advice, Circuit, Column, Error}, }; - use ff::Field; + use halo2curves::ff::Field; use halo2curves::pasta::vesta; #[test] diff --git a/halo2_proofs/src/circuit/layouter.rs b/halo2_proofs/src/circuit/layouter.rs index f73d7d7d73..81aed85090 100644 --- a/halo2_proofs/src/circuit/layouter.rs +++ b/halo2_proofs/src/circuit/layouter.rs @@ -4,7 +4,7 @@ use std::cmp; use std::collections::HashSet; use std::fmt; -use ff::Field; +use halo2curves::ff::Field; use super::{Cell, RegionIndex, Value}; use crate::plonk::{Advice, Any, Assigned, Column, Error, Fixed, Instance, Selector, TableColumn}; diff --git a/halo2_proofs/src/circuit/value.rs b/halo2_proofs/src/circuit/value.rs index 1a1bf4f9a2..1fbe4855bd 100644 --- a/halo2_proofs/src/circuit/value.rs +++ b/halo2_proofs/src/circuit/value.rs @@ -1,7 +1,7 @@ use std::borrow::Borrow; use std::ops::{Add, Mul, Neg, Sub}; -use group::ff::Field; +use halo2curves::ff::Field; use crate::plonk::{Assigned, Error}; diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index 71a92c57fb..40fd179d23 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -8,11 +8,11 @@ use std::ops::{Add, Mul, Neg, Range}; use std::time::{Duration, Instant}; use blake2b_simd::blake2b; -use ff::Field; -use ff::FromUniformBytes; -use ff::PrimeField; -use ff::WithSmallOrderMulGroup; -use group::Group; +use halo2curves::ff::Field; +use halo2curves::ff::FromUniformBytes; +use halo2curves::ff::PrimeField; +use halo2curves::ff::WithSmallOrderMulGroup; +use halo2curves::group::Group; use crate::plonk::permutation::keygen::Assembly; use crate::plonk::sealed::SealedPhase; @@ -192,7 +192,7 @@ impl + Field> Mul for Value { /// plonk::{Advice, Any, Circuit, Column, ConstraintSystem, Error, Selector}, /// poly::Rotation, /// }; -/// use ff::PrimeField; +/// use halo2curves::ff::PrimeField; /// use halo2curves::pasta::Fp; /// const K: u32 = 5; /// diff --git a/halo2_proofs/src/dev/cost.rs b/halo2_proofs/src/dev/cost.rs index d3043508f5..36724d737f 100644 --- a/halo2_proofs/src/dev/cost.rs +++ b/halo2_proofs/src/dev/cost.rs @@ -7,8 +7,8 @@ use std::{ ops::{Add, Mul}, }; -use ff::{Field, PrimeField}; -use group::prime::PrimeGroup; +use halo2curves::ff::{Field, PrimeField}; +use halo2curves::group::prime::PrimeGroup; use crate::{ circuit::Value, diff --git a/halo2_proofs/src/dev/failure.rs b/halo2_proofs/src/dev/failure.rs index e90b42f29f..afe53346a3 100644 --- a/halo2_proofs/src/dev/failure.rs +++ b/halo2_proofs/src/dev/failure.rs @@ -1,8 +1,8 @@ use std::collections::{BTreeMap, HashSet}; use std::fmt::{self, Debug}; -use ff::{PrimeField, WithSmallOrderMulGroup}; -use group::ff::Field; +use halo2curves::ff::{PrimeField, WithSmallOrderMulGroup}; +use halo2curves::ff::Field; use super::metadata::{DebugColumn, DebugVirtualCell}; use super::MockProver; diff --git a/halo2_proofs/src/dev/failure/emitter.rs b/halo2_proofs/src/dev/failure/emitter.rs index e84ba8013e..c5afecf860 100644 --- a/halo2_proofs/src/dev/failure/emitter.rs +++ b/halo2_proofs/src/dev/failure/emitter.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use std::iter; -use group::ff::Field; +use halo2curves::ff::Field; use super::FailureLocation; use crate::{ diff --git a/halo2_proofs/src/dev/gates.rs b/halo2_proofs/src/dev/gates.rs index cfc71c021e..d9e46aaa71 100644 --- a/halo2_proofs/src/dev/gates.rs +++ b/halo2_proofs/src/dev/gates.rs @@ -3,7 +3,7 @@ use std::{ fmt::{self, Write}, }; -use ff::PrimeField; +use halo2curves::ff::PrimeField; use crate::{ dev::util, @@ -31,7 +31,7 @@ struct Gate { /// # Examples /// /// ``` -/// use ff::Field; +/// use halo2curves::ff::Field; /// use halo2_proofs::{ /// circuit::{Layouter, SimpleFloorPlanner}, /// dev::CircuitGates, diff --git a/halo2_proofs/src/dev/graph.rs b/halo2_proofs/src/dev/graph.rs index 5a43313dea..d3a1a5cfe4 100644 --- a/halo2_proofs/src/dev/graph.rs +++ b/halo2_proofs/src/dev/graph.rs @@ -1,4 +1,4 @@ -use ff::Field; +use halo2curves::ff::Field; use tabbycat::{AttrList, Edge, GraphBuilder, GraphType, Identity, StmtList}; use crate::{ diff --git a/halo2_proofs/src/dev/graph/layout.rs b/halo2_proofs/src/dev/graph/layout.rs index 0f2e67a81d..af1334510f 100644 --- a/halo2_proofs/src/dev/graph/layout.rs +++ b/halo2_proofs/src/dev/graph/layout.rs @@ -1,4 +1,4 @@ -use ff::Field; +use halo2curves::ff::Field; use plotters::{ coord::Shift, prelude::{DrawingArea, DrawingAreaErrorKind, DrawingBackend}, diff --git a/halo2_proofs/src/dev/util.rs b/halo2_proofs/src/dev/util.rs index 3200844bdb..5fd2f19a0a 100644 --- a/halo2_proofs/src/dev/util.rs +++ b/halo2_proofs/src/dev/util.rs @@ -1,8 +1,8 @@ use std::collections::BTreeMap; -use ff::PrimeField; -use ff::WithSmallOrderMulGroup; -use group::ff::Field; +use halo2curves::ff::PrimeField; +use halo2curves::ff::WithSmallOrderMulGroup; +use halo2curves::ff::Field; use super::{metadata, CellValue, Value}; use crate::{ diff --git a/halo2_proofs/src/helpers.rs b/halo2_proofs/src/helpers.rs index 7d549556b1..dd3cc558d9 100644 --- a/halo2_proofs/src/helpers.rs +++ b/halo2_proofs/src/helpers.rs @@ -1,7 +1,7 @@ use crate::poly::Polynomial; -use ff::Field; -use ff::FromUniformBytes; -use ff::PrimeField; +use halo2curves::ff::Field; +use halo2curves::ff::FromUniformBytes; +use halo2curves::ff::PrimeField; use halo2curves::{pairing::Engine, serde::SerdeObject, CurveAffine}; use num_bigint::BigUint; use std::io; diff --git a/halo2_proofs/src/lib.rs b/halo2_proofs/src/lib.rs index 4abf110da2..e616c0e9c0 100644 --- a/halo2_proofs/src/lib.rs +++ b/halo2_proofs/src/lib.rs @@ -36,6 +36,6 @@ pub mod dev; mod helpers; pub use helpers::SerdeFormat; -pub use ff; -pub use group; pub use halo2curves as curves; +pub use halo2curves::ff; +pub use halo2curves::group; diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index 4e584b98a3..8e64670ecb 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -6,8 +6,8 @@ //! [plonk]: https://eprint.iacr.org/2019/953 use blake2b_simd::Params as Blake2bParams; -use ff::{FromUniformBytes, PrimeField}; -use group::ff::Field; +use halo2curves::ff::Field; +use halo2curves::ff::{FromUniformBytes, PrimeField}; use halo2curves::pairing::Engine; use halo2curves::CurveAffineExt; diff --git a/halo2_proofs/src/plonk/assigned.rs b/halo2_proofs/src/plonk/assigned.rs index 46d527b915..083f66b26c 100644 --- a/halo2_proofs/src/plonk/assigned.rs +++ b/halo2_proofs/src/plonk/assigned.rs @@ -1,6 +1,6 @@ use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; -use group::ff::Field; +use halo2curves::ff::Field; /// A value assigned to a cell within a circuit. /// @@ -450,7 +450,7 @@ mod proptests { ops::{Add, Mul, Neg, Sub}, }; - use group::ff::Field; + use halo2curves::ff::Field; use halo2curves::pasta::Fp; use proptest::{collection::vec, prelude::*, sample::select}; diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index 9e17d5b5c2..d38ff738db 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -1,6 +1,6 @@ use core::cmp::max; use core::ops::{Add, Mul}; -use ff::Field; +use halo2curves::ff::Field; use std::collections::HashMap; use std::{ convert::TryFrom, @@ -351,7 +351,7 @@ impl TryFrom> for Column { /// circuit::{Chip, Layouter, Value}, /// plonk::{Advice, Column, Error, Selector}, /// }; -/// use ff::{Field, PrimeField}; +/// use halo2curves::ff::{Field, PrimeField}; /// # use halo2_proofs::plonk::Fixed; /// /// struct Config { diff --git a/halo2_proofs/src/plonk/circuit/compress_selectors.rs b/halo2_proofs/src/plonk/circuit/compress_selectors.rs index 3de6b4dfc2..138f58ef79 100644 --- a/halo2_proofs/src/plonk/circuit/compress_selectors.rs +++ b/halo2_proofs/src/plonk/circuit/compress_selectors.rs @@ -1,5 +1,5 @@ use super::Expression; -use ff::Field; +use halo2curves::ff::Field; /// This describes a selector and where it is activated. #[derive(Debug, Clone)] diff --git a/halo2_proofs/src/plonk/evaluation.rs b/halo2_proofs/src/plonk/evaluation.rs index 00e9981202..3ab22bfa56 100644 --- a/halo2_proofs/src/plonk/evaluation.rs +++ b/halo2_proofs/src/plonk/evaluation.rs @@ -11,10 +11,10 @@ use crate::{ }, transcript::{EncodedChallenge, TranscriptWrite}, }; -use ff::PrimeField; -use ff::WithSmallOrderMulGroup; -use group::prime::PrimeCurve; -use group::{ +use halo2curves::ff::PrimeField; +use halo2curves::ff::WithSmallOrderMulGroup; +use halo2curves::group::prime::PrimeCurve; +use halo2curves::group::{ ff::{BatchInvert, Field}, Curve, }; diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index ad67668015..6dec5b5515 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -2,8 +2,8 @@ use std::ops::Range; -use ff::{Field, FromUniformBytes}; -use group::Curve; +use halo2curves::ff::{Field, FromUniformBytes}; +use halo2curves::group::Curve; use super::{ circuit::{ diff --git a/halo2_proofs/src/plonk/lookup.rs b/halo2_proofs/src/plonk/lookup.rs index e0d0db5c0c..22d16ef15a 100644 --- a/halo2_proofs/src/plonk/lookup.rs +++ b/halo2_proofs/src/plonk/lookup.rs @@ -1,5 +1,5 @@ use super::circuit::Expression; -use ff::Field; +use halo2curves::ff::Field; use std::fmt::{self, Debug}; pub(crate) mod prover; diff --git a/halo2_proofs/src/plonk/lookup/prover.rs b/halo2_proofs/src/plonk/lookup/prover.rs index 703fa61a62..5866164212 100644 --- a/halo2_proofs/src/plonk/lookup/prover.rs +++ b/halo2_proofs/src/plonk/lookup/prover.rs @@ -13,9 +13,9 @@ use crate::{ }, transcript::{EncodedChallenge, TranscriptWrite}, }; -use ff::{PrimeField, WithSmallOrderMulGroup}; -use group::prime::PrimeCurveAffine; -use group::{ +use halo2curves::ff::{PrimeField, WithSmallOrderMulGroup}; +use halo2curves::group::prime::PrimeCurveAffine; +use halo2curves::group::{ ff::{BatchInvert, Field}, Curve, }; diff --git a/halo2_proofs/src/plonk/lookup/verifier.rs b/halo2_proofs/src/plonk/lookup/verifier.rs index afc99f8127..6b23d64819 100644 --- a/halo2_proofs/src/plonk/lookup/verifier.rs +++ b/halo2_proofs/src/plonk/lookup/verifier.rs @@ -10,7 +10,7 @@ use crate::{ poly::{commitment::MSM, Rotation, VerifierQuery}, transcript::{EncodedChallenge, TranscriptRead}, }; -use ff::{Field, PrimeField}; +use halo2curves::ff::{Field, PrimeField}; #[derive(Debug)] pub struct PermutationCommitments { diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index a0a20df718..57fb9e2f8d 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -8,7 +8,7 @@ use crate::{ poly::{Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial}, SerdeFormat, }; -use ff::PrimeField; +use halo2curves::ff::PrimeField; pub(crate) mod keygen; pub(crate) mod prover; diff --git a/halo2_proofs/src/plonk/permutation/keygen.rs b/halo2_proofs/src/plonk/permutation/keygen.rs index 0a541f5164..e8faf9a337 100644 --- a/halo2_proofs/src/plonk/permutation/keygen.rs +++ b/halo2_proofs/src/plonk/permutation/keygen.rs @@ -1,5 +1,5 @@ -use ff::Field; -use group::Curve; +use halo2curves::ff::Field; +use halo2curves::group::Curve; use super::{Argument, ProvingKey, VerifyingKey}; use crate::{ @@ -10,7 +10,7 @@ use crate::{ EvaluationDomain, }, }; -use ff::PrimeField; +use halo2curves::ff::PrimeField; /// Struct that accumulates all the necessary data in order to construct the permutation argument. #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/halo2_proofs/src/plonk/permutation/prover.rs b/halo2_proofs/src/plonk/permutation/prover.rs index bba2b73688..0511fc29f0 100644 --- a/halo2_proofs/src/plonk/permutation/prover.rs +++ b/halo2_proofs/src/plonk/permutation/prover.rs @@ -1,5 +1,5 @@ -use ff::PrimeField; -use group::{ +use halo2curves::ff::PrimeField; +use halo2curves::group::{ ff::{BatchInvert, Field}, Curve, }; diff --git a/halo2_proofs/src/plonk/permutation/verifier.rs b/halo2_proofs/src/plonk/permutation/verifier.rs index 3ee0443f53..cc11629abb 100644 --- a/halo2_proofs/src/plonk/permutation/verifier.rs +++ b/halo2_proofs/src/plonk/permutation/verifier.rs @@ -1,4 +1,4 @@ -use ff::Field; +use halo2curves::ff::Field; use std::iter; use super::super::{circuit::Any, ChallengeBeta, ChallengeGamma, ChallengeX}; @@ -9,7 +9,7 @@ use crate::{ poly::{commitment::MSM, Rotation, VerifierQuery}, transcript::{EncodedChallenge, TranscriptRead}, }; -use ff::PrimeField; +use halo2curves::ff::PrimeField; #[derive(Debug)] pub struct Committed { diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index 45e580bbe3..e430338370 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -1,5 +1,5 @@ -use ff::{Field, FromUniformBytes}; -use group::Curve; +use halo2curves::ff::{Field, FromUniformBytes}; +use halo2curves::group::Curve; use halo2curves::CurveExt; use rand_core::RngCore; use std::collections::BTreeSet; @@ -32,7 +32,7 @@ use crate::{ poly::batch_invert_assigned, transcript::{EncodedChallenge, TranscriptWrite}, }; -use group::prime::PrimeCurveAffine; +use halo2curves::group::prime::PrimeCurveAffine; /// This creates a proof for the provided `circuit` when given the public /// parameters `params` and the proving key [`ProvingKey`] that was diff --git a/halo2_proofs/src/plonk/vanishing/prover.rs b/halo2_proofs/src/plonk/vanishing/prover.rs index d394b8c0de..b556531e0a 100644 --- a/halo2_proofs/src/plonk/vanishing/prover.rs +++ b/halo2_proofs/src/plonk/vanishing/prover.rs @@ -1,7 +1,7 @@ use std::iter; -use ff::Field; -use group::Curve; +use halo2curves::ff::Field; +use halo2curves::group::Curve; use rand_core::RngCore; use super::Argument; diff --git a/halo2_proofs/src/plonk/vanishing/verifier.rs b/halo2_proofs/src/plonk/vanishing/verifier.rs index 0881dfb2c0..785a70959c 100644 --- a/halo2_proofs/src/plonk/vanishing/verifier.rs +++ b/halo2_proofs/src/plonk/vanishing/verifier.rs @@ -1,6 +1,6 @@ use std::iter; -use ff::Field; +use halo2curves::ff::Field; use crate::{ arithmetic::CurveAffine, diff --git a/halo2_proofs/src/plonk/verifier.rs b/halo2_proofs/src/plonk/verifier.rs index 32fd638c86..a7b6933ea7 100644 --- a/halo2_proofs/src/plonk/verifier.rs +++ b/halo2_proofs/src/plonk/verifier.rs @@ -1,5 +1,5 @@ -use ff::{Field, FromUniformBytes}; -use group::Curve; +use halo2curves::ff::{Field, FromUniformBytes}; +use halo2curves::group::Curve; use rand_core::RngCore; use std::iter; diff --git a/halo2_proofs/src/plonk/verifier/batch.rs b/halo2_proofs/src/plonk/verifier/batch.rs index 04e08be4af..3403a9b963 100644 --- a/halo2_proofs/src/plonk/verifier/batch.rs +++ b/halo2_proofs/src/plonk/verifier/batch.rs @@ -1,7 +1,7 @@ use std::{io, marker::PhantomData}; -use ff::FromUniformBytes; -use group::ff::Field; +use halo2curves::ff::FromUniformBytes; +use halo2curves::ff::Field; use halo2curves::CurveAffine; use rand_core::{OsRng, RngCore}; use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; diff --git a/halo2_proofs/src/poly.rs b/halo2_proofs/src/poly.rs index 70c99a83a1..24dae0d471 100644 --- a/halo2_proofs/src/poly.rs +++ b/halo2_proofs/src/poly.rs @@ -7,8 +7,8 @@ use crate::helpers::SerdePrimeField; use crate::plonk::Assigned; use crate::SerdeFormat; -use ff::PrimeField; -use group::ff::{BatchInvert, Field}; +use halo2curves::ff::PrimeField; +use halo2curves::ff::{BatchInvert, Field}; use std::fmt::Debug; use std::io; use std::marker::PhantomData; diff --git a/halo2_proofs/src/poly/commitment.rs b/halo2_proofs/src/poly/commitment.rs index 6517df5ec1..5638d09ff4 100644 --- a/halo2_proofs/src/poly/commitment.rs +++ b/halo2_proofs/src/poly/commitment.rs @@ -5,8 +5,8 @@ use super::{ }; use crate::poly::Error; use crate::transcript::{EncodedChallenge, TranscriptRead, TranscriptWrite}; -use ff::{Field, PrimeField, WithSmallOrderMulGroup}; -use group::Curve; +use halo2curves::ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use halo2curves::group::Curve; use halo2curves::{CurveAffine, CurveExt}; use rand_core::RngCore; use std::{ diff --git a/halo2_proofs/src/poly/domain.rs b/halo2_proofs/src/poly/domain.rs index e2884f3d25..b8c031d46d 100644 --- a/halo2_proofs/src/poly/domain.rs +++ b/halo2_proofs/src/poly/domain.rs @@ -8,8 +8,8 @@ use crate::{ use super::{Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, Rotation}; -use ff::WithSmallOrderMulGroup; -use group::{ +use halo2curves::ff::WithSmallOrderMulGroup; +use halo2curves::group::{ ff::{BatchInvert, Field, PrimeField}, Group, }; diff --git a/halo2_proofs/src/poly/evaluator.rs b/halo2_proofs/src/poly/evaluator.rs index ea3e24ddf1..84e01ad87d 100644 --- a/halo2_proofs/src/poly/evaluator.rs +++ b/halo2_proofs/src/poly/evaluator.rs @@ -8,7 +8,7 @@ use std::{ sync::Arc, }; -use group::ff::Field; +use halo2curves::ff::Field; use halo2curves::FieldExt; use super::{ diff --git a/halo2_proofs/src/poly/ipa/commitment.rs b/halo2_proofs/src/poly/ipa/commitment.rs index 461c0d4b26..838fcb3e49 100644 --- a/halo2_proofs/src/poly/ipa/commitment.rs +++ b/halo2_proofs/src/poly/ipa/commitment.rs @@ -11,8 +11,8 @@ use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, Par use crate::poly::ipa::msm::MSMIPA; use crate::poly::{Coeff, LagrangeCoeff, Polynomial}; -use ff::{Field, PrimeField}; -use group::{prime::PrimeCurveAffine, Curve, Group as _}; +use halo2curves::ff::{Field, PrimeField}; +use halo2curves::group::{prime::PrimeCurveAffine, Curve, Group as _}; use std::marker::PhantomData; use std::ops::{Add, AddAssign, Mul, MulAssign}; @@ -242,8 +242,8 @@ mod test { use crate::poly::ipa::msm::MSMIPA; use crate::poly::{Coeff, LagrangeCoeff, Polynomial}; - use ff::{Field, PrimeField}; - use group::{prime::PrimeCurveAffine, Curve, Group as _}; + use halo2curves::ff::{Field, PrimeField}; + use halo2curves::group::{prime::PrimeCurveAffine, Curve, Group as _}; use std::marker::PhantomData; use std::ops::{Add, AddAssign, Mul, MulAssign}; @@ -303,7 +303,7 @@ mod test { fn test_opening_proof() { const K: u32 = 6; - use ff::Field; + use halo2curves::ff::Field; use rand_core::OsRng; use super::super::commitment::{Blind, Params}; diff --git a/halo2_proofs/src/poly/ipa/commitment/prover.rs b/halo2_proofs/src/poly/ipa/commitment/prover.rs index d176987c96..adf986e04b 100644 --- a/halo2_proofs/src/poly/ipa/commitment/prover.rs +++ b/halo2_proofs/src/poly/ipa/commitment/prover.rs @@ -1,4 +1,4 @@ -use ff::Field; +use halo2curves::ff::Field; use rand_core::RngCore; use super::{Params, ParamsIPA}; @@ -10,7 +10,7 @@ use crate::poly::commitment::ParamsProver; use crate::poly::{commitment::Blind, Coeff, Polynomial}; use crate::transcript::{EncodedChallenge, TranscriptWrite}; -use group::Curve; +use halo2curves::group::Curve; use std::io::{self, Write}; /// Create a polynomial commitment opening proof for the polynomial defined diff --git a/halo2_proofs/src/poly/ipa/commitment/verifier.rs b/halo2_proofs/src/poly/ipa/commitment/verifier.rs index 0b60842899..71087611a5 100644 --- a/halo2_proofs/src/poly/ipa/commitment/verifier.rs +++ b/halo2_proofs/src/poly/ipa/commitment/verifier.rs @@ -1,6 +1,6 @@ use std::io::Read; -use group::{ +use halo2curves::group::{ ff::{BatchInvert, Field}, Curve, }; diff --git a/halo2_proofs/src/poly/ipa/msm.rs b/halo2_proofs/src/poly/ipa/msm.rs index 3316e25337..3c2fc814b8 100644 --- a/halo2_proofs/src/poly/ipa/msm.rs +++ b/halo2_proofs/src/poly/ipa/msm.rs @@ -4,8 +4,8 @@ use crate::poly::{ commitment::{CommitmentScheme, Params, MSM}, ipa::commitment::ParamsVerifierIPA, }; -use ff::Field; -use group::Group; +use halo2curves::ff::Field; +use halo2curves::group::Group; use std::collections::BTreeMap; /// A multiscalar multiplication in the polynomial commitment scheme @@ -70,7 +70,7 @@ impl<'a, C: CurveAffine> MSMIPA<'a, C> { impl<'a, C: CurveAffine> MSM for MSMIPA<'a, C> { fn append_term(&mut self, scalar: C::Scalar, point: C::Curve) { if !bool::from(point.is_identity()) { - use group::Curve; + use halo2curves::group::Curve; let point = point.to_affine(); let xy = point.coordinates().unwrap(); let x = *xy.x(); @@ -228,7 +228,7 @@ mod tests { commitment::{Params, MSM}, ipa::msm::MSMIPA, }; - use group::Curve; + use halo2curves::group::Curve; use halo2curves::{ pasta::{Ep, EpAffine, Fp, Fq}, CurveAffine, diff --git a/halo2_proofs/src/poly/ipa/multiopen.rs b/halo2_proofs/src/poly/ipa/multiopen.rs index 4aa6bd0de4..e1b37dbf12 100644 --- a/halo2_proofs/src/poly/ipa/multiopen.rs +++ b/halo2_proofs/src/poly/ipa/multiopen.rs @@ -11,7 +11,7 @@ use crate::{arithmetic::CurveAffine, poly::query::Query, transcript::ChallengeSc mod prover; mod verifier; -use ff::PrimeField; +use halo2curves::ff::PrimeField; pub use prover::ProverIPA; pub use verifier::VerifierIPA; diff --git a/halo2_proofs/src/poly/ipa/multiopen/prover.rs b/halo2_proofs/src/poly/ipa/multiopen/prover.rs index 6d65e7ae64..e48ec99954 100644 --- a/halo2_proofs/src/poly/ipa/multiopen/prover.rs +++ b/halo2_proofs/src/poly/ipa/multiopen/prover.rs @@ -9,8 +9,8 @@ use crate::poly::query::ProverQuery; use crate::poly::{Coeff, Polynomial}; use crate::transcript::{EncodedChallenge, TranscriptWrite}; -use ff::Field; -use group::Curve; +use halo2curves::ff::Field; +use halo2curves::group::Curve; use rand_core::RngCore; use std::io; use std::marker::PhantomData; diff --git a/halo2_proofs/src/poly/ipa/multiopen/verifier.rs b/halo2_proofs/src/poly/ipa/multiopen/verifier.rs index 391f89e15b..10d6fe8dcd 100644 --- a/halo2_proofs/src/poly/ipa/multiopen/verifier.rs +++ b/halo2_proofs/src/poly/ipa/multiopen/verifier.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use std::io::Read; use std::marker::PhantomData; -use ff::Field; +use halo2curves::ff::Field; use rand_core::RngCore; use super::{ diff --git a/halo2_proofs/src/poly/ipa/strategy.rs b/halo2_proofs/src/poly/ipa/strategy.rs index c8d385f90c..23e42697bf 100644 --- a/halo2_proofs/src/poly/ipa/strategy.rs +++ b/halo2_proofs/src/poly/ipa/strategy.rs @@ -14,8 +14,8 @@ use crate::{ }, transcript::EncodedChallenge, }; -use ff::Field; -use group::Curve; +use halo2curves::ff::Field; +use halo2curves::group::Curve; use halo2curves::CurveAffine; use rand_core::{OsRng, RngCore}; diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index 6076ee7673..91d40c5a0f 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -6,8 +6,8 @@ use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, Par use crate::poly::{Coeff, LagrangeCoeff, Polynomial}; use crate::SerdeFormat; -use ff::{Field, PrimeField, WithSmallOrderMulGroup}; -use group::{prime::PrimeCurveAffine, Curve, Group as _}; +use halo2curves::ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use halo2curves::group::{prime::PrimeCurveAffine, Curve, Group as _}; use halo2curves::pairing::Engine; use rand_core::{OsRng, RngCore}; use std::fmt::Debug; @@ -188,7 +188,7 @@ where let (g, g_lagrange) = match format { SerdeFormat::Processed => { - use group::GroupEncoding; + use halo2curves::group::GroupEncoding; let load_points_from_file_parallelly = |reader: &mut R| -> io::Result>> { let mut points_compressed = @@ -370,8 +370,8 @@ mod test { use crate::poly::kzg::multiopen::ProverSHPLONK; use crate::poly::{Coeff, LagrangeCoeff, Polynomial}; - use ff::{Field, PrimeField}; - use group::{prime::PrimeCurveAffine, Curve, Group as _}; + use halo2curves::ff::{Field, PrimeField}; + use halo2curves::group::{prime::PrimeCurveAffine, Curve, Group as _}; use halo2curves::bn256::G1Affine; use std::marker::PhantomData; use std::ops::{Add, AddAssign, Mul, MulAssign}; @@ -407,7 +407,7 @@ mod test { fn test_parameter_serialisation_roundtrip() { const K: u32 = 4; - use ff::Field; + use halo2curves::ff::Field; use rand_core::OsRng; use super::super::commitment::{Blind, Params}; diff --git a/halo2_proofs/src/poly/kzg/msm.rs b/halo2_proofs/src/poly/kzg/msm.rs index ae410424c8..01afb9bc81 100644 --- a/halo2_proofs/src/poly/kzg/msm.rs +++ b/halo2_proofs/src/poly/kzg/msm.rs @@ -5,8 +5,8 @@ use crate::{ arithmetic::{best_multiexp, parallelize, CurveAffine}, poly::commitment::MSM, }; -use ff::PrimeField; -use group::{Curve, Group}; +use halo2curves::ff::PrimeField; +use halo2curves::group::{Curve, Group}; use halo2curves::pairing::{Engine, MillerLoopResult, MultiMillerLoop}; /// A multiscalar multiplication in the polynomial commitment scheme @@ -27,7 +27,7 @@ impl MSMKZG { /// Prepares all scalars in the MSM to linear combination pub fn combine_with_base(&mut self, base: E::Scalar) { - use ff::Field; + use halo2curves::ff::Field; let mut acc = E::Scalar::ONE; if !self.scalars.is_empty() { for scalar in self.scalars.iter_mut().rev() { @@ -64,7 +64,7 @@ impl MSM for MSMKZG { } fn eval(&self) -> E::G1 { - use group::prime::PrimeCurveAffine; + use halo2curves::group::prime::PrimeCurveAffine; let mut bases = vec![E::G1Affine::identity(); self.scalars.len()]; E::G1::batch_normalize(&self.bases, &mut bases); best_multiexp(&self.scalars, &bases) @@ -93,7 +93,7 @@ impl PreMSM { } pub(crate) fn normalize(self) -> MSMKZG { - use group::prime::PrimeCurveAffine; + use halo2curves::group::prime::PrimeCurveAffine; let (scalars, bases) = self .projectives_msms diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc.rs index a5b22244f2..22703f274c 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc.rs @@ -1,7 +1,7 @@ mod prover; mod verifier; -use ff::PrimeField; +use halo2curves::ff::PrimeField; pub use prover::ProverGWC; pub use verifier::VerifierGWC; diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs index da3d7bf07c..25e1fea0c1 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs @@ -12,8 +12,8 @@ use crate::poly::{ }; use crate::transcript::{EncodedChallenge, TranscriptWrite}; -use ff::{Field, PrimeField, WithSmallOrderMulGroup}; -use group::Curve; +use halo2curves::ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use halo2curves::group::Curve; use halo2curves::pairing::Engine; use rand_core::RngCore; use std::fmt::Debug; diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs index 6da691b7be..ed307c3421 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs @@ -19,8 +19,8 @@ use crate::poly::{ }; use crate::transcript::{EncodedChallenge, TranscriptRead}; -use ff::{Field, PrimeField, WithSmallOrderMulGroup}; -use group::Group; +use halo2curves::ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use halo2curves::group::Group; use halo2curves::pairing::{Engine, MillerLoopResult, MultiMillerLoop}; use rand_core::OsRng; diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs index d60c8f1c03..c6f7a599c8 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs @@ -1,7 +1,7 @@ mod prover; mod verifier; -use ff::PrimeField; +use halo2curves::ff::PrimeField; pub use prover::ProverSHPLONK; pub use verifier::VerifierSHPLONK; @@ -149,7 +149,7 @@ where #[cfg(test)] mod proptests { - use ff::FromUniformBytes; + use halo2curves::ff::FromUniformBytes; use proptest::{ collection::vec, prelude::*, diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs index 4d5a9ed900..0f63aae752 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs @@ -13,8 +13,8 @@ use crate::poly::Rotation; use crate::poly::{commitment::Params, Coeff, Polynomial}; use crate::transcript::{EncodedChallenge, TranscriptWrite}; -use ff::{Field, PrimeField, WithSmallOrderMulGroup}; -use group::Curve; +use halo2curves::ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use halo2curves::group::Curve; use halo2curves::pairing::Engine; use rand_core::RngCore; use rayon::prelude::*; diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs index 69183c1eb2..a809ae1352 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs @@ -21,8 +21,8 @@ use crate::poly::{ Error, }; use crate::transcript::{EncodedChallenge, TranscriptRead}; -use ff::{Field, PrimeField, WithSmallOrderMulGroup}; -use group::Group; +use halo2curves::ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use halo2curves::group::Group; use halo2curves::pairing::{Engine, MillerLoopResult, MultiMillerLoop}; use rand_core::OsRng; use std::ops::MulAssign; diff --git a/halo2_proofs/src/poly/kzg/strategy.rs b/halo2_proofs/src/poly/kzg/strategy.rs index 9fc4d1c2fa..24ee5d265d 100644 --- a/halo2_proofs/src/poly/kzg/strategy.rs +++ b/halo2_proofs/src/poly/kzg/strategy.rs @@ -15,8 +15,8 @@ use crate::{ }, transcript::{EncodedChallenge, TranscriptRead}, }; -use ff::{Field, PrimeField, WithSmallOrderMulGroup}; -use group::Group; +use halo2curves::ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use halo2curves::group::Group; use halo2curves::{ pairing::{Engine, MillerLoopResult, MultiMillerLoop}, CurveAffine, diff --git a/halo2_proofs/src/poly/multiopen.rs b/halo2_proofs/src/poly/multiopen.rs index 854018e90a..df93b85b7a 100644 --- a/halo2_proofs/src/poly/multiopen.rs +++ b/halo2_proofs/src/poly/multiopen.rs @@ -11,8 +11,8 @@ use crate::{ }; use crate::poly::Rotation; -use ff::Field; -use group::Group; +use halo2curves::ff::Field; +use halo2curves::group::Group; use rand::RngCore; use std::{ collections::{BTreeMap, BTreeSet}, @@ -153,7 +153,7 @@ mod tests { TranscriptWrite, }; - use ff::Field; + use halo2curves::ff::Field; use rand::RngCore; use rand_core::OsRng; use std::collections::BTreeSet; @@ -168,8 +168,8 @@ mod tests { #[test] fn test_roundtrip() { - use ff::Field; - use group::Curve; + use halo2curves::ff::Field; + use halo2curves::group::Curve; use rand_core::OsRng; use super::*; diff --git a/halo2_proofs/src/poly/multiopen_test.rs b/halo2_proofs/src/poly/multiopen_test.rs index fa447a1a1f..78819affa2 100644 --- a/halo2_proofs/src/poly/multiopen_test.rs +++ b/halo2_proofs/src/poly/multiopen_test.rs @@ -17,8 +17,8 @@ mod test { Keccak256Write, TranscriptRead, TranscriptReadBuffer, TranscriptWrite, TranscriptWriterBuffer, }; - use ff::Field; - use group::{Curve, Group}; + use halo2curves::ff::Field; + use halo2curves::group::{Curve, Group}; use halo2curves::CurveAffine; use rand_core::{OsRng, RngCore}; use std::io::{Read, Write}; diff --git a/halo2_proofs/src/poly/query.rs b/halo2_proofs/src/poly/query.rs index c596e6a71c..a805122d59 100644 --- a/halo2_proofs/src/poly/query.rs +++ b/halo2_proofs/src/poly/query.rs @@ -5,7 +5,7 @@ use crate::{ arithmetic::eval_polynomial, poly::{commitment, Coeff, Polynomial}, }; -use ff::Field; +use halo2curves::ff::Field; use halo2curves::CurveAffine; pub trait Query: Sized + Clone + Send + Sync { diff --git a/halo2_proofs/src/transcript.rs b/halo2_proofs/src/transcript.rs index f2bf2997ea..c80844e2df 100644 --- a/halo2_proofs/src/transcript.rs +++ b/halo2_proofs/src/transcript.rs @@ -2,8 +2,8 @@ //! transcripts. use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; -use ff::FromUniformBytes; -use group::ff::PrimeField; +use halo2curves::ff::FromUniformBytes; +use halo2curves::ff::PrimeField; use sha3::{Digest, Keccak256}; use std::convert::TryInto; diff --git a/halo2_proofs/src/transcript/blake2b.rs b/halo2_proofs/src/transcript/blake2b.rs index d76a4dea39..34c0c16564 100644 --- a/halo2_proofs/src/transcript/blake2b.rs +++ b/halo2_proofs/src/transcript/blake2b.rs @@ -3,8 +3,8 @@ use super::{ TranscriptWrite, TranscriptWriterBuffer, }; use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; -use ff::Field; -use group::ff::PrimeField; +use halo2curves::ff::Field; +use halo2curves::ff::PrimeField; use halo2curves::{Coordinates, CurveAffine, FieldExt}; use num_bigint::BigUint; use std::convert::TryInto; diff --git a/halo2_proofs/src/transcript/mod.rs.bak b/halo2_proofs/src/transcript/mod.rs.bak index f33cdad523..9eddbbfbb2 100644 --- a/halo2_proofs/src/transcript/mod.rs.bak +++ b/halo2_proofs/src/transcript/mod.rs.bak @@ -8,8 +8,8 @@ pub use self::poseidon::{PoseidonRead, PoseidonWrite}; pub use blake2b::{Blake2bRead, Blake2bWrite}; use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; -use ff::Field; -use group::ff::PrimeField; +use halo2curves::ff::Field; +use halo2curves::ff::PrimeField; use halo2curves::{Coordinates, CurveAffine, FieldExt}; use num_bigint::BigUint; use std::convert::TryInto; diff --git a/halo2_proofs/src/transcript/poseidon.rs b/halo2_proofs/src/transcript/poseidon.rs index 0d4f0935ec..d24bfb92c7 100644 --- a/halo2_proofs/src/transcript/poseidon.rs +++ b/halo2_proofs/src/transcript/poseidon.rs @@ -1,7 +1,7 @@ use super::{Challenge255, EncodedChallenge, Transcript, TranscriptRead, TranscriptWrite}; use crate::helpers::base_to_scalar; -use ff::{Field, FromUniformBytes}; -use group::ff::PrimeField; +use halo2curves::ff::{Field, FromUniformBytes}; +use halo2curves::ff::PrimeField; use halo2curves::serde::SerdeObject; use halo2curves::{Coordinates, CurveAffine}; use num_bigint::BigUint; diff --git a/halo2_proofs/tests/plonk_api.rs b/halo2_proofs/tests/plonk_api.rs index 1b47f219d7..169cacbd74 100644 --- a/halo2_proofs/tests/plonk_api.rs +++ b/halo2_proofs/tests/plonk_api.rs @@ -2,9 +2,9 @@ #![allow(clippy::op_ref)] use assert_matches::assert_matches; -use ff::FromUniformBytes; -use ff::PrimeField; -use ff::WithSmallOrderMulGroup; +use halo2curves::ff::FromUniformBytes; +use halo2curves::ff::PrimeField; +use halo2curves::ff::WithSmallOrderMulGroup; use halo2_proofs::arithmetic::Field; use halo2_proofs::circuit::{Cell, Layouter, SimpleFloorPlanner, Value}; use halo2_proofs::dev::MockProver; From b7b431229d86f84ffc04fd58c482c872db738204 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Mon, 13 Mar 2023 19:29:52 -0400 Subject: [PATCH 61/62] fix fieldext in examples --- halo2_proofs/examples/circuit-layout.rs | 15 +++++----- halo2_proofs/src/circuit/layouter.rs | 2 +- halo2_proofs/src/poly/evaluator.rs | 40 ++++++++++++------------- halo2_proofs/src/poly/multiopen.rs | 8 ++--- halo2_proofs/src/transcript/blake2b.rs | 2 +- halo2_proofs/src/transcript/mod.rs.bak | 2 +- 6 files changed, 34 insertions(+), 35 deletions(-) diff --git a/halo2_proofs/examples/circuit-layout.rs b/halo2_proofs/examples/circuit-layout.rs index 29a7533c9c..c2c29c078b 100644 --- a/halo2_proofs/examples/circuit-layout.rs +++ b/halo2_proofs/examples/circuit-layout.rs @@ -1,9 +1,8 @@ use halo2curves::ff::Field; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{Cell, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Assigned, Circuit, Column, ConstraintSystem, Error, Fixed, TableColumn}, - poly::Rotation, + poly::Rotation, ff::PrimeField, }; use halo2curves::pasta::Fp; use rand_core::OsRng; @@ -28,7 +27,7 @@ struct PlonkConfig { sl: TableColumn, } -trait StandardCs { +trait StandardCs { fn raw_multiply(&self, region: &mut Region, f: F) -> Result<(Cell, Cell, Cell), Error> where F: FnMut() -> Value<(Assigned, Assigned, Assigned)>; @@ -39,17 +38,17 @@ trait StandardCs { fn lookup_table(&self, layouter: &mut impl Layouter, values: &[FF]) -> Result<(), Error>; } -struct MyCircuit { +struct MyCircuit { a: Value, lookup_table: Vec, } -struct StandardPlonk { +struct StandardPlonk { config: PlonkConfig, _marker: PhantomData, } -impl StandardPlonk { +impl StandardPlonk { fn new(config: PlonkConfig) -> Self { StandardPlonk { config, @@ -58,7 +57,7 @@ impl StandardPlonk { } } -impl StandardCs for StandardPlonk { +impl StandardCs for StandardPlonk { fn raw_multiply( &self, region: &mut Region, @@ -159,7 +158,7 @@ impl StandardCs for StandardPlonk { } } -impl Circuit for MyCircuit { +impl Circuit for MyCircuit { type Config = PlonkConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/halo2_proofs/src/circuit/layouter.rs b/halo2_proofs/src/circuit/layouter.rs index 81aed85090..1a436c3811 100644 --- a/halo2_proofs/src/circuit/layouter.rs +++ b/halo2_proofs/src/circuit/layouter.rs @@ -14,7 +14,7 @@ use crate::plonk::{Advice, Any, Assigned, Column, Error, Fixed, Instance, Select /// This trait is used for implementing region assignments: /// /// ```ignore -/// impl<'a, F: FieldExt, C: Chip, CS: Assignment + 'a> Layouter for MyLayouter<'a, C, CS> { +/// impl<'a, F: PrimeField, C: Chip, CS: Assignment + 'a> Layouter for MyLayouter<'a, C, CS> { /// fn assign_region( /// &mut self, /// assignment: impl FnOnce(Region<'_, F, C>) -> Result<(), Error>, diff --git a/halo2_proofs/src/poly/evaluator.rs b/halo2_proofs/src/poly/evaluator.rs index 84e01ad87d..b50e2d5640 100644 --- a/halo2_proofs/src/poly/evaluator.rs +++ b/halo2_proofs/src/poly/evaluator.rs @@ -9,7 +9,7 @@ use std::{ }; use halo2curves::ff::Field; -use halo2curves::FieldExt; +use halo2curves::PrimeField; use super::{ Basis, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, Rotation, @@ -135,7 +135,7 @@ impl Evaluator { ) -> Polynomial where E: Copy + Send + Sync, - F: FieldExt, + F: PrimeField, B: BasisOps, { // Traverse `ast` to collect the used leaves. @@ -192,7 +192,7 @@ impl Evaluator { }) .collect(); - struct AstContext<'a, E, F: FieldExt, B: Basis> { + struct AstContext<'a, E, F: PrimeField, B: Basis> { domain: &'a EvaluationDomain, poly_len: usize, chunk_size: usize, @@ -200,7 +200,7 @@ impl Evaluator { leaves: &'a HashMap, &'a [F]>, } - fn recurse( + fn recurse( ast: &Ast, ctx: &AstContext<'_, E, F, B>, ) -> Vec { @@ -489,21 +489,21 @@ impl MulAssign for Ast { /// Operations which can be performed over a given basis. pub(crate) trait BasisOps: Basis { - fn empty_poly(domain: &EvaluationDomain) -> Polynomial; - fn constant_term( + fn empty_poly(domain: &EvaluationDomain) -> Polynomial; + fn constant_term( poly_len: usize, chunk_size: usize, chunk_index: usize, scalar: F, ) -> Vec; - fn linear_term( + fn linear_term( domain: &EvaluationDomain, poly_len: usize, chunk_size: usize, chunk_index: usize, scalar: F, ) -> Vec; - fn rotate( + fn rotate( domain: &EvaluationDomain, poly: &Polynomial, rotation: Rotation, @@ -511,11 +511,11 @@ pub(crate) trait BasisOps: Basis { } impl BasisOps for Coeff { - fn empty_poly(domain: &EvaluationDomain) -> Polynomial { + fn empty_poly(domain: &EvaluationDomain) -> Polynomial { domain.empty_coeff() } - fn constant_term( + fn constant_term( poly_len: usize, chunk_size: usize, chunk_index: usize, @@ -528,7 +528,7 @@ impl BasisOps for Coeff { chunk } - fn linear_term( + fn linear_term( _: &EvaluationDomain, poly_len: usize, chunk_size: usize, @@ -550,7 +550,7 @@ impl BasisOps for Coeff { chunk } - fn rotate( + fn rotate( _: &EvaluationDomain, _: &Polynomial, _: Rotation, @@ -560,11 +560,11 @@ impl BasisOps for Coeff { } impl BasisOps for LagrangeCoeff { - fn empty_poly(domain: &EvaluationDomain) -> Polynomial { + fn empty_poly(domain: &EvaluationDomain) -> Polynomial { domain.empty_lagrange() } - fn constant_term( + fn constant_term( poly_len: usize, chunk_size: usize, chunk_index: usize, @@ -573,7 +573,7 @@ impl BasisOps for LagrangeCoeff { vec![scalar; cmp::min(chunk_size, poly_len - chunk_size * chunk_index)] } - fn linear_term( + fn linear_term( domain: &EvaluationDomain, poly_len: usize, chunk_size: usize, @@ -592,7 +592,7 @@ impl BasisOps for LagrangeCoeff { .collect() } - fn rotate( + fn rotate( _: &EvaluationDomain, poly: &Polynomial, rotation: Rotation, @@ -602,11 +602,11 @@ impl BasisOps for LagrangeCoeff { } impl BasisOps for ExtendedLagrangeCoeff { - fn empty_poly(domain: &EvaluationDomain) -> Polynomial { + fn empty_poly(domain: &EvaluationDomain) -> Polynomial { domain.empty_extended() } - fn constant_term( + fn constant_term( poly_len: usize, chunk_size: usize, chunk_index: usize, @@ -615,7 +615,7 @@ impl BasisOps for ExtendedLagrangeCoeff { vec![scalar; cmp::min(chunk_size, poly_len - chunk_size * chunk_index)] } - fn linear_term( + fn linear_term( domain: &EvaluationDomain, poly_len: usize, chunk_size: usize, @@ -637,7 +637,7 @@ impl BasisOps for ExtendedLagrangeCoeff { .collect() } - fn rotate( + fn rotate( domain: &EvaluationDomain, poly: &Polynomial, rotation: Rotation, diff --git a/halo2_proofs/src/poly/multiopen.rs b/halo2_proofs/src/poly/multiopen.rs index df93b85b7a..689179cb61 100644 --- a/halo2_proofs/src/poly/multiopen.rs +++ b/halo2_proofs/src/poly/multiopen.rs @@ -5,7 +5,7 @@ use super::{commitment::ParamsVerifier, PairMSM}; use crate::{ - arithmetic::{eval_polynomial, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, CurveAffine, PrimeField}, pairing::arithmetic::{MillerLoopResult, MultiMillerLoop}, poly::{msm::MSM, Coeff, Error, Polynomial}, }; @@ -129,7 +129,7 @@ impl<'r, 'params: 'r, C: CurveAffine> PartialEq for CommitmentReference<'r, C> { } } -trait Query: Sized + Clone { +trait Query: Sized + Clone { type Commitment: PartialEq + Clone; fn get_rotation(&self) -> Rotation; @@ -141,7 +141,7 @@ trait Query: Sized + Clone { #[cfg(test)] mod tests { - use crate::arithmetic::{eval_polynomial, FieldExt}; + use crate::arithmetic::{eval_polynomial, PrimeField}; use crate::pairing::bn256::{Bn256, Fr, G1Affine}; use crate::poly::{ commitment::{Params, ParamsVerifier}, @@ -173,7 +173,7 @@ mod tests { use rand_core::OsRng; use super::*; - use crate::arithmetic::{eval_polynomial, FieldExt}; + use crate::arithmetic::{eval_polynomial, PrimeField}; use crate::poly::{commitment::Params, EvaluationDomain}; use crate::transcript::Challenge255; diff --git a/halo2_proofs/src/transcript/blake2b.rs b/halo2_proofs/src/transcript/blake2b.rs index 34c0c16564..59517ba3e6 100644 --- a/halo2_proofs/src/transcript/blake2b.rs +++ b/halo2_proofs/src/transcript/blake2b.rs @@ -5,7 +5,7 @@ use super::{ use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; use halo2curves::ff::Field; use halo2curves::ff::PrimeField; -use halo2curves::{Coordinates, CurveAffine, FieldExt}; +use halo2curves::{Coordinates, CurveAffine, PrimeField}; use num_bigint::BigUint; use std::convert::TryInto; use std::io::{self, Read, Write}; diff --git a/halo2_proofs/src/transcript/mod.rs.bak b/halo2_proofs/src/transcript/mod.rs.bak index 9eddbbfbb2..ed7b76df17 100644 --- a/halo2_proofs/src/transcript/mod.rs.bak +++ b/halo2_proofs/src/transcript/mod.rs.bak @@ -10,7 +10,7 @@ pub use blake2b::{Blake2bRead, Blake2bWrite}; use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; use halo2curves::ff::Field; use halo2curves::ff::PrimeField; -use halo2curves::{Coordinates, CurveAffine, FieldExt}; +use halo2curves::{Coordinates, CurveAffine, PrimeField}; use num_bigint::BigUint; use std::convert::TryInto; use std::io::{self, Read, Write}; From e072052a74e625a139a014fad430c0c485e3f3ed Mon Sep 17 00:00:00 2001 From: zhenfei Date: Mon, 13 Mar 2023 23:32:10 -0400 Subject: [PATCH 62/62] cargo fmt --- halo2_proofs/benches/arithmetic.rs | 2 +- halo2_proofs/benches/dev_lookup.rs | 2 +- halo2_proofs/benches/fft.rs | 2 +- halo2_proofs/benches/plonk.rs | 4 ++-- halo2_proofs/examples/circuit-layout.rs | 5 +++-- halo2_proofs/examples/cost-model.rs | 4 ++-- halo2_proofs/examples/serialization.rs | 2 +- halo2_proofs/examples/shuffle.rs | 4 ++-- halo2_proofs/examples/simple-example.rs | 2 +- halo2_proofs/examples/two-chip.rs | 4 ++-- halo2_proofs/src/arithmetic.rs | 3 ++- halo2_proofs/src/dev/failure.rs | 2 +- halo2_proofs/src/dev/util.rs | 2 +- halo2_proofs/src/plonk/verifier/batch.rs | 2 +- halo2_proofs/src/poly/kzg/commitment.rs | 2 +- halo2_proofs/src/transcript/poseidon.rs | 2 +- halo2_proofs/tests/plonk_api.rs | 6 +++--- 17 files changed, 26 insertions(+), 24 deletions(-) diff --git a/halo2_proofs/benches/arithmetic.rs b/halo2_proofs/benches/arithmetic.rs index 0f5695bcc3..6d5ee6ad5c 100644 --- a/halo2_proofs/benches/arithmetic.rs +++ b/halo2_proofs/benches/arithmetic.rs @@ -3,8 +3,8 @@ extern crate criterion; use crate::arithmetic::small_multiexp; use crate::halo2curves::pasta::{EqAffine, Fp}; -use halo2curves::ff::Field; use halo2_proofs::*; +use halo2curves::ff::Field; use halo2_proofs::poly::{commitment::ParamsProver, ipa::commitment::ParamsIPA}; diff --git a/halo2_proofs/benches/dev_lookup.rs b/halo2_proofs/benches/dev_lookup.rs index 74ab31f02b..d0f63c53e1 100644 --- a/halo2_proofs/benches/dev_lookup.rs +++ b/halo2_proofs/benches/dev_lookup.rs @@ -1,11 +1,11 @@ #[macro_use] extern crate criterion; -use halo2curves::ff::PrimeField; use halo2_proofs::circuit::{Layouter, SimpleFloorPlanner, Value}; use halo2_proofs::dev::MockProver; use halo2_proofs::plonk::*; use halo2_proofs::poly::Rotation; +use halo2curves::ff::PrimeField; use halo2curves::pasta::pallas; use std::marker::PhantomData; diff --git a/halo2_proofs/benches/fft.rs b/halo2_proofs/benches/fft.rs index 40c6b35b39..7990648c7a 100644 --- a/halo2_proofs/benches/fft.rs +++ b/halo2_proofs/benches/fft.rs @@ -2,8 +2,8 @@ extern crate criterion; use crate::arithmetic::best_fft; -use halo2curves::ff::Field; use halo2_proofs::*; +use halo2curves::ff::Field; use halo2curves::pasta::Fp; use criterion::{BenchmarkId, Criterion}; diff --git a/halo2_proofs/benches/plonk.rs b/halo2_proofs/benches/plonk.rs index cbbee900bc..ae429b48a5 100644 --- a/halo2_proofs/benches/plonk.rs +++ b/halo2_proofs/benches/plonk.rs @@ -1,12 +1,12 @@ #[macro_use] extern crate criterion; -use halo2curves::ff::Field; -use halo2curves::ff::PrimeField; use halo2_proofs::circuit::{Cell, Layouter, SimpleFloorPlanner, Value}; use halo2_proofs::plonk::*; use halo2_proofs::poly::{commitment::ParamsProver, Rotation}; use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite, Challenge255}; +use halo2curves::ff::Field; +use halo2curves::ff::PrimeField; use halo2curves::pasta::{EqAffine, Fp}; use rand_core::OsRng; diff --git a/halo2_proofs/examples/circuit-layout.rs b/halo2_proofs/examples/circuit-layout.rs index c2c29c078b..7e946322c7 100644 --- a/halo2_proofs/examples/circuit-layout.rs +++ b/halo2_proofs/examples/circuit-layout.rs @@ -1,9 +1,10 @@ -use halo2curves::ff::Field; use halo2_proofs::{ circuit::{Cell, Layouter, Region, SimpleFloorPlanner, Value}, + ff::PrimeField, plonk::{Advice, Assigned, Circuit, Column, ConstraintSystem, Error, Fixed, TableColumn}, - poly::Rotation, ff::PrimeField, + poly::Rotation, }; +use halo2curves::ff::Field; use halo2curves::pasta::Fp; use rand_core::OsRng; use std::marker::PhantomData; diff --git a/halo2_proofs/examples/cost-model.rs b/halo2_proofs/examples/cost-model.rs index eba20ff959..afbeb4fdd4 100644 --- a/halo2_proofs/examples/cost-model.rs +++ b/halo2_proofs/examples/cost-model.rs @@ -5,10 +5,10 @@ use std::{ time::{Duration, Instant}, }; -use halo2curves::ff::Field; -use halo2curves::group::{Curve, Group}; use gumdrop::Options; use halo2_proofs::arithmetic::best_multiexp; +use halo2curves::ff::Field; +use halo2curves::group::{Curve, Group}; use halo2curves::pasta::pallas; struct Estimator { diff --git a/halo2_proofs/examples/serialization.rs b/halo2_proofs/examples/serialization.rs index c8a792d7fa..5279c846b8 100644 --- a/halo2_proofs/examples/serialization.rs +++ b/halo2_proofs/examples/serialization.rs @@ -3,7 +3,6 @@ use std::{ io::{BufReader, BufWriter, Write}, }; -use halo2curves::ff::Field; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, plonk::{ @@ -24,6 +23,7 @@ use halo2_proofs::{ SerdeFormat, }; use halo2curves::bn256::{Bn256, Fr, G1Affine}; +use halo2curves::ff::Field; use rand_core::OsRng; #[derive(Clone, Copy)] diff --git a/halo2_proofs/examples/shuffle.rs b/halo2_proofs/examples/shuffle.rs index f4f64a03bf..bb02dee4d1 100644 --- a/halo2_proofs/examples/shuffle.rs +++ b/halo2_proofs/examples/shuffle.rs @@ -1,5 +1,3 @@ -use halo2curves::ff::PrimeField; -use halo2curves::ff::{BatchInvert, FromUniformBytes, WithSmallOrderMulGroup}; use halo2_proofs::{ arithmetic::CurveAffine, circuit::{floor_planner::V1, Layouter, Value}, @@ -19,6 +17,8 @@ use halo2_proofs::{ Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }, }; +use halo2curves::ff::PrimeField; +use halo2curves::ff::{BatchInvert, FromUniformBytes, WithSmallOrderMulGroup}; use rand_core::{OsRng, RngCore}; use std::iter; diff --git a/halo2_proofs/examples/simple-example.rs b/halo2_proofs/examples/simple-example.rs index 166b94e4e8..32976bc7c4 100644 --- a/halo2_proofs/examples/simple-example.rs +++ b/halo2_proofs/examples/simple-example.rs @@ -1,11 +1,11 @@ use std::marker::PhantomData; -use halo2curves::ff::PrimeField; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Selector}, poly::Rotation, }; +use halo2curves::ff::PrimeField; // ANCHOR: instructions trait NumericInstructions: Chip { diff --git a/halo2_proofs/examples/two-chip.rs b/halo2_proofs/examples/two-chip.rs index 57f5929346..a27e213f9a 100644 --- a/halo2_proofs/examples/two-chip.rs +++ b/halo2_proofs/examples/two-chip.rs @@ -1,11 +1,11 @@ use std::marker::PhantomData; -use halo2curves::ff::PrimeField; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance, Selector}, poly::Rotation, }; +use halo2curves::ff::PrimeField; // ANCHOR: field-instructions /// A variable representing a number. @@ -496,8 +496,8 @@ impl Circuit for MyCircuit { #[allow(clippy::many_single_char_names)] fn main() { - use halo2curves::ff::Field; use halo2_proofs::dev::MockProver; + use halo2curves::ff::Field; use halo2curves::pasta::Fp; use rand_core::OsRng; diff --git a/halo2_proofs/src/arithmetic.rs b/halo2_proofs/src/arithmetic.rs index 2006dc0743..37826b017a 100644 --- a/halo2_proofs/src/arithmetic.rs +++ b/halo2_proofs/src/arithmetic.rs @@ -8,12 +8,13 @@ mod util; pub use field_fft::{best_fft, parallel_fft}; pub use group_fft::{best_group_fft, g_to_lagrange, parallel_group_fft}; +use halo2curves::serde::SerdeObject; pub use multi_exp::{best_multiexp, small_multiexp}; pub use util::{generate_twiddle_lookup_table, parallelize}; use super::multicore; pub use halo2curves::ff::Field; -use halo2curves::ff::{BatchInvert, PrimeField}; +use halo2curves::ff::{BatchInvert, FromUniformBytes, PrimeField, WithSmallOrderMulGroup}; use halo2curves::group::{Curve, Group}; pub use halo2curves::{CurveAffine, CurveExt}; diff --git a/halo2_proofs/src/dev/failure.rs b/halo2_proofs/src/dev/failure.rs index afe53346a3..38d2dbe69b 100644 --- a/halo2_proofs/src/dev/failure.rs +++ b/halo2_proofs/src/dev/failure.rs @@ -1,8 +1,8 @@ use std::collections::{BTreeMap, HashSet}; use std::fmt::{self, Debug}; -use halo2curves::ff::{PrimeField, WithSmallOrderMulGroup}; use halo2curves::ff::Field; +use halo2curves::ff::{PrimeField, WithSmallOrderMulGroup}; use super::metadata::{DebugColumn, DebugVirtualCell}; use super::MockProver; diff --git a/halo2_proofs/src/dev/util.rs b/halo2_proofs/src/dev/util.rs index 5fd2f19a0a..b82c9ef959 100644 --- a/halo2_proofs/src/dev/util.rs +++ b/halo2_proofs/src/dev/util.rs @@ -1,8 +1,8 @@ use std::collections::BTreeMap; +use halo2curves::ff::Field; use halo2curves::ff::PrimeField; use halo2curves::ff::WithSmallOrderMulGroup; -use halo2curves::ff::Field; use super::{metadata, CellValue, Value}; use crate::{ diff --git a/halo2_proofs/src/plonk/verifier/batch.rs b/halo2_proofs/src/plonk/verifier/batch.rs index 3403a9b963..29e13394a7 100644 --- a/halo2_proofs/src/plonk/verifier/batch.rs +++ b/halo2_proofs/src/plonk/verifier/batch.rs @@ -1,7 +1,7 @@ use std::{io, marker::PhantomData}; -use halo2curves::ff::FromUniformBytes; use halo2curves::ff::Field; +use halo2curves::ff::FromUniformBytes; use halo2curves::CurveAffine; use rand_core::{OsRng, RngCore}; use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index 91d40c5a0f..a2cac4c7db 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -370,9 +370,9 @@ mod test { use crate::poly::kzg::multiopen::ProverSHPLONK; use crate::poly::{Coeff, LagrangeCoeff, Polynomial}; + use halo2curves::bn256::G1Affine; use halo2curves::ff::{Field, PrimeField}; use halo2curves::group::{prime::PrimeCurveAffine, Curve, Group as _}; - use halo2curves::bn256::G1Affine; use std::marker::PhantomData; use std::ops::{Add, AddAssign, Mul, MulAssign}; diff --git a/halo2_proofs/src/transcript/poseidon.rs b/halo2_proofs/src/transcript/poseidon.rs index d24bfb92c7..110412dc2e 100644 --- a/halo2_proofs/src/transcript/poseidon.rs +++ b/halo2_proofs/src/transcript/poseidon.rs @@ -1,7 +1,7 @@ use super::{Challenge255, EncodedChallenge, Transcript, TranscriptRead, TranscriptWrite}; use crate::helpers::base_to_scalar; -use halo2curves::ff::{Field, FromUniformBytes}; use halo2curves::ff::PrimeField; +use halo2curves::ff::{Field, FromUniformBytes}; use halo2curves::serde::SerdeObject; use halo2curves::{Coordinates, CurveAffine}; use num_bigint::BigUint; diff --git a/halo2_proofs/tests/plonk_api.rs b/halo2_proofs/tests/plonk_api.rs index 169cacbd74..e3ab49bd70 100644 --- a/halo2_proofs/tests/plonk_api.rs +++ b/halo2_proofs/tests/plonk_api.rs @@ -2,9 +2,6 @@ #![allow(clippy::op_ref)] use assert_matches::assert_matches; -use halo2curves::ff::FromUniformBytes; -use halo2curves::ff::PrimeField; -use halo2curves::ff::WithSmallOrderMulGroup; use halo2_proofs::arithmetic::Field; use halo2_proofs::circuit::{Cell, Layouter, SimpleFloorPlanner, Value}; use halo2_proofs::dev::MockProver; @@ -20,6 +17,9 @@ use halo2_proofs::transcript::{ Blake2bRead, Blake2bWrite, Challenge255, EncodedChallenge, TranscriptReadBuffer, TranscriptWriterBuffer, }; +use halo2curves::ff::FromUniformBytes; +use halo2curves::ff::PrimeField; +use halo2curves::ff::WithSmallOrderMulGroup; use rand_core::{OsRng, RngCore}; use std::marker::PhantomData;