From d76f55239d98632007e8117b4510740c060b8a3d Mon Sep 17 00:00:00 2001 From: CPerezz Date: Fri, 9 Feb 2024 18:57:00 +0100 Subject: [PATCH] chore: Remove dependency on CurveAffine --- halo2_backend/src/plonk.rs | 2 +- halo2_backend/src/plonk/evaluation.rs | 163 ++++++++++++++------------ halo2_backend/src/plonk/keygen.rs | 7 +- 3 files changed, 95 insertions(+), 77 deletions(-) diff --git a/halo2_backend/src/plonk.rs b/halo2_backend/src/plonk.rs index 37f89e31fc..4e4fbe25a9 100644 --- a/halo2_backend/src/plonk.rs +++ b/halo2_backend/src/plonk.rs @@ -324,7 +324,7 @@ pub struct ProvingKey { fixed_values: Vec>, fixed_polys: Vec>, permutation: permutation::ProvingKey, - ev: Evaluator, + ev: Evaluator, } impl ProvingKey diff --git a/halo2_backend/src/plonk/evaluation.rs b/halo2_backend/src/plonk/evaluation.rs index df8396c6b8..29d4eaa225 100644 --- a/halo2_backend/src/plonk/evaluation.rs +++ b/halo2_backend/src/plonk/evaluation.rs @@ -1,18 +1,35 @@ use crate::multicore; +use crate::plonk::lookup::prover::Committed; +use crate::plonk::permutation::Argument; use crate::plonk::{lookup, permutation, ProvingKey}; use crate::poly::Basis; use crate::{ - arithmetic::{parallelize, CurveAffine}, - poly::{Coeff, ExtendedLagrangeCoeff, Polynomial}, + arithmetic::{eval_polynomial, parallelize, CurveAffine}, + poly::{ + commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, + Polynomial, ProverQuery, + }, + transcript::{EncodedChallenge, TranscriptWrite}, +}; +use group::prime::PrimeCurve; +use group::{ + ff::{BatchInvert, Field, PrimeField, WithSmallOrderMulGroup}, + Curve, }; -use group::ff::{Field, PrimeField, WithSmallOrderMulGroup}; use halo2_common::plonk::{ConstraintSystem, Expression}; -use halo2_common::poly::LagrangeCoeff; use halo2_middleware::circuit::Any; use halo2_middleware::poly::Rotation; use itertools::Itertools; - -use super::shuffle; +use std::any::TypeId; +use std::convert::TryInto; +use std::num::ParseIntError; +use std::slice; +use std::time::Instant; +use std::{ + collections::BTreeMap, + iter, + ops::{Index, Mul, MulAssign}, +}; /// Return the index in the polynomial of size `isize` after rotation `rot`. fn get_rotation_idx(idx: usize, rot: i32, rot_scale: i32, isize: i32) -> usize { @@ -52,21 +69,19 @@ impl Default for ValueSource { impl ValueSource { /// Get the value for this source - #[allow(clippy::too_many_arguments)] pub fn get( &self, rotations: &[usize], constants: &[F], intermediates: &[F], - // TODO: Why Option?? fixed_values: &[Option>], advice_values: &[Option>], instance_values: &[Option>], challenges: &[F], + y_powers: &[F], beta: &F, gamma: &F, theta: &F, - y_powers: &[F], ) -> F { match self { ValueSource::Constant(idx) => constants[*idx], @@ -80,7 +95,7 @@ impl ValueSource { advice_values[*column_index].as_ref().unwrap()[rotations[*rotation]] } ValueSource::Instance(column_index, rotation) => { - assert!(advice_values[*column_index].is_some()); + assert!(instance_values[*column_index].is_some()); instance_values[*column_index].as_ref().unwrap()[rotations[*rotation]] } ValueSource::Challenge(index) => challenges[*index], @@ -115,7 +130,6 @@ pub enum Calculation { impl Calculation { /// Get the resulting value of this calculation - #[allow(clippy::too_many_arguments)] pub fn evaluate( &self, rotations: &[usize], @@ -125,10 +139,10 @@ impl Calculation { advice_values: &[Option>], instance_values: &[Option>], challenges: &[F], + y_powers: &[F], beta: &F, gamma: &F, theta: &F, - y_powers: &[F], ) -> F { let get_value = |value: &ValueSource| { value.get( @@ -139,10 +153,10 @@ impl Calculation { advice_values, instance_values, challenges, + y_powers, beta, gamma, theta, - y_powers, ) }; match self { @@ -166,7 +180,7 @@ impl Calculation { } #[derive(Clone, Default, Debug)] -struct ConstraintCluster { +struct ConstraintCluster { /// Used fixed columns in each cluster used_fixed_columns: Vec, /// Used instance columns in each cluster @@ -174,7 +188,7 @@ struct ConstraintCluster { /// Used advice columns in each cluster used_advice_columns: Vec, /// Custom gates evalution - evaluator: GraphEvaluator, + evaluator: GraphEvaluator, /// The first index of constraints are being evaluated at in each cluster first_constraint_idx: usize, /// The last index of constraints are being evaluated at in each cluster @@ -185,26 +199,28 @@ struct ConstraintCluster { /// Evaluator #[derive(Clone, Default, Debug)] -pub struct Evaluator { +pub struct Evaluator { /// list of constraint clusters - custom_gate_clusters: Vec>, + custom_gate_clusters: Vec>, /// Number of custom gate constraints num_custom_gate_constraints: usize, /// Lookups evalution, degree, used instance and advice columns + #[allow(clippy::type_complexity)] lookups: Vec<( - GraphEvaluator, + GraphEvaluator, usize, (Vec, Vec, Vec), )>, + /// Powers of y num_y_powers: usize, } /// GraphEvaluator #[derive(Clone, Debug)] -pub struct GraphEvaluator { +pub struct GraphEvaluator { /// Constants - pub constants: Vec, + pub constants: Vec, /// Rotations pub rotations: Vec, /// Calculations @@ -215,9 +231,9 @@ pub struct GraphEvaluator { /// EvaluationData #[derive(Default, Debug)] -pub struct EvaluationData { +pub struct EvaluationData { /// Intermediates - pub intermediates: Vec, + pub intermediates: Vec, /// Rotations pub rotations: Vec, } @@ -231,16 +247,15 @@ pub struct CalculationInfo { pub target: usize, } -// TODO: Move to utils or something similar? fn merge_unique(a: Vec, b: Vec) -> Vec { let mut result = a; result.extend(b); result.into_iter().unique().collect() } -impl Evaluator { +impl> Evaluator { /// Creates a new evaluation structure - pub fn new(cs: &ConstraintSystem) -> Self { + pub fn new(cs: &ConstraintSystem) -> Self { let mut ev = Evaluator::default(); let mut constraint_idx = 0; @@ -377,26 +392,26 @@ impl Evaluator { } /// Evaluate h poly - pub(in crate::plonk) fn evaluate_h( + pub(in crate::plonk) fn evaluate_h>( &self, pk: &ProvingKey, - advice_polys: &[&[Polynomial]], - instance_polys: &[&[Polynomial]], - challenges: &[C::ScalarExt], - y: C::ScalarExt, - beta: C::ScalarExt, - gamma: C::ScalarExt, - theta: C::ScalarExt, + advice_polys: &[&[Polynomial]], + instance_polys: &[&[Polynomial]], + challenges: &[F], + y: F, + beta: F, + gamma: F, + theta: F, lookups: &[Vec>], permutations: &[permutation::prover::Committed], - ) -> Polynomial { + ) -> Polynomial { let domain = &pk.vk.domain; 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 one = F::ONE; let p = &pk.vk.cs.permutation; let num_parts = domain.extended_len() >> domain.k(); let num_clusters = (domain.extended_k() - domain.k() + 1) as usize; @@ -404,7 +419,7 @@ impl Evaluator { assert!(self.custom_gate_clusters.len() <= num_clusters); // Initialize the the powers of y and constraint counter - let mut y_powers = vec![C::ScalarExt::ONE; self.num_y_powers * instance_polys.len()]; + let mut y_powers = vec![F::ONE; self.num_y_powers * instance_polys.len()]; for i in 1..self.num_y_powers { y_powers[i] = y_powers[i - 1] * y; } @@ -415,14 +430,18 @@ impl Evaluator { let mut value_part_clusters = Vec::new(); value_part_clusters.resize(num_clusters, Vec::new()); - for cluster_idx in 0..num_clusters { - value_part_clusters[cluster_idx].resize(1 << cluster_idx, domain.empty_lagrange()); + for (cluster_idx, cluster) in value_part_clusters + .iter_mut() + .enumerate() + .take(num_clusters) + { + cluster.resize(1 << cluster_idx, domain.empty_lagrange()); } // Calculate the quotient polynomial for each part let mut current_extended_omega = one; for part_idx in 0..num_parts { - let mut fixed: Vec>> = + let mut fixed: Vec>> = vec![None; pk.fixed_polys.len()]; 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); @@ -527,15 +546,15 @@ impl Evaluator { let chunk_len = pk.vk.cs.degree() - 2; let delta_start = beta * &C::Scalar::ZETA; - let permutation_product_cosets: Vec> = - sets.iter() - .map(|set| { - domain.coeff_to_extended_part( - set.permutation_product_poly.clone(), - current_extended_omega, - ) - }) - .collect(); + let permutation_product_cosets: Vec> = sets + .iter() + .map(|set| { + domain.coeff_to_extended_part( + set.permutation_product_poly.clone(), + current_extended_omega, + ) + }) + .collect(); let first_set_permutation_product_coset = permutation_product_cosets.first().unwrap(); @@ -652,7 +671,7 @@ impl Evaluator { } } - let permutation_cosets: Vec> = pk + let permutation_cosets: Vec> = pk .permutation .polys .iter() @@ -959,15 +978,11 @@ impl Evaluator { } } -impl Default for GraphEvaluator { +impl Default for GraphEvaluator { fn default() -> Self { Self { // Fixed positions to allow easy access - constants: vec![ - C::ScalarExt::ZERO, - C::ScalarExt::ONE, - C::ScalarExt::from(2u64), - ], + constants: vec![F::ZERO, F::ONE, F::ONE + F::ONE], rotations: Vec::new(), calculations: Vec::new(), num_intermediates: 0, @@ -975,7 +990,7 @@ impl Default for GraphEvaluator { } } -impl GraphEvaluator { +impl GraphEvaluator { /// Adds a rotation fn add_rotation(&mut self, rotation: &Rotation) -> usize { let position = self.rotations.iter().position(|&c| c == rotation.0); @@ -989,7 +1004,7 @@ impl GraphEvaluator { } /// Adds a constant - fn add_constant(&mut self, constant: &C::ScalarExt) -> ValueSource { + fn add_constant(&mut self, constant: &F) -> ValueSource { let position = self.constants.iter().position(|&c| c == *constant); ValueSource::Constant(match position { Some(pos) => pos, @@ -1024,7 +1039,7 @@ impl GraphEvaluator { } /// Generates an optimized evaluation for the expression - fn add_expression(&mut self, expr: &Expression) -> ValueSource { + fn add_expression(&mut self, expr: &Expression) -> ValueSource { match expr { Expression::Constant(scalar) => self.add_constant(scalar), Expression::Selector(_selector) => unreachable!(), @@ -1113,9 +1128,9 @@ impl GraphEvaluator { } } Expression::Scaled(a, f) => { - if *f == C::ScalarExt::ZERO { + if *f == F::ZERO { ValueSource::Constant(0) - } else if *f == C::ScalarExt::ONE { + } else if *f == F::ONE { self.add_expression(a) } else { let cst = self.add_constant(f); @@ -1127,28 +1142,28 @@ impl GraphEvaluator { } /// Creates a new evaluation structure - pub fn instance(&self) -> EvaluationData { + pub fn instance(&self) -> EvaluationData { EvaluationData { - intermediates: vec![C::ScalarExt::ZERO; self.num_intermediates], + intermediates: vec![F::ZERO; self.num_intermediates], rotations: vec![0usize; self.rotations.len()], } } pub fn evaluate( &self, - data: &mut EvaluationData, - fixed: &[Option>], - advice: &[Option>], - instance: &[Option>], - challenges: &[C::ScalarExt], - y_powers: &[C::ScalarExt], - beta: &C::ScalarExt, - gamma: &C::ScalarExt, - theta: &C::ScalarExt, + data: &mut EvaluationData, + fixed: &[Option>], + advice: &[Option>], + instance: &[Option>], + challenges: &[F], + y_powers: &[F], + beta: &F, + gamma: &F, + theta: &F, idx: usize, rot_scale: i32, isize: i32, - ) -> C::ScalarExt { + ) -> F { // All rotation index values for (rot_idx, rot) in self.rotations.iter().enumerate() { data.rotations[rot_idx] = get_rotation_idx(idx, *rot, rot_scale, isize); @@ -1164,10 +1179,10 @@ impl GraphEvaluator { advice, instance, challenges, + y_powers, beta, gamma, theta, - y_powers, ); } @@ -1175,7 +1190,7 @@ impl GraphEvaluator { if let Some(calc) = self.calculations.last() { data.intermediates[calc.target] } else { - C::ScalarExt::ZERO + F::ZERO } } } diff --git a/halo2_backend/src/plonk/keygen.rs b/halo2_backend/src/plonk/keygen.rs index b5c05de8a8..feda9082c8 100644 --- a/halo2_backend/src/plonk/keygen.rs +++ b/halo2_backend/src/plonk/keygen.rs @@ -138,12 +138,12 @@ where // 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_coeff(); + let mut l_last = vk.domain.empty_lagrange(); l_last[params.n() as usize - vk.cs.blinding_factors() - 1] = C::Scalar::ONE; // Compute l_active_row(X) let one = C::Scalar::ONE; - let mut l_active_row = vk.domain.empty_coeff(); + 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; @@ -151,6 +151,9 @@ where } }); + 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);