From a37694dec69c5231a288d5881677fc2a9cc1ef80 Mon Sep 17 00:00:00 2001 From: iquerejeta Date: Tue, 21 Jan 2025 10:01:19 +0100 Subject: [PATCH] Downsize parameters to match size of the circuit --- benches/plonk.rs | 2 +- examples/serialization.rs | 6 +++--- examples/vector-ops-unblinded.rs | 2 +- src/plonk/keygen.rs | 16 +++++++++++----- src/plonk/prover.rs | 4 ++-- src/poly/commitment.rs | 3 +++ src/poly/kzg/params.rs | 8 ++++++++ tests/plonk_api.rs | 15 ++++++++------- 8 files changed, 37 insertions(+), 19 deletions(-) diff --git a/benches/plonk.rs b/benches/plonk.rs index ec3773d2a..2af67f091 100644 --- a/benches/plonk.rs +++ b/benches/plonk.rs @@ -261,7 +261,7 @@ fn criterion_benchmark(c: &mut Criterion) { a: Value::unknown(), k, }; - let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); + let vk = keygen_vk_with_k(¶ms, &empty_circuit, k).expect("keygen_vk should not fail"); let pk = keygen_pk(vk, &empty_circuit).expect("keygen_pk should not fail"); (params, pk) } diff --git a/examples/serialization.rs b/examples/serialization.rs index b1c66a8c0..f77462a91 100644 --- a/examples/serialization.rs +++ b/examples/serialization.rs @@ -10,8 +10,8 @@ use halo2_proofs::transcript::{CircuitTranscript, Transcript}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, plonk::{ - create_proof, keygen_pk, keygen_vk, prepare, Advice, Circuit, Column, ConstraintSystem, - Error, Fixed, Instance, ProvingKey, + create_proof, keygen_pk, keygen_vk_with_k, prepare, Advice, Circuit, Column, + ConstraintSystem, Error, Fixed, Instance, ProvingKey, }, poly::{ kzg::{params::ParamsKZG, KZGCommitmentScheme}, @@ -128,7 +128,7 @@ fn main() { let k = 4; let circuit = StandardPlonk(Fr::random(OsRng)); let params = ParamsKZG::::unsafe_setup(k, OsRng); - let vk = keygen_vk::<_, KZGCommitmentScheme, _>(¶ms, &circuit) + let vk = keygen_vk_with_k::<_, KZGCommitmentScheme, _>(¶ms, &circuit, k) .expect("vk should not fail"); let pk = keygen_pk(vk, &circuit).expect("pk should not fail"); diff --git a/examples/vector-ops-unblinded.rs b/examples/vector-ops-unblinded.rs index 8b8a4e3af..66b118e01 100644 --- a/examples/vector-ops-unblinded.rs +++ b/examples/vector-ops-unblinded.rs @@ -479,7 +479,7 @@ where + Ord, { let params: ParamsKZG = ParamsKZG::unsafe_setup(k, OsRng); - let vk = keygen_vk(¶ms, &circuit).unwrap(); + let vk = keygen_vk_with_k(¶ms, &circuit, k).unwrap(); let pk = keygen_pk(vk, &circuit).unwrap(); let proof = { diff --git a/src/plonk/keygen.rs b/src/plonk/keygen.rs index 6b9a2fd57..b26ca6a8e 100644 --- a/src/plonk/keygen.rs +++ b/src/plonk/keygen.rs @@ -243,13 +243,13 @@ pub fn k_from_circuit, C: Circuit>(circ .expect("A circuit which can be implemented with at most 2^24 rows.") } -/// Generate a `VerifyingKey` from an instance of `Circuit`. +/// Generates a `VerifyingKey` from a `Circuit` instance. /// -/// This function automatically generates the VK using the smallest -/// value of k required for the ConcreteCircuit. -/// To specify a particular value for k, use keygen_vk_with_k instead. +/// Automatically determines the smallest `k` required for the given circuit +/// and adjusts the received parameters to match the circuit's size. +/// Use `keygen_vk_with_k` to specify a custom `k` value. pub fn keygen_vk( - params: &CS::Parameters, + params: &mut CS::Parameters, circuit: &ConcreteCircuit, ) -> Result, Error> where @@ -259,6 +259,12 @@ where { let k = k_from_circuit(circuit); + if params.max_k() < k { + return Err(Error::not_enough_rows_available(params.max_k())); + } + + params.downsize(k); + keygen_vk_with_k(params, circuit, k) } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 5bc27d696..090eb4994 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -610,8 +610,8 @@ fn test_create_proof() { } } - let params: ParamsKZG = ParamsKZG::unsafe_setup(3, OsRng); - let vk = keygen_vk(¶ms, &MyCircuit).expect("keygen_vk should not fail"); + let mut params: ParamsKZG = ParamsKZG::unsafe_setup(3, OsRng); + let vk = keygen_vk(&mut params, &MyCircuit).expect("keygen_vk should not fail"); let pk = keygen_pk(vk, &MyCircuit).expect("keygen_pk should not fail"); let mut transcript = CircuitTranscript::<_>::init(); diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index 1ea0b9359..c56743707 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -79,4 +79,7 @@ pub trait Guard>: Sized { pub trait Params { /// Returns the max size of polynomials that these parameters can commit to fn max_k(&self) -> u32; + + /// Downsize the params to work with a circuit of size `new_k` + fn downsize(&mut self, new_k: u32); } diff --git a/src/poly/kzg/params.rs b/src/poly/kzg/params.rs index 8cfdde91f..8219d89e9 100644 --- a/src/poly/kzg/params.rs +++ b/src/poly/kzg/params.rs @@ -27,11 +27,19 @@ impl Params for ParamsKZG { self.g.len().ilog2() } + + fn downsize(&mut self, new_k: u32) { + ParamsKZG::::downsize(self, new_k) + } } impl ParamsKZG { /// Downsize the current parameters to match a smaller `k`. pub fn downsize(&mut self, new_k: u32) { + if self.max_k() == new_k { + return; + } + let n = 1 << new_k; assert!(n < self.g_lagrange.len() as u32); self.g.truncate(n as usize); diff --git a/tests/plonk_api.rs b/tests/plonk_api.rs index b0947b9e7..ba439a5fd 100644 --- a/tests/plonk_api.rs +++ b/tests/plonk_api.rs @@ -7,8 +7,9 @@ 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, prepare as prepare_plonk_proof, - Advice, Circuit, Column, ConstraintSystem, Error, Fixed, ProvingKey, TableColumn, VerifyingKey, + create_proof as create_plonk_proof, keygen_pk, keygen_vk, keygen_vk_with_k, + prepare as prepare_plonk_proof, Advice, Circuit, Column, ConstraintSystem, Error, Fixed, + ProvingKey, TableColumn, VerifyingKey, }; use halo2_proofs::poly::commitment::{Guard, PolynomialCommitmentScheme}; use halo2_proofs::poly::kzg::params::ParamsKZG; @@ -414,7 +415,7 @@ fn plonk_api() { // k that is too small for the minimum required number of rows. let much_too_small_params= <$scheme as PolynomialCommitmentScheme<$field>>::gen_params(1); assert_matches!( - keygen_vk::<_, $scheme, _>(&much_too_small_params, &empty_circuit), + keygen_vk_with_k::<_, $scheme, _>(&much_too_small_params, &empty_circuit, 1), Err(Error::NotEnoughRowsAvailable { current_k: 1, }) @@ -424,7 +425,7 @@ fn plonk_api() { // k that is too small for the number of rows the circuit uses. let slightly_too_small_params = <$scheme as PolynomialCommitmentScheme<$field>>::gen_params(K-1); assert_matches!( - keygen_vk::<_, $scheme, _>(&slightly_too_small_params, &empty_circuit), + keygen_vk_with_k::<_, $scheme, _>(&slightly_too_small_params, &empty_circuit, K - 1), Err(Error::NotEnoughRowsAvailable { current_k, }) if current_k == K - 1 @@ -433,7 +434,7 @@ fn plonk_api() { } fn keygen>( - params: &Scheme::Parameters, + params: &mut Scheme::Parameters, ) -> ProvingKey where F: FromUniformBytes<64> + WithSmallOrderMulGroup<3> + Ord, @@ -529,9 +530,9 @@ fn plonk_api() { bad_keys!(Fr, Scheme); let rng = OsRng; - let params = ParamsKZG::::unsafe_setup(K, rng); + let mut params = ParamsKZG::::unsafe_setup(K, rng); - let pk = keygen::(¶ms); + let pk = keygen::(&mut params); let proof = create_proof::, _>(rng, ¶ms, &pk);