From 3260031fb2dfb4c3596d25a973f69e2279f7b6d5 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 5 Oct 2022 14:21:12 +0200 Subject: [PATCH 1/6] Select logic --- plonky2/src/fri/mod.rs | 2 +- plonky2/src/gates/selectors.rs | 2 +- plonky2/src/plonk/circuit_data.rs | 4 +- .../plonk/conditional_recursive_verifier.rs | 275 ++++++++++++++++++ plonky2/src/plonk/mod.rs | 1 + 5 files changed, 280 insertions(+), 4 deletions(-) create mode 100644 plonky2/src/plonk/conditional_recursive_verifier.rs diff --git a/plonky2/src/fri/mod.rs b/plonky2/src/fri/mod.rs index 5eaf012e..38286312 100644 --- a/plonky2/src/fri/mod.rs +++ b/plonky2/src/fri/mod.rs @@ -50,7 +50,7 @@ impl FriConfig { /// FRI parameters, including generated parameters which are specific to an instance size, in /// contrast to `FriConfig` which is user-specified and independent of instance size. -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub struct FriParams { /// User-specified FRI configuration. pub config: FriConfig, diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index fff5d967..6cea86a7 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -9,7 +9,7 @@ use crate::hash::hash_types::RichField; /// Placeholder value to indicate that a gate doesn't use a selector polynomial. pub(crate) const UNUSED_SELECTOR: usize = u32::MAX as usize; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub(crate) struct SelectorsInfo { pub(crate) selector_indices: Vec, pub(crate) groups: Vec>, diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index f2363f41..c22eae3e 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -29,7 +29,7 @@ use crate::plonk::prover::prove; use crate::plonk::verifier::verify; use crate::util::timing::TimingTree; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct CircuitConfig { pub num_wires: usize, pub num_routed_wires: usize, @@ -239,7 +239,7 @@ pub struct VerifierOnlyCircuitData, const D: usize> { } /// Circuit data required by both the prover and the verifier. -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub struct CommonCircuitData< F: RichField + Extendable, C: GenericConfig, diff --git a/plonky2/src/plonk/conditional_recursive_verifier.rs b/plonky2/src/plonk/conditional_recursive_verifier.rs new file mode 100644 index 00000000..7e5a63ae --- /dev/null +++ b/plonky2/src/plonk/conditional_recursive_verifier.rs @@ -0,0 +1,275 @@ +use itertools::Itertools; +use plonky2_field::extension::Extendable; + +use crate::fri::proof::{ + FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget, +}; +use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; +use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; +use crate::hash::merkle_proofs::MerkleProofTarget; +use crate::iop::ext_target::ExtensionTarget; +use crate::iop::target::{BoolTarget, Target}; +use crate::plonk::circuit_builder::CircuitBuilder; +use crate::plonk::circuit_data::{CommonCircuitData, VerifierCircuitTarget}; +use crate::plonk::config::{AlgebraicHasher, GenericConfig}; +use crate::plonk::proof::{OpeningSetTarget, ProofTarget, ProofWithPublicInputsTarget}; + +impl, const D: usize> CircuitBuilder { + pub fn conditionally_verify_proof>( + &mut self, + condition: BoolTarget, + proof_with_pis: ProofWithPublicInputsTarget, + inner_verifier_data: &VerifierCircuitTarget, + inner_common_data: &CommonCircuitData, + ) where + C::Hasher: AlgebraicHasher, + { + let dummy_proof = self.add_virtual_proof_with_pis(inner_common_data); + let dummy_verifier_data = VerifierCircuitTarget { + constants_sigmas_cap: self + .add_virtual_cap(inner_common_data.config.fri_config.cap_height), + }; + let ProofWithPublicInputsTarget { + proof: + ProofTarget { + wires_cap, + plonk_zs_partial_products_cap, + quotient_polys_cap, + openings, + opening_proof, + }, + public_inputs, + } = proof_with_pis; + let ProofWithPublicInputsTarget { + proof: + ProofTarget { + wires_cap: dummy_wires_cap, + plonk_zs_partial_products_cap: dummy_plonk_zs_partial_products_cap, + quotient_polys_cap: dummy_quotient_polys_cap, + openings: dummy_openings, + + opening_proof: dummy_opening_proof, + }, + public_inputs: dummy_public_inputs, + } = dummy_proof; + + let selected_wires_cap = self.select_cap(condition, wires_cap, dummy_wires_cap); + let selected_plonk_zs_partial_products_cap = self.select_cap( + condition, + plonk_zs_partial_products_cap, + dummy_plonk_zs_partial_products_cap, + ); + let selected_quotient_polys_cap = + self.select_cap(condition, quotient_polys_cap, dummy_quotient_polys_cap); + let selected_openings = self.select_opening_set(condition, openings, dummy_openings); + let selected_opening_proof = + self.select_opening_proof(condition, opening_proof, dummy_opening_proof); + let selected_public_inputs = self.select_vec(condition, public_inputs, dummy_public_inputs); + let selected_proof = ProofWithPublicInputsTarget { + proof: ProofTarget { + wires_cap: selected_wires_cap, + plonk_zs_partial_products_cap: selected_plonk_zs_partial_products_cap, + quotient_polys_cap: selected_quotient_polys_cap, + openings: selected_openings, + opening_proof: selected_opening_proof, + }, + public_inputs: selected_public_inputs, + }; + let selected_verifier_data = VerifierCircuitTarget { + constants_sigmas_cap: self.select_cap( + condition, + inner_verifier_data.constants_sigmas_cap.clone(), + dummy_verifier_data.constants_sigmas_cap, + ), + }; + + self.verify_proof(selected_proof, &selected_verifier_data, inner_common_data); + } + + fn select_vec(&mut self, b: BoolTarget, v0: Vec, v1: Vec) -> Vec { + v0.into_iter() + .zip_eq(v1) + .map(|(t0, t1)| self.select(b, t0, t1)) + .collect() + } + + fn select_cap( + &mut self, + b: BoolTarget, + cap0: MerkleCapTarget, + cap1: MerkleCapTarget, + ) -> MerkleCapTarget { + assert_eq!(cap0.0.len(), cap1.0.len()); + MerkleCapTarget( + cap0.0 + .into_iter() + .zip_eq(cap1.0) + .map(|(h0, h1)| HashOutTarget { + elements: std::array::from_fn(|i| { + self.select(b, h0.elements[i], h1.elements[i]) + }), + }) + .collect(), + ) + } + + fn select_vec_cap( + &mut self, + b: BoolTarget, + v0: Vec, + v1: Vec, + ) -> Vec { + v0.into_iter() + .zip_eq(v1) + .map(|(c0, c1)| self.select_cap(b, c0, c1)) + .collect() + } + + fn select_opening_set( + &mut self, + b: BoolTarget, + os0: OpeningSetTarget, + os1: OpeningSetTarget, + ) -> OpeningSetTarget { + OpeningSetTarget { + constants: self.select_vec_ext(b, os0.constants, os1.constants), + plonk_sigmas: self.select_vec_ext(b, os0.plonk_sigmas, os1.plonk_sigmas), + wires: self.select_vec_ext(b, os0.wires, os1.wires), + plonk_zs: self.select_vec_ext(b, os0.plonk_zs, os1.plonk_zs), + plonk_zs_next: self.select_vec_ext(b, os0.plonk_zs_next, os1.plonk_zs_next), + partial_products: self.select_vec_ext(b, os0.partial_products, os1.partial_products), + quotient_polys: self.select_vec_ext(b, os0.quotient_polys, os1.quotient_polys), + } + } + + fn select_vec_ext( + &mut self, + b: BoolTarget, + v0: Vec>, + v1: Vec>, + ) -> Vec> { + v0.into_iter() + .zip_eq(v1) + .map(|(e0, e1)| self.select_ext(b, e0, e1)) + .collect() + } + + fn select_opening_proof( + &mut self, + b: BoolTarget, + proof0: FriProofTarget, + proof1: FriProofTarget, + ) -> FriProofTarget { + FriProofTarget { + commit_phase_merkle_caps: self.select_vec_cap( + b, + proof0.commit_phase_merkle_caps, + proof1.commit_phase_merkle_caps, + ), + query_round_proofs: self.select_vec_query_round( + b, + proof0.query_round_proofs, + proof1.query_round_proofs, + ), + final_poly: PolynomialCoeffsExtTarget(self.select_vec_ext( + b, + proof0.final_poly.0, + proof1.final_poly.0, + )), + pow_witness: self.select(b, proof0.pow_witness, proof1.pow_witness), + } + } + + fn select_query_round( + &mut self, + b: BoolTarget, + qr0: FriQueryRoundTarget, + qr1: FriQueryRoundTarget, + ) -> FriQueryRoundTarget { + FriQueryRoundTarget { + initial_trees_proof: self.select_initial_tree_proof( + b, + qr0.initial_trees_proof, + qr1.initial_trees_proof, + ), + steps: self.select_vec_query_step(b, qr0.steps, qr1.steps), + } + } + + fn select_vec_query_round( + &mut self, + b: BoolTarget, + v0: Vec>, + v1: Vec>, + ) -> Vec> { + v0.into_iter() + .zip_eq(v1) + .map(|(qr0, qr1)| self.select_query_round(b, qr0, qr1)) + .collect() + } + + fn select_initial_tree_proof( + &mut self, + b: BoolTarget, + proof0: FriInitialTreeProofTarget, + proof1: FriInitialTreeProofTarget, + ) -> FriInitialTreeProofTarget { + FriInitialTreeProofTarget { + evals_proofs: proof0 + .evals_proofs + .into_iter() + .zip_eq(proof1.evals_proofs) + .map(|((v0, p0), (v1, p1))| { + ( + self.select_vec(b, v0, v1), + self.select_merkle_proof(b, p0, p1), + ) + }) + .collect(), + } + } + + fn select_merkle_proof( + &mut self, + b: BoolTarget, + proof0: MerkleProofTarget, + proof1: MerkleProofTarget, + ) -> MerkleProofTarget { + MerkleProofTarget { + siblings: proof0 + .siblings + .into_iter() + .zip_eq(proof1.siblings) + .map(|(h0, h1)| HashOutTarget { + elements: std::array::from_fn(|i| { + self.select(b, h0.elements[i], h1.elements[i]) + }), + }) + .collect(), + } + } + + fn select_query_step( + &mut self, + b: BoolTarget, + qs0: FriQueryStepTarget, + qs1: FriQueryStepTarget, + ) -> FriQueryStepTarget { + FriQueryStepTarget { + evals: self.select_vec_ext(b, qs0.evals, qs1.evals), + merkle_proof: self.select_merkle_proof(b, qs0.merkle_proof, qs1.merkle_proof), + } + } + + fn select_vec_query_step( + &mut self, + b: BoolTarget, + v0: Vec>, + v1: Vec>, + ) -> Vec> { + v0.into_iter() + .zip_eq(v1) + .map(|(qs0, qs1)| self.select_query_step(b, qs0, qs1)) + .collect() + } +} diff --git a/plonky2/src/plonk/mod.rs b/plonky2/src/plonk/mod.rs index 73e6c96e..8cd7443f 100644 --- a/plonky2/src/plonk/mod.rs +++ b/plonky2/src/plonk/mod.rs @@ -1,5 +1,6 @@ pub mod circuit_builder; pub mod circuit_data; +pub mod conditional_recursive_verifier; pub mod config; pub(crate) mod copy_constraint; mod get_challenges; From 2982f45afa0ee071578e6ab795e72a9adaec0d6b Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 5 Oct 2022 15:38:06 +0200 Subject: [PATCH 2/6] Add test --- .../plonk/conditional_recursive_verifier.rs | 133 ++++++++++++++---- 1 file changed, 104 insertions(+), 29 deletions(-) diff --git a/plonky2/src/plonk/conditional_recursive_verifier.rs b/plonky2/src/plonk/conditional_recursive_verifier.rs index 7e5a63ae..0c6455c5 100644 --- a/plonky2/src/plonk/conditional_recursive_verifier.rs +++ b/plonky2/src/plonk/conditional_recursive_verifier.rs @@ -13,6 +13,7 @@ use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::{CommonCircuitData, VerifierCircuitTarget}; use crate::plonk::config::{AlgebraicHasher, GenericConfig}; use crate::plonk::proof::{OpeningSetTarget, ProofTarget, ProofWithPublicInputsTarget}; +use crate::with_context; impl, const D: usize> CircuitBuilder { pub fn conditionally_verify_proof>( @@ -20,15 +21,12 @@ impl, const D: usize> CircuitBuilder { condition: BoolTarget, proof_with_pis: ProofWithPublicInputsTarget, inner_verifier_data: &VerifierCircuitTarget, + dummy_proof_with_pis: ProofWithPublicInputsTarget, + dummy_verifier_data: &VerifierCircuitTarget, inner_common_data: &CommonCircuitData, ) where C::Hasher: AlgebraicHasher, { - let dummy_proof = self.add_virtual_proof_with_pis(inner_common_data); - let dummy_verifier_data = VerifierCircuitTarget { - constants_sigmas_cap: self - .add_virtual_cap(inner_common_data.config.fri_config.cap_height), - }; let ProofWithPublicInputsTarget { proof: ProofTarget { @@ -51,35 +49,38 @@ impl, const D: usize> CircuitBuilder { opening_proof: dummy_opening_proof, }, public_inputs: dummy_public_inputs, - } = dummy_proof; + } = dummy_proof_with_pis; - let selected_wires_cap = self.select_cap(condition, wires_cap, dummy_wires_cap); - let selected_plonk_zs_partial_products_cap = self.select_cap( - condition, - plonk_zs_partial_products_cap, - dummy_plonk_zs_partial_products_cap, - ); - let selected_quotient_polys_cap = - self.select_cap(condition, quotient_polys_cap, dummy_quotient_polys_cap); - let selected_openings = self.select_opening_set(condition, openings, dummy_openings); - let selected_opening_proof = - self.select_opening_proof(condition, opening_proof, dummy_opening_proof); - let selected_public_inputs = self.select_vec(condition, public_inputs, dummy_public_inputs); - let selected_proof = ProofWithPublicInputsTarget { - proof: ProofTarget { - wires_cap: selected_wires_cap, - plonk_zs_partial_products_cap: selected_plonk_zs_partial_products_cap, - quotient_polys_cap: selected_quotient_polys_cap, - openings: selected_openings, - opening_proof: selected_opening_proof, - }, - public_inputs: selected_public_inputs, - }; + let selected_proof = with_context!(self, "select proof", { + let selected_wires_cap = self.select_cap(condition, wires_cap, dummy_wires_cap); + let selected_plonk_zs_partial_products_cap = self.select_cap( + condition, + plonk_zs_partial_products_cap, + dummy_plonk_zs_partial_products_cap, + ); + let selected_quotient_polys_cap = + self.select_cap(condition, quotient_polys_cap, dummy_quotient_polys_cap); + let selected_openings = self.select_opening_set(condition, openings, dummy_openings); + let selected_opening_proof = + self.select_opening_proof(condition, opening_proof, dummy_opening_proof); + let selected_public_inputs = + self.select_vec(condition, public_inputs, dummy_public_inputs); + ProofWithPublicInputsTarget { + proof: ProofTarget { + wires_cap: selected_wires_cap, + plonk_zs_partial_products_cap: selected_plonk_zs_partial_products_cap, + quotient_polys_cap: selected_quotient_polys_cap, + openings: selected_openings, + opening_proof: selected_opening_proof, + }, + public_inputs: selected_public_inputs, + } + }); let selected_verifier_data = VerifierCircuitTarget { constants_sigmas_cap: self.select_cap( condition, inner_verifier_data.constants_sigmas_cap.clone(), - dummy_verifier_data.constants_sigmas_cap, + dummy_verifier_data.constants_sigmas_cap.clone(), ), }; @@ -273,3 +274,77 @@ impl, const D: usize> CircuitBuilder { .collect() } } + +#[cfg(test)] +mod tests { + use anyhow::Result; + + use super::*; + use crate::field::types::Field; + use crate::gates::noop::NoopGate; + use crate::iop::witness::{PartialWitness, Witness}; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + + #[test] + fn test_conditional_recursive_verifier() -> Result<()> { + init_logger(); + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + + let mut builder = CircuitBuilder::::new(config.clone()); + let mut pw = PartialWitness::new(); + let t = builder.add_virtual_target(); + pw.set_target(t, F::rand()); + builder.register_public_input(t); + let _t2 = builder.square(t); + for _ in 0..64 { + builder.add_gate(NoopGate, vec![]); + } + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof.clone())?; + + let mut builder = CircuitBuilder::::new(config); + let mut pw = PartialWitness::new(); + let pt = builder.add_virtual_proof_with_pis(&data.common); + pw.set_proof_with_pis_target(&pt, &proof); + let dummy_pt = builder.add_virtual_proof_with_pis(&data.common); + pw.set_proof_with_pis_target(&dummy_pt, &proof); + + let inner_data = VerifierCircuitTarget { + constants_sigmas_cap: builder.add_virtual_cap(data.common.config.fri_config.cap_height), + }; + pw.set_cap_target( + &inner_data.constants_sigmas_cap, + &data.verifier_only.constants_sigmas_cap, + ); + let dummy_inner_data = VerifierCircuitTarget { + constants_sigmas_cap: builder.add_virtual_cap(data.common.config.fri_config.cap_height), + }; + pw.set_cap_target( + &dummy_inner_data.constants_sigmas_cap, + &data.verifier_only.constants_sigmas_cap, + ); + let b = builder.constant_bool(F::rand().0 % 2 == 0); + builder.conditionally_verify_proof( + b, + pt, + &inner_data, + dummy_pt, + &dummy_inner_data, + &data.common, + ); + + builder.print_gate_counts(100); + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + fn init_logger() { + let _ = env_logger::builder().format_timestamp(None).try_init(); + } +} From 52c82f0c21ffa4e0a5340116ea967cc009c7360f Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 5 Oct 2022 16:32:38 +0200 Subject: [PATCH 3/6] Minor --- plonky2/src/fri/mod.rs | 4 ++-- plonky2/src/gates/selectors.rs | 2 +- plonky2/src/plonk/circuit_data.rs | 4 ++-- .../plonk/conditional_recursive_verifier.rs | 18 ++++++++++-------- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/plonky2/src/fri/mod.rs b/plonky2/src/fri/mod.rs index 38286312..82f21ec6 100644 --- a/plonky2/src/fri/mod.rs +++ b/plonky2/src/fri/mod.rs @@ -11,7 +11,7 @@ mod validate_shape; pub mod verifier; pub mod witness_util; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone)] pub struct FriConfig { /// `rate = 2^{-rate_bits}`. pub rate_bits: usize, @@ -50,7 +50,7 @@ impl FriConfig { /// FRI parameters, including generated parameters which are specific to an instance size, in /// contrast to `FriConfig` which is user-specified and independent of instance size. -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug)] pub struct FriParams { /// User-specified FRI configuration. pub config: FriConfig, diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index 6cea86a7..fff5d967 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -9,7 +9,7 @@ use crate::hash::hash_types::RichField; /// Placeholder value to indicate that a gate doesn't use a selector polynomial. pub(crate) const UNUSED_SELECTOR: usize = u32::MAX as usize; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone)] pub(crate) struct SelectorsInfo { pub(crate) selector_indices: Vec, pub(crate) groups: Vec>, diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index c22eae3e..f2363f41 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -29,7 +29,7 @@ use crate::plonk::prover::prove; use crate::plonk::verifier::verify; use crate::util::timing::TimingTree; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug)] pub struct CircuitConfig { pub num_wires: usize, pub num_routed_wires: usize, @@ -239,7 +239,7 @@ pub struct VerifierOnlyCircuitData, const D: usize> { } /// Circuit data required by both the prover and the verifier. -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug)] pub struct CommonCircuitData< F: RichField + Extendable, C: GenericConfig, diff --git a/plonky2/src/plonk/conditional_recursive_verifier.rs b/plonky2/src/plonk/conditional_recursive_verifier.rs index 0c6455c5..4fe79b4c 100644 --- a/plonky2/src/plonk/conditional_recursive_verifier.rs +++ b/plonky2/src/plonk/conditional_recursive_verifier.rs @@ -16,13 +16,15 @@ use crate::plonk::proof::{OpeningSetTarget, ProofTarget, ProofWithPublicInputsTa use crate::with_context; impl, const D: usize> CircuitBuilder { + /// Verify `proof0` if `condition` else verify `proof1`. + /// `proof0` and `proof1` are assumed to use the same `CommonCircuitData`. pub fn conditionally_verify_proof>( &mut self, condition: BoolTarget, - proof_with_pis: ProofWithPublicInputsTarget, - inner_verifier_data: &VerifierCircuitTarget, - dummy_proof_with_pis: ProofWithPublicInputsTarget, - dummy_verifier_data: &VerifierCircuitTarget, + proof_with_pis0: ProofWithPublicInputsTarget, + inner_verifier_data0: &VerifierCircuitTarget, + proof_with_pis1: ProofWithPublicInputsTarget, + verifier_data1: &VerifierCircuitTarget, inner_common_data: &CommonCircuitData, ) where C::Hasher: AlgebraicHasher, @@ -37,7 +39,7 @@ impl, const D: usize> CircuitBuilder { opening_proof, }, public_inputs, - } = proof_with_pis; + } = proof_with_pis0; let ProofWithPublicInputsTarget { proof: ProofTarget { @@ -49,7 +51,7 @@ impl, const D: usize> CircuitBuilder { opening_proof: dummy_opening_proof, }, public_inputs: dummy_public_inputs, - } = dummy_proof_with_pis; + } = proof_with_pis1; let selected_proof = with_context!(self, "select proof", { let selected_wires_cap = self.select_cap(condition, wires_cap, dummy_wires_cap); @@ -79,8 +81,8 @@ impl, const D: usize> CircuitBuilder { let selected_verifier_data = VerifierCircuitTarget { constants_sigmas_cap: self.select_cap( condition, - inner_verifier_data.constants_sigmas_cap.clone(), - dummy_verifier_data.constants_sigmas_cap.clone(), + inner_verifier_data0.constants_sigmas_cap.clone(), + verifier_data1.constants_sigmas_cap.clone(), ), }; From 66c21931ce265342048714d27a67a5de85ee3d06 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 5 Oct 2022 16:34:24 +0200 Subject: [PATCH 4/6] Minor --- plonky2/src/fri/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plonky2/src/fri/mod.rs b/plonky2/src/fri/mod.rs index 82f21ec6..5eaf012e 100644 --- a/plonky2/src/fri/mod.rs +++ b/plonky2/src/fri/mod.rs @@ -11,7 +11,7 @@ mod validate_shape; pub mod verifier; pub mod witness_util; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct FriConfig { /// `rate = 2^{-rate_bits}`. pub rate_bits: usize, From ce0a4f448014c0b6e5c5a6c64538f700514dd6b5 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 5 Oct 2022 16:42:55 +0200 Subject: [PATCH 5/6] Use `ArithmeticGate` for `select` --- plonky2/src/gadgets/select.rs | 5 ++--- plonky2/src/plonk/conditional_recursive_verifier.rs | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/plonky2/src/gadgets/select.rs b/plonky2/src/gadgets/select.rs index db9be843..d234a003 100644 --- a/plonky2/src/gadgets/select.rs +++ b/plonky2/src/gadgets/select.rs @@ -32,9 +32,8 @@ impl, const D: usize> CircuitBuilder { /// See `select_ext`. pub fn select(&mut self, b: BoolTarget, x: Target, y: Target) -> Target { - let x_ext = self.convert_to_ext(x); - let y_ext = self.convert_to_ext(y); - self.select_ext(b, x_ext, y_ext).to_target_array()[0] + let tmp = self.mul_sub(b.target, y, y); + self.mul_sub(b.target, x, tmp) } } diff --git a/plonky2/src/plonk/conditional_recursive_verifier.rs b/plonky2/src/plonk/conditional_recursive_verifier.rs index 4fe79b4c..1a006e07 100644 --- a/plonky2/src/plonk/conditional_recursive_verifier.rs +++ b/plonky2/src/plonk/conditional_recursive_verifier.rs @@ -24,7 +24,7 @@ impl, const D: usize> CircuitBuilder { proof_with_pis0: ProofWithPublicInputsTarget, inner_verifier_data0: &VerifierCircuitTarget, proof_with_pis1: ProofWithPublicInputsTarget, - verifier_data1: &VerifierCircuitTarget, + inner_verifier_data1: &VerifierCircuitTarget, inner_common_data: &CommonCircuitData, ) where C::Hasher: AlgebraicHasher, @@ -82,7 +82,7 @@ impl, const D: usize> CircuitBuilder { constants_sigmas_cap: self.select_cap( condition, inner_verifier_data0.constants_sigmas_cap.clone(), - verifier_data1.constants_sigmas_cap.clone(), + inner_verifier_data1.constants_sigmas_cap.clone(), ), }; From 2bb63a6f11804e352c4908eebe9c552c11066956 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 6 Oct 2022 09:43:42 +0200 Subject: [PATCH 6/6] PR feedback --- .../plonk/conditional_recursive_verifier.rs | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/plonky2/src/plonk/conditional_recursive_verifier.rs b/plonky2/src/plonk/conditional_recursive_verifier.rs index 1a006e07..8d5b2e88 100644 --- a/plonky2/src/plonk/conditional_recursive_verifier.rs +++ b/plonky2/src/plonk/conditional_recursive_verifier.rs @@ -32,41 +32,39 @@ impl, const D: usize> CircuitBuilder { let ProofWithPublicInputsTarget { proof: ProofTarget { - wires_cap, - plonk_zs_partial_products_cap, - quotient_polys_cap, - openings, - opening_proof, + wires_cap: wires_cap0, + plonk_zs_partial_products_cap: plonk_zs_partial_products_cap0, + quotient_polys_cap: quotient_polys_cap0, + openings: openings0, + opening_proof: opening_proof0, }, - public_inputs, + public_inputs: public_inputs0, } = proof_with_pis0; let ProofWithPublicInputsTarget { proof: ProofTarget { - wires_cap: dummy_wires_cap, - plonk_zs_partial_products_cap: dummy_plonk_zs_partial_products_cap, - quotient_polys_cap: dummy_quotient_polys_cap, - openings: dummy_openings, - - opening_proof: dummy_opening_proof, + wires_cap: wires_cap1, + plonk_zs_partial_products_cap: plonk_zs_partial_products_cap1, + quotient_polys_cap: quotient_polys_cap1, + openings: openings1, + opening_proof: opening_proof1, }, - public_inputs: dummy_public_inputs, + public_inputs: public_inputs1, } = proof_with_pis1; let selected_proof = with_context!(self, "select proof", { - let selected_wires_cap = self.select_cap(condition, wires_cap, dummy_wires_cap); + let selected_wires_cap = self.select_cap(condition, wires_cap0, wires_cap1); let selected_plonk_zs_partial_products_cap = self.select_cap( condition, - plonk_zs_partial_products_cap, - dummy_plonk_zs_partial_products_cap, + plonk_zs_partial_products_cap0, + plonk_zs_partial_products_cap1, ); let selected_quotient_polys_cap = - self.select_cap(condition, quotient_polys_cap, dummy_quotient_polys_cap); - let selected_openings = self.select_opening_set(condition, openings, dummy_openings); + self.select_cap(condition, quotient_polys_cap0, quotient_polys_cap1); + let selected_openings = self.select_opening_set(condition, openings0, openings1); let selected_opening_proof = - self.select_opening_proof(condition, opening_proof, dummy_opening_proof); - let selected_public_inputs = - self.select_vec(condition, public_inputs, dummy_public_inputs); + self.select_opening_proof(condition, opening_proof0, opening_proof1); + let selected_public_inputs = self.select_vec(condition, public_inputs0, public_inputs1); ProofWithPublicInputsTarget { proof: ProofTarget { wires_cap: selected_wires_cap, @@ -96,6 +94,17 @@ impl, const D: usize> CircuitBuilder { .collect() } + fn select_hash( + &mut self, + b: BoolTarget, + h0: HashOutTarget, + h1: HashOutTarget, + ) -> HashOutTarget { + HashOutTarget { + elements: std::array::from_fn(|i| self.select(b, h0.elements[i], h1.elements[i])), + } + } + fn select_cap( &mut self, b: BoolTarget, @@ -107,11 +116,7 @@ impl, const D: usize> CircuitBuilder { cap0.0 .into_iter() .zip_eq(cap1.0) - .map(|(h0, h1)| HashOutTarget { - elements: std::array::from_fn(|i| { - self.select(b, h0.elements[i], h1.elements[i]) - }), - }) + .map(|(h0, h1)| self.select_hash(b, h0, h1)) .collect(), ) } @@ -243,11 +248,7 @@ impl, const D: usize> CircuitBuilder { .siblings .into_iter() .zip_eq(proof1.siblings) - .map(|(h0, h1)| HashOutTarget { - elements: std::array::from_fn(|i| { - self.select(b, h0.elements[i], h1.elements[i]) - }), - }) + .map(|(h0, h1)| self.select_hash(b, h0, h1)) .collect(), } }