diff --git a/benches/plonk.rs b/benches/plonk.rs index ed419421a..7f1d19114 100644 --- a/benches/plonk.rs +++ b/benches/plonk.rs @@ -12,8 +12,8 @@ use std::marker::PhantomData; use criterion::{BenchmarkId, Criterion}; use halo2_proofs::poly::kzg::{params::ParamsKZG, KZGCommitmentScheme}; -use halo2_proofs::utils::rational::Rational; use halo2_proofs::transcript::{CircuitTranscript, Transcript}; +use halo2_proofs::utils::rational::Rational; fn criterion_benchmark(c: &mut Criterion) { /// This represents an advice column at a certain row in the ConstraintSystem diff --git a/examples/proof-size.rs b/examples/proof-size.rs index db467b4d2..9b92a3b4e 100644 --- a/examples/proof-size.rs +++ b/examples/proof-size.rs @@ -88,7 +88,7 @@ const K: u32 = 11; fn main() { let circuit = TestCircuit {}; - let model = from_circuit_to_model_circuit::<_, _, 56, 56>( + let model = from_circuit_to_model_circuit::<_, _, 32, 32>( Some(K), &circuit, vec![], diff --git a/examples/shuffle.rs b/examples/shuffle.rs deleted file mode 100644 index 8a594da64..000000000 --- a/examples/shuffle.rs +++ /dev/null @@ -1,346 +0,0 @@ -use blake2b_simd::State; -use ff::{BatchInvert, FromUniformBytes, WithSmallOrderMulGroup}; -use halo2_proofs::poly::kzg::{params::ParamsKZG, KZGCommitmentScheme}; -use halo2_proofs::transcript::{CircuitTranscript, Hashable, Sampleable, Transcript}; -use halo2_proofs::{ - utils::arithmetic::Field, - circuit::{floor_planner::V1, Layouter, Value}, - dev::{metadata, FailureLocation, MockProver, VerifyFailure}, - plonk::*, -}; -use halo2curves::pairing::MultiMillerLoop; -use halo2curves::serde::SerdeObject; -use halo2curves::{bn256, pairing::Engine, CurveAffine}; -use rand_core::{OsRng, RngCore}; -use std::iter; - -fn rand_2d_array(rng: &mut R) -> [[F; H]; W] { - [(); W].map(|_| [(); H].map(|_| F::random(&mut *rng))) -} - -fn shuffled( - original: [[F; H]; W], - rng: &mut R, -) -> [[F; H]; W] { - let mut shuffled = original; - - for row in (1..H).rev() { - let rand_row = (rng.next_u32() as usize) % row; - for column in shuffled.iter_mut() { - column.swap(row, rand_row); - } - } - - shuffled -} - -#[derive(Clone)] -struct MyConfig { - q_shuffle: Selector, - q_first: Selector, - q_last: Selector, - original: [Column; W], - shuffled: [Column; W], - theta: Challenge, - gamma: Challenge, - z: Column, -} - -impl MyConfig { - 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)); - let shuffled = [(); W].map(|_| meta.advice_column_in(FirstPhase)); - let [theta, gamma] = [(); 2].map(|_| meta.challenge_usable_after(FirstPhase)); - // Second phase - let z = meta.advice_column_in(SecondPhase); - - meta.create_gate("z should start with 1", |_| { - let one = Expression::Constant(F::ONE); - - vec![q_first.expr() * (one - z.cur())] - }); - - meta.create_gate("z should end with 1", |_| { - let one = Expression::Constant(F::ONE); - - vec![q_last.expr() * (one - z.cur())] - }); - - meta.create_gate("z should have valid transition", |_| { - let q_shuffle = q_shuffle.expr(); - let original = original.map(|advice| advice.cur()); - let shuffled = shuffled.map(|advice| advice.cur()); - let [theta, gamma] = [theta, gamma].map(|challenge| challenge.expr()); - - // Compress - let original = original - .iter() - .cloned() - .reduce(|acc, a| acc * theta.clone() + a) - .unwrap(); - let shuffled = shuffled - .iter() - .cloned() - .reduce(|acc, a| acc * theta.clone() + a) - .unwrap(); - - vec![q_shuffle * (z.cur() * (original + gamma.clone()) - z.next() * (shuffled + gamma))] - }); - - Self { - q_shuffle, - q_first, - q_last, - original, - shuffled, - theta, - gamma, - z, - } - } -} - -#[derive(Clone, Default)] -struct MyCircuit { - original: Value<[[F; H]; W]>, - shuffled: Value<[[F; H]; W]>, -} - -impl MyCircuit { - fn rand(rng: &mut R) -> Self { - let original = rand_2d_array::(rng); - let shuffled = shuffled(original, rng); - - Self { - original: Value::known(original), - shuffled: Value::known(shuffled), - } - } -} - -impl Circuit for MyCircuit { - type Config = MyConfig; - type FloorPlanner = V1; - #[cfg(feature = "circuit-params")] - type Params = (); - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - MyConfig::configure(meta) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let theta = layouter.get_challenge(config.theta); - let gamma = layouter.get_challenge(config.gamma); - - layouter.assign_region( - || "Shuffle original into shuffled", - |mut region| { - // Keygen - config.q_first.enable(&mut region, 0)?; - config.q_last.enable(&mut region, H)?; - for offset in 0..H { - config.q_shuffle.enable(&mut region, offset)?; - } - - // First phase - for (idx, (&column, values)) in config - .original - .iter() - .zip(self.original.transpose_array().iter()) - .enumerate() - { - for (offset, &value) in values.transpose_array().iter().enumerate() { - region.assign_advice( - || format!("original[{idx}][{offset}]"), - column, - offset, - || value, - )?; - } - } - for (idx, (&column, values)) in config - .shuffled - .iter() - .zip(self.shuffled.transpose_array().iter()) - .enumerate() - { - for (offset, &value) in values.transpose_array().iter().enumerate() { - region.assign_advice( - || format!("shuffled[{idx}][{offset}]"), - column, - offset, - || value, - )?; - } - } - - // Second phase - let z = self.original.zip(self.shuffled).zip(theta).zip(gamma).map( - |(((original, shuffled), theta), gamma)| { - let mut product = vec![F::ZERO; H]; - for (idx, product) in product.iter_mut().enumerate() { - let mut compressed = F::ZERO; - for value in shuffled.iter() { - compressed *= theta; - compressed += value[idx]; - } - - *product = compressed + gamma - } - - product.iter_mut().batch_invert(); - - for (idx, product) in product.iter_mut().enumerate() { - let mut compressed = F::ZERO; - for value in original.iter() { - compressed *= theta; - compressed += value[idx]; - } - - *product *= compressed + gamma - } - - #[allow(clippy::let_and_return)] - let z = iter::once(F::ONE) - .chain(product) - .scan(F::ONE, |state, cur| { - *state *= &cur; - Some(*state) - }) - .collect::>(); - - #[cfg(feature = "sanity-checks")] - assert_eq!(F::ONE, *z.last().unwrap()); - - z - }, - ); - for (offset, value) in z.transpose_vec(H + 1).into_iter().enumerate() { - region.assign_advice(|| format!("z[{offset}]"), config.z, offset, || value)?; - } - - Ok(()) - }, - ) - } -} - -fn test_mock_prover, const W: usize, const H: usize>( - k: u32, - circuit: MyCircuit, - expected: Result<(), Vec<(metadata::Constraint, FailureLocation)>>, -) { - let prover = MockProver::run(k, &circuit, vec![]).unwrap(); - match (prover.verify(), expected) { - (Ok(_), Ok(_)) => {} - (Err(err), Err(expected)) => { - assert_eq!( - err.into_iter() - .map(|failure| match failure { - VerifyFailure::ConstraintNotSatisfied { - constraint, - location, - .. - } => (constraint, location), - _ => panic!("MockProver::verify has result unmatching expected"), - }) - .collect::>(), - expected - ) - } - (_, _) => panic!("MockProver::verify has result unmatching expected"), - }; -} - -fn test_prover( - k: u32, - circuit: MyCircuit, - expected: bool, -) where - E::G1Affine: - Default + SerdeObject + Hashable + CurveAffine, - E::Fr: WithSmallOrderMulGroup<3> - + FromUniformBytes<64> - + SerdeObject - + Sampleable - + Hashable - + Ord, -{ - let params = ParamsKZG::::new(k); - let vk = keygen_vk(¶ms, &circuit).unwrap(); - let pk = keygen_pk(¶ms, vk, &circuit).unwrap(); - - let proof = { - let mut transcript = CircuitTranscript::::init(); - - create_proof::, _, _>( - ¶ms, - &pk, - &[circuit], - &[&[]], - OsRng, - &mut transcript, - ) - .expect("proof generation should not fail"); - - transcript.finalize() - }; - - let mut transcript = CircuitTranscript::::init_from_bytes(&proof[..]); - - let verifier = verify_proof::, _>( - ¶ms, - pk.get_vk(), - &[&[]], - &mut transcript, - ); - - assert_eq!(verifier.is_ok(), expected); -} - -fn main() { - const W: usize = 4; - const H: usize = 32; - const K: u32 = 8; - - let circuit = &MyCircuit::<_, W, H>::rand(&mut OsRng); - - { - test_mock_prover(K, circuit.clone(), Ok(())); - test_prover::(K, circuit.clone(), true); - } - - #[cfg(not(feature = "sanity-checks"))] - { - use std::ops::IndexMut; - - let mut circuit = circuit.clone(); - circuit.shuffled = circuit.shuffled.map(|mut shuffled| { - shuffled.index_mut(0).swap(0, 1); - shuffled - }); - - test_mock_prover( - K, - circuit.clone(), - Err(vec![( - ((1, "z should end with 1").into(), 0, "").into(), - FailureLocation::InRegion { - region: (0, "Shuffle original into shuffled").into(), - offset: 32, - }, - )]), - ); - test_prover::(K, circuit, false); - } -} diff --git a/examples/simple-example.rs b/examples/simple-example.rs index 4666124bf..45ab6675b 100644 --- a/examples/simple-example.rs +++ b/examples/simple-example.rs @@ -1,10 +1,10 @@ use std::marker::PhantomData; use halo2_proofs::{ - utils::arithmetic::Field, circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Selector}, poly::Rotation, + utils::arithmetic::Field, }; // ANCHOR: instructions diff --git a/examples/two-chip.rs b/examples/two-chip.rs index 97f37e8cc..60dac6bb1 100644 --- a/examples/two-chip.rs +++ b/examples/two-chip.rs @@ -1,10 +1,10 @@ use std::marker::PhantomData; use halo2_proofs::{ - utils::arithmetic::Field, circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance, Selector}, poly::Rotation, + utils::arithmetic::Field, }; // ANCHOR: field-instructions diff --git a/examples/vector-mul.rs b/examples/vector-mul.rs index bfeb3d5fb..791a52c37 100644 --- a/examples/vector-mul.rs +++ b/examples/vector-mul.rs @@ -1,10 +1,10 @@ use std::marker::PhantomData; use halo2_proofs::{ - utils::arithmetic::Field, circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance, Selector}, poly::Rotation, + utils::arithmetic::Field, }; // ANCHOR: instructions diff --git a/examples/vector-ops-unblinded.rs b/examples/vector-ops-unblinded.rs index 72ae05a06..136c34b3c 100644 --- a/examples/vector-ops-unblinded.rs +++ b/examples/vector-ops-unblinded.rs @@ -8,10 +8,10 @@ use ff::{FromUniformBytes, WithSmallOrderMulGroup}; use halo2_proofs::poly::kzg::{params::ParamsKZG, KZGCommitmentScheme}; use halo2_proofs::transcript::{CircuitTranscript, Hashable, Sampleable, Transcript}; use halo2_proofs::{ - utils::arithmetic::Field, circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value}, plonk::*, poly::Rotation, + utils::arithmetic::Field, }; use halo2curves::pairing::{Engine, MultiMillerLoop}; use halo2curves::serde::SerdeObject; diff --git a/src/circuit/mod.rs b/src/circuit/mod.rs index d89fec0f7..29c8f856f 100644 --- a/src/circuit/mod.rs +++ b/src/circuit/mod.rs @@ -133,7 +133,7 @@ impl AssignedCell { impl AssignedCell where - for<'v> Rational: From<&'v V>, + for<'v> Rational: From<&'v V>, { /// Returns the field element value of the [`AssignedCell`]. pub fn value_field(&self) -> Value> { @@ -157,7 +157,7 @@ impl AssignedCell, F> { impl AssignedCell where - for<'v> Rational: From<&'v V>, + for<'v> Rational: From<&'v V>, { /// Copies the value to a given advice cell and constrains them to be equal. /// @@ -281,9 +281,9 @@ impl<'r, F: Field> Region<'r, F> { constant: VR, ) -> Result, Error> where - for<'vr> Rational: From<&'vr VR>, - A: Fn() -> AR, - AR: Into, + for<'vr> Rational: From<&'vr VR>, + A: Fn() -> AR, + AR: Into, { let cell = self.region.assign_advice_from_constant( &|| annotation().into(), diff --git a/src/dev/mod.rs b/src/dev/mod.rs index 2e1f4d9cf..a7093472a 100644 --- a/src/dev/mod.rs +++ b/src/dev/mod.rs @@ -151,10 +151,10 @@ impl Mul for Value { // If poison is multiplied by zero, then we treat the poison as unconstrained // and we don't propagate it. (Value::Real(x), Value::Poison) | (Value::Poison, Value::Real(x)) - if x.is_zero_vartime() => - { - Value::Real(F::ZERO) - } + if x.is_zero_vartime() => + { + Value::Real(F::ZERO) + } _ => Value::Poison, } } @@ -683,8 +683,8 @@ impl + Ord> MockProver { hash = blake2b(&hash).as_bytes().try_into().unwrap(); F::from_uniform_bytes(&hash) }) - .take(cs.num_challenges) - .collect() + .take(cs.num_challenges) + .collect() }; let mut prover = MockProver { @@ -825,12 +825,12 @@ impl + Ord> MockProver { // Check that it was assigned! if r.cells.contains_key(&(cell.column, cell_row)) || gate.polynomials().par_iter().all(|expr| { - self.cell_is_irrelevant( - cell, - expr, - gate_row as usize, - ) - }) + self.cell_is_irrelevant( + cell, + expr, + gate_row as usize, + ) + }) { None } else { @@ -871,70 +871,70 @@ impl + Ord> MockProver { .clone() .into_par_iter() .chain(blinding_rows.into_par_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, + .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(), ), - &|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, - ), + 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(), - }), - } - }) - .collect::>() - }) - .collect::>() + ), + }), + Value::Poison => Some(VerifyFailure::ConstraintPoisoned { + constraint: ( + (gate_index, gate.name()).into(), + poly_index, + gate.constraint_name(poly_index), + ) + .into(), + }), + } + }) + .collect::>() + }) + .collect::>() }); let load = |expression: &Expression, row| { @@ -1190,7 +1190,7 @@ impl + Ord> MockProver { (self.expr_is_constantly_zero(e1, offset) || self.expr_is_constantly_zero(e2, offset)) || (self.cell_is_irrelevant(cell, e1, offset) - && self.cell_is_irrelevant(cell, e2, offset)) + && self.cell_is_irrelevant(cell, e2, offset)) } Expression::Scaled(e, factor) => { factor.is_zero().into() || self.cell_is_irrelevant(cell, e, offset) @@ -1537,7 +1537,7 @@ mod tests { Fp::from(6u64), ]], ) - .unwrap(); + .unwrap(); assert_eq!( prover.verify(), Err(vec![VerifyFailure::Lookup { diff --git a/src/lib.rs b/src/lib.rs index c57687a2d..3ab96252c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,5 @@ pub mod plonk; pub mod poly; pub mod transcript; - pub mod dev; pub mod utils; diff --git a/src/plonk/evaluation.rs b/src/plonk/evaluation.rs index 5ff7ee5f2..e8c2b86d9 100644 --- a/src/plonk/evaluation.rs +++ b/src/plonk/evaluation.rs @@ -1,10 +1,10 @@ -use crate::utils::multicore; use crate::plonk::{lookup, permutation, Any, ProvingKey}; use crate::poly::commitment::PolynomialCommitmentScheme; use crate::poly::Basis; +use crate::utils::multicore; use crate::{ - utils::arithmetic::parallelize, poly::{Coeff, ExtendedLagrangeCoeff, Polynomial, Rotation}, + utils::arithmetic::parallelize, }; use ff::{PrimeField, WithSmallOrderMulGroup}; use group::ff::Field; diff --git a/src/plonk/keygen.rs b/src/plonk/keygen.rs index 14c3d091e..fa57ada32 100644 --- a/src/plonk/keygen.rs +++ b/src/plonk/keygen.rs @@ -17,7 +17,7 @@ use crate::circuit::Value; use crate::poly::batch_invert_rational; use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; use crate::utils::rational::Rational; -use crate::{utils::arithmetic::parallelize, poly::EvaluationDomain}; +use crate::{poly::EvaluationDomain, utils::arithmetic::parallelize}; pub(crate) fn create_domain( k: u32, diff --git a/src/plonk/lookup/prover.rs b/src/plonk/lookup/prover.rs index f8bf2df23..3e40a56c4 100644 --- a/src/plonk/lookup/prover.rs +++ b/src/plonk/lookup/prover.rs @@ -4,8 +4,8 @@ use crate::plonk::evaluation::evaluate; use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; use crate::transcript::{Hashable, Transcript}; use crate::{ - utils::arithmetic::{eval_polynomial, parallelize}, poly::{Coeff, EvaluationDomain, LagrangeCoeff, Polynomial, ProverQuery, Rotation}, + utils::arithmetic::{eval_polynomial, parallelize}, }; use ff::{PrimeField, WithSmallOrderMulGroup}; use group::ff::BatchInvert; diff --git a/src/plonk/mod.rs b/src/plonk/mod.rs index 2d7193db9..318493557 100644 --- a/src/plonk/mod.rs +++ b/src/plonk/mod.rs @@ -8,12 +8,15 @@ use blake2b_simd::Params as Blake2bParams; use group::ff::FromUniformBytes; -use crate::utils::helpers::{byte_length, polynomial_slice_byte_length, ProcessedSerdeObject, read_polynomial_vec, write_polynomial_slice}; use crate::poly::{ Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, PinnedEvaluationDomain, Polynomial, }; use crate::transcript::{Hashable, Transcript}; +use crate::utils::helpers::{ + byte_length, polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice, + ProcessedSerdeObject, +}; use crate::utils::SerdeFormat; mod circuit; @@ -185,11 +188,11 @@ impl, CS: PolynomialCommitmentScheme> VerifyingK 10 + (self.fixed_commitments.len() * byte_length::(format)) + self.permutation.bytes_length(format) + self.selectors.len() - * (self - .selectors - .first() - .map(|selector| (selector.len() + 7) / 8) - .unwrap_or(0)) + * (self + .selectors + .first() + .map(|selector| (selector.len() + 7) / 8) + .unwrap_or(0)) } fn from_parts( diff --git a/src/plonk/permutation.rs b/src/plonk/permutation.rs index 8555d7bb0..f0614ba59 100644 --- a/src/plonk/permutation.rs +++ b/src/plonk/permutation.rs @@ -2,10 +2,8 @@ use super::circuit::{Any, Column}; use crate::{ - utils::helpers::{ - polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice, - }, poly::{Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial}, + utils::helpers::{polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice}, utils::SerdeFormat, }; @@ -15,8 +13,8 @@ pub(crate) mod verifier; pub use keygen::Assembly; -use crate::utils::helpers::{byte_length, ProcessedSerdeObject}; use crate::poly::commitment::PolynomialCommitmentScheme; +use crate::utils::helpers::{byte_length, ProcessedSerdeObject}; use ff::PrimeField; use halo2curves::serde::SerdeObject; use std::io; @@ -149,10 +147,7 @@ impl ProvingKey { } /// Writes proving key for a single permutation argument to buffer using `Polynomial::write`. - pub(super) fn write( - &self, - writer: &mut W, - ) -> io::Result<()> { + 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)?; diff --git a/src/plonk/permutation/keygen.rs b/src/plonk/permutation/keygen.rs index dc45e1c40..93b8118dd 100644 --- a/src/plonk/permutation/keygen.rs +++ b/src/plonk/permutation/keygen.rs @@ -2,9 +2,9 @@ use ff::WithSmallOrderMulGroup; use super::{Argument, ProvingKey, VerifyingKey}; use crate::{ - utils::arithmetic::parallelize, plonk::{Any, Column, Error}, poly::EvaluationDomain, + utils::arithmetic::parallelize, }; #[cfg(feature = "thread-safe-region")] diff --git a/src/plonk/permutation/prover.rs b/src/plonk/permutation/prover.rs index ebea470f9..2e6e3e970 100644 --- a/src/plonk/permutation/prover.rs +++ b/src/plonk/permutation/prover.rs @@ -9,9 +9,9 @@ use super::{Argument, ProvingKey}; use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; use crate::transcript::{Hashable, Transcript}; use crate::{ - utils::arithmetic::{eval_polynomial, parallelize}, plonk::{self, Error}, poly::{Coeff, LagrangeCoeff, Polynomial, ProverQuery, Rotation}, + utils::arithmetic::{eval_polynomial, parallelize}, }; pub(crate) struct CommittedSet { diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 34d1111c6..18fea4c94 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -14,17 +14,17 @@ use super::{ }; use crate::{ - utils::arithmetic::eval_polynomial, // circuit::Value, // plonk::Assigned, poly::{Basis, Coeff, LagrangeCoeff, Polynomial, ProverQuery}, + utils::arithmetic::eval_polynomial, }; use crate::circuit::Value; use crate::poly::batch_invert_rational; use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; -use crate::utils::rational::Rational; use crate::transcript::{Hashable, Sampleable, Transcript}; +use crate::utils::rational::Rational; use halo2curves::serde::SerdeObject; /// This creates a proof for the provided `circuit` when given the public diff --git a/src/plonk/vanishing/prover.rs b/src/plonk/vanishing/prover.rs index c750fdc8f..b284d9911 100644 --- a/src/plonk/vanishing/prover.rs +++ b/src/plonk/vanishing/prover.rs @@ -9,10 +9,10 @@ use super::Argument; use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; use crate::transcript::{Hashable, Transcript}; use crate::{ - utils::arithmetic::{eval_polynomial, parallelize}, - utils::multicore::current_num_threads, plonk::Error, poly::{Coeff, EvaluationDomain, ExtendedLagrangeCoeff, Polynomial, ProverQuery}, + utils::arithmetic::{eval_polynomial, parallelize}, + utils::multicore::current_num_threads, }; pub(in crate::plonk) struct Committed { diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index 8d0edc61f..974a0a1cc 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -3,10 +3,10 @@ use halo2curves::serde::SerdeObject; use std::iter; use super::{vanishing, Error, VerifyingKey}; -use crate::utils::arithmetic::compute_inner_product; use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; use crate::poly::VerifierQuery; use crate::transcript::{read_n, Hashable, Sampleable, Transcript}; +use crate::utils::arithmetic::compute_inner_product; /// Returns a boolean indicating whether or not the proof is valid pub fn verify_proof< diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index 66be2076e..fc05ecc79 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -1,9 +1,9 @@ //! Trait for a commitment scheme use crate::poly::{Coeff, Error, LagrangeCoeff, Polynomial, ProverQuery, VerifierQuery}; use crate::transcript::{Hashable, Sampleable, Transcript}; +use crate::utils::helpers::ProcessedSerdeObject; use ff::PrimeField; use std::fmt::Debug; -use crate::utils::helpers::ProcessedSerdeObject; /// Public interface for a Polynomial Commitment Scheme (PCS) pub trait PolynomialCommitmentScheme: Clone + Debug { diff --git a/src/poly/kzg/mod.rs b/src/poly/kzg/mod.rs index c3b17b5d9..3b8af9d47 100644 --- a/src/poly/kzg/mod.rs +++ b/src/poly/kzg/mod.rs @@ -8,12 +8,12 @@ pub mod params; use std::fmt::Debug; -use crate::utils::arithmetic::{kate_division, powers, MSM}; use crate::poly::kzg::msm::{DualMSM, MSMKZG}; use crate::poly::kzg::params::{ParamsKZG, ParamsVerifierKZG}; use crate::poly::query::Query; use crate::poly::query::VerifierQuery; use crate::poly::{Coeff, Error, Polynomial, ProverQuery}; +use crate::utils::arithmetic::{kate_division, powers, MSM}; use crate::poly::commitment::PolynomialCommitmentScheme; use crate::transcript::{Hashable, Sampleable, Transcript}; @@ -212,7 +212,6 @@ where #[cfg(test)] mod tests { - use crate::utils::arithmetic::eval_polynomial; use crate::poly::commitment::PolynomialCommitmentScheme; use crate::poly::kzg::params::{ParamsKZG, ParamsVerifierKZG}; use crate::poly::kzg::KZGCommitmentScheme; @@ -221,6 +220,7 @@ mod tests { Error, EvaluationDomain, }; use crate::transcript::{CircuitTranscript, Hashable, Sampleable, Transcript}; + use crate::utils::arithmetic::eval_polynomial; use blake2b_simd::State as Blake2bState; use ff::WithSmallOrderMulGroup; use halo2curves::pairing::{Engine, MultiMillerLoop}; diff --git a/src/poly/kzg/params.rs b/src/poly/kzg/params.rs index 6758461a3..31ecb14ad 100644 --- a/src/poly/kzg/params.rs +++ b/src/poly/kzg/params.rs @@ -1,5 +1,5 @@ -use crate::utils::arithmetic::{g_to_lagrange, parallelize}; use crate::poly::{LagrangeCoeff, Polynomial}; +use crate::utils::arithmetic::{g_to_lagrange, parallelize}; use crate::utils::SerdeFormat; use ff::{Field, PrimeField}; @@ -10,11 +10,11 @@ use std::fmt::Debug; use crate::poly::commitment::Params; use crate::poly::kzg::KZGCommitmentScheme; +use crate::utils::helpers::ProcessedSerdeObject; use halo2curves::msm::msm_best; use halo2curves::serde::SerdeObject; use halo2curves::CurveAffine; use std::io; -use crate::utils::helpers::ProcessedSerdeObject; use super::msm::MSMKZG; diff --git a/src/poly/mod.rs b/src/poly/mod.rs index 8bf2e625c..d6ded960d 100644 --- a/src/poly/mod.rs +++ b/src/poly/mod.rs @@ -7,11 +7,11 @@ use crate::utils::SerdeFormat; use ff::{BatchInvert, PrimeField}; use group::ff::Field; +use halo2curves::serde::SerdeObject; use std::fmt::Debug; use std::io; use std::marker::PhantomData; use std::ops::{Add, Deref, DerefMut, Index, IndexMut, Mul, RangeFrom, RangeFull, Sub}; -use halo2curves::serde::SerdeObject; mod domain; mod query; @@ -21,10 +21,10 @@ pub mod kzg; pub mod commitment; +use crate::utils::helpers::read_f; use crate::utils::rational::Rational; pub use domain::*; pub use query::{ProverQuery, VerifierQuery}; -use crate::utils::helpers::{read_f}; /// This is an error that could occur during proving or circuit synthesis. // TODO: these errors need to be cleaned up @@ -156,10 +156,7 @@ 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) -> io::Result<()> { writer.write_all(&(self.values.len() as u32).to_be_bytes())?; for value in self.values.iter() { value.write_raw(writer)?; diff --git a/src/poly/query.rs b/src/poly/query.rs index 0b6fd16f1..7e7fe8dd3 100644 --- a/src/poly/query.rs +++ b/src/poly/query.rs @@ -3,8 +3,8 @@ use std::fmt::Debug; use crate::poly::commitment::PolynomialCommitmentScheme; use crate::{ - utils::arithmetic::eval_polynomial, poly::{Coeff, Polynomial}, + utils::arithmetic::eval_polynomial, }; pub trait Query: Sized + Clone + Send + Sync { @@ -108,28 +108,6 @@ where } } -// #[allow(clippy::upper_case_acronyms)] -// #[derive(Clone, Debug)] -// pub enum CommitmentReference<'r, C: CurveAffine, M: MSM> { -// Commitment(&'r C), -// MSM(&'r M), -// } -// -// impl<'r, C: CurveAffine, M: MSM> Copy for CommitmentReference<'r, C, M> {} -// -// impl<'r, C: CurveAffine, M: MSM> PartialEq for CommitmentReference<'r, C, M> { -// #![allow(clippy::vtable_address_comparisons)] -// 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, -// } -// } -// } - impl> Query for VerifierQuery { type Commitment = CS::Commitment; type Eval = F; diff --git a/src/utils/helpers.rs b/src/utils/helpers.rs index 3b98514ad..57ef1cdc9 100644 --- a/src/utils/helpers.rs +++ b/src/utils/helpers.rs @@ -3,9 +3,9 @@ use crate::poly::Polynomial; use ff::PrimeField; use group::prime::PrimeCurveAffine; +use group::GroupEncoding; use halo2curves::serde::SerdeObject; use std::io; -use group::GroupEncoding; /// This enum specifies how various types are serialized and deserialized. #[derive(Clone, Copy, Debug)] @@ -47,17 +47,19 @@ pub fn byte_length(format: SerdeFormat) -> us /// Helper function to read a field element with a serde format. There is no way to compress field /// elements, so `Processed` and `RawBytes` act equivalently. -pub(crate) fn read_f(reader: &mut R, format: SerdeFormat) -> io::Result { - match format { - SerdeFormat::Processed => {::read_raw(reader)} - SerdeFormat::RawBytes => {::read_raw(reader)} - SerdeFormat::RawBytesUnchecked => {Ok(::read_raw_unchecked(reader))} - } +pub(crate) fn read_f( + reader: &mut R, + format: SerdeFormat, +) -> io::Result { + match format { + SerdeFormat::Processed => ::read_raw(reader), + SerdeFormat::RawBytes => ::read_raw(reader), + SerdeFormat::RawBytesUnchecked => Ok(::read_raw_unchecked(reader)), + } } /// Trait for serialising SerdeObjects -impl ProcessedSerdeObject for C -{ +impl ProcessedSerdeObject for C { /// 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. @@ -69,9 +71,10 @@ impl ProcessedSerdeObject for C SerdeFormat::Processed => { let mut compressed = ::Repr::default(); reader.read_exact(compressed.as_mut())?; - Option::from(Self::from_bytes(&compressed)) - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Invalid point encoding in proof")) - }, + Option::from(Self::from_bytes(&compressed)).ok_or_else(|| { + io::Error::new(io::ErrorKind::Other, "Invalid point encoding in proof") + }) + } SerdeFormat::RawBytes => ::read_raw(reader), SerdeFormat::RawBytesUnchecked => Ok(::read_raw_unchecked(reader)), } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 0658aaf47..ab861289b 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -5,4 +5,4 @@ pub mod helpers; pub(crate) mod multicore; pub mod rational; -pub use helpers::SerdeFormat; \ No newline at end of file +pub use helpers::SerdeFormat; diff --git a/tests/plonk_api.rs b/tests/plonk_api.rs index 5b9e64d86..13dd3ca30 100644 --- a/tests/plonk_api.rs +++ b/tests/plonk_api.rs @@ -1,558 +1,549 @@ -// #![allow(clippy::many_single_char_names)] -// #![allow(clippy::op_ref)] -// -// use assert_matches::assert_matches; -// use ff::{FromUniformBytes}; -// use halo2_proofs::arithmetic::Field; -// use halo2_proofs::circuit::{Cell, Layouter, SimpleFloorPlanner, Value}; -// use halo2_proofs::dev::MockProver; -// use halo2_proofs::plonk::{ -// create_proof as create_plonk_proof, keygen_pk, keygen_vk, verify_proof as verify_plonk_proof, -// Advice, Assigned, Circuit, Column, ConstraintSystem, Error, Fixed, ProvingKey, TableColumn, -// VerifyingKey, -// }; -// use halo2_proofs::poly::commitment::{CommitmentScheme, ParamsProver, Prover, Verifier}; -// use halo2_proofs::poly::Rotation; -// use halo2_proofs::poly::VerificationStrategy; -// use halo2_proofs::transcript::{ -// Blake2bRead, Blake2bWrite, Challenge255, EncodedChallenge, TranscriptReadBuffer, -// TranscriptWriterBuffer, -// }; -// 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 -// #[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, -// } -// } -// } -// -// 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())) -// }, -// ) -// } -// 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())) -// }, -// ) -// } -// 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 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(()) -// } -// } -// -// impl Circuit for MyCircuit { -// type Config = PlonkConfig; -// type FloorPlanner = SimpleFloorPlanner; -// #[cfg(feature = "circuit-params")] -// type Params = (); -// -// fn without_witnesses(&self) -> Self { -// Self { -// a: Value::unknown(), -// lookup_table: self.lookup_table.clone(), -// } -// } -// -// 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, -// } -// } -// -// 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(()) -// } -// } -// -// 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 { -// a: Value::unknown(), -// lookup_table: lookup_table.clone(), -// }; -// -// // Check that we get an error if we try to initialize the proving key with a value of -// // k that is too small for the minimum required number of rows. -// let much_too_small_params= <$scheme as CommitmentScheme>::ParamsProver::new(1); -// assert_matches!( -// keygen_vk(&much_too_small_params, &empty_circuit), -// Err(Error::NotEnoughRowsAvailable { -// current_k, -// }) if current_k == 1 -// ); -// -// // Check that we get an error if we try to initialize the proving key with a value of -// // k that is too small for the number of rows the circuit uses. -// let slightly_too_small_params = <$scheme as CommitmentScheme>::ParamsProver::new(K-1); -// assert_matches!( -// keygen_vk(&slightly_too_small_params, &empty_circuit), -// Err(Error::NotEnoughRowsAvailable { -// current_k, -// }) if current_k == K - 1 -// ); -// }}; -// } -// -// fn keygen(params: &Scheme::ParamsProver) -> ProvingKey -// where -// Scheme::Scalar: FromUniformBytes<64> + WithSmallOrderMulGroup<3>, -// { -// 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: Ord + WithSmallOrderMulGroup<3> + FromUniformBytes<64>, -// { -// 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: Ord + WithSmallOrderMulGroup<3> + FromUniformBytes<64>, -// { -// let (_, instance, _) = common!(Scheme); -// let pubinputs = [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()); -// } -// -// use halo2_proofs::poly::kzg::params::{KZGCommitmentScheme, ParamsKZG}; -// use halo2_proofs::poly::kzg::gwc::{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[..], -// ); -// } +#![allow(clippy::many_single_char_names)] +#![allow(clippy::op_ref)] + +use assert_matches::assert_matches; +use blake2b_simd::State; +use ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup}; +use halo2_proofs::circuit::{Cell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::dev::MockProver; +use halo2_proofs::plonk::{ + create_proof as create_plonk_proof, keygen_pk, keygen_vk, verify_proof as verify_plonk_proof, + Advice, Circuit, Column, ConstraintSystem, Error, Fixed, ProvingKey, TableColumn, VerifyingKey, +}; +use halo2_proofs::poly::commitment::PolynomialCommitmentScheme; +use halo2_proofs::poly::kzg::params::ParamsKZG; +use halo2_proofs::poly::kzg::KZGCommitmentScheme; +use halo2_proofs::poly::Rotation; +use halo2_proofs::transcript::{CircuitTranscript, Hashable, Sampleable, Transcript}; +use halo2_proofs::utils::arithmetic::Field; +use halo2_proofs::utils::rational::Rational; +use halo2curves::serde::SerdeObject; +use rand_core::{CryptoRng, 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 + #[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<(Rational, Rational, Rational)>; + fn raw_add( + &self, + layouter: &mut impl Layouter, + f: F, + ) -> Result<(Cell, Cell, Cell), Error> + where + F: FnMut() -> Value<(Rational, Rational, Rational)>; + 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, + } + } + } + + impl StandardCs for StandardPlonk { + fn raw_multiply( + &self, + layouter: &mut impl Layouter, + mut f: F, + ) -> Result<(Cell, Cell, Cell), Error> + where + F: FnMut() -> Value<(Rational, Rational, Rational)>, + { + 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())) + }, + ) + } + fn raw_add( + &self, + layouter: &mut impl Layouter, + mut f: F, + ) -> Result<(Cell, Cell, Cell), Error> + where + F: FnMut() -> Value<(Rational, Rational, Rational)>, + { + 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())) + }, + ) + } + 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 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(()) + } + } + + impl Circuit for MyCircuit { + type Config = PlonkConfig; + type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); + + fn without_witnesses(&self) -> Self { + Self { + a: Value::unknown(), + lookup_table: self.lookup_table.clone(), + } + } + + 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, + } + } + + 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(()) + } + } + + macro_rules! common { + ($field:ident) => {{ + let a = $field::from(2834758237) * $field::ZETA; + let instance = $field::ONE + $field::ONE; + let lookup_table = vec![instance, a, a, $field::ZERO]; + (a, instance, lookup_table) + }}; + } + + macro_rules! bad_keys { + ($field: ident, $scheme:ident) => {{ + let (_, _, lookup_table) = common!($field); + let empty_circuit: MyCircuit<$field> = MyCircuit { + a: Value::unknown(), + lookup_table: lookup_table.clone(), + }; + + // Check that we get an error if we try to initialize the proving key with a value of + // k that is too small for the minimum required number of rows. + let much_too_small_params= <$scheme as PolynomialCommitmentScheme<$field>>::Parameters::new(1); + assert_matches!( + keygen_vk::<_, $scheme, _>(&much_too_small_params, &empty_circuit), + Err(Error::NotEnoughRowsAvailable { + current_k, + }) if current_k == 1 + ); + + // Check that we get an error if we try to initialize the proving key with a value of + // k that is too small for the number of rows the circuit uses. + let slightly_too_small_params = <$scheme as PolynomialCommitmentScheme<$field>>::Parameters::new(K-1); + assert_matches!( + keygen_vk::<_, $scheme, _>(&slightly_too_small_params, &empty_circuit), + Err(Error::NotEnoughRowsAvailable { + current_k, + }) if current_k == K - 1 + ); + }}; + } + + fn keygen>( + params: &Scheme::Parameters, + params_vk: &Scheme::VerifierParameters, + ) -> ProvingKey + where + F: FromUniformBytes<64> + WithSmallOrderMulGroup<3>, + { + let (_, _, lookup_table) = common!(F); + let empty_circuit: MyCircuit = MyCircuit { + a: Value::unknown(), + lookup_table, + }; + + // Initialize the proving key + let vk = keygen_vk(params_vk, &empty_circuit).expect("keygen_vk should not fail"); + + keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail") + } + + fn create_proof< + F: PrimeField, + Scheme: PolynomialCommitmentScheme, + T: Transcript, + R: RngCore + CryptoRng, + >( + rng: R, + params: &Scheme::Parameters, + pk: &ProvingKey, + ) -> Vec + where + F: Ord + + WithSmallOrderMulGroup<3> + + FromUniformBytes<64> + + Sampleable + + Hashable + + SerdeObject, + Scheme::Commitment: Hashable, + { + let (a, instance, lookup_table) = common!(F); + + let circuit: MyCircuit = MyCircuit { + a: Value::known(a), + lookup_table, + }; + + let mut transcript = T::init(); + + 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, T: Transcript>( + params_verifier: &Scheme::VerifierParameters, + vk: &VerifyingKey, + proof: &[u8], + ) where + F: Ord + + WithSmallOrderMulGroup<3> + + FromUniformBytes<64> + + Sampleable + + Hashable + + SerdeObject, + Scheme::Commitment: Hashable, + { + let (_, instance, _) = common!(F); + let pubinputs = [instance]; + + let mut transcript = T::init_from_bytes(proof); + + let verifier = verify_plonk_proof( + params_verifier, + vk, + &[&[&pubinputs[..]], &[&pubinputs[..]]], + &mut transcript, + ); + + assert!(verifier.is_ok()); + } + + use halo2curves::bn256::{Bn256, Fr}; + + type Scheme = KZGCommitmentScheme; + bad_keys!(Fr, Scheme); + + let params = ParamsKZG::::new(K); + let rng = OsRng; + + let pk = keygen::(¶ms, params.verifier_params()); + + let proof = create_proof::, _>(rng, ¶ms, &pk); + + let verifier_params = params.verifier_params(); + + verify_proof::<_, _, CircuitTranscript>(verifier_params, pk.get_vk(), &proof[..]); +}