diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cdce1546c0..23e2bc22e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,15 +17,18 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] include: - feature_set: basic - features: batch,dev-graph,gadget-traces + features: dev-graph,gadget-traces - feature_set: all - features: batch,dev-graph,gadget-traces,test-dev-graph,thread-safe-region,sanity-checks,circuit-params + features: dev-graph,gadget-traces,test-dev-graph,thread-safe-region,sanity-checks,circuit-params steps: - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: override: false + - name: Install libfontconfig1-dev + if: runner.os == 'Linux' + run: sudo apt-get install -y libfontconfig1-dev - name: Run tests uses: actions-rs/cargo@v1 with: @@ -42,6 +45,7 @@ jobs: - wasm32-wasi steps: + - run: sudo apt-get install -y libfontconfig1-dev - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: @@ -52,13 +56,14 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --no-default-features --features batch,dev-graph,gadget-traces --target ${{ matrix.target }} + args: --no-default-features --features dev-graph,gadget-traces --target ${{ matrix.target }} bitrot: name: Bitrot check runs-on: ubuntu-latest steps: + - run: sudo apt-get install -y libfontconfig1-dev - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: @@ -75,6 +80,7 @@ jobs: runs-on: ubuntu-latest steps: + - run: sudo apt-get install -y libfontconfig1-dev - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: @@ -97,6 +103,7 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: + - run: sudo apt-get install -y libfontconfig1-dev - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/lints-beta.yml b/.github/workflows/lints-beta.yml index e7fffa7a76..4077469819 100644 --- a/.github/workflows/lints-beta.yml +++ b/.github/workflows/lints-beta.yml @@ -12,6 +12,7 @@ jobs: continue-on-error: true steps: + - run: sudo apt-get install -y libfontconfig1-dev - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/lints-stable.yml b/.github/workflows/lints-stable.yml index 7666dae1df..a7ff199bbc 100644 --- a/.github/workflows/lints-stable.yml +++ b/.github/workflows/lints-stable.yml @@ -10,6 +10,7 @@ jobs: runs-on: ubuntu-latest steps: + - run: sudo apt-get install -y libfontconfig1-dev - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: diff --git a/Cargo.toml b/Cargo.toml index a12a604279..393a017f14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,14 +64,13 @@ assert_matches = "1.5" criterion = "0.3" gumdrop = "0.8" proptest = "1" -rand_core = { version = "0.6", default-features = false, features = ["getrandom"] } serde_json = "1" -[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dev-dependencies] +[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] getrandom = { version = "0.2", features = ["js"] } [features] -default = ["batch", "bits"] +default = ["bits"] dev-graph = ["plotters", "tabbycat"] test-dev-graph = [ "dev-graph", @@ -83,7 +82,6 @@ bits = ["halo2curves/bits"] gadget-traces = ["backtrace"] thread-safe-region = [] sanity-checks = [] -batch = ["rand_core/getrandom"] circuit-params = [] cost-estimator = ["serde", "serde_derive"] derive_serde = ["halo2curves/derive_serde"] diff --git a/benches/plonk.rs b/benches/plonk.rs index 7f1d191142..ec3773d2ab 100644 --- a/benches/plonk.rs +++ b/benches/plonk.rs @@ -11,15 +11,14 @@ use rand_core::OsRng; use std::marker::PhantomData; use criterion::{BenchmarkId, Criterion}; +use halo2_proofs::poly::commitment::Guard; +use halo2_proofs::poly::kzg::params::ParamsVerifierKZG; use halo2_proofs::poly::kzg::{params::ParamsKZG, KZGCommitmentScheme}; use halo2_proofs::transcript::{CircuitTranscript, Transcript}; use halo2_proofs::utils::rational::Rational; +use halo2curves::bn256::Bn256; fn criterion_benchmark(c: &mut Criterion) { - /// 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, @@ -257,13 +256,13 @@ fn criterion_benchmark(c: &mut Criterion) { ParamsKZG, ProvingKey>, ) { - let params: ParamsKZG = ParamsKZG::new(k); + let params: ParamsKZG = ParamsKZG::unsafe_setup(k, OsRng); let empty_circuit: MyCircuit = MyCircuit { a: Value::unknown(), k, }; let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); - let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); + let pk = keygen_pk(vk, &empty_circuit).expect("keygen_pk should not fail"); (params, pk) } @@ -294,20 +293,19 @@ fn criterion_benchmark(c: &mut Criterion) { } fn verifier( - params: &ParamsKZG, + params: &ParamsVerifierKZG, vk: &VerifyingKey>, proof: &[u8], ) { let mut transcript = CircuitTranscript::init_from_bytes(proof); - assert!( - verify_proof::, _>( - params, - vk, - &[&[]], - &mut transcript - ) - .is_ok() - ); + assert!(prepare::, _>( + vk, + &[&[]], + &mut transcript + ) + .unwrap() + .verify(params) + .is_ok()); } let k_range = 8..=16; @@ -345,7 +343,7 @@ fn criterion_benchmark(c: &mut Criterion) { BenchmarkId::from_parameter(k), &(¶ms, pk.get_vk(), &proof[..]), |b, &(params, vk, proof)| { - b.iter(|| verifier(params, vk, proof)); + b.iter(|| verifier(¶ms.verifier_params(), vk, proof)); }, ); } diff --git a/examples/circuit-layout.rs b/examples/circuit-layout.rs index b65adf5599..ab1eccfcdc 100644 --- a/examples/circuit-layout.rs +++ b/examples/circuit-layout.rs @@ -1,17 +1,14 @@ use ff::Field; +use halo2_proofs::utils::rational::Rational; use halo2_proofs::{ circuit::{Cell, Layouter, Region, SimpleFloorPlanner, Value}, - plonk::{Advice, Assigned, Circuit, Column, ConstraintSystem, Error, Fixed, TableColumn}, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, TableColumn}, poly::Rotation, }; use halo2curves::pasta::Fp; use rand_core::OsRng; use std::marker::PhantomData; -/// 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, @@ -30,10 +27,10 @@ struct PlonkConfig { trait StandardCs { fn raw_multiply(&self, region: &mut Region, f: F) -> Result<(Cell, Cell, Cell), Error> where - F: FnMut() -> Value<(Assigned, Assigned, Assigned)>; + F: FnMut() -> Value<(Rational, Rational, Rational)>; fn raw_add(&self, region: &mut Region, f: F) -> Result<(Cell, Cell, Cell), Error> where - F: FnMut() -> Value<(Assigned, Assigned, Assigned)>; + F: FnMut() -> Value<(Rational, Rational, Rational)>; fn copy(&self, region: &mut Region, a: Cell, b: Cell) -> Result<(), Error>; fn lookup_table(&self, layouter: &mut impl Layouter, values: &[FF]) -> Result<(), Error>; } @@ -64,7 +61,7 @@ impl StandardCs for StandardPlonk { mut f: F, ) -> Result<(Cell, Cell, Cell), Error> where - F: FnMut() -> Value<(Assigned, Assigned, Assigned)>, + F: FnMut() -> Value<(Rational, Rational, Rational)>, { let mut value = None; let lhs = region.assign_advice( @@ -101,7 +98,7 @@ impl StandardCs for StandardPlonk { } fn raw_add(&self, region: &mut Region, mut f: F) -> Result<(Cell, Cell, Cell), Error> where - F: FnMut() -> Value<(Assigned, Assigned, Assigned)>, + F: FnMut() -> Value<(Rational, Rational, Rational)>, { let mut value = None; let lhs = region.assign_advice( @@ -247,7 +244,7 @@ impl Circuit for MyCircuit { layouter.assign_region( || format!("region_{i}"), |mut region| { - let a: Value> = self.a.into(); + let a: Value> = self.a.into(); let mut a_squared = Value::unknown(); let (a0, _, c0) = cs.raw_multiply(&mut region, || { a_squared = a.square(); diff --git a/examples/serialization.rs b/examples/serialization.rs index 287aa061b8..b1c66a8c0e 100644 --- a/examples/serialization.rs +++ b/examples/serialization.rs @@ -5,12 +5,13 @@ use std::{ }; use ff::Field; +use halo2_proofs::poly::commitment::Guard; use halo2_proofs::transcript::{CircuitTranscript, Transcript}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, plonk::{ - create_proof, keygen_pk, keygen_vk, verify_proof, Advice, Circuit, Column, - ConstraintSystem, Error, Fixed, Instance, ProvingKey, + create_proof, keygen_pk, keygen_vk, prepare, Advice, Circuit, Column, ConstraintSystem, + Error, Fixed, Instance, ProvingKey, }, poly::{ kzg::{params::ParamsKZG, KZGCommitmentScheme}, @@ -126,10 +127,10 @@ impl Circuit for StandardPlonk { fn main() { let k = 4; let circuit = StandardPlonk(Fr::random(OsRng)); - let params = ParamsKZG::::setup(k, OsRng); + let params = ParamsKZG::::unsafe_setup(k, OsRng); let vk = keygen_vk::<_, KZGCommitmentScheme, _>(¶ms, &circuit) .expect("vk should not fail"); - let pk = keygen_pk(¶ms, vk, &circuit).expect("pk should not fail"); + let pk = keygen_pk(vk, &circuit).expect("pk should not fail"); let f = File::create("serialization-test.pk").unwrap(); let mut writer = BufWriter::new(f); @@ -166,11 +167,12 @@ fn main() { let mut transcript = CircuitTranscript::::init_from_bytes(&proof[..]); - assert!(verify_proof::, _>( - ¶ms, + assert!(prepare::, _>( pk.get_vk(), &[instances], &mut transcript, ) + .unwrap() + .verify(¶ms.verifier_params()) .is_ok()); } diff --git a/examples/vector-ops-unblinded.rs b/examples/vector-ops-unblinded.rs index 136c34b3c3..8b8a4e3afd 100644 --- a/examples/vector-ops-unblinded.rs +++ b/examples/vector-ops-unblinded.rs @@ -5,6 +5,7 @@ use blake2b_simd::State; use std::marker::PhantomData; use ff::{FromUniformBytes, WithSmallOrderMulGroup}; +use halo2_proofs::poly::commitment::Guard; use halo2_proofs::poly::kzg::{params::ParamsKZG, KZGCommitmentScheme}; use halo2_proofs::transcript::{CircuitTranscript, Hashable, Sampleable, Transcript}; use halo2_proofs::{ @@ -477,9 +478,9 @@ where + Hashable + Ord, { - let params = ParamsKZG::::new(k); + let params: ParamsKZG = ParamsKZG::unsafe_setup(k, OsRng); let vk = keygen_vk(¶ms, &circuit).unwrap(); - let pk = keygen_pk(¶ms, vk, &circuit).unwrap(); + let pk = keygen_pk(vk, &circuit).unwrap(); let proof = { let mut transcript = CircuitTranscript::::init(); @@ -500,12 +501,9 @@ where let accepted = { let mut transcript = CircuitTranscript::::init_from_bytes(&proof[..]); - verify_proof::, _>( - ¶ms, - pk.get_vk(), - &[&[&instances]], - &mut transcript, - ) + prepare::, _>(pk.get_vk(), &[&[&instances]], &mut transcript) + .unwrap() + .verify(¶ms.verifier_params()) }; assert_eq!(accepted.is_ok(), expected); diff --git a/rust-toolchain b/rust-toolchain index 32a6ce3c71..79e15fd493 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.76.0 +1.77.0 diff --git a/src/dev/cost_model.rs b/src/dev/cost_model.rs index 3381a501b1..8ac8f7c7fd 100644 --- a/src/dev/cost_model.rs +++ b/src/dev/cost_model.rs @@ -268,7 +268,7 @@ fn run_mock_prover_with_fallback, C: Circu circuit: &C, instances: Vec>, ) -> MockProver { - (5..25) + (1..25) .find_map(|k| { panic::catch_unwind(AssertUnwindSafe(|| { MockProver::run(k, circuit, instances.clone()).unwrap() diff --git a/src/dev/graph.rs b/src/dev/graph.rs index 11654fe415..b5a08950f3 100644 --- a/src/dev/graph.rs +++ b/src/dev/graph.rs @@ -1,11 +1,12 @@ use ff::Field; use tabbycat::{AttrList, Edge, GraphBuilder, GraphType, Identity, StmtList}; +use crate::utils::rational::Rational; use crate::{ circuit::Value, plonk::{ - Advice, Any, Assigned, Assignment, Challenge, Circuit, Column, ConstraintSystem, Error, - Fixed, FloorPlanner, Instance, Selector, + Advice, Any, Assignment, Challenge, Circuit, Column, ConstraintSystem, Error, Fixed, + FloorPlanner, Instance, Selector, }, }; @@ -123,7 +124,7 @@ impl Assignment for Graph { ) -> Result<(), Error> where V: FnOnce() -> Value, - VR: Into>, + VR: Into>, A: FnOnce() -> AR, AR: Into, { @@ -140,7 +141,7 @@ impl Assignment for Graph { ) -> Result<(), Error> where V: FnOnce() -> Value, - VR: Into>, + VR: Into>, A: FnOnce() -> AR, AR: Into, { @@ -163,7 +164,7 @@ impl Assignment for Graph { &mut self, _: Column, _: usize, - _: Value>, + _: Value>, ) -> Result<(), Error> { Ok(()) } diff --git a/src/dev/graph/layout.rs b/src/dev/graph/layout.rs index 94bd7eea14..025c04a997 100644 --- a/src/dev/graph/layout.rs +++ b/src/dev/graph/layout.rs @@ -106,7 +106,7 @@ impl CircuitLayout { cs.constants.clone(), ) .unwrap(); - let (cs, selector_polys) = cs.compress_selectors(layout.selectors); + let (cs, selector_polys) = cs.directly_convert_selectors_to_fixed(layout.selectors.clone()); let non_selector_fixed_columns = cs.num_fixed_columns - selector_polys.len(); // Figure out what order to render the columns in. @@ -115,7 +115,7 @@ impl CircuitLayout { let column_index = |cs: &ConstraintSystem, column: RegionColumn| { let column: Column = match column { RegionColumn::Column(col) => col, - RegionColumn::Selector(selector) => cs.selector_map[selector.0].into(), + RegionColumn::Selector(_) => panic!("We shouldn't have selectors by now"), }; column.index() + match column.column_type() { diff --git a/src/dev/mod.rs b/src/dev/mod.rs index a7093472a2..d76c5f89fe 100644 --- a/src/dev/mod.rs +++ b/src/dev/mod.rs @@ -20,9 +20,11 @@ use crate::{ }, }; -use crate::utils::multicore::{ - IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, ParallelIterator, - ParallelSliceMut, +use rayon::{ + iter::{ + IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, ParallelIterator, + }, + slice::ParallelSliceMut, }; pub mod metadata; @@ -912,9 +914,9 @@ impl + Ord> MockProver { 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( + 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, diff --git a/src/plonk/circuit.rs b/src/plonk/circuit.rs index 70b295f2a8..9953f34e5b 100644 --- a/src/plonk/circuit.rs +++ b/src/plonk/circuit.rs @@ -1338,10 +1338,10 @@ impl Product for Expression { } } -/// Represents an index into a vector where each entry corresponds to a distinct -/// point that polynomials are queried at. -#[derive(Copy, Clone, Debug)] -pub(crate) struct PointIndex(pub usize); +// /// Represents an index into a vector where each entry corresponds to a distinct +// /// point that polynomials are queried at. +// #[derive(Copy, Clone, Debug)] +// pub(crate) struct PointIndex(pub usize); /// A "virtual cell" is a PLONK cell that has been queried at a particular relative offset /// within a custom gate. diff --git a/src/plonk/evaluation.rs b/src/plonk/evaluation.rs index e8c2b86d96..c71f256945 100644 --- a/src/plonk/evaluation.rs +++ b/src/plonk/evaluation.rs @@ -1,7 +1,6 @@ use crate::plonk::{lookup, permutation, Any, ProvingKey}; use crate::poly::commitment::PolynomialCommitmentScheme; use crate::poly::Basis; -use crate::utils::multicore; use crate::{ poly::{Coeff, ExtendedLagrangeCoeff, Polynomial, Rotation}, utils::arithmetic::parallelize, @@ -171,8 +170,6 @@ pub struct Evaluator { pub custom_gates: GraphEvaluator, /// Lookups evalution pub lookups: Vec>, - /// Shuffle evalution - pub shuffles: Vec>, } /// GraphEvaluator @@ -313,7 +310,7 @@ impl> Evaluator { let mut values = domain.empty_extended(); // Core expression evaluations - let num_threads = multicore::current_num_threads(); + let num_threads = rayon::current_num_threads(); for (((advice, instance), lookups), permutation) in advice .iter() .zip(instance.iter()) @@ -321,7 +318,7 @@ impl> Evaluator { .zip(permutations.iter()) { // Custom gates - multicore::scope(|scope| { + rayon::scope(|scope| { let chunk_size = (size + num_threads - 1) / num_threads; for (thread_idx, values) in values.chunks_mut(chunk_size).enumerate() { let start = thread_idx * chunk_size; diff --git a/src/plonk/keygen.rs b/src/plonk/keygen.rs index fa57ada327..982babe1d5 100644 --- a/src/plonk/keygen.rs +++ b/src/plonk/keygen.rs @@ -1,5 +1,6 @@ #![allow(clippy::int_plus_one)] +use std::marker::PhantomData; use std::ops::Range; use ff::{Field, FromUniformBytes, WithSmallOrderMulGroup}; @@ -198,33 +199,85 @@ impl Assignment for Assembly { } } +// This code also appears in `keygen`. We duplicate it here for simplicity of the +// function body. +fn k_from_circuit, C: Circuit>(circuit: &C) -> u32 { + // TODO: We could optimize the order here. + (1..25) + .find(|k| { + let n = 2usize.pow(*k); + + let mut cs = ConstraintSystem::default(); + #[cfg(feature = "circuit-params")] + let config = C::configure_with_params(&mut cs, circuit.params()); + #[cfg(not(feature = "circuit-params"))] + let config = C::configure(&mut cs); + let cs = cs; + + if n < cs.minimum_rows() { + return false; + } + + let zero_poly = Polynomial { + values: vec![F::ZERO.into(); n], + _marker: PhantomData, + }; + + let mut assembly = Assembly { + k: *k, + fixed: vec![zero_poly; cs.num_fixed_columns], + permutation: permutation::Assembly::new(n, &cs.permutation), + selectors: vec![vec![false; n]; cs.num_selectors], + usable_rows: 0..n - (cs.blinding_factors() + 1), + _marker: std::marker::PhantomData, + }; + + // Synthesize the circuit to obtain URS + C::FloorPlanner::synthesize( + &mut assembly, + circuit, + config.clone(), + cs.constants.clone(), + ) + .is_ok() + }) + .expect("A circuit which can be implemented with at most 2^24 rows.") +} + /// Generate a `VerifyingKey` from an instance of `Circuit`. /// By default, selector compression is turned **off**. pub fn keygen_vk( - params: &CS::VerifierParameters, + params: &CS::Parameters, circuit: &ConcreteCircuit, ) -> Result, Error> where - F: WithSmallOrderMulGroup<3> + FromUniformBytes<64>, + F: WithSmallOrderMulGroup<3> + FromUniformBytes<64> + Ord, CS: PolynomialCommitmentScheme, ConcreteCircuit: Circuit, { + let k = k_from_circuit(circuit); + if params.max_k() < k { + return Err(Error::NotEnoughRowsAvailable { + current_k: params.max_k(), + }); + } + let (domain, cs, config) = create_domain::( - params.k(), + k, #[cfg(feature = "circuit-params")] circuit.params(), ); - if (params.n() as usize) < cs.minimum_rows() { - return Err(Error::not_enough_rows_available(params.k())); + if (domain.n as usize) < cs.minimum_rows() { + return Err(Error::not_enough_rows_available(domain.k())); } let mut assembly: Assembly = Assembly { - k: params.k(), + k: domain.k(), fixed: vec![domain.empty_lagrange_rational(); cs.num_fixed_columns], - permutation: permutation::keygen::Assembly::new(params.n() as usize, &cs.permutation), - selectors: vec![vec![false; params.n() as usize]; cs.num_selectors], - usable_rows: 0..params.n() as usize - (cs.blinding_factors() + 1), + permutation: permutation::keygen::Assembly::new(domain.n as usize, &cs.permutation), + selectors: vec![vec![false; domain.n as usize]; cs.num_selectors], + usable_rows: 0..domain.n as usize - (cs.blinding_factors() + 1), _marker: std::marker::PhantomData, }; @@ -252,7 +305,7 @@ where let fixed_commitments = fixed .iter() - .map(|poly| params.commit_lagrange(poly)) + .map(|poly| CS::commit_lagrange(params, poly)) .collect(); Ok(VerifyingKey::from_parts( @@ -266,7 +319,6 @@ where /// Generate a `ProvingKey` from a `VerifyingKey` and an instance of `Circuit`. pub fn keygen_pk( - params: &CS::Parameters, vk: VerifyingKey, circuit: &ConcreteCircuit, ) -> Result, Error> @@ -283,16 +335,13 @@ where let cs = cs; - if (params.n() as usize) < cs.minimum_rows() { - return Err(Error::not_enough_rows_available(params.k())); - } - + let n = vk.domain.n as usize; let mut assembly: Assembly = Assembly { - k: params.k(), + k: vk.domain.k(), fixed: vec![vk.domain.empty_lagrange_rational(); cs.num_fixed_columns], - permutation: permutation::keygen::Assembly::new(params.n() as usize, &cs.permutation), - selectors: vec![vec![false; params.n() as usize]; cs.num_selectors], - usable_rows: 0..params.n() as usize - (cs.blinding_factors() + 1), + permutation: permutation::keygen::Assembly::new(n, &cs.permutation), + selectors: vec![vec![false; n]; cs.num_selectors], + usable_rows: 0..n - (cs.blinding_factors() + 1), _marker: std::marker::PhantomData, }; @@ -322,10 +371,9 @@ where .map(|poly| vk.domain.coeff_to_extended(poly.clone())) .collect(); - let permutation_pk = - assembly - .permutation - .build_pk::(params, &vk.domain, &cs.permutation); + let permutation_pk = assembly + .permutation + .build_pk::(&vk.domain, &cs.permutation); // Compute l_0(X) // TODO: this can be done more efficiently @@ -346,7 +394,7 @@ 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_lagrange(); - l_last[params.n() as usize - cs.blinding_factors() - 1] = F::ONE; + l_last[n - cs.blinding_factors() - 1] = F::ONE; let l_last = vk.domain.lagrange_to_coeff(l_last); let l_last = vk.domain.coeff_to_extended(l_last); diff --git a/src/plonk/lookup/prover.rs b/src/plonk/lookup/prover.rs index 3e40a56c4c..c2a73d535e 100644 --- a/src/plonk/lookup/prover.rs +++ b/src/plonk/lookup/prover.rs @@ -1,13 +1,13 @@ use super::super::{circuit::Expression, Error, ProvingKey}; use super::Argument; use crate::plonk::evaluation::evaluate; -use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; +use crate::poly::commitment::PolynomialCommitmentScheme; use crate::transcript::{Hashable, Transcript}; use crate::{ poly::{Coeff, EvaluationDomain, LagrangeCoeff, Polynomial, ProverQuery, Rotation}, utils::arithmetic::{eval_polynomial, parallelize}, }; -use ff::{PrimeField, WithSmallOrderMulGroup}; +use ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup}; use group::ff::BatchInvert; use halo2curves::serde::SerdeObject; use rand_core::{CryptoRng, RngCore}; @@ -43,6 +43,7 @@ impl + Ord> Argument { /// obtaining A' and S', and /// - constructs Permuted struct using permuted_input_value = A', and /// permuted_table_expression = S'. + /// /// The Permuted struct is used to update the Lookup, and is then returned. #[allow(clippy::too_many_arguments)] pub(in crate::plonk) fn commit_permuted< @@ -65,6 +66,7 @@ impl + Ord> Argument { transcript: &mut T, ) -> Result, Error> where + F: FromUniformBytes<64> + SerdeObject, CS::Commitment: Hashable, { // Closure to get values of expressions and compress them @@ -74,7 +76,7 @@ impl + Ord> Argument { .map(|expression| { pk.vk.domain.lagrange_from_vec(evaluate( expression, - params.n() as usize, + domain.n as usize, 1, fixed_values, advice_values, @@ -97,7 +99,6 @@ impl + Ord> Argument { // Permute compressed (InputExpression, TableExpression) pair let (permuted_input_expression, permuted_table_expression) = permute_expression_pair( pk, - params, domain, &mut rng, &compressed_input_expression, @@ -107,7 +108,7 @@ impl + Ord> Argument { // Closure to construct commitment to vector of values let commit_values = |values: &Polynomial| { let poly = pk.vk.domain.lagrange_to_coeff(values.clone()); - let commitment = params.commit_lagrange(values); + let commitment = CS::commit_lagrange(params, values); (poly, commitment) }; @@ -152,6 +153,7 @@ impl> Permuted { transcript: &mut T, ) -> Result, Error> where + F: WithSmallOrderMulGroup<3> + FromUniformBytes<64> + SerdeObject, CS::Commitment: Hashable, { let blinding_factors = pk.vk.cs.blinding_factors(); @@ -166,7 +168,7 @@ impl> Permuted { // s_j(X) is the jth table expression in this lookup, // s'(X) is the compression of the permuted table expressions, // and i is the ith row of the expression. - let mut lookup_product = vec![F::ZERO; params.n() as usize]; + let mut lookup_product = vec![F::ZERO; pk.vk.n() as usize]; // Denominator uses the permuted input expression and permuted table expression parallelize(&mut lookup_product, |lookup_product, start| { for ((lookup_product, permuted_input_value), permuted_table_value) in lookup_product @@ -217,11 +219,11 @@ impl> Permuted { }) // Take all rows including the "last" row which should // be a boolean (and ideally 1, else soundness is broken) - .take(params.n() as usize - blinding_factors) + .take(pk.vk.n() as usize - blinding_factors) // Chain random blinding factors. .chain((0..blinding_factors).map(|_| F::random(&mut rng))) .collect::>(); - assert_eq!(z.len(), params.n() as usize); + assert_eq!(z.len(), pk.vk.n() as usize); let z = pk.vk.domain.lagrange_from_vec(z); #[cfg(feature = "sanity-checks")] @@ -229,7 +231,7 @@ impl> Permuted { // It can be used for debugging purposes. { // While in Lagrange basis, check that product is correctly constructed - let u = (params.n() as usize) - (blinding_factors + 1); + let u = (pk.vk.n() as usize) - (blinding_factors + 1); // l_0(X) * (1 - z(X)) = 0 assert_eq!(z[0], F::ONE); @@ -242,15 +244,15 @@ impl> Permuted { let permuted_table_value = &self.permuted_table_expression[i]; - left *= &(*beta + permuted_input_value); - left *= &(*gamma + permuted_table_value); + left *= &(beta + permuted_input_value); + left *= &(gamma + permuted_table_value); let mut right = z[i]; let mut input_term = self.compressed_input_expression[i]; let mut table_term = self.compressed_table_expression[i]; - input_term += &(*beta); - table_term += &(*gamma); + input_term += &(beta); + table_term += &(gamma); right *= &(input_term * &table_term); assert_eq!(left, right); @@ -262,7 +264,7 @@ impl> Permuted { assert_eq!(z[u], F::ONE); } - let product_commitment = params.commit_lagrange(&z); + let product_commitment = CS::commit_lagrange(params, &z); let z = pk.vk.domain.lagrange_to_coeff(z); // Hash product commitment @@ -356,21 +358,20 @@ type ExpressionPair = (Polynomial, Polynomial + Ord, - CS: PolynomialCommitmentScheme, - R: RngCore, ->( +fn permute_expression_pair, R: RngCore>( pk: &ProvingKey, - params: &CS::Parameters, domain: &EvaluationDomain, mut rng: R, input_expression: &Polynomial, table_expression: &Polynomial, -) -> Result, Error> { +) -> Result, Error> +where + F: WithSmallOrderMulGroup<3> + Ord + FromUniformBytes<64> + SerdeObject, +{ let blinding_factors = pk.vk.cs.blinding_factors(); - let usable_rows = params.n() as usize - (blinding_factors + 1); + let usable_rows = pk.vk.n() as usize - (blinding_factors + 1); let mut permuted_input_expression: Vec = input_expression.to_vec(); permuted_input_expression.truncate(usable_rows); @@ -423,8 +424,8 @@ fn permute_expression_pair< permuted_input_expression.extend((0..(blinding_factors + 1)).map(|_| F::random(&mut rng))); permuted_table_coeffs.extend((0..(blinding_factors + 1)).map(|_| F::random(&mut rng))); - assert_eq!(permuted_input_expression.len(), params.n() as usize); - assert_eq!(permuted_table_coeffs.len(), params.n() as usize); + assert_eq!(permuted_input_expression.len(), pk.vk.n() as usize); + assert_eq!(permuted_table_coeffs.len(), pk.vk.n() as usize); #[cfg(feature = "sanity-checks")] { diff --git a/src/plonk/mod.rs b/src/plonk/mod.rs index 318493557b..7366e3aa4b 100644 --- a/src/plonk/mod.rs +++ b/src/plonk/mod.rs @@ -66,15 +66,19 @@ where CS: PolynomialCommitmentScheme, CS::Commitment: SerdeObject, { + /// Returns `n` + pub fn n(&self) -> u64 { + self.domain.n + } /// Writes a verifying key to a buffer. /// /// Writes a curve element according to `format`: /// - `Processed`: Writes a compressed curve element with coordinates in standard form. - /// Writes a field element in standard form, with endianness specified by the - /// `PrimeField` implementation. + /// Writes a field element in standard form, with endianness specified by the + /// `PrimeField` implementation. /// - Otherwise: Writes an uncompressed curve element with coordinates in Montgomery form - /// Writes a field element into raw bytes in its internal Montgomery representation, - /// WITHOUT performing the expensive Montgomery reduction. + /// Writes a field element into raw bytes in its internal Montgomery representation, + /// WITHOUT performing the expensive Montgomery reduction. pub fn write(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> { // Version byte that will be checked on read. writer.write_all(&[VERSION])?; @@ -333,7 +337,7 @@ where /// Writes a curve element according to `format`: /// - `Processed`: Writes a compressed curve element with coordinates in standard form. /// Writes a field element in standard form, with endianness specified by the - /// `PrimeField` implementation. + /// `PrimeField` implementation. /// - Otherwise: Writes an uncompressed curve element with coordinates in Montgomery form /// Writes a field element into raw bytes in its internal Montgomery representation, /// WITHOUT performing the expensive Montgomery reduction. diff --git a/src/plonk/permutation/keygen.rs b/src/plonk/permutation/keygen.rs index 93b8118dd6..c378eb074b 100644 --- a/src/plonk/permutation/keygen.rs +++ b/src/plonk/permutation/keygen.rs @@ -8,12 +8,15 @@ use crate::{ }; #[cfg(feature = "thread-safe-region")] -use crate::utils::multicore::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; +use { + ff::PrimeField, + rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}, +}; #[cfg(not(feature = "thread-safe-region"))] -use crate::utils::multicore::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; +use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; -use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; +use crate::poly::commitment::PolynomialCommitmentScheme; use rayon::iter::IntoParallelRefMutIterator; #[cfg(feature = "thread-safe-region")] use std::collections::{BTreeSet, HashMap}; @@ -113,20 +116,19 @@ impl Assembly { pub(crate) fn build_vk, CS: PolynomialCommitmentScheme>( self, - params: &CS::VerifierParameters, + params: &CS::Parameters, domain: &EvaluationDomain, p: &Argument, ) -> VerifyingKey { build_vk(params, domain, p, |i, j| self.mapping[i][j]) } - pub(crate) fn build_pk, CS: PolynomialCommitmentScheme>( + pub(crate) fn build_pk>( self, - params: &CS::Parameters, domain: &EvaluationDomain, p: &Argument, ) -> ProvingKey { - build_pk::<_, CS>(params, domain, p, |i, j| self.mapping[i][j]) + build_pk::<_>(domain, p, |i, j| self.mapping[i][j]) } /// Returns columns that participate in the permutation argument. @@ -240,8 +242,6 @@ impl Assembly { /// Builds the ordered mapping of the cycles. /// This will only get executed once. pub fn build_ordered_mapping(&mut self) { - use crate::multicore::IntoParallelRefMutIterator; - // will only get called once if self.ordered_cycles.is_empty() && !self.cycles.is_empty() { self.ordered_cycles = self @@ -282,9 +282,12 @@ impl Assembly { } } - pub(crate) fn build_vk>( + pub(crate) fn build_vk< + F: PrimeField + WithSmallOrderMulGroup<3>, + CS: PolynomialCommitmentScheme, + >( &mut self, - params: &CS::VerifierParameters, + params: &CS::Parameters, domain: &EvaluationDomain, p: &Argument, ) -> VerifyingKey { @@ -292,14 +295,13 @@ impl Assembly { build_vk(params, domain, p, |i, j| self.mapping_at_idx(i, j)) } - pub(crate) fn build_pk>( + pub(crate) fn build_pk>( &mut self, - params: &CS::Parameters, domain: &EvaluationDomain, p: &Argument, ) -> ProvingKey { self.build_ordered_mapping(); - build_pk(params, domain, p, |i, j| self.mapping_at_idx(i, j)) + build_pk(domain, p, |i, j| self.mapping_at_idx(i, j)) } /// Returns columns that participate in the permutation argument. @@ -319,14 +321,13 @@ impl Assembly { } } -pub(crate) fn build_pk, CS: PolynomialCommitmentScheme>( - params: &CS::Parameters, +pub(crate) fn build_pk>( domain: &EvaluationDomain, p: &Argument, mapping: impl Fn(usize, usize) -> (usize, usize) + Sync, ) -> ProvingKey { // Compute [omega^0, omega^1, ..., omega^{params.n - 1}] - let mut omega_powers = vec![F::ZERO; params.n() as usize]; + let mut omega_powers = vec![F::ZERO; domain.n as usize]; { let omega = domain.get_omega(); parallelize(&mut omega_powers, |o, start| { @@ -401,13 +402,13 @@ pub(crate) fn build_pk, CS: PolynomialCommitmentSch } pub(crate) fn build_vk, CS: PolynomialCommitmentScheme>( - params: &CS::VerifierParameters, + params: &CS::Parameters, domain: &EvaluationDomain, p: &Argument, mapping: impl Fn(usize, usize) -> (usize, usize) + Sync, ) -> VerifyingKey { // Compute [omega^0, omega^1, ..., omega^{params.n - 1}] - let mut omega_powers = vec![F::ZERO; params.n() as usize]; + let mut omega_powers = vec![F::ZERO; domain.n as usize]; { let omega = domain.get_omega(); parallelize(&mut omega_powers, |o, start| { @@ -452,7 +453,7 @@ pub(crate) fn build_vk, CS: PolynomialCommitmentSch let mut commitments = Vec::with_capacity(p.columns.len()); for permutation in &permutations { // Compute commitment to permutation polynomial - commitments.push(params.commit_lagrange(permutation)); + commitments.push(CS::commit_lagrange(params, permutation)); } VerifyingKey { commitments } diff --git a/src/plonk/permutation/prover.rs b/src/plonk/permutation/prover.rs index 2e6e3e9707..4a15799263 100644 --- a/src/plonk/permutation/prover.rs +++ b/src/plonk/permutation/prover.rs @@ -6,7 +6,7 @@ use std::iter::{self, ExactSizeIterator}; use super::super::circuit::Any; use super::{Argument, ProvingKey}; -use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; +use crate::poly::commitment::PolynomialCommitmentScheme; use crate::transcript::{Hashable, Transcript}; use crate::{ plonk::{self, Error}, @@ -80,7 +80,7 @@ impl Argument { // where p_j(X) is the jth column in this permutation, // and i is the ith row of the column. - let mut modified_values = vec![F::ONE; params.n() as usize]; + let mut modified_values = vec![F::ONE; domain.n as usize]; // Iterate over each column of the permutation for (&column, permuted_column_values) in columns.iter().zip(permutations.iter()) { @@ -138,7 +138,7 @@ impl Argument { // Compute the evaluations of the permutation product polynomial // over our domain, starting with z[0] = 1 let mut z = vec![last_z]; - for row in 1..(params.n() as usize) { + for row in 1..(domain.n as usize) { let mut tmp = z[row - 1]; tmp *= &modified_values[row - 1]; @@ -146,13 +146,13 @@ impl Argument { } let mut z = domain.lagrange_from_vec(z); // Set blinding factors - for z in &mut z[params.n() as usize - blinding_factors..] { + for z in &mut z[domain.n as usize - blinding_factors..] { *z = F::random(&mut rng); } // Set new last_z - last_z = z[params.n() as usize - (blinding_factors + 1)]; + last_z = z[domain.n as usize - (blinding_factors + 1)]; - let permutation_product_commitment = params.commit_lagrange(&z); + let permutation_product_commitment = CS::commit_lagrange(params, &z); let permutation_product_poly = domain.lagrange_to_coeff(z); // Hash the permutation product commitment diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 18fea4c94a..64122509c7 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -1,4 +1,4 @@ -use ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use ff::{Field, FromUniformBytes, PrimeField, WithSmallOrderMulGroup}; use rand_core::{CryptoRng, RngCore}; use std::collections::{BTreeSet, HashSet}; use std::ops::RangeTo; @@ -22,7 +22,7 @@ use crate::{ use crate::circuit::Value; use crate::poly::batch_invert_rational; -use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; +use crate::poly::commitment::PolynomialCommitmentScheme; use crate::transcript::{Hashable, Sampleable, Transcript}; use crate::utils::rational::Rational; use halo2curves::serde::SerdeObject; @@ -32,7 +32,7 @@ use halo2curves::serde::SerdeObject; /// generated previously for the same circuit. The provided `instances` /// are zero-padded internally. pub fn create_proof< - F: WithSmallOrderMulGroup<3>, + F, CS: PolynomialCommitmentScheme, T: Transcript, ConcreteCircuit: Circuit, @@ -46,7 +46,12 @@ pub fn create_proof< ) -> Result<(), Error> where CS::Commitment: Hashable + SerdeObject, - F: Sampleable + Hashable + SerdeObject + Ord, + F: WithSmallOrderMulGroup<3> + + Sampleable + + Hashable + + SerdeObject + + Ord + + FromUniformBytes<64>, { if circuits.len() != instances.len() { return Err(Error::InvalidInstances); @@ -84,7 +89,7 @@ where .iter() .map(|values| { let mut poly = domain.empty_lagrange(); - assert_eq!(poly.len(), params.n() as usize); + assert_eq!(poly.len(), domain.n as usize); if values.len() > (poly.len() - (meta.blinding_factors() + 1)) { return Err(Error::InstanceTooLarge); } @@ -270,7 +275,7 @@ where ]; let mut challenges = HashMap::::with_capacity(meta.num_challenges); - let unusable_rows_start = params.n() as usize - (meta.blinding_factors() + 1); + let unusable_rows_start = domain.n as usize - (meta.blinding_factors() + 1); for current_phase in pk.vk.cs.phases() { let column_indices = meta .advice_column_phase @@ -289,7 +294,7 @@ where circuits.iter().zip(advice.iter_mut()).zip(instances) { let mut witness = WitnessCollection { - k: params.k(), + k: domain.k(), current_phase, advice: vec![domain.empty_lagrange_rational(); meta.num_advice_columns], unblinded_advice: HashSet::from_iter(meta.unblinded_advice_columns.clone()), @@ -341,7 +346,7 @@ where let advice_commitments: Vec<_> = advice_values .iter() - .map(|poly| params.commit_lagrange(poly)) + .map(|poly| CS::commit_lagrange(params, poly)) .collect(); for commitment in &advice_commitments { @@ -605,9 +610,9 @@ fn test_create_proof() { } } - let params: ParamsKZG = KZGCommitmentScheme::setup(3); + let params: ParamsKZG = ParamsKZG::unsafe_setup(3, OsRng); let vk = keygen_vk(¶ms, &MyCircuit).expect("keygen_vk should not fail"); - let pk = keygen_pk(¶ms, vk, &MyCircuit).expect("keygen_pk should not fail"); + let pk = keygen_pk(vk, &MyCircuit).expect("keygen_pk should not fail"); let mut transcript = CircuitTranscript::<_>::init(); // Create proof with wrong number of instances diff --git a/src/plonk/vanishing/prover.rs b/src/plonk/vanishing/prover.rs index b284d99117..116149e0d9 100644 --- a/src/plonk/vanishing/prover.rs +++ b/src/plonk/vanishing/prover.rs @@ -6,15 +6,16 @@ use rand_chacha::ChaCha20Rng; use rand_core::{RngCore, SeedableRng}; use super::Argument; -use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; +use crate::poly::commitment::PolynomialCommitmentScheme; use crate::transcript::{Hashable, Transcript}; use crate::{ plonk::Error, poly::{Coeff, EvaluationDomain, ExtendedLagrangeCoeff, Polynomial, ProverQuery}, utils::arithmetic::{eval_polynomial, parallelize}, - utils::multicore::current_num_threads, }; +use rayon::current_num_threads; + pub(in crate::plonk) struct Committed { random_poly: Polynomial, } @@ -98,7 +99,7 @@ impl> Committed { // Split h(X) up into pieces let h_pieces = h_poly - .chunks_exact(params.n() as usize) + .chunks_exact(domain.n as usize) .map(|v| domain.coeff_from_vec(v.to_vec())) .collect::>(); drop(h_poly); diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index 974a0a1ccb..fed4e7912a 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -1,25 +1,25 @@ -use ff::WithSmallOrderMulGroup; +use ff::{FromUniformBytes, WithSmallOrderMulGroup}; use halo2curves::serde::SerdeObject; use std::iter; use super::{vanishing, Error, VerifyingKey}; -use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; +use crate::poly::commitment::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< - F: WithSmallOrderMulGroup<3> + Hashable + Sampleable + SerdeObject, - CS: PolynomialCommitmentScheme, - T: Transcript, ->( - params: &CS::VerifierParameters, +/// Prepares a plonk proof into a PCS instance that can be finalized or batched. +pub fn prepare, T: Transcript>( vk: &VerifyingKey, instances: &[&[&[F]]], transcript: &mut T, -) -> Result<(), Error> +) -> Result where + F: WithSmallOrderMulGroup<3> + + Hashable + + Sampleable + + SerdeObject + + FromUniformBytes<64>, CS::Commitment: Hashable + SerdeObject, { // Check that instances matches the expected number of instance columns @@ -120,7 +120,7 @@ where // satisfied with high probability. let x: F = transcript.squeeze_challenge(); let instance_evals = { - let xn = x.pow([params.n()]); + let xn = x.pow([vk.n()]); let (min_rotation, max_rotation) = vk.cs .instance_queries @@ -189,7 +189,7 @@ where // commitments open to the correct values. let vanishing = { // x^n - let xn = x.pow([params.n()]); + let xn = x.pow([vk.n()]); let blinding_factors = vk.cs.blinding_factors(); let l_evals = vk @@ -211,7 +211,7 @@ where .flat_map(|(((advice_evals, instance_evals), permutation), lookups)| { let challenges = &challenges; let fixed_evals = &fixed_evals; - std::iter::empty() + iter::empty() // Evaluate the circuit using the custom gates provided .chain(vk.cs.gates.iter().flat_map(move |gate| { gate.polynomials().iter().map(move |poly| { @@ -304,5 +304,5 @@ where // We are now convinced the circuit is satisfied so long as the // polynomial commitments open to the correct values. - CS::verify(params, queries, transcript).map_err(|_| Error::Opening) + CS::prepare(queries, transcript).map_err(|_| Error::Opening) } diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index c21c53fa35..af755d9c9c 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -8,20 +8,33 @@ use std::fmt::Debug; /// Public interface for a Polynomial Commitment Scheme (PCS) pub trait PolynomialCommitmentScheme: Clone + Debug { /// Parameters needed to generate a proof in the PCS - type Parameters: Params; + type Parameters: Params; /// Parameters needed to verify a proof in the PCS - type VerifierParameters: Params; + type VerifierParameters; /// Type of a committed polynomial type Commitment: Clone + Copy + Debug + Default + PartialEq + ProcessedSerdeObject + Send + Sync; - /// Setup the parameters for the PCS - fn setup(k: u32) -> Self::Parameters; + /// Verification guard. Allows for batch verification + type VerificationGuard: Guard; + + /// Generates the parameters of the polynomial commitment scheme + fn gen_params(k: u32) -> Self::Parameters; + + /// Extract the `VerifierParameters` from `Parameters` + fn get_verifier_params(params: &Self::Parameters) -> Self::VerifierParameters; /// Commit to a polynomial in coefficient form fn commit(params: &Self::Parameters, polynomial: &Polynomial) -> Self::Commitment; + /// Commit to a polynomial expressed in Lagrange evaluations form (over the underlying domain + /// specified in params). + fn commit_lagrange( + params: &Self::Parameters, + poly: &Polynomial, + ) -> Self::Commitment; + /// Create an opening proof at a specific query fn open<'com, T: Transcript, I>( params: &Self::Parameters, @@ -34,27 +47,38 @@ pub trait PolynomialCommitmentScheme: Clone + Debug { Self::Commitment: Hashable; /// Verify an opening proof at a given query - fn verify( - params: &Self::VerifierParameters, + fn prepare( verifier_query: I, transcript: &mut T, - ) -> Result<(), Error> + ) -> Result where I: IntoIterator> + Clone, - F: Sampleable, // This is not necessarily part of a PCS + F: Sampleable, Self::Commitment: Hashable; } -/// Interface for prover/verifier params -pub trait Params> { - /// Logarithmic size of polynomials that can be committed with these parameters - fn k(&self) -> u32; +/// Interface for verifier finalizer +pub trait Guard>: Sized { + /// Finalize the verification guard + fn verify(self, params: &CS::VerifierParameters) -> Result<(), Error>; - /// Size of polynomials that can be committed with these parameters - fn n(&self) -> u64; + /// Finalize a batch of verification guards + fn batch_verify<'a, I, J>(guards: I, params: J) -> Result<(), Error> + where + I: ExactSizeIterator, + J: ExactSizeIterator, + CS::VerifierParameters: 'a, + { + assert_eq!(guards.len(), params.len()); + guards + .into_iter() + .zip(params) + .try_for_each(|(guard, params)| guard.verify(params)) + } +} - /// This commits to a polynomial using its evaluations over the $2^k$ size - /// evaluation domain. The commitment will be blinded by the blinding factor - /// `r`. - fn commit_lagrange(&self, poly: &Polynomial) -> CS::Commitment; +/// Interface for PCS params +pub trait Params { + /// Returns the max size of polynomials that these parameters can commit to + fn max_k(&self) -> u32; } diff --git a/src/poly/domain.rs b/src/poly/domain.rs index bc181baa6d..54b06bbd28 100644 --- a/src/poly/domain.rs +++ b/src/poly/domain.rs @@ -16,7 +16,7 @@ use std::marker::PhantomData; /// domain of size $2^{k} * j$ with $j \neq 0$. #[derive(Clone, Debug)] pub struct EvaluationDomain { - n: u64, + pub(crate) n: u64, k: u32, extended_k: u32, omega: F, diff --git a/src/poly/kzg/mod.rs b/src/poly/kzg/mod.rs index 3b8af9d471..cca1aa09b2 100644 --- a/src/poly/kzg/mod.rs +++ b/src/poly/kzg/mod.rs @@ -12,17 +12,19 @@ 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::poly::{Coeff, Error, LagrangeCoeff, Polynomial, ProverQuery}; use crate::utils::arithmetic::{kate_division, powers, MSM}; use crate::poly::commitment::PolynomialCommitmentScheme; use crate::transcript::{Hashable, Sampleable, Transcript}; use ff::Field; use group::prime::PrimeCurveAffine; +use group::Group; use halo2curves::msm::msm_best; use halo2curves::pairing::MultiMillerLoop; use halo2curves::serde::SerdeObject; use halo2curves::CurveAffine; +use rand_core::OsRng; #[derive(Clone, Debug)] /// KZG verifier @@ -38,10 +40,14 @@ where type Parameters = ParamsKZG; type VerifierParameters = ParamsVerifierKZG; type Commitment = E::G1Affine; + type VerificationGuard = DualMSM; - /// Unsafe function - do not use in production - fn setup(k: u32) -> ParamsKZG { - ParamsKZG::new(k) + fn gen_params(k: u32) -> Self::Parameters { + ParamsKZG::unsafe_setup(k, OsRng) + } + + fn get_verifier_params(params: &Self::Parameters) -> Self::VerifierParameters { + params.verifier_params() } fn commit( @@ -56,6 +62,18 @@ where msm_best(&scalars, &bases[0..size]).into() } + fn commit_lagrange( + params: &Self::Parameters, + poly: &Polynomial, + ) -> E::G1Affine { + let mut scalars = Vec::with_capacity(poly.len()); + scalars.extend(poly.iter()); + let bases = ¶ms.g_lagrange; + let size = scalars.len(); + assert!(bases.len() >= size); + msm_best(&scalars, &bases[0..size]).into() + } + fn open<'com, T: Transcript, I>( params: &Self::Parameters, prover_query: I, @@ -99,11 +117,7 @@ where Ok(()) } - fn verify( - params: &Self::VerifierParameters, - verifier_query: I, - transcript: &mut T, - ) -> Result<(), Error> + fn prepare(verifier_query: I, transcript: &mut T) -> Result, Error> where E::Fr: Sampleable, E::G1Affine: Hashable, @@ -159,20 +173,16 @@ where witness.append_term(power_of_u, wi.to_curve()); } - let mut msm = DualMSM::new(params); + let mut msm = DualMSM::new(); msm.left.add_msm(&witness); msm.right.add_msm(&witness_with_aux); msm.right.add_msm(&commitment_multi); - let g0: E::G1 = params.g[0].to_curve(); + let g0 = E::G1::generator(); msm.right.append_term(eval_multi, -g0); - if msm.check() { - Ok(()) - } else { - Err(Error::OpeningError) - } + Ok(msm) } } @@ -212,7 +222,7 @@ where #[cfg(test)] mod tests { - use crate::poly::commitment::PolynomialCommitmentScheme; + use crate::poly::commitment::{Guard, PolynomialCommitmentScheme}; use crate::poly::kzg::params::{ParamsKZG, ParamsVerifierKZG}; use crate::poly::kzg::KZGCommitmentScheme; use crate::poly::{ @@ -226,21 +236,22 @@ mod tests { use halo2curves::pairing::{Engine, MultiMillerLoop}; use halo2curves::serde::SerdeObject; use halo2curves::CurveAffine; + use rand_core::OsRng; #[test] fn test_roundtrip_gwc() { - use crate::poly::kzg::KZGCommitmentScheme; use halo2curves::bn256::Bn256; const K: u32 = 4; - let params = KZGCommitmentScheme::::setup(K); + let params: ParamsKZG = ParamsKZG::unsafe_setup(K, OsRng); let proof = create_proof::<_, CircuitTranscript>(¶ms); - verify::<_, CircuitTranscript>(¶ms, &proof[..], false); + let verifier_params = params.verifier_params(); + verify::<_, CircuitTranscript>(&verifier_params, &proof[..], false); - verify::>(¶ms, &proof[..], true); + verify::>(&verifier_params, &proof[..], true); } fn verify( @@ -282,13 +293,13 @@ mod tests { valid_queries }; - let result = KZGCommitmentScheme::verify(verifier_params, queries, &mut transcript) - .map_err(|_| Error::OpeningError); + let result = + KZGCommitmentScheme::prepare(queries, &mut transcript).map_err(|_| Error::OpeningError); if should_fail { - assert!(result.is_err()); + assert!(result.unwrap().verify(verifier_params).is_err()); } else { - assert!(result.is_ok()); + assert!(result.unwrap().verify(verifier_params).is_ok()); } } @@ -300,7 +311,8 @@ mod tests { + Default + CurveAffine, { - let domain = EvaluationDomain::new(1, kzg_params.k); + let k = (kzg_params.g.len() - 1).ilog2() + 1; + let domain = EvaluationDomain::new(1, k); let mut ax = domain.empty_coeff(); for (i, a) in ax.iter_mut().enumerate() { diff --git a/src/poly/kzg/msm.rs b/src/poly/kzg/msm.rs index 84bf039efb..f8d12b839a 100644 --- a/src/poly/kzg/msm.rs +++ b/src/poly/kzg/msm.rs @@ -1,13 +1,18 @@ use std::fmt::Debug; -use super::params::ParamsKZG; +use super::params::ParamsVerifierKZG; +use crate::poly::commitment::{Guard, PolynomialCommitmentScheme}; +use crate::poly::kzg::KZGCommitmentScheme; +use crate::poly::Error; use crate::utils::arithmetic::parallelize; use crate::utils::arithmetic::MSM; +use group::prime::PrimeCurveAffine; use group::{Curve, Group}; use halo2curves::msm::msm_best; +use halo2curves::serde::SerdeObject; use halo2curves::{ pairing::{Engine, MillerLoopResult, MultiMillerLoop}, - CurveAffine, CurveExt, + CurveAffine, }; /// A multiscalar multiplication in the polynomial commitment scheme @@ -68,7 +73,6 @@ where } fn eval(&self) -> E::G1 { - use group::prime::PrimeCurveAffine; let mut bases = vec![E::G1Affine::identity(); self.scalars.len()]; E::G1::batch_normalize(&self.bases, &mut bases); msm_best(&self.scalars, &bases) @@ -83,32 +87,42 @@ where } } -impl<'params, E: MultiMillerLoop + Debug> From<&'params ParamsKZG> for DualMSM<'params, E> +/// Two channel MSM accumulator +#[derive(Debug, Clone)] +pub struct DualMSM { + pub(crate) left: MSMKZG, + pub(crate) right: MSMKZG, +} + +impl Default for DualMSM where - E::G1Affine: CurveAffine::Fr, CurveExt = ::G1>, - E::G1: CurveExt, + E::G1Affine: CurveAffine, { - fn from(params: &'params ParamsKZG) -> Self { - DualMSM::new(params) + fn default() -> Self { + Self::new() } } -/// Two channel MSM accumulator -#[derive(Debug, Clone)] -pub struct DualMSM<'a, E: Engine> { - pub(crate) params: &'a ParamsKZG, - pub(crate) left: MSMKZG, - pub(crate) right: MSMKZG, +impl Guard> for DualMSM +where + E::Fr: SerdeObject, + E::G1Affine: Default + SerdeObject + CurveAffine, +{ + fn verify( + self, + params: & as PolynomialCommitmentScheme>::VerifierParameters, + ) -> Result<(), Error> { + self.check(params).then_some(()).ok_or(Error::OpeningError) + } } -impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E> +impl DualMSM where E::G1Affine: CurveAffine, { /// Create a new two channel MSM accumulator instance - pub fn new(params: &'a ParamsKZG) -> Self { + pub fn new() -> Self { Self { - params, left: MSMKZG::new(), right: MSMKZG::new(), } @@ -127,9 +141,9 @@ where } /// Performs final pairing check with given verifier params and two channel linear combination - pub fn check(self) -> bool { - let s_g2_prepared = E::G2Prepared::from(self.params.s_g2); - let n_g2_prepared = E::G2Prepared::from(-self.params.g2); + pub fn check(self, params: &ParamsVerifierKZG) -> bool { + let s_g2_prepared = E::G2Prepared::from(params.s_g2); + let n_g2_prepared = E::G2Prepared::from(-E::G2Affine::generator()); let left = self.left.eval(); let right = self.right.eval(); diff --git a/src/poly/kzg/params.rs b/src/poly/kzg/params.rs index 31ecb14ad6..454c10acac 100644 --- a/src/poly/kzg/params.rs +++ b/src/poly/kzg/params.rs @@ -1,61 +1,38 @@ -use crate::poly::{LagrangeCoeff, Polynomial}; use crate::utils::arithmetic::{g_to_lagrange, parallelize}; use crate::utils::SerdeFormat; use ff::{Field, PrimeField}; use group::{prime::PrimeCurveAffine, Curve, Group}; -use halo2curves::pairing::{Engine, MultiMillerLoop}; -use rand_core::{OsRng, RngCore}; +use halo2curves::pairing::Engine; +use rand_core::RngCore; 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 super::msm::MSMKZG; - /// These are the public parameters for the polynomial commitment scheme. #[derive(Debug, Clone)] pub struct ParamsKZG { - pub(crate) k: u32, - pub(crate) n: u64, pub(crate) g: Vec, pub(crate) g_lagrange: Vec, pub(crate) g2: E::G2Affine, pub(crate) s_g2: E::G2Affine, } -impl Params> for ParamsKZG -where - E::Fr: SerdeObject, - E::G1Affine: Default + SerdeObject + CurveAffine, -{ - fn k(&self) -> u32 { - self.k - } +impl Params for ParamsKZG { + fn max_k(&self) -> u32 { + assert_eq!(self.g.len(), self.g_lagrange.len()); - fn n(&self) -> u64 { - self.n - } - - fn commit_lagrange(&self, poly: &Polynomial) -> E::G1Affine { - let mut scalars = Vec::with_capacity(poly.len()); - scalars.extend(poly.iter()); - let bases = &self.g_lagrange; - let size = scalars.len(); - assert!(bases.len() >= size); - msm_best(&scalars, &bases[0..size]).into() + self.g.len().ilog2() } } impl ParamsKZG { /// Initializes parameters for the curve, draws toxic secret from given rng. /// MUST NOT be used in production. - pub fn setup(k: u32, rng: R) -> Self { + pub fn unsafe_setup(k: u32, rng: R) -> Self { // 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); @@ -115,8 +92,6 @@ impl ParamsKZG { let s_g2 = (g2 * s).into(); Self { - k, - n, g, g_lagrange, g2, @@ -135,8 +110,6 @@ impl ParamsKZG { s_g2: E::G2Affine, ) -> Self { Self { - k, - n: 1 << k, g_lagrange: match g_lagrange { Some(g_l) => g_l, None => g_to_lagrange(g.iter().map(PrimeCurveAffine::to_curve).collect(), k), @@ -163,7 +136,7 @@ impl ParamsKZG { E::G1Affine: CurveAffine + ProcessedSerdeObject, E::G2Affine: CurveAffine + ProcessedSerdeObject, { - writer.write_all(&self.k.to_le_bytes())?; + writer.write_all(&(self.g.len() as u64).to_le_bytes())?; for el in self.g.iter() { el.write(writer, format)?; } @@ -181,10 +154,9 @@ impl ParamsKZG { E::G1Affine: CurveAffine + ProcessedSerdeObject, E::G2Affine: CurveAffine + ProcessedSerdeObject, { - let mut k = [0u8; 4]; - reader.read_exact(&mut k[..])?; - let k = u32::from_le_bytes(k); - let n = 1 << k; + let mut n = [0u8; 8]; + reader.read_exact(&mut n[..])?; + let n = u64::from_le_bytes(n) as usize; let (g, g_lagrange) = match format { SerdeFormat::Processed => { @@ -253,8 +225,6 @@ impl ParamsKZG { let s_g2 = E::G2Affine::read(reader, format)?; Ok(Self { - k, - n: n as u64, g, g_lagrange, g2, @@ -266,72 +236,45 @@ impl ParamsKZG { // TODO: see the issue at https://github.com/appliedzkp/halo2/issues/45 // So we probably need much smaller verifier key. However for new bases in g1 should be in verifier keys. /// KZG multi-open verification parameters -pub type ParamsVerifierKZG = ParamsKZG; +#[derive(Debug)] +pub struct ParamsVerifierKZG { + pub(crate) s_g2: E::G2Affine, +} -impl<'params, E: Engine + Debug> ParamsKZG +impl ParamsVerifierKZG where E::G1Affine: CurveAffine + ProcessedSerdeObject, E::G2Affine: CurveAffine + ProcessedSerdeObject, { - /// TODO - pub fn k(&self) -> u32 { - self.k - } - - /// TODO - pub fn n(&self) -> u64 { - self.n - } - - /// TODO - pub fn downsize(&mut self, k: u32) { - assert!(k <= self.k); - - self.k = k; - self.n = 1 << k; - - self.g.truncate(self.n as usize); - self.g_lagrange = g_to_lagrange(self.g.iter().map(|g| g.to_curve()).collect(), k); - } - - /// TODO - pub fn empty_msm(&'params self) -> MSMKZG { - MSMKZG::new() - } - - /// Writes params to a buffer. - pub fn write(&self, writer: &mut W) -> io::Result<()> { - self.write_custom(writer, SerdeFormat::RawBytes) + /// Writes parameters to buffer + pub fn write(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> { + self.s_g2.write(writer, format)?; + Ok(()) } /// Reads params from a buffer. - pub fn read(reader: &mut R) -> io::Result { - Self::read_custom(reader, SerdeFormat::RawBytes) - } -} - -impl<'params, E: Engine + Debug> ParamsKZG { - /// TODO - pub fn verifier_params(&'params self) -> &'params ParamsVerifierKZG { - self - } + pub fn read(reader: &mut R, format: SerdeFormat) -> io::Result { + let s_g2 = E::G2Affine::read(reader, format)?; - /// UNSAFE function - do not use in production - pub fn new(k: u32) -> Self { - Self::setup(k, OsRng) + Ok(Self { s_g2 }) } +} - /// TODO - pub fn get_g(&self) -> &[E::G1Affine] { - &self.g +impl ParamsKZG { + /// Consume the prover parameters into verifier parameters. Need to specify the size of + /// public inputs. + pub fn verifier_params(&self) -> ParamsVerifierKZG { + ParamsVerifierKZG { s_g2: self.s_g2 } } } #[cfg(test)] mod test { - use crate::poly::commitment::{Params, PolynomialCommitmentScheme}; + use crate::poly::commitment::PolynomialCommitmentScheme; use crate::poly::kzg::params::ParamsKZG; use crate::poly::kzg::KZGCommitmentScheme; + use crate::utils::SerdeFormat; + use rand_core::OsRng; #[test] fn test_commit_lagrange() { @@ -340,7 +283,7 @@ mod test { use crate::poly::EvaluationDomain; use halo2curves::bn256::{Bn256, Fr}; - let params = ParamsKZG::::new(K); + let params: ParamsKZG = ParamsKZG::unsafe_setup(K, OsRng); let domain = EvaluationDomain::new(1, K); let mut a = domain.empty_lagrange(); @@ -351,7 +294,7 @@ mod test { let b = domain.lagrange_to_coeff(a.clone()); - let tmp = params.commit_lagrange(&a); + let tmp = KZGCommitmentScheme::commit_lagrange(¶ms, &a); let commitment = KZGCommitmentScheme::commit(¶ms, &b); assert_eq!(commitment, tmp); @@ -363,13 +306,13 @@ mod test { use crate::halo2curves::bn256::Bn256; - let params0 = ParamsKZG::::new(K); + let params0: ParamsKZG = ParamsKZG::unsafe_setup(K, OsRng); let mut data = vec![]; - ParamsKZG::write(¶ms0, &mut data).unwrap(); - let params1 = ParamsKZG::::read::<_>(&mut &data[..]).unwrap(); + ParamsKZG::write_custom(¶ms0, &mut data, SerdeFormat::RawBytesUnchecked).unwrap(); + let params1 = + ParamsKZG::::read_custom::<_>(&mut &data[..], SerdeFormat::RawBytesUnchecked) + .unwrap(); - assert_eq!(params0.k, params1.k); - assert_eq!(params0.n, params1.n); assert_eq!(params0.g.len(), params1.g.len()); assert_eq!(params0.g_lagrange.len(), params1.g_lagrange.len()); diff --git a/src/poly/mod.rs b/src/poly/mod.rs index d6ded960d4..7b60626a25 100644 --- a/src/poly/mod.rs +++ b/src/poly/mod.rs @@ -59,8 +59,8 @@ impl Basis for ExtendedLagrangeCoeff {} /// basis. #[derive(Clone, Debug)] pub struct Polynomial { - values: Vec, - _marker: PhantomData, + pub(crate) values: Vec, + pub(crate) _marker: PhantomData, } impl Index for Polynomial { @@ -197,7 +197,7 @@ pub(crate) fn batch_invert_rational( impl Polynomial, LagrangeCoeff> { pub(crate) fn invert( &self, - inv_denoms: impl Iterator + ExactSizeIterator, + inv_denoms: impl ExactSizeIterator, ) -> Polynomial { assert_eq!(inv_denoms.len(), self.values.len()); Polynomial { diff --git a/src/transcript/implementors.rs b/src/transcript/implementors.rs new file mode 100644 index 0000000000..7b171bb834 --- /dev/null +++ b/src/transcript/implementors.rs @@ -0,0 +1,54 @@ +use crate::transcript::{ + Hashable, Sampleable, TranscriptHash, BLAKE2B_PREFIX_CHALLENGE, BLAKE2B_PREFIX_COMMON, +}; +use blake2b_simd::{Params, State as Blake2bState}; +use ff::FromUniformBytes; +use group::GroupEncoding; +use halo2curves::bn256::{Fr, G1Affine}; + +impl TranscriptHash for Blake2bState { + type Input = Vec; + type Output = Vec; + + fn init() -> Self { + Params::new() + .hash_length(64) + .key(b"Domain separator for transcript") + .to_state() + } + + fn absorb(&mut self, input: &Self::Input) -> &mut Self { + self.update(&[BLAKE2B_PREFIX_COMMON]); + self.update(input) + } + + fn squeeze(&mut self) -> Self::Output { + self.update(&[BLAKE2B_PREFIX_CHALLENGE]); + self.finalize().as_bytes().to_vec() + } +} + +/////////////////////////////////////////////////// +/// Implementation of Hashable for BN with Blake // +/////////////////////////////////////////////////// + +impl Hashable for G1Affine { + fn to_input(&self) -> Vec { + self.to_bytes().as_ref().to_vec() + } +} + +impl Hashable for Fr { + fn to_input(&self) -> Vec { + self.to_bytes().to_vec() + } +} + +impl Sampleable for Fr { + fn sample(out: Vec) -> Self { + assert!(out.len() <= 64); + let mut bytes = [0u8; 64]; + bytes[..out.len()].copy_from_slice(&out); + Fr::from_uniform_bytes(&bytes) + } +} diff --git a/src/transcript/mod.rs b/src/transcript/mod.rs index 0850f373af..ace81739a4 100644 --- a/src/transcript/mod.rs +++ b/src/transcript/mod.rs @@ -1,10 +1,7 @@ //! This module contains utilities and traits for dealing with Fiat-Shamir //! transcripts. -use blake2b_simd::{Params, State as Blake2bState}; +mod implementors; -use ff::FromUniformBytes; -use group::GroupEncoding; -use halo2curves::bn256::{Fr, G1Affine}; use halo2curves::serde::SerdeObject; use std::io::{self, Cursor}; @@ -121,53 +118,6 @@ impl Transcript for CircuitTranscript { } } -impl TranscriptHash for Blake2bState { - type Input = Vec; - type Output = Vec; - - fn init() -> Self { - Params::new() - .hash_length(64) - .key(b"Domain separator for transcript") - .to_state() - } - - fn absorb(&mut self, input: &Self::Input) -> &mut Self { - self.update(&[BLAKE2B_PREFIX_COMMON]); - self.update(input) - } - - fn squeeze(&mut self) -> Self::Output { - self.update(&[BLAKE2B_PREFIX_CHALLENGE]); - self.finalize().as_bytes().to_vec() - } -} - -/////////////////////////////////////////////////// -/// Implementation of Hashable for BN with Blake // -/////////////////////////////////////////////////// - -impl Hashable for G1Affine { - fn to_input(&self) -> Vec { - self.to_bytes().as_ref().to_vec() - } -} - -impl Hashable for Fr { - fn to_input(&self) -> Vec { - self.to_bytes().to_vec() - } -} - -impl Sampleable for Fr { - fn sample(out: Vec) -> Self { - assert!(out.len() <= 64); - let mut bytes = [0u8; 64]; - bytes[..out.len()].copy_from_slice(&out); - Fr::from_uniform_bytes(&bytes) - } -} - pub(crate) fn read_n(transcript: &mut T, n: usize) -> io::Result> where T: Transcript, diff --git a/src/utils/arithmetic.rs b/src/utils/arithmetic.rs index e831b19f59..697e3a02c8 100644 --- a/src/utils/arithmetic.rs +++ b/src/utils/arithmetic.rs @@ -1,7 +1,6 @@ //! This module provides common utilities, traits and structures for group, //! field and polynomial arithmetic. -use super::multicore; pub use ff::Field; use group::prime::PrimeCurveAffine; use group::{ @@ -63,13 +62,13 @@ pub fn eval_polynomial(poly: &[F], point: F) -> F { .fold(F::ZERO, |acc, coeff| acc * point + coeff) } let n = poly.len(); - let num_threads = multicore::current_num_threads(); + let num_threads = rayon::current_num_threads(); if n * 2 < num_threads { evaluate(poly, point) } else { let chunk_size = (n + num_threads - 1) / num_threads; let mut parts = vec![F::ZERO; num_threads]; - multicore::scope(|scope| { + rayon::scope(|scope| { for (chunk_idx, (out, poly)) in parts.chunks_mut(1).zip(poly.chunks(chunk_size)).enumerate() { @@ -149,13 +148,13 @@ pub fn parallelize(v: &mu let f = &f; let total_iters = v.len(); - let num_threads = multicore::current_num_threads(); + let num_threads = rayon::current_num_threads(); let base_chunk_size = total_iters / num_threads; let cutoff_chunk_id = total_iters % num_threads; let split_pos = cutoff_chunk_id * (base_chunk_size + 1); let (v_hi, v_lo) = v.split_at_mut(split_pos); - multicore::scope(|scope| { + rayon::scope(|scope| { // Skip special-case: number of iterations is cleanly divided by number of threads. if cutoff_chunk_id != 0 { for (chunk_id, chunk) in v_hi.chunks_exact_mut(base_chunk_size + 1).enumerate() { diff --git a/src/utils/mod.rs b/src/utils/mod.rs index ab861289b0..a600627c59 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -2,7 +2,6 @@ pub mod arithmetic; pub mod helpers; -pub(crate) mod multicore; pub mod rational; pub use helpers::SerdeFormat; diff --git a/tests/plonk_api.rs b/tests/plonk_api.rs index 13dd3ca302..b0947b9e70 100644 --- a/tests/plonk_api.rs +++ b/tests/plonk_api.rs @@ -3,14 +3,14 @@ use assert_matches::assert_matches; use blake2b_simd::State; -use ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup}; +use ff::{FromUniformBytes, 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, + create_proof as create_plonk_proof, keygen_pk, keygen_vk, prepare as prepare_plonk_proof, Advice, Circuit, Column, ConstraintSystem, Error, Fixed, ProvingKey, TableColumn, VerifyingKey, }; -use halo2_proofs::poly::commitment::PolynomialCommitmentScheme; +use halo2_proofs::poly::commitment::{Guard, PolynomialCommitmentScheme}; use halo2_proofs::poly::kzg::params::ParamsKZG; use halo2_proofs::poly::kzg::KZGCommitmentScheme; use halo2_proofs::poly::Rotation; @@ -25,10 +25,6 @@ use std::marker::PhantomData; 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, @@ -416,17 +412,17 @@ fn plonk_api() { // 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); + let much_too_small_params= <$scheme as PolynomialCommitmentScheme<$field>>::gen_params(1); assert_matches!( keygen_vk::<_, $scheme, _>(&much_too_small_params, &empty_circuit), Err(Error::NotEnoughRowsAvailable { - current_k, - }) if current_k == 1 + 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); + let slightly_too_small_params = <$scheme as PolynomialCommitmentScheme<$field>>::gen_params(K-1); assert_matches!( keygen_vk::<_, $scheme, _>(&slightly_too_small_params, &empty_circuit), Err(Error::NotEnoughRowsAvailable { @@ -436,12 +432,11 @@ fn plonk_api() { }}; } - fn keygen>( + fn keygen>( params: &Scheme::Parameters, - params_vk: &Scheme::VerifierParameters, ) -> ProvingKey where - F: FromUniformBytes<64> + WithSmallOrderMulGroup<3>, + F: FromUniformBytes<64> + WithSmallOrderMulGroup<3> + Ord, { let (_, _, lookup_table) = common!(F); let empty_circuit: MyCircuit = MyCircuit { @@ -450,13 +445,13 @@ fn plonk_api() { }; // Initialize the proving key - let vk = keygen_vk(params_vk, &empty_circuit).expect("keygen_vk should not fail"); + 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") + keygen_pk(vk, &empty_circuit).expect("keygen_pk should not fail") } fn create_proof< - F: PrimeField, + F, Scheme: PolynomialCommitmentScheme, T: Transcript, R: RngCore + CryptoRng, @@ -503,7 +498,7 @@ fn plonk_api() { transcript.finalize() } - fn verify_proof, T: Transcript>( + fn verify_proof, T: Transcript>( params_verifier: &Scheme::VerifierParameters, vk: &VerifyingKey, proof: &[u8], @@ -521,14 +516,11 @@ fn plonk_api() { let mut transcript = T::init_from_bytes(proof); - let verifier = verify_plonk_proof( - params_verifier, - vk, - &[&[&pubinputs[..]], &[&pubinputs[..]]], - &mut transcript, - ); + let verifier = + prepare_plonk_proof(vk, &[&[&pubinputs[..]], &[&pubinputs[..]]], &mut transcript) + .unwrap(); - assert!(verifier.is_ok()); + assert!(verifier.verify(params_verifier).is_ok()); } use halo2curves::bn256::{Bn256, Fr}; @@ -536,14 +528,16 @@ fn plonk_api() { type Scheme = KZGCommitmentScheme; bad_keys!(Fr, Scheme); - let params = ParamsKZG::::new(K); let rng = OsRng; + let params = ParamsKZG::::unsafe_setup(K, rng); - let pk = keygen::(¶ms, params.verifier_params()); + let pk = keygen::(¶ms); let proof = create_proof::, _>(rng, ¶ms, &pk); - let verifier_params = params.verifier_params(); - - verify_proof::<_, _, CircuitTranscript>(verifier_params, pk.get_vk(), &proof[..]); + verify_proof::<_, _, CircuitTranscript>( + ¶ms.verifier_params(), + pk.get_vk(), + &proof[..], + ); }