From 36492ddc17a00f0c1b7f77cec2d4a37ec6b123fd Mon Sep 17 00:00:00 2001 From: kilic Date: Fri, 29 Dec 2023 01:42:33 +0300 Subject: [PATCH 1/9] update `halo2curves` to 0.5.0 --- halo2_proofs/Cargo.toml | 2 +- halo2_proofs/src/dev/cost.rs | 6 +- halo2_proofs/src/poly/kzg/commitment.rs | 48 ++++++------- halo2_proofs/src/poly/kzg/msm.rs | 67 ++++++++++++++----- .../src/poly/kzg/multiopen/gwc/prover.rs | 6 +- .../src/poly/kzg/multiopen/gwc/verifier.rs | 9 +-- .../src/poly/kzg/multiopen/shplonk/prover.rs | 22 +++--- .../poly/kzg/multiopen/shplonk/verifier.rs | 18 ++--- halo2_proofs/src/poly/kzg/strategy.rs | 57 +++++++++++----- rust-toolchain | 2 +- 10 files changed, 150 insertions(+), 87 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 7393de109b..15bd97e74e 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -51,7 +51,7 @@ harness = false backtrace = { version = "0.3", optional = true } ff = "0.13" group = "0.13" -halo2curves = { version = "0.1.0" } +halo2curves = { version = "0.5.0" } rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" # MSRV 1.66.0 diff --git a/halo2_proofs/src/dev/cost.rs b/halo2_proofs/src/dev/cost.rs index 1f131a2d40..735f1f0dc7 100644 --- a/halo2_proofs/src/dev/cost.rs +++ b/halo2_proofs/src/dev/cost.rs @@ -102,11 +102,11 @@ impl Layout { total_rows: 0, total_advice_rows: 0, total_fixed_rows: 0, - /// Any cells assigned outside of a region. + // Any cells assigned outside of a region. loose_cells: vec![], - /// Pairs of cells between which we have equality constraints. + // Pairs of cells between which we have equality constraints. equality: vec![], - /// Selector assignments used for optimization pass + // Selector assignments used for optimization pass selectors: vec![vec![false; n]; num_selectors], } } diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index c9157f843d..114b9ac013 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -7,6 +7,7 @@ use crate::SerdeFormat; use ff::{Field, PrimeField}; use group::{prime::PrimeCurveAffine, Curve, Group}; use halo2curves::pairing::Engine; +use halo2curves::CurveExt; use rand_core::{OsRng, RngCore}; use std::fmt::Debug; use std::marker::PhantomData; @@ -34,11 +35,11 @@ pub struct KZGCommitmentScheme { impl CommitmentScheme for KZGCommitmentScheme where - E::Scalar: PrimeField, - E::G1Affine: SerdeCurveAffine, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { - type Scalar = E::Scalar; + type Scalar = E::Fr; type Curve = E::G1Affine; type ParamsProver = ParamsKZG; @@ -55,19 +56,20 @@ where impl ParamsKZG where - E::Scalar: PrimeField, + E::G1Affine: SerdeCurveAffine, + E::G1: CurveExt, { /// 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 { - // 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); + // Largest root of unity exponent of the Engine is `2^E::Fr::S`, so we can + // only support FFTs of polynomials below degree `2^E::Fr::S`. + assert!(k <= E::Fr::S); let n: u64 = 1 << k; // Calculate g = [G1, [s] G1, [s^2] G1, ..., [s^(n-1)] G1] in parallel. let g1 = E::G1Affine::generator(); - let s = ::random(rng); + let s = ::random(rng); let mut g_projective = vec![E::G1::identity(); n as usize]; parallelize(&mut g_projective, |g, start| { @@ -88,14 +90,14 @@ where }; let mut g_lagrange_projective = vec![E::G1::identity(); n as usize]; - let mut root = E::Scalar::ROOT_OF_UNITY; - for _ in k..E::Scalar::S { + let mut root = E::Fr::ROOT_OF_UNITY; + for _ in k..E::Fr::S { root = root.square(); } - let n_inv = E::Scalar::from(n) + let n_inv = E::Fr::from(n) .invert() .expect("inversion should be ok for n = 1<(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> where - E::G1Affine: SerdeCurveAffine, E::G2Affine: SerdeCurveAffine, { writer.write_all(&self.k.to_le_bytes())?; @@ -182,7 +183,6 @@ where /// 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]; @@ -274,8 +274,8 @@ pub type ParamsVerifierKZG = ParamsKZG; impl<'params, E: Engine + Debug> Params<'params, E::G1Affine> for ParamsKZG where - E::Scalar: PrimeField, - E::G1Affine: SerdeCurveAffine, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { type MSM = MSMKZG; @@ -302,11 +302,7 @@ where MSMKZG::new() } - fn commit_lagrange( - &self, - poly: &Polynomial, - _: Blind, - ) -> E::G1 { + fn commit_lagrange(&self, poly: &Polynomial, _: Blind) -> E::G1 { let mut scalars = Vec::with_capacity(poly.len()); scalars.extend(poly.iter()); let bases = &self.g_lagrange; @@ -328,16 +324,16 @@ where impl<'params, E: Engine + Debug> ParamsVerifier<'params, E::G1Affine> for ParamsKZG where - E::Scalar: PrimeField, - E::G1Affine: SerdeCurveAffine, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { } impl<'params, E: Engine + Debug> ParamsProver<'params, E::G1Affine> for ParamsKZG where - E::Scalar: PrimeField, - E::G1Affine: SerdeCurveAffine, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { type ParamsVerifier = ParamsVerifierKZG; @@ -350,7 +346,7 @@ where Self::setup(k, OsRng) } - fn commit(&self, poly: &Polynomial, _: Blind) -> E::G1 { + fn commit(&self, poly: &Polynomial, _: Blind) -> E::G1 { let mut scalars = Vec::with_capacity(poly.len()); scalars.extend(poly.iter()); let bases = &self.g; diff --git a/halo2_proofs/src/poly/kzg/msm.rs b/halo2_proofs/src/poly/kzg/msm.rs index 77758d1b97..f9b8c284bd 100644 --- a/halo2_proofs/src/poly/kzg/msm.rs +++ b/halo2_proofs/src/poly/kzg/msm.rs @@ -6,16 +6,27 @@ use crate::{ poly::commitment::MSM, }; use group::{Curve, Group}; -use halo2curves::pairing::{Engine, MillerLoopResult, MultiMillerLoop}; +use halo2curves::{ + pairing::{Engine, MillerLoopResult, MultiMillerLoop}, + CurveAffine, CurveExt, +}; /// A multiscalar multiplication in the polynomial commitment scheme #[derive(Clone, Default, Debug)] -pub struct MSMKZG { - pub(crate) scalars: Vec, +pub struct MSMKZG +where + E::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ + pub(crate) scalars: Vec, pub(crate) bases: Vec, } -impl MSMKZG { +impl MSMKZG +where + E::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ /// Create an empty MSM instance pub fn new() -> Self { MSMKZG { @@ -25,9 +36,9 @@ impl MSMKZG { } /// Prepares all scalars in the MSM to linear combination - pub fn combine_with_base(&mut self, base: E::Scalar) { + pub fn combine_with_base(&mut self, base: E::Fr) { use ff::Field; - let mut acc = E::Scalar::ONE; + let mut acc = E::Fr::ONE; if !self.scalars.is_empty() { for scalar in self.scalars.iter_mut().rev() { *scalar *= &acc; @@ -37,8 +48,12 @@ impl MSMKZG { } } -impl MSM for MSMKZG { - fn append_term(&mut self, scalar: E::Scalar, point: E::G1) { +impl MSM for MSMKZG +where + E::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ + fn append_term(&mut self, scalar: E::Fr, point: E::G1) { self.scalars.push(scalar); self.bases.push(point); } @@ -48,7 +63,7 @@ impl MSM for MSMKZG { self.bases.extend(other.bases().iter()); } - fn scale(&mut self, factor: E::Scalar) { + fn scale(&mut self, factor: E::Fr) { if !self.scalars.is_empty() { parallelize(&mut self.scalars, |scalars, _| { for other_scalar in scalars { @@ -73,18 +88,26 @@ impl MSM for MSMKZG { self.bases.clone() } - fn scalars(&self) -> Vec { + fn scalars(&self) -> Vec { self.scalars.clone() } } /// A projective point collector #[derive(Debug, Clone)] -pub(crate) struct PreMSM { +pub(crate) struct PreMSM +where + E::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ projectives_msms: Vec>, } -impl PreMSM { +impl PreMSM +where + E::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ pub(crate) fn new() -> Self { PreMSM { projectives_msms: vec![], @@ -109,7 +132,11 @@ 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::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ fn from(params: &'params ParamsKZG) -> Self { DualMSM::new(params) } @@ -117,13 +144,21 @@ 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::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ 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::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ /// Create a new two channel MSM accumulator instance pub fn new(params: &'a ParamsKZG) -> Self { Self { @@ -134,7 +169,7 @@ impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E> { } /// Scale all scalars in the MSM by some scaling factor - pub fn scale(&mut self, e: E::Scalar) { + pub fn scale(&mut self, e: E::Fr) { self.left.scale(e); self.right.scale(e); } diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs index 8add3eef38..ecea01cb01 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs @@ -8,9 +8,9 @@ use crate::poly::query::ProverQuery; use crate::poly::{commitment::Blind, Polynomial}; use crate::transcript::{EncodedChallenge, TranscriptWrite}; -use ff::PrimeField; use group::Curve; use halo2curves::pairing::Engine; +use halo2curves::CurveExt; use rand_core::RngCore; use std::fmt::Debug; use std::io; @@ -25,8 +25,8 @@ pub struct ProverGWC<'params, E: Engine> { /// Create a multi-opening proof impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme> for ProverGWC<'params, E> where - E::Scalar: PrimeField, - E::G1Affine: SerdeCurveAffine, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { const QUERY_INSTANCE: bool = false; diff --git a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs index 776c8408bc..fcfda6941f 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs @@ -13,8 +13,9 @@ use crate::poly::query::{CommitmentReference, VerifierQuery}; use crate::poly::Error; use crate::transcript::{EncodedChallenge, TranscriptRead}; -use ff::{Field, PrimeField}; +use ff::Field; use halo2curves::pairing::{Engine, MultiMillerLoop}; +use halo2curves::CurveExt; #[derive(Debug)] /// Concrete KZG verifier with GWC variant @@ -25,8 +26,8 @@ pub struct VerifierGWC<'params, E: Engine> { impl<'params, E> Verifier<'params, KZGCommitmentScheme> for VerifierGWC<'params, E> where E: MultiMillerLoop + Debug, - E::Scalar: PrimeField, - E::G1Affine: SerdeCurveAffine, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { type Guard = GuardKZG<'params, E>; @@ -63,7 +64,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::Fr::ZERO; let mut witness = MSMKZG::::new(); let mut witness_with_aux = MSMKZG::::new(); diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs index 31fe3a0c10..b18bf4919f 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs @@ -13,9 +13,10 @@ use crate::poly::{Coeff, Polynomial}; use crate::transcript::{EncodedChallenge, TranscriptWrite}; use crate::multicore::IntoParallelIterator; -use ff::{Field, PrimeField}; +use ff::Field; use group::Curve; use halo2curves::pairing::Engine; +use halo2curves::CurveExt; use rand_core::RngCore; use std::fmt::Debug; use std::io; @@ -107,8 +108,9 @@ impl<'a, E: Engine> ProverSHPLONK<'a, E> { impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme> for ProverSHPLONK<'params, E> where - E::Scalar: Ord + PrimeField, - E::G1Affine: SerdeCurveAffine, + E::Fr: Ord, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { const QUERY_INSTANCE: bool = false; @@ -166,7 +168,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::Fr::ZERO); Polynomial { values: poly, @@ -202,7 +204,7 @@ where .map(quotient_contribution) .collect::>(); - let h_x: Polynomial = quotient_polynomials + let h_x: Polynomial = quotient_polynomials .into_iter() .zip(powers(*v)) .map(|(poly, power_of_v)| poly * power_of_v) @@ -240,7 +242,7 @@ where // and combine polynomials with same evaluation point set // L_i(X) = linear_combination(y, L_i_j(X)) // where y is random scalar to combine inner contributors - let l_x: Polynomial = inner_contributions + let l_x: Polynomial = inner_contributions .into_iter() .zip(powers(*y)) .map(|(poly, power_of_y)| poly * power_of_y) @@ -253,14 +255,14 @@ where #[allow(clippy::type_complexity)] let (linearisation_contributions, z_diffs): ( - Vec>, - Vec, + Vec>, + Vec, ) = rotation_sets .into_par_iter() .map(linearisation_contribution) .unzip(); - let l_x: Polynomial = linearisation_contributions + let l_x: Polynomial = linearisation_contributions .into_iter() .zip(powers(*v)) .map(|(poly, power_of_v)| poly * power_of_v) @@ -275,7 +277,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::Fr::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 53930f88dd..5d03940177 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs @@ -15,8 +15,9 @@ use crate::poly::kzg::strategy::GuardKZG; use crate::poly::query::{CommitmentReference, VerifierQuery}; use crate::poly::Error; use crate::transcript::{EncodedChallenge, TranscriptRead}; -use ff::{Field, PrimeField}; +use ff::Field; use halo2curves::pairing::{Engine, MultiMillerLoop}; +use halo2curves::CurveExt; use std::ops::MulAssign; /// Concrete KZG multiopen verifier with SHPLONK variant @@ -28,8 +29,9 @@ pub struct VerifierSHPLONK<'params, E: Engine> { impl<'params, E> Verifier<'params, KZGCommitmentScheme> for VerifierSHPLONK<'params, E> where E: MultiMillerLoop + Debug, - E::Scalar: PrimeField + Ord, - E::G1Affine: SerdeCurveAffine, + E::Fr: Ord, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { type Guard = GuardKZG<'params, E>; @@ -69,10 +71,10 @@ 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::Fr::ZERO, E::Fr::ZERO); + let (mut outer_msm, mut r_outer_acc) = (PreMSM::::new(), E::Fr::ZERO); for (i, (rotation_set, power_of_v)) in rotation_sets.iter().zip(powers(*v)).enumerate() { - let diffs: Vec = super_point_set + let diffs: Vec = super_point_set .iter() .filter(|point| !rotation_set.points.contains(point)) .copied() @@ -83,7 +85,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::Fr::ONE; } else { z_diff_i.mul_assign(z_0_diff_inverse); } @@ -129,7 +131,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::Fr::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 14b6565b80..ee80d800ac 100644 --- a/halo2_proofs/src/poly/kzg/strategy.rs +++ b/halo2_proofs/src/poly/kzg/strategy.rs @@ -10,30 +10,41 @@ use crate::{ strategy::{Guard, VerificationStrategy}, }, }; -use ff::{Field, PrimeField}; -use halo2curves::pairing::{Engine, MultiMillerLoop}; +use ff::Field; +use halo2curves::{ + pairing::{Engine, MultiMillerLoop}, + CurveAffine, CurveExt, +}; use rand_core::OsRng; use std::fmt::Debug; /// Wrapper for linear verification accumulator #[derive(Debug, Clone)] -pub struct GuardKZG<'params, E: MultiMillerLoop + Debug> { +pub struct GuardKZG<'params, E: MultiMillerLoop + Debug> +where + E::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ pub(crate) msm_accumulator: DualMSM<'params, E>, } /// Define accumulator type as `DualMSM` impl<'params, E> Guard> for GuardKZG<'params, E> where - E::Scalar: PrimeField, E: MultiMillerLoop + Debug, - E::G1Affine: SerdeCurveAffine, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { type MSMAccumulator = DualMSM<'params, E>; } /// KZG specific operations -impl<'params, E: MultiMillerLoop + Debug> GuardKZG<'params, E> { +impl<'params, E: MultiMillerLoop + Debug> GuardKZG<'params, E> +where + E::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ pub(crate) fn new(msm_accumulator: DualMSM<'params, E>) -> Self { Self { msm_accumulator } } @@ -41,11 +52,19 @@ 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::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ 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::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ /// Constructs an empty batch verifier pub fn new(params: &'params ParamsKZG) -> Self { AccumulatorStrategy { @@ -61,11 +80,19 @@ 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::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ pub(crate) msm: DualMSM<'params, E>, } -impl<'params, E: MultiMillerLoop + Debug> SingleStrategy<'params, E> { +impl<'params, E: MultiMillerLoop + Debug> SingleStrategy<'params, E> +where + E::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, +{ /// Constructs an empty batch verifier pub fn new(params: &'params ParamsKZG) -> Self { SingleStrategy { @@ -85,8 +112,8 @@ impl< >, > VerificationStrategy<'params, KZGCommitmentScheme, V> for AccumulatorStrategy<'params, E> where - E::Scalar: PrimeField, - E::G1Affine: SerdeCurveAffine, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { type Output = Self; @@ -99,7 +126,7 @@ where mut self, f: impl FnOnce(V::MSMAccumulator) -> Result, ) -> Result { - self.msm_accumulator.scale(E::Scalar::random(OsRng)); + self.msm_accumulator.scale(E::Fr::random(OsRng)); // Guard is updated with new msm contributions let guard = f(self.msm_accumulator)?; @@ -124,8 +151,8 @@ impl< >, > VerificationStrategy<'params, KZGCommitmentScheme, V> for SingleStrategy<'params, E> where - E::Scalar: PrimeField, - E::G1Affine: SerdeCurveAffine, + E::G1Affine: SerdeCurveAffine::Fr, CurveExt = ::G1>, + E::G1: CurveExt, E::G2Affine: SerdeCurveAffine, { type Output = (); diff --git a/rust-toolchain b/rust-toolchain index b6148bc0a7..65ee095984 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.66.0 +1.67.0 From fbbc3a72a21326f30196d514fe92194eb8d122a1 Mon Sep 17 00:00:00 2001 From: kilic Date: Sun, 7 Jan 2024 19:51:14 +0300 Subject: [PATCH 2/9] fix multicore compiling issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Carlos PĂ©rez <37264926+CPerezz@users.noreply.github.com> --- halo2_proofs/Cargo.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 15bd97e74e..4f53059e55 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -51,7 +51,7 @@ harness = false backtrace = { version = "0.3", optional = true } ff = "0.13" group = "0.13" -halo2curves = { version = "0.5.0" } +halo2curves = { version = "0.5.0", default-features = false } rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" # MSRV 1.66.0 @@ -80,8 +80,8 @@ serde_json = "1" getrandom = { version = "0.2", features = ["js"] } [features] -default = ["batch", "multicore"] -multicore = ["maybe-rayon/threads"] +default = ["batch", "multicore", "bits"] +multicore = ["maybe-rayon/threads", "halo2curves/multicore"] dev-graph = ["plotters", "tabbycat"] test-dev-graph = [ "dev-graph", @@ -89,6 +89,7 @@ test-dev-graph = [ "plotters/bitmap_encoder", "plotters/ttf", ] +bits = ["halo2curves/bits"] gadget-traces = ["backtrace"] thread-safe-region = [] sanity-checks = [] From 8e9e06998be10b7f26402dea5a8f27c35b5232a1 Mon Sep 17 00:00:00 2001 From: kilic Date: Sun, 7 Jan 2024 23:18:23 +0300 Subject: [PATCH 3/9] fix clippy --- halo2_proofs/benches/dev_lookup.rs | 4 +- halo2_proofs/examples/circuit-layout.rs | 2 +- halo2_proofs/examples/proof-size.rs | 4 +- halo2_proofs/examples/shuffle.rs | 11 +--- halo2_proofs/src/circuit.rs | 2 +- halo2_proofs/src/circuit/table_layouter.rs | 2 +- halo2_proofs/src/dev.rs | 8 +-- halo2_proofs/src/dev/failure.rs | 68 ++++++++++------------ halo2_proofs/src/dev/failure/emitter.rs | 26 ++++----- halo2_proofs/src/dev/gates.rs | 18 +++--- halo2_proofs/src/dev/graph.rs | 2 +- halo2_proofs/src/dev/graph/layout.rs | 2 +- halo2_proofs/src/dev/util.rs | 4 +- halo2_proofs/src/plonk/circuit.rs | 13 ++--- halo2_proofs/src/plonk/error.rs | 21 +++---- halo2_proofs/tests/plonk_api.rs | 2 +- 16 files changed, 87 insertions(+), 102 deletions(-) diff --git a/halo2_proofs/benches/dev_lookup.rs b/halo2_proofs/benches/dev_lookup.rs index 62ed5a7f19..569ffd1019 100644 --- a/halo2_proofs/benches/dev_lookup.rs +++ b/halo2_proofs/benches/dev_lookup.rs @@ -62,7 +62,7 @@ fn criterion_benchmark(c: &mut Criterion) { |mut table| { for row in 0u64..(1 << 8) { table.assign_cell( - || format!("row {}", row), + || format!("row {row}"), config.table, row as usize, || Value::known(F::from(row + 1)), @@ -79,7 +79,7 @@ fn criterion_benchmark(c: &mut Criterion) { for offset in 0u64..(1 << 10) { config.selector.enable(&mut region, offset as usize)?; region.assign_advice( - || format!("offset {}", offset), + || format!("offset {offset}"), config.advice, offset as usize, || Value::known(F::from((offset % 256) + 1)), diff --git a/halo2_proofs/examples/circuit-layout.rs b/halo2_proofs/examples/circuit-layout.rs index 18de27a783..b65adf5599 100644 --- a/halo2_proofs/examples/circuit-layout.rs +++ b/halo2_proofs/examples/circuit-layout.rs @@ -245,7 +245,7 @@ impl Circuit for MyCircuit { for i in 0..10 { layouter.assign_region( - || format!("region_{}", i), + || format!("region_{i}"), |mut region| { let a: Value> = self.a.into(); let mut a_squared = Value::unknown(); diff --git a/halo2_proofs/examples/proof-size.rs b/halo2_proofs/examples/proof-size.rs index f2b3cf7322..3d5b242fb0 100644 --- a/halo2_proofs/examples/proof-size.rs +++ b/halo2_proofs/examples/proof-size.rs @@ -53,7 +53,7 @@ impl Circuit for TestCircuit { |mut table| { for row in 0u64..(1 << 8) { table.assign_cell( - || format!("row {}", row), + || format!("row {row}"), config.table, row as usize, || Value::known(Fp::from(row + 1)), @@ -70,7 +70,7 @@ impl Circuit for TestCircuit { for offset in 0u64..(1 << 10) { config.selector.enable(&mut region, offset as usize)?; region.assign_advice( - || format!("offset {}", offset), + || format!("offset {offset}"), config.advice, offset as usize, || Value::known(Fp::from((offset % 256) + 1)), diff --git a/halo2_proofs/examples/shuffle.rs b/halo2_proofs/examples/shuffle.rs index 17bbb3330a..35a85cb9f0 100644 --- a/halo2_proofs/examples/shuffle.rs +++ b/halo2_proofs/examples/shuffle.rs @@ -168,7 +168,7 @@ impl Circuit for MyCircuit { for (offset, &value) in values.transpose_array().iter().enumerate() { region.assign_advice( - || format!("original[{}][{}]", idx, offset), + || format!("original[{idx}][{offset}]"), column, offset, || value, @@ -183,7 +183,7 @@ impl Circuit for MyCircuit { for (offset, &value) in values.transpose_array().iter().enumerate() { region.assign_advice( - || format!("shuffled[{}][{}]", idx, offset), + || format!("shuffled[{idx}][{offset}]"), column, offset, || value, @@ -233,12 +233,7 @@ impl Circuit for MyCircuit }, ); for (offset, value) in z.transpose_vec(H + 1).into_iter().enumerate() { - region.assign_advice( - || format!("z[{}]", offset), - config.z, - offset, - || value, - )?; + region.assign_advice(|| format!("z[{offset}]"), config.z, offset, || value)?; } Ok(()) diff --git a/halo2_proofs/src/circuit.rs b/halo2_proofs/src/circuit.rs index 3fab93997c..56a6be0e5c 100644 --- a/halo2_proofs/src/circuit.rs +++ b/halo2_proofs/src/circuit.rs @@ -572,7 +572,7 @@ impl<'a, F: Field, L: Layouter + 'a> Drop for NamespacedLayouter<'a, F, L> { if is_second_frame { // Resolve this instruction pointer to a symbol name. backtrace::resolve_frame(frame, |symbol| { - gadget_name = symbol.name().map(|name| format!("{:#}", name)); + gadget_name = symbol.name().map(|name| format!("{name:#}")); }); // We are done! diff --git a/halo2_proofs/src/circuit/table_layouter.rs b/halo2_proofs/src/circuit/table_layouter.rs index 5efe11735c..06338bb896 100644 --- a/halo2_proofs/src/circuit/table_layouter.rs +++ b/halo2_proofs/src/circuit/table_layouter.rs @@ -103,7 +103,7 @@ impl<'r, 'a, F: Field, CS: Assignment + 'a> TableLayouter return Err(Error::TableError(TableError::OverwriteDefault( column, format!("{:?}", entry.0.unwrap()), - format!("{:?}", value), + format!("{value:?}"), ))) } _ => (), diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index 192c55b982..6df373bf66 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -756,12 +756,12 @@ impl + Ord> MockProver { // 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) + 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) + panic!("invalid lookup row id {row_id}") } } @@ -1199,12 +1199,12 @@ impl + Ord> MockProver { // check all the row ids are valid gate_row_ids.par_iter().for_each(|row_id| { if !self.usable_rows.contains(row_id) { - panic!("invalid gate row id {}", row_id); + panic!("invalid gate row id {row_id}"); } }); lookup_input_row_ids.par_iter().for_each(|row_id| { if !self.usable_rows.contains(row_id) { - panic!("invalid gate row id {}", row_id); + panic!("invalid gate row id {row_id}"); } }); diff --git a/halo2_proofs/src/dev/failure.rs b/halo2_proofs/src/dev/failure.rs index 38b5b0ea61..f9f5c27ded 100644 --- a/halo2_proofs/src/dev/failure.rs +++ b/halo2_proofs/src/dev/failure.rs @@ -39,9 +39,9 @@ pub enum FailureLocation { impl fmt::Display for FailureLocation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::InRegion { region, offset } => write!(f, "in {} at offset {}", region, offset), + Self::InRegion { region, offset } => write!(f, "in {region} at offset {offset}"), Self::OutsideRegion { row } => { - write!(f, "outside any region, on row {}", row) + write!(f, "outside any region, on row {row}") } } } @@ -248,8 +248,7 @@ impl fmt::Display for VerifyFailure { } => { write!( f, - "{} uses {} at offset {}, which requires cell in instance column {:?} at row {} to be assigned.", - region, gate, gate_offset, column, row + "{region} uses {gate} at offset {gate_offset}, which requires cell in instance column {column:?} at row {row} to be assigned.", ) } Self::ConstraintNotSatisfied { @@ -257,7 +256,7 @@ impl fmt::Display for VerifyFailure { location, cell_values, } => { - writeln!(f, "{} is not satisfied {}", constraint, location)?; + writeln!(f, "{constraint} is not satisfied {location}")?; for (dvc, value) in cell_values.iter().map(|(vc, string)| { let ann_map = match location { FailureLocation::InRegion { region, offset: _ } => { @@ -268,15 +267,14 @@ impl fmt::Display for VerifyFailure { (DebugVirtualCell::from((vc, ann_map.as_ref())), string) }) { - writeln!(f, "- {} = {}", dvc, value)?; + writeln!(f, "- {dvc} = {value}")?; } Ok(()) } Self::ConstraintPoisoned { constraint } => { write!( f, - "{} is active on an unusable row - missing selector?", - constraint + "{constraint} is active on an unusable row - missing selector?" ) } Self::Lookup { @@ -286,8 +284,7 @@ impl fmt::Display for VerifyFailure { } => { write!( f, - "Lookup {}(index: {}) is not satisfied {}", - name, lookup_index, location + "Lookup {name}(index: {lookup_index}) is not satisfied {location}", ) } Self::Shuffle { @@ -297,8 +294,7 @@ impl fmt::Display for VerifyFailure { } => { write!( f, - "Shuffle {}(index: {}) is not satisfied {}", - name, shuffle_index, location + "Shuffle {name}(index: {shuffle_index}) is not satisfied {location}" ) } Self::Permutation { column, location } => { @@ -350,9 +346,9 @@ impl Debug for VerifyFailure { .collect(), }; - write!(f, "{:#?}", debug) + write!(f, "{debug:#?}") } - _ => write!(f, "{:#}", self), + _ => write!(f, "{self:#}"), } } } @@ -394,7 +390,7 @@ fn render_cell_not_assigned( if cell.column == column && gate_offset as i32 + cell.rotation.0 == offset as i32 { "X".to_string() } else { - format!("x{}", i) + format!("x{i}") } }); } @@ -456,7 +452,7 @@ fn render_constraint_not_satisfied( .entry(cell.rotation) .or_default() .entry(cell.column) - .or_insert(format!("x{}", i)); + .or_insert(format!("x{i}")); } eprintln!("error: constraint not satisfied"); @@ -481,7 +477,7 @@ fn render_constraint_not_satisfied( eprintln!(); eprintln!(" Assigned cell values:"); for (i, (_, value)) in cell_values.iter().enumerate() { - eprintln!(" x{} = {}", i, value); + eprintln!(" x{i} = {value}"); } } @@ -526,7 +522,7 @@ fn render_lookup( // expressions for the table side of lookups. let lookup_columns = lookup.table_expressions.iter().map(|expr| { expr.evaluate( - &|f| format! {"Const: {:#?}", f}, + &|f| format! {"Const: {f:#?}"}, &|s| format! {"S{}", s.0}, &|query| { format!( @@ -562,10 +558,10 @@ fn render_lookup( ) }, &|challenge| format! {"C{}", challenge.index()}, - &|query| format! {"-{}", query}, - &|a, b| format! {"{} + {}", a,b}, - &|a, b| format! {"{} * {}", a,b}, - &|a, b| format! {"{} * {:?}", a, b}, + &|query| format! {"-{query}"}, + &|a, b| format! {"{a} + {b}"}, + &|a, b| format! {"{a} * {b}"}, + &|a, b| format! {"{a} * {b:?}"}, ) }); @@ -604,7 +600,7 @@ fn render_lookup( eprintln!(")"); eprintln!(); - eprintln!(" Lookup '{}' inputs:", name); + eprintln!(" Lookup '{name}' inputs:"); for (i, input) in lookup.input_expressions.iter().enumerate() { // Fetch the cell values (since we don't store them in VerifyFailure::Lookup). let cell_values = input.evaluate( @@ -643,7 +639,7 @@ fn render_lookup( .entry(cell.rotation) .or_default() .entry(cell.column) - .or_insert(format!("x{}", i)); + .or_insert(format!("x{i}")); } if i != 0 { @@ -658,7 +654,7 @@ fn render_lookup( emitter::render_cell_layout(" | ", location, &columns, &layout, |_, rotation| { if rotation == 0 { - eprint!(" <--{{ Lookup '{}' inputs queried here", name); + eprint!(" <--{{ Lookup '{name}' inputs queried here"); } }); @@ -666,7 +662,7 @@ fn render_lookup( eprintln!(" |"); eprintln!(" | Assigned cell values:"); for (i, (_, value)) in cell_values.iter().enumerate() { - eprintln!(" | x{} = {}", i, value); + eprintln!(" | x{i} = {value}"); } } } @@ -692,7 +688,7 @@ fn render_shuffle( let shuffle_columns = shuffle.shuffle_expressions.iter().map(|expr| { expr.evaluate( - &|f| format! {"Const: {:#?}", f}, + &|f| format! {"Const: {f:#?}"}, &|s| format! {"S{}", s.0}, &|query| { format!( @@ -728,10 +724,10 @@ fn render_shuffle( ) }, &|challenge| format! {"C{}", challenge.index()}, - &|query| format! {"-{}", query}, - &|a, b| format! {"{} + {}", a,b}, - &|a, b| format! {"{} * {}", a,b}, - &|a, b| format! {"{} * {:?}", a, b}, + &|query| format! {"-{query}"}, + &|a, b| format! {"{a} + {b}"}, + &|a, b| format! {"{a} * {b}"}, + &|a, b| format! {"{a} * {b:?}"}, ) }); @@ -769,7 +765,7 @@ fn render_shuffle( eprintln!(")"); eprintln!(); - eprintln!(" Shuffle '{}' inputs:", name); + eprintln!(" Shuffle '{name}' inputs:"); for (i, input) in shuffle.input_expressions.iter().enumerate() { // Fetch the cell values (since we don't store them in VerifyFailure::Shuffle). let cell_values = input.evaluate( @@ -808,7 +804,7 @@ fn render_shuffle( .entry(cell.rotation) .or_default() .entry(cell.column) - .or_insert(format!("x{}", i)); + .or_insert(format!("x{i}")); } if i != 0 { @@ -823,7 +819,7 @@ fn render_shuffle( emitter::render_cell_layout(" | ", location, &columns, &layout, |_, rotation| { if rotation == 0 { - eprint!(" <--{{ Shuffle '{}' inputs queried here", name); + eprint!(" <--{{ Shuffle '{name}' inputs queried here"); } }); @@ -831,7 +827,7 @@ fn render_shuffle( eprintln!(" |"); eprintln!(" | Assigned cell values:"); for (i, (_, value)) in cell_values.iter().enumerate() { - eprintln!(" | x{} = {}", i, value); + eprintln!(" | x{i} = {value}"); } } } @@ -871,7 +867,7 @@ impl VerifyFailure { shuffle_index, location, } => render_shuffle(prover, name, *shuffle_index, location), - _ => eprintln!("{}", self), + _ => eprintln!("{self}"), } } } diff --git a/halo2_proofs/src/dev/failure/emitter.rs b/halo2_proofs/src/dev/failure/emitter.rs index edd61f3060..24109d599b 100644 --- a/halo2_proofs/src/dev/failure/emitter.rs +++ b/halo2_proofs/src/dev/failure/emitter.rs @@ -53,16 +53,16 @@ pub(super) fn render_cell_layout( FailureLocation::InRegion { region, offset } => { col_headers .push_str(format!("{}Cell layout in region '{}':\n", prefix, region.name).as_str()); - col_headers.push_str(format!("{} | Offset |", prefix).as_str()); + col_headers.push_str(format!("{prefix} | Offset |").as_str()); Some(*offset as i32) } FailureLocation::OutsideRegion { row } => { - col_headers.push_str(format!("{}Cell layout at row {}:\n", prefix, row).as_str()); - col_headers.push_str(format!("{} |Rotation|", prefix).as_str()); + col_headers.push_str(format!("{prefix}Cell layout at row {row}:\n").as_str()); + col_headers.push_str(format!("{prefix} |Rotation|").as_str()); None } }; - eprint!("\n{}", col_headers); + eprint!("\n{col_headers}"); let widths: Vec = columns .iter() @@ -112,7 +112,7 @@ pub(super) fn render_cell_layout( } eprintln!(); - eprint!("{} +--------+", prefix); + eprint!("{prefix} +--------+"); for &width in widths.iter() { eprint!("{}+", padded('-', width, "")); } @@ -185,23 +185,23 @@ pub(super) fn expression_to_string( &|challenge| format!("C{}({})", challenge.index(), challenge.phase()), &|a| { if a.contains(' ') { - format!("-({})", a) + format!("-({a})") } else { - format!("-{}", a) + format!("-{a}") } }, &|a, b| { if let Some(b) = b.strip_prefix('-') { - format!("{} - {}", a, b) + format!("{a} - {b}") } else { - format!("{} + {}", a, b) + format!("{a} + {b}") } }, &|a, b| match (a.contains(' '), b.contains(' ')) { - (false, false) => format!("{} * {}", a, b), - (false, true) => format!("{} * ({})", a, b), - (true, false) => format!("({}) * {}", a, b), - (true, true) => format!("({}) * ({})", a, b), + (false, false) => format!("{a} * {b}"), + (false, true) => format!("{a} * ({b})"), + (true, false) => format!("({a}) * {b}"), + (true, true) => format!("({a}) * ({b})"), }, &|a, s| { if a.contains(' ') { diff --git a/halo2_proofs/src/dev/gates.rs b/halo2_proofs/src/dev/gates.rs index 352415bcd9..4421c0967f 100644 --- a/halo2_proofs/src/dev/gates.rs +++ b/halo2_proofs/src/dev/gates.rs @@ -146,23 +146,23 @@ impl CircuitGates { &|challenge| format!("C{}({})", challenge.index(), challenge.phase()), &|a| { if a.contains(' ') { - format!("-({})", a) + format!("-({a})") } else { - format!("-{}", a) + format!("-{a}") } }, &|a, b| { if let Some(b) = b.strip_prefix('-') { - format!("{} - {}", a, b) + format!("{a} - {b}") } else { - format!("{} + {}", a, b) + format!("{a} + {b}") } }, &|a, b| match (a.contains(' '), b.contains(' ')) { - (false, false) => format!("{} * {}", a, b), - (false, true) => format!("{} * ({})", a, b), - (true, false) => format!("({}) * {}", a, b), - (true, true) => format!("({}) * ({})", a, b), + (false, false) => format!("{a} * {b}"), + (false, true) => format!("{a} * ({b})"), + (true, false) => format!("({a}) * {b}"), + (true, true) => format!("({a}) * ({b})"), }, &|a, s| { if a.contains(' ') { @@ -264,7 +264,7 @@ impl CircuitGates { let mut ret = String::new(); let w = &mut ret; for query in &queries { - write!(w, "{},", query).unwrap(); + write!(w, "{query},").unwrap(); } writeln!(w, "Name").unwrap(); diff --git a/halo2_proofs/src/dev/graph.rs b/halo2_proofs/src/dev/graph.rs index b273940036..11654fe415 100644 --- a/halo2_proofs/src/dev/graph.rs +++ b/halo2_proofs/src/dev/graph.rs @@ -36,7 +36,7 @@ pub fn circuit_dot_graph>( .into_iter() .map(|(name, gadget_name)| { if let Some(gadget_name) = gadget_name { - format!("[{}] {}", gadget_name, name) + format!("[{gadget_name}] {name}") } else { name } diff --git a/halo2_proofs/src/dev/graph/layout.rs b/halo2_proofs/src/dev/graph/layout.rs index 7d00434aa2..94bd7eea14 100644 --- a/halo2_proofs/src/dev/graph/layout.rs +++ b/halo2_proofs/src/dev/graph/layout.rs @@ -312,7 +312,7 @@ impl CircuitLayout { root.draw( &(EmptyElement::at((0, usable_rows)) + Text::new( - format!("{} usable rows", usable_rows), + format!("{usable_rows} usable rows"), (10, 10), ("sans-serif", 15.0).into_font(), )), diff --git a/halo2_proofs/src/dev/util.rs b/halo2_proofs/src/dev/util.rs index 28489acf91..a663f9b80b 100644 --- a/halo2_proofs/src/dev/util.rs +++ b/halo2_proofs/src/dev/util.rs @@ -63,11 +63,11 @@ pub(super) fn format_value(v: F) -> String { "-1".into() } else { // Format value as hex. - let s = format!("{:?}", v); + let s = format!("{v:?}"); // Remove leading zeroes. let s = s.strip_prefix("0x").unwrap(); let s = s.trim_start_matches('0'); - format!("0x{}", s) + format!("0x{s}") } } diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index 98445a5881..5107554186 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -1110,7 +1110,7 @@ impl Expression { fn write_identifier(&self, writer: &mut W) -> std::io::Result<()> { match self { - Expression::Constant(scalar) => write!(writer, "{:?}", scalar), + Expression::Constant(scalar) => write!(writer, "{scalar:?}"), Expression::Selector(selector) => write!(writer, "selector[{}]", selector.0), Expression::Fixed(query) => { write!( @@ -1157,7 +1157,7 @@ impl Expression { } Expression::Scaled(a, f) => { a.write_identifier(writer)?; - write!(writer, "*{:?}", f) + write!(writer, "*{f:?}") } } } @@ -2206,7 +2206,7 @@ impl ConstraintSystem { if let Some(previous_phase) = phase.prev() { self.assert_phase_exists( previous_phase, - format!("Column in later phase {:?}", phase).as_str(), + format!("Column in later phase {phase:?}").as_str(), ); } @@ -2231,7 +2231,7 @@ impl ConstraintSystem { if let Some(previous_phase) = phase.prev() { self.assert_phase_exists( previous_phase, - format!("Column in later phase {:?}", phase).as_str(), + format!("Column in later phase {phase:?}").as_str(), ); } @@ -2264,7 +2264,7 @@ impl ConstraintSystem { let phase = phase.to_sealed(); self.assert_phase_exists( phase, - format!("Challenge usable after phase {:?}", phase).as_str(), + format!("Challenge usable after phase {phase:?}").as_str(), ); let tmp = Challenge { @@ -2285,8 +2285,7 @@ impl ConstraintSystem { .find(|advice_column_phase| **advice_column_phase == phase) .unwrap_or_else(|| { panic!( - "No Column is used in phase {:?} while allocating a new {:?}", - phase, resource + "No Column is used in phase {phase:?} while allocating a new {resource:?}" ) }); } diff --git a/halo2_proofs/src/plonk/error.rs b/halo2_proofs/src/plonk/error.rs index d4a7e11c14..e6caded801 100644 --- a/halo2_proofs/src/plonk/error.rs +++ b/halo2_proofs/src/plonk/error.rs @@ -63,11 +63,10 @@ impl fmt::Display for Error { Error::ConstraintSystemFailure => write!(f, "The constraint system is not satisfied"), Error::BoundsFailure => write!(f, "An out-of-bounds index was passed to the backend"), Error::Opening => write!(f, "Multi-opening proof was invalid"), - Error::Transcript(e) => write!(f, "Transcript error: {}", e), + Error::Transcript(e) => write!(f, "Transcript error: {e}"), Error::NotEnoughRowsAvailable { current_k } => write!( f, - "k = {} is too small for the given circuit. Try using a larger value of k", - current_k, + "k = {current_k} is too small for the given circuit. Try using a larger value of k", ), Error::InstanceTooLarge => write!(f, "Instance vectors are larger than the circuit"), Error::NotEnoughColumnsForConstants => { @@ -78,10 +77,9 @@ impl fmt::Display for Error { } Error::ColumnNotInPermutation(column) => write!( f, - "Column {:?} must be included in the permutation. Help: try applying `meta.enable_equalty` on the column", - column + "Column {column:?} must be included in the permutation. Help: try applying `meta.enable_equalty` on the column", ), - Error::TableError(error) => write!(f, "{}", error) + Error::TableError(error) => write!(f, "{error}") } } } @@ -114,23 +112,20 @@ impl fmt::Display for TableError { TableError::ColumnNotAssigned(col) => { write!( f, - "{:?} not fully assigned. Help: assign a value at offset 0.", - col + "{col:?} not fully assigned. Help: assign a value at offset 0.", ) } TableError::UnevenColumnLengths((col, col_len), (table, table_len)) => write!( f, - "{:?} has length {} while {:?} has length {}", - col, col_len, table, table_len + "{col:?} has length {col_len} while {table:?} has length {table_len}", ), TableError::UsedColumn(col) => { - write!(f, "{:?} has already been used", col) + write!(f, "{col:?} has already been used") } TableError::OverwriteDefault(col, default, val) => { write!( f, - "Attempted to overwrite default value {} with {} in {:?}", - default, val, col + "Attempted to overwrite default value {default} with {val} in {col:?}", ) } } diff --git a/halo2_proofs/tests/plonk_api.rs b/halo2_proofs/tests/plonk_api.rs index 307dbdfef0..28ffb399ff 100644 --- a/halo2_proofs/tests/plonk_api.rs +++ b/halo2_proofs/tests/plonk_api.rs @@ -491,7 +491,7 @@ fn plonk_api() { // Check this circuit is satisfied. let prover = match MockProver::run(K, &circuit, vec![vec![instance]]) { Ok(prover) => prover, - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), }; assert_eq!(prover.verify(), Ok(())); From 757613ab2705d6563ed3761a3cf81ca351f03e51 Mon Sep 17 00:00:00 2001 From: kilic Date: Mon, 8 Jan 2024 19:41:53 +0300 Subject: [PATCH 4/9] bump version to 0.3.0 --- halo2/Cargo.toml | 2 +- halo2_proofs/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/halo2/Cargo.toml b/halo2/Cargo.toml index ba934102b6..5618165271 100644 --- a/halo2/Cargo.toml +++ b/halo2/Cargo.toml @@ -19,7 +19,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"] [dependencies] -halo2_proofs = { version = "0.2", path = "../halo2_proofs", default-features = false } +halo2_proofs = { version = "0.3", path = "../halo2_proofs", default-features = false } [lib] bench = false diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 4f53059e55..2ab33ba5d7 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "halo2_proofs" -version = "0.2.0" +version = "0.3.0" authors = [ "Sean Bowe ", "Ying Tong Lai ", From 0e71b9183a5beae6ceb9571f9641b4cb43fb96d9 Mon Sep 17 00:00:00 2001 From: kilic Date: Wed, 10 Jan 2024 12:46:59 +0300 Subject: [PATCH 5/9] update `halo2curves` to v0.6.0 replace `maybe-rayon` with `rayon` v1.8 --- .github/workflows/ci.yml | 2 +- README.md | 9 ++--- halo2_proofs/Cargo.toml | 7 ++-- halo2_proofs/README.md | 6 +-- halo2_proofs/benches/commit_zk.rs | 9 +---- halo2_proofs/examples/vector-mul.rs | 34 ---------------- halo2_proofs/src/dev.rs | 5 --- halo2_proofs/src/multicore.rs | 39 +++---------------- halo2_proofs/src/plonk/permutation/keygen.rs | 25 +++--------- halo2_proofs/src/plonk/verifier/batch.rs | 7 ++-- .../src/poly/kzg/multiopen/shplonk.rs | 5 +-- .../src/poly/kzg/multiopen/shplonk/prover.rs | 5 +-- 12 files changed, 28 insertions(+), 125 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56efd9a3d8..cdce1546c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: - feature_set: basic features: batch,dev-graph,gadget-traces - feature_set: all - features: batch,dev-graph,gadget-traces,multicore,test-dev-graph,thread-safe-region,sanity-checks,circuit-params + features: batch,dev-graph,gadget-traces,test-dev-graph,thread-safe-region,sanity-checks,circuit-params steps: - uses: actions/checkout@v3 diff --git a/README.md b/README.md index ad803dbae8..3c7aa59572 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,11 @@ minor version bump. ## Controlling parallelism -`halo2` currently uses [rayon](https://github.com/rayon-rs/rayon) for parallel computation. -The `RAYON_NUM_THREADS` environment variable can be used to set the number of threads. +`halo2` currently uses [rayon](https://github.com/rayon-rs/rayon) for parallel computation. The `RAYON_NUM_THREADS` environment variable can be used to set the number of threads. -You can disable `rayon` by disabling the `"multicore"` feature. -Warning! Halo2 will lose access to parallelism if you disable the `"multicore"` feature. -This will significantly degrade performance. +When compiling to WASM-targets, notice that since version `1.7`, `rayon` will fallback automatically (with no need to handle features) to require `getrandom` in order to be able to work. For more info related to WASM-compilation. + +See: [Rayon: Usage with WebAssembly](https://github.com/rayon-rs/rayon#usage-with-webassembly) for more ## License diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 2ab33ba5d7..30c0d13f49 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -51,15 +51,15 @@ harness = false backtrace = { version = "0.3", optional = true } ff = "0.13" group = "0.13" -halo2curves = { version = "0.5.0", default-features = false } +halo2curves = { version = "^0.6", default-features = false } rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" # MSRV 1.66.0 sha3 = "0.9.1" rand_chacha = "0.3" -maybe-rayon = { version = "0.1.0", default-features = false } serde = { version = "1", optional = true, features = ["derive"] } serde_derive = { version = "1", optional = true} +rayon = "1.8" # Developer tooling dependencies plotters = { version = "0.3.0", default-features = false, optional = true } @@ -80,8 +80,7 @@ serde_json = "1" getrandom = { version = "0.2", features = ["js"] } [features] -default = ["batch", "multicore", "bits"] -multicore = ["maybe-rayon/threads", "halo2curves/multicore"] +default = ["batch","bits"] dev-graph = ["plotters", "tabbycat"] test-dev-graph = [ "dev-graph", diff --git a/halo2_proofs/README.md b/halo2_proofs/README.md index 7aeebeb849..bdb9a63639 100644 --- a/halo2_proofs/README.md +++ b/halo2_proofs/README.md @@ -15,9 +15,9 @@ minor version bump. computation. The `RAYON_NUM_THREADS` environment variable can be used to set the number of threads. -You can disable `rayon` by disabling the `"multicore"` feature. -Warning! Halo2 will lose access to parallelism if you disable the `"multicore"` feature. -This will significantly degrade performance. +When compiling to WASM-targets, notice that since version `1.7`, `rayon` will fallback automatically (with no need to handle features) to require `getrandom` in order to be able to work. For more info related to WASM-compilation. + +See: [Rayon: Usage with WebAssembly](https://github.com/rayon-rs/rayon#usage-with-webassembly) for more ## License diff --git a/halo2_proofs/benches/commit_zk.rs b/halo2_proofs/benches/commit_zk.rs index a6a33a934b..d06bed0f97 100644 --- a/halo2_proofs/benches/commit_zk.rs +++ b/halo2_proofs/benches/commit_zk.rs @@ -7,16 +7,9 @@ use halo2curves::pasta::pallas::Scalar; use rand_chacha::rand_core::RngCore; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; +use rayon::current_num_threads; use std::{collections::HashMap, iter}; -#[cfg(feature = "multicore")] -use maybe_rayon::current_num_threads; - -#[cfg(not(feature = "multicore"))] -fn current_num_threads() -> usize { - 1 -} - fn rand_poly_serial(mut rng: ChaCha20Rng, domain: usize) -> Vec { // Sample a random polynomial of degree n - 1 let mut random_poly = vec![Scalar::zero(); 1 << domain]; diff --git a/halo2_proofs/examples/vector-mul.rs b/halo2_proofs/examples/vector-mul.rs index 4b971dc97f..01728fdf36 100644 --- a/halo2_proofs/examples/vector-mul.rs +++ b/halo2_proofs/examples/vector-mul.rs @@ -178,40 +178,6 @@ impl NumericInstructions for FieldChip { let config = self.config(); assert_eq!(a.len(), b.len()); - #[cfg(feature = "thread-safe-region")] - { - use maybe_rayon::prelude::{ - IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator, - }; - layouter.assign_region( - || "mul", - |region: Region<'_, F>| { - let thread_safe_region = std::sync::Mutex::new(region); - a.par_iter() - .zip(b.par_iter()) - .enumerate() - .map(|(i, (a, b))| { - let mut region = thread_safe_region.lock().unwrap(); - - config.s_mul.enable(&mut region, i)?; - - a.0.copy_advice(|| "lhs", &mut region, config.advice[0], i)?; - b.0.copy_advice(|| "rhs", &mut region, config.advice[1], i)?; - - let value = a.0.value().copied() * b.0.value(); - - // Finally, we do the assignment to the output, returning a - // variable to be used in another part of the circuit. - region - .assign_advice(|| "lhs * rhs", config.advice[2], i, || value) - .map(Number) - }) - .collect() - }, - ) - } - - #[cfg(not(feature = "thread-safe-region"))] layouter.assign_region( || "mul", |mut region: Region<'_, F>| { diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index 6df373bf66..0790aa7d5c 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -20,7 +20,6 @@ use crate::{ }, }; -#[cfg(feature = "multicore")] use crate::multicore::{ IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, ParallelIterator, ParallelSliceMut, @@ -1177,7 +1176,6 @@ impl + Ord> MockProver { /// Returns `Ok(())` if this `MockProver` is satisfied, or a list of errors indicating /// the reasons that the circuit is not satisfied. /// Constraints and lookup are checked at `usable_rows`, parallelly. - #[cfg(feature = "multicore")] pub fn verify_par(&self) -> Result<(), Vec> { self.verify_at_rows_par(self.usable_rows.clone(), self.usable_rows.clone()) } @@ -1185,7 +1183,6 @@ impl + Ord> MockProver { /// 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`, parallelly. - #[cfg(feature = "multicore")] pub fn verify_at_rows_par>( &self, gate_row_ids: I, @@ -1653,7 +1650,6 @@ impl + Ord> MockProver { /// ```ignore /// assert_eq!(prover.verify_par(), Ok(())); /// ``` - #[cfg(feature = "multicore")] pub fn assert_satisfied_par(&self) { if let Err(errs) = self.verify_par() { for err in errs { @@ -1675,7 +1671,6 @@ impl + Ord> MockProver { /// ```ignore /// assert_eq!(prover.verify_at_rows_par(), Ok(())); /// ``` - #[cfg(feature = "multicore")] pub fn assert_satisfied_at_rows_par>( &self, gate_row_ids: I, diff --git a/halo2_proofs/src/multicore.rs b/halo2_proofs/src/multicore.rs index 60502f07d2..04f748b9e1 100644 --- a/halo2_proofs/src/multicore.rs +++ b/halo2_proofs/src/multicore.rs @@ -1,29 +1,17 @@ -#[cfg(all( - feature = "multicore", - target_arch = "wasm32", - not(target_feature = "atomics") -))] +#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] compile_error!( "The multicore feature flag is not supported on wasm32 architectures without atomics" ); -pub use maybe_rayon::{ - iter::{IntoParallelIterator, IntoParallelRefMutIterator, ParallelIterator}, - join, scope, Scope, -}; - -#[cfg(feature = "multicore")] -pub use maybe_rayon::{ +pub use rayon::{ current_num_threads, iter::{IndexedParallelIterator, IntoParallelRefIterator}, + iter::{IntoParallelIterator, IntoParallelRefMutIterator, ParallelIterator}, + join, scope, slice::ParallelSliceMut, + Scope, }; -#[cfg(not(feature = "multicore"))] -pub fn current_num_threads() -> usize { - 1 -} - pub trait TryFoldAndReduce { /// Implements `iter.try_fold().try_reduce()` for `rayon::iter::ParallelIterator`, /// falling back on `Iterator::try_fold` when the `multicore` feature flag is @@ -38,12 +26,11 @@ pub trait TryFoldAndReduce { ) -> Result; } -#[cfg(feature = "multicore")] impl TryFoldAndReduce for I where T: Send + Sync, E: Send + Sync, - I: maybe_rayon::iter::ParallelIterator>, + I: rayon::iter::ParallelIterator>, { fn try_fold_and_reduce( self, @@ -54,17 +41,3 @@ where .try_reduce(&identity, |a, b| fold_op(a, Ok(b))) } } - -#[cfg(not(feature = "multicore"))] -impl TryFoldAndReduce for I -where - I: std::iter::Iterator>, -{ - fn try_fold_and_reduce( - mut self, - identity: impl Fn() -> T + Send + Sync, - fold_op: impl Fn(T, Result) -> Result + Send + Sync, - ) -> Result { - self.try_fold(identity(), fold_op) - } -} diff --git a/halo2_proofs/src/plonk/permutation/keygen.rs b/halo2_proofs/src/plonk/permutation/keygen.rs index 9451cebd1f..0d78f00ac5 100644 --- a/halo2_proofs/src/plonk/permutation/keygen.rs +++ b/halo2_proofs/src/plonk/permutation/keygen.rs @@ -11,8 +11,11 @@ use crate::{ }, }; -#[cfg(feature = "multicore")] -use crate::multicore::{IndexedParallelIterator, ParallelIterator}; +#[cfg(feature = "thread-safe-region")] +use crate::multicore::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; + +#[cfg(not(feature = "thread-safe-region"))] +use crate::multicore::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; #[cfg(feature = "thread-safe-region")] use std::collections::{BTreeSet, HashMap}; @@ -133,21 +136,12 @@ impl Assembly { &self.columns } - #[cfg(feature = "multicore")] /// Returns mappings of the copies. pub fn mapping( &self, ) -> impl Iterator + '_> { - use crate::multicore::IntoParallelRefIterator; - self.mapping.iter().map(|c| c.par_iter().copied()) } - - #[cfg(not(feature = "multicore"))] - /// Returns mappings of the copies. - pub fn mapping(&self) -> impl Iterator + '_> { - self.mapping.iter().map(|c| c.iter().copied()) - } } #[cfg(feature = "thread-safe-region")] @@ -315,25 +309,16 @@ impl Assembly { &self.columns } - #[cfg(feature = "multicore")] /// Returns mappings of the copies. pub fn mapping( &self, ) -> impl Iterator + '_> { - use crate::multicore::IntoParallelIterator; - (0..self.num_cols).map(move |i| { (0..self.col_len) .into_par_iter() .map(move |j| self.mapping_at_idx(i, j)) }) } - - #[cfg(not(feature = "multicore"))] - /// Returns mappings of the copies. - pub fn mapping(&self) -> impl Iterator + '_> { - (0..self.num_cols).map(move |i| (0..self.col_len).map(move |j| self.mapping_at_idx(i, j))) - } } pub(crate) fn build_pk<'params, C: CurveAffine, P: Params<'params, C>>( diff --git a/halo2_proofs/src/plonk/verifier/batch.rs b/halo2_proofs/src/plonk/verifier/batch.rs index 173d552e5f..ba3e2419e6 100644 --- a/halo2_proofs/src/plonk/verifier/batch.rs +++ b/halo2_proofs/src/plonk/verifier/batch.rs @@ -5,7 +5,9 @@ use rand_core::OsRng; use super::{verify_proof, VerificationStrategy}; use crate::{ - multicore::{IntoParallelIterator, TryFoldAndReduce}, + multicore::{ + IndexedParallelIterator, IntoParallelIterator, ParallelIterator, TryFoldAndReduce, + }, plonk::{Error, VerifyingKey}, poly::{ commitment::{Params, MSM}, @@ -19,9 +21,6 @@ use crate::{ transcript::{Blake2bRead, TranscriptReadBuffer}, }; -#[cfg(feature = "multicore")] -use crate::multicore::{IndexedParallelIterator, ParallelIterator}; - /// A proof verification strategy that returns the proof's MSM. /// /// `BatchVerifier` handles the accumulation of the MSMs for the batched proofs. diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs index bed814cc68..d0814e83e3 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk.rs @@ -1,16 +1,13 @@ mod prover; mod verifier; -use crate::multicore::IntoParallelIterator; +use crate::multicore::{IntoParallelIterator, ParallelIterator}; use crate::{poly::query::Query, transcript::ChallengeScalar}; use ff::Field; pub use prover::ProverSHPLONK; use std::collections::BTreeSet; pub use verifier::VerifierSHPLONK; -#[cfg(feature = "multicore")] -use crate::multicore::ParallelIterator; - #[derive(Clone, Copy, Debug)] struct U {} type ChallengeU = ChallengeScalar; diff --git a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs index b18bf4919f..5001d69094 100644 --- a/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs +++ b/halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs @@ -12,7 +12,7 @@ use crate::poly::query::{PolynomialPointer, ProverQuery}; use crate::poly::{Coeff, Polynomial}; use crate::transcript::{EncodedChallenge, TranscriptWrite}; -use crate::multicore::IntoParallelIterator; +use crate::multicore::{IntoParallelIterator, ParallelIterator}; use ff::Field; use group::Curve; use halo2curves::pairing::Engine; @@ -23,9 +23,6 @@ use std::io; use std::marker::PhantomData; use std::ops::MulAssign; -#[cfg(feature = "multicore")] -use crate::multicore::ParallelIterator; - fn div_by_vanishing(poly: Polynomial, roots: &[F]) -> Vec { let poly = roots .iter() From b441884eea6a97caf5d0b9bf1633aee6e3f37f5d Mon Sep 17 00:00:00 2001 From: kilic Date: Wed, 10 Jan 2024 14:04:42 +0300 Subject: [PATCH 6/9] remove compilation check for `atomic` --- halo2_proofs/src/multicore.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/halo2_proofs/src/multicore.rs b/halo2_proofs/src/multicore.rs index 04f748b9e1..4d30b91a8b 100644 --- a/halo2_proofs/src/multicore.rs +++ b/halo2_proofs/src/multicore.rs @@ -1,8 +1,3 @@ -#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] -compile_error!( - "The multicore feature flag is not supported on wasm32 architectures without atomics" -); - pub use rayon::{ current_num_threads, iter::{IndexedParallelIterator, IntoParallelRefIterator}, From 6b9245f5728906f1d63c4c69940f3366540799f1 Mon Sep 17 00:00:00 2001 From: kilic Date: Wed, 10 Jan 2024 14:47:48 +0300 Subject: [PATCH 7/9] fix: specific halo2curves version --- halo2_proofs/Cargo.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 30c0d13f49..e854748789 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -51,7 +51,7 @@ harness = false backtrace = { version = "0.3", optional = true } ff = "0.13" group = "0.13" -halo2curves = { version = "^0.6", default-features = false } +halo2curves = { version = "0.6.0" } rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" # MSRV 1.66.0 @@ -80,7 +80,7 @@ serde_json = "1" getrandom = { version = "0.2", features = ["js"] } [features] -default = ["batch","bits"] +default = ["batch"] dev-graph = ["plotters", "tabbycat"] test-dev-graph = [ "dev-graph", @@ -88,7 +88,6 @@ test-dev-graph = [ "plotters/bitmap_encoder", "plotters/ttf", ] -bits = ["halo2curves/bits"] gadget-traces = ["backtrace"] thread-safe-region = [] sanity-checks = [] From 371700133db7f4e58179eb1e136af77974e522b5 Mon Sep 17 00:00:00 2001 From: kilic Date: Wed, 10 Jan 2024 17:17:47 +0300 Subject: [PATCH 8/9] bring back bits as feature --- halo2_proofs/Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index e854748789..e340407dd6 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -51,7 +51,7 @@ harness = false backtrace = { version = "0.3", optional = true } ff = "0.13" group = "0.13" -halo2curves = { version = "0.6.0" } +halo2curves = { version = "0.6.0", default-features = false } rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" # MSRV 1.66.0 @@ -80,7 +80,7 @@ serde_json = "1" getrandom = { version = "0.2", features = ["js"] } [features] -default = ["batch"] +default = ["batch", "bits"] dev-graph = ["plotters", "tabbycat"] test-dev-graph = [ "dev-graph", @@ -88,6 +88,7 @@ test-dev-graph = [ "plotters/bitmap_encoder", "plotters/ttf", ] +bits = ["halo2curves/bits"] gadget-traces = ["backtrace"] thread-safe-region = [] sanity-checks = [] From 47e71c82842b26c3e81cbfd1a65f669518cf6315 Mon Sep 17 00:00:00 2001 From: kilic Date: Wed, 10 Jan 2024 17:23:55 +0300 Subject: [PATCH 9/9] remove serial `dev::assert_satisfied` --- halo2_proofs/src/dev.rs | 469 +--------------------------------------- 1 file changed, 5 insertions(+), 464 deletions(-) diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index 0790aa7d5c..7a3aca10cc 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -737,453 +737,15 @@ impl + Ord> MockProver { /// Returns `Ok(())` if this `MockProver` is satisfied, or a list of errors indicating /// the reasons that the circuit is not satisfied. + /// Constraints and lookup are checked at `usable_rows`, parallelly. 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; - - match cell.column.column_type() { - Any::Instance => { - // Handle instance cells, which are not in the region. - let instance_value = - &self.instance[cell.column.index()][cell_row]; - match instance_value { - InstanceValue::Assigned(_) => None, - _ => Some(VerifyFailure::InstanceCellNotAssigned { - gate: (gate_index, gate.name()).into(), - region: (r_i, r.name.clone()).into(), - gate_offset: *selector_row, - column: cell.column.try_into().unwrap(), - row: cell_row, - }), - } - } - _ => { - // 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(), - r.annotations.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().chain(blinding_rows)).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, - ), - &|challenge| Value::Real(self.challenges[challenge.index()]), - &|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 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.unwrap()]; - 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.unwrap()]; - 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.unwrap()]; - 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] - .value(), - ) - }, - &|challenge| Value::Real(self.challenges[challenge.index()]), - &|a| -a, - &|a, b| a + b, - &|a, b| a * b, - &|a, scalar| a * scalar, - &Value::Real(F::ZERO), - ) - }; - - 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)| { - 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() - .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.clone(), - lookup_index, - location: FailureLocation::find_expressions( - &self.cs, - &self.regions, - *input_row, - lookup.input_expressions.iter(), - ), - }) - } else { - None - } - }) - .collect::>() - }); - - let shuffle_errors = - self.cs - .shuffles - .iter() - .enumerate() - .flat_map(|(shuffle_index, shuffle)| { - assert!(shuffle.shuffle_expressions.len() == shuffle.input_expressions.len()); - assert!(self.usable_rows.end > 0); - - let mut shuffle_rows: Vec>> = self - .usable_rows - .clone() - .map(|row| { - let t = shuffle - .shuffle_expressions - .iter() - .map(move |c| load(c, row)) - .collect(); - t - }) - .collect(); - shuffle_rows.sort(); - - let mut input_rows: Vec<(Vec>, usize)> = self - .usable_rows - .clone() - .map(|input_row| { - let t = shuffle - .input_expressions - .iter() - .map(move |c| load(c, input_row)) - .collect(); - - (t, input_row) - }) - .collect(); - input_rows.sort(); - - input_rows - .iter() - .zip(shuffle_rows.iter()) - .filter_map(|((input_value, row), shuffle_value)| { - if shuffle_value != input_value { - Some(VerifyFailure::Shuffle { - name: shuffle.name.clone(), - shuffle_index, - location: FailureLocation::find_expressions( - &self.cs, - &self.regions, - *row, - shuffle.input_expressions.iter(), - ), - }) - } else { - None - } - }) - .collect::>() - }); - - let mapping = self.permutation.mapping(); - // 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 => { - let cell: &InstanceValue = &self.instance[c.index()][row]; - CellValue::Assigned(cell.value()) - } - }) - .unwrap() - }; - - // Iterate over each column of the permutation - mapping.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 - .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(), - ), - }) - } - }) - .collect::>() - }) - }; - - let mut errors: Vec<_> = iter::empty() - .chain(selector_errors) - .chain(gate_errors) - .chain(lookup_errors) - .chain(perm_errors) - .chain(shuffle_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 - /// the reasons that the circuit is not satisfied. - /// Constraints and lookup are checked at `usable_rows`, parallelly. - pub fn verify_par(&self) -> Result<(), Vec> { - 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 /// 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`, parallelly. - pub fn verify_at_rows_par>( + pub fn verify_at_rows>( &self, gate_row_ids: I, lookup_input_row_ids: I, @@ -1639,27 +1201,6 @@ impl + Ord> MockProver { } } - /// Panics if the circuit being checked by this `MockProver` is not satisfied. - /// - /// Any verification failures will be pretty-printed to stderr before the function - /// panics. - /// - /// Internally, this function uses a parallel aproach in order to verify the `MockProver` contents. - /// - /// Apart from the stderr output, this method is equivalent to: - /// ```ignore - /// assert_eq!(prover.verify_par(), Ok(())); - /// ``` - pub fn assert_satisfied_par(&self) { - if let Err(errs) = self.verify_par() { - for err in errs { - err.emit(self); - eprintln!(); - } - panic!("circuit was not satisfied"); - } - } - /// Panics if the circuit being checked by this `MockProver` is not satisfied. /// /// Any verification failures will be pretty-printed to stderr before the function @@ -1669,14 +1210,14 @@ impl + Ord> MockProver { /// /// Apart from the stderr output, this method is equivalent to: /// ```ignore - /// assert_eq!(prover.verify_at_rows_par(), Ok(())); + /// assert_eq!(prover.verify_at_rows(), Ok(())); /// ``` - pub fn assert_satisfied_at_rows_par>( + pub fn assert_satisfied_at_rows>( &self, gate_row_ids: I, lookup_input_row_ids: I, ) { - if let Err(errs) = self.verify_at_rows_par(gate_row_ids, lookup_input_row_ids) { + if let Err(errs) = self.verify_at_rows(gate_row_ids, lookup_input_row_ids) { for err in errs { err.emit(self); eprintln!();