From a6e64d1c7eb2a0f75e03153188bb33a1d57b2d2b Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Sun, 23 Jan 2022 23:27:26 -0800 Subject: [PATCH] Replace `proof_to_proof_target` (#445) * Replace `proof_to_proof_target` With a `add_virtual_proof_with_pis` method that uses the inner circuit data, but does not require constructing a proof. Note that this doesn't support IVC yet. For that, I think we can add a variant of `add_virtual_proof_with_pis` that takes several parameters like FRI arities, but does not involve `CommonCircuitData` (since no circuit has been build yet). It might also be best to avoid large objects like `FriParams`, and pass just the data we need. Then there will be some nontrivial work to do recursion with "estimated" parameters (degree, arities, etc), check if the estimates were correct, and try again if not. * PR feedback --- plonky2/src/fri/proof.rs | 7 +- plonky2/src/fri/prover.rs | 5 +- plonky2/src/fri/recursive_verifier.rs | 79 ++++++- plonky2/src/gadgets/polynomial.rs | 1 + plonky2/src/hash/merkle_proofs.rs | 2 +- plonky2/src/plonk/circuit_builder.rs | 18 ++ plonky2/src/plonk/circuit_data.rs | 24 ++- plonky2/src/plonk/proof.rs | 2 + plonky2/src/plonk/recursive_verifier.rs | 267 +++++++++++------------- plonky2/src/plonk/verifier.rs | 4 + 10 files changed, 246 insertions(+), 163 deletions(-) diff --git a/plonky2/src/fri/proof.rs b/plonky2/src/fri/proof.rs index ff81c2c5..f96db781 100644 --- a/plonky2/src/fri/proof.rs +++ b/plonky2/src/fri/proof.rs @@ -26,7 +26,7 @@ pub struct FriQueryStep, H: Hasher, const D: usi pub merkle_proof: MerkleProof, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct FriQueryStepTarget { pub evals: Vec>, pub merkle_proof: MerkleProofTarget, @@ -51,7 +51,7 @@ impl> FriInitialTreeProof { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct FriInitialTreeProofTarget { pub evals_proofs: Vec<(Vec, MerkleProofTarget)>, } @@ -80,7 +80,7 @@ pub struct FriQueryRound, H: Hasher, const D: us pub steps: Vec>, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct FriQueryRoundTarget { pub initial_trees_proof: FriInitialTreeProofTarget, pub steps: Vec>, @@ -111,6 +111,7 @@ pub struct FriProof, H: Hasher, const D: usize> pub pow_witness: F, } +#[derive(Debug)] pub struct FriProofTarget { pub commit_phase_merkle_caps: Vec, pub query_round_proofs: Vec>, diff --git a/plonky2/src/fri/prover.rs b/plonky2/src/fri/prover.rs index d2731600..e814beae 100644 --- a/plonky2/src/fri/prover.rs +++ b/plonky2/src/fri/prover.rs @@ -72,9 +72,8 @@ fn fri_committed_trees, C: GenericConfig, let mut trees = Vec::new(); let mut shift = F::MULTIPLICATIVE_GROUP_GENERATOR; - let num_reductions = fri_params.reduction_arity_bits.len(); - for i in 0..num_reductions { - let arity = 1 << fri_params.reduction_arity_bits[i]; + for arity_bits in &fri_params.reduction_arity_bits { + let arity = 1 << arity_bits; reverse_index_bits_in_place(&mut values.values); let chunked_values = values diff --git a/plonky2/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs index 63d07035..a9a224d1 100644 --- a/plonky2/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -2,7 +2,9 @@ use itertools::Itertools; use plonky2_field::extension_field::Extendable; use plonky2_util::{log2_strict, reverse_index_bits_in_place}; -use crate::fri::proof::{FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget}; +use crate::fri::proof::{ + FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget, +}; use crate::fri::structure::{FriBatchInfoTarget, FriInstanceInfoTarget, FriOpeningsTarget}; use crate::fri::{FriConfig, FriParams}; use crate::gadgets::interpolation::InterpolationGate; @@ -420,6 +422,81 @@ impl, const D: usize> CircuitBuilder { assert!(p_ambiguous < query_error * 1e-5, "A non-negligible portion of field elements are in the range that permits non-canonical encodings. Need to do more analysis or enforce canonical encodings."); } + + pub(crate) fn add_virtual_fri_proof( + &mut self, + num_leaves_per_oracle: &[usize], + params: &FriParams, + ) -> FriProofTarget { + let cap_height = params.config.cap_height; + let num_queries = params.config.num_query_rounds; + let commit_phase_merkle_caps = (0..params.reduction_arity_bits.len()) + .map(|_| self.add_virtual_cap(cap_height)) + .collect(); + let query_round_proofs = (0..num_queries) + .map(|_| self.add_virtual_fri_query(num_leaves_per_oracle, params)) + .collect(); + let final_poly = self.add_virtual_poly_coeff_ext(params.final_poly_len()); + let pow_witness = self.add_virtual_target(); + FriProofTarget { + commit_phase_merkle_caps, + query_round_proofs, + final_poly, + pow_witness, + } + } + + fn add_virtual_fri_query( + &mut self, + num_leaves_per_oracle: &[usize], + params: &FriParams, + ) -> FriQueryRoundTarget { + let cap_height = params.config.cap_height; + assert!(params.lde_bits() >= cap_height); + let mut merkle_proof_len = params.lde_bits() - cap_height; + + let initial_trees_proof = + self.add_virtual_fri_initial_trees_proof(num_leaves_per_oracle, merkle_proof_len); + + let mut steps = vec![]; + for &arity_bits in ¶ms.reduction_arity_bits { + assert!(merkle_proof_len >= arity_bits); + merkle_proof_len -= arity_bits; + steps.push(self.add_virtual_fri_query_step(arity_bits, merkle_proof_len)); + } + + FriQueryRoundTarget { + initial_trees_proof, + steps, + } + } + + fn add_virtual_fri_initial_trees_proof( + &mut self, + num_leaves_per_oracle: &[usize], + initial_merkle_proof_len: usize, + ) -> FriInitialTreeProofTarget { + let evals_proofs = num_leaves_per_oracle + .iter() + .map(|&num_oracle_leaves| { + let leaves = self.add_virtual_targets(num_oracle_leaves); + let merkle_proof = self.add_virtual_merkle_proof(initial_merkle_proof_len); + (leaves, merkle_proof) + }) + .collect(); + FriInitialTreeProofTarget { evals_proofs } + } + + fn add_virtual_fri_query_step( + &mut self, + arity_bits: usize, + merkle_proof_len: usize, + ) -> FriQueryStepTarget { + FriQueryStepTarget { + evals: self.add_virtual_extension_targets(1 << arity_bits), + merkle_proof: self.add_virtual_merkle_proof(merkle_proof_len), + } + } } /// For each opening point, holds the reduced (by `alpha`) evaluations of each polynomial that's diff --git a/plonky2/src/gadgets/polynomial.rs b/plonky2/src/gadgets/polynomial.rs index 195eabd3..6e4a9bb4 100644 --- a/plonky2/src/gadgets/polynomial.rs +++ b/plonky2/src/gadgets/polynomial.rs @@ -6,6 +6,7 @@ use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::reducing::ReducingFactorTarget; +#[derive(Debug)] pub struct PolynomialCoeffsExtTarget(pub Vec>); impl PolynomialCoeffsExtTarget { diff --git a/plonky2/src/hash/merkle_proofs.rs b/plonky2/src/hash/merkle_proofs.rs index 60fe236a..c2f3655d 100644 --- a/plonky2/src/hash/merkle_proofs.rs +++ b/plonky2/src/hash/merkle_proofs.rs @@ -17,7 +17,7 @@ pub struct MerkleProof> { pub siblings: Vec, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct MerkleProofTarget { /// The Merkle digest of each sibling subtree, staying from the bottommost layer. pub siblings: Vec, diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 33b44054..e4abe611 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -15,6 +15,7 @@ use crate::fri::{FriConfig, FriParams}; use crate::gadgets::arithmetic::BaseArithmeticOperation; use crate::gadgets::arithmetic_extension::ExtensionArithmeticOperation; use crate::gadgets::arithmetic_u32::U32Target; +use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; use crate::gates::arithmetic_u32::U32ArithmeticGate; @@ -28,6 +29,7 @@ use crate::gates::random_access::RandomAccessGate; use crate::gates::subtraction_u32::U32SubtractionGate; use crate::gates::switch::SwitchGate; use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; +use crate::hash::merkle_proofs::MerkleProofTarget; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{ CopyGenerator, RandomValueGenerator, SimpleGenerator, WitnessGenerator, @@ -172,6 +174,12 @@ impl, const D: usize> CircuitBuilder { (0..n).map(|_i| self.add_virtual_hash()).collect() } + pub(crate) fn add_virtual_merkle_proof(&mut self, len: usize) -> MerkleProofTarget { + MerkleProofTarget { + siblings: self.add_virtual_hashes(len), + } + } + pub fn add_virtual_extension_target(&mut self) -> ExtensionTarget { ExtensionTarget(self.add_virtual_targets(D).try_into().unwrap()) } @@ -182,6 +190,14 @@ impl, const D: usize> CircuitBuilder { .collect() } + pub(crate) fn add_virtual_poly_coeff_ext( + &mut self, + num_coeffs: usize, + ) -> PolynomialCoeffsExtTarget { + let coeffs = self.add_virtual_extension_targets(num_coeffs); + PolynomialCoeffsExtTarget(coeffs) + } + // TODO: Unsafe pub fn add_virtual_bool_target(&mut self) -> BoolTarget { BoolTarget::new_unsafe(self.add_virtual_target()) @@ -596,6 +612,7 @@ impl, const D: usize> CircuitBuilder { // Hash the public inputs, and route them to a `PublicInputGate` which will enforce that // those hash wires match the claimed public inputs. + let num_public_inputs = self.public_inputs.len(); let public_inputs_hash = self.hash_n_to_hash::(self.public_inputs.clone(), true); let pi_gate = self.add_gate(PublicInputGate, vec![]); @@ -736,6 +753,7 @@ impl, const D: usize> CircuitBuilder { num_gate_constraints, num_constants, num_virtual_targets: self.virtual_target_index, + num_public_inputs, k_is, num_partial_products, circuit_digest, diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index 35c37991..dd7ebc25 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -234,6 +234,8 @@ pub struct CommonCircuitData< pub(crate) num_virtual_targets: usize, + pub(crate) num_public_inputs: usize, + /// The `{k_i}` valued used in `S_ID_i` in Plonk's permutation argument. pub(crate) k_is: Vec, @@ -341,34 +343,42 @@ impl, C: GenericConfig, const D: usize> } fn fri_preprocessed_polys(&self) -> Vec { - let num_preprocessed_polys = self.sigmas_range().end; FriPolynomialInfo::from_range( PlonkOracle::CONSTANTS_SIGMAS.index, - 0..num_preprocessed_polys, + 0..self.num_preprocessed_polys(), ) } + pub(crate) fn num_preprocessed_polys(&self) -> usize { + self.sigmas_range().end + } + fn fri_wire_polys(&self) -> Vec { let num_wire_polys = self.config.num_wires; FriPolynomialInfo::from_range(PlonkOracle::WIRES.index, 0..num_wire_polys) } fn fri_zs_partial_products_polys(&self) -> Vec { - let num_zs_partial_products_polys = - self.config.num_challenges * (1 + self.num_partial_products); FriPolynomialInfo::from_range( PlonkOracle::ZS_PARTIAL_PRODUCTS.index, - 0..num_zs_partial_products_polys, + 0..self.num_zs_partial_products_polys(), ) } + pub(crate) fn num_zs_partial_products_polys(&self) -> usize { + self.config.num_challenges * (1 + self.num_partial_products) + } + fn fri_zs_polys(&self) -> Vec { FriPolynomialInfo::from_range(PlonkOracle::ZS_PARTIAL_PRODUCTS.index, self.zs_range()) } fn fri_quotient_polys(&self) -> Vec { - let num_quotient_polys = self.config.num_challenges * self.quotient_degree_factor; - FriPolynomialInfo::from_range(PlonkOracle::QUOTIENT.index, 0..num_quotient_polys) + FriPolynomialInfo::from_range(PlonkOracle::QUOTIENT.index, 0..self.num_quotient_polys()) + } + + pub(crate) fn num_quotient_polys(&self) -> usize { + self.config.num_challenges * self.quotient_degree_factor } fn fri_all_polys(&self) -> Vec { diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index 07ca7c9e..7fbdc671 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -32,6 +32,7 @@ pub struct Proof, C: GenericConfig, const pub opening_proof: FriProof, } +#[derive(Debug)] pub struct ProofTarget { pub wires_cap: MerkleCapTarget, pub plonk_zs_partial_products_cap: MerkleCapTarget, @@ -255,6 +256,7 @@ pub(crate) struct FriInferredElements, const D: usi pub Vec, ); +#[derive(Debug)] pub struct ProofWithPublicInputsTarget { pub proof: ProofTarget, pub public_inputs: Vec, diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index 38024eea..6b3b6b0c 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -5,7 +5,7 @@ use crate::iop::challenger::RecursiveChallenger; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData, VerifierCircuitTarget}; use crate::plonk::config::{AlgebraicHasher, GenericConfig}; -use crate::plonk::proof::ProofWithPublicInputsTarget; +use crate::plonk::proof::{OpeningSetTarget, ProofTarget, ProofWithPublicInputsTarget}; use crate::plonk::vanishing_poly::eval_vanishing_poly_recursively; use crate::plonk::vars::EvaluationTargets; use crate::util::reducing::ReducingFactorTarget; @@ -13,7 +13,7 @@ use crate::with_context; impl, const D: usize> CircuitBuilder { /// Recursively verifies an inner proof. - pub fn add_recursive_verifier>( + pub fn verify_proof_with_pis>( &mut self, proof_with_pis: ProofWithPublicInputsTarget, inner_config: &CircuitConfig, @@ -26,12 +26,34 @@ impl, const D: usize> CircuitBuilder { proof, public_inputs, } = proof_with_pis; + + assert_eq!(public_inputs.len(), inner_common_data.num_public_inputs); + let public_inputs_hash = self.hash_n_to_hash::(public_inputs, true); + + self.verify_proof( + proof, + public_inputs_hash, + inner_config, + inner_verifier_data, + inner_common_data, + ); + } + + /// Recursively verifies an inner proof. + pub fn verify_proof>( + &mut self, + proof: ProofTarget, + public_inputs_hash: HashOutTarget, + inner_config: &CircuitConfig, + inner_verifier_data: &VerifierCircuitTarget, + inner_common_data: &CommonCircuitData, + ) where + C::Hasher: AlgebraicHasher, + { let one = self.one_extension(); let num_challenges = inner_config.num_challenges; - let public_inputs_hash = &self.hash_n_to_hash::(public_inputs, true); - let mut challenger = RecursiveChallenger::::new(self); let (betas, gammas, alphas, zeta) = @@ -41,7 +63,7 @@ impl, const D: usize> CircuitBuilder { self.constants(&inner_common_data.circuit_digest.elements), ); challenger.observe_hash(&digest); - challenger.observe_hash(public_inputs_hash); + challenger.observe_hash(&public_inputs_hash); challenger.observe_cap(&proof.wires_cap); let betas = challenger.get_n_challenges(self, num_challenges); @@ -61,7 +83,7 @@ impl, const D: usize> CircuitBuilder { let vars = EvaluationTargets { local_constants, local_wires, - public_inputs_hash, + public_inputs_hash: &public_inputs_hash, }; let local_zs = &proof.openings.plonk_zs; let next_zs = &proof.openings.plonk_zs_right; @@ -123,137 +145,81 @@ impl, const D: usize> CircuitBuilder { ) ); } -} -#[cfg(test)] -mod tests { - use anyhow::Result; - use log::{info, Level}; - use plonky2_util::log2_strict; - - use super::*; - use crate::fri::proof::{ - FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget, - }; - use crate::fri::reduction_strategies::FriReductionStrategy; - use crate::fri::FriConfig; - use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; - use crate::gates::noop::NoopGate; - use crate::hash::merkle_proofs::MerkleProofTarget; - use crate::iop::witness::{PartialWitness, Witness}; - use crate::plonk::circuit_data::VerifierOnlyCircuitData; - use crate::plonk::config::{ - GMiMCGoldilocksConfig, GenericConfig, KeccakGoldilocksConfig, PoseidonGoldilocksConfig, - }; - use crate::plonk::proof::{ - CompressedProofWithPublicInputs, OpeningSetTarget, Proof, ProofTarget, - ProofWithPublicInputs, - }; - use crate::plonk::prover::prove; - use crate::util::timing::TimingTree; - - // Construct a `FriQueryRoundTarget` with the same dimensions as the ones in `proof`. - fn get_fri_query_round< - F: RichField + Extendable, - C: GenericConfig, - const D: usize, - >( - proof: &Proof, - builder: &mut CircuitBuilder, - ) -> FriQueryRoundTarget { - let mut query_round = FriQueryRoundTarget { - initial_trees_proof: FriInitialTreeProofTarget { - evals_proofs: vec![], - }, - steps: vec![], - }; - for (v, merkle_proof) in &proof.opening_proof.query_round_proofs[0] - .initial_trees_proof - .evals_proofs - { - query_round.initial_trees_proof.evals_proofs.push(( - builder.add_virtual_targets(v.len()), - MerkleProofTarget { - siblings: builder.add_virtual_hashes(merkle_proof.siblings.len()), - }, - )); - } - for step in &proof.opening_proof.query_round_proofs[0].steps { - query_round.steps.push(FriQueryStepTarget { - evals: builder.add_virtual_extension_targets(step.evals.len()), - merkle_proof: MerkleProofTarget { - siblings: builder.add_virtual_hashes(step.merkle_proof.siblings.len()), - }, - }); - } - query_round - } - - // Construct a `ProofTarget` with the same dimensions as `proof`. - fn proof_to_proof_target< - F: RichField + Extendable, - C: GenericConfig, - const D: usize, - >( - proof_with_pis: &ProofWithPublicInputs, - builder: &mut CircuitBuilder, + pub fn add_virtual_proof_with_pis>( + &mut self, + common_data: &CommonCircuitData, ) -> ProofWithPublicInputsTarget { - let ProofWithPublicInputs { - proof, - public_inputs, - } = proof_with_pis; - - let wires_cap = builder.add_virtual_cap(log2_strict(proof.wires_cap.0.len())); - let plonk_zs_cap = - builder.add_virtual_cap(log2_strict(proof.plonk_zs_partial_products_cap.0.len())); - let quotient_polys_cap = - builder.add_virtual_cap(log2_strict(proof.quotient_polys_cap.0.len())); - - let openings = OpeningSetTarget { - constants: builder.add_virtual_extension_targets(proof.openings.constants.len()), - plonk_sigmas: builder.add_virtual_extension_targets(proof.openings.plonk_sigmas.len()), - wires: builder.add_virtual_extension_targets(proof.openings.wires.len()), - plonk_zs: builder.add_virtual_extension_targets(proof.openings.plonk_zs.len()), - plonk_zs_right: builder - .add_virtual_extension_targets(proof.openings.plonk_zs_right.len()), - partial_products: builder - .add_virtual_extension_targets(proof.openings.partial_products.len()), - quotient_polys: builder - .add_virtual_extension_targets(proof.openings.quotient_polys.len()), - }; - let query_round_proofs = (0..proof.opening_proof.query_round_proofs.len()) - .map(|_| get_fri_query_round(proof, builder)) - .collect(); - let commit_phase_merkle_caps = proof - .opening_proof - .commit_phase_merkle_caps - .iter() - .map(|r| builder.add_virtual_cap(log2_strict(r.0.len()))) - .collect(); - let opening_proof = FriProofTarget { - commit_phase_merkle_caps, - query_round_proofs, - final_poly: PolynomialCoeffsExtTarget( - builder.add_virtual_extension_targets(proof.opening_proof.final_poly.len()), - ), - pow_witness: builder.add_virtual_target(), - }; - - let proof = ProofTarget { - wires_cap, - plonk_zs_partial_products_cap: plonk_zs_cap, - quotient_polys_cap, - openings, - opening_proof, - }; - - let public_inputs = builder.add_virtual_targets(public_inputs.len()); + let proof = self.add_virtual_proof(common_data); + let public_inputs = self.add_virtual_targets(common_data.num_public_inputs); ProofWithPublicInputsTarget { proof, public_inputs, } } + fn add_virtual_proof>( + &mut self, + common_data: &CommonCircuitData, + ) -> ProofTarget { + let config = &common_data.config; + let fri_params = &common_data.fri_params; + let cap_height = fri_params.config.cap_height; + + let num_leaves_per_oracle = &[ + common_data.num_preprocessed_polys(), + config.num_wires, + common_data.num_zs_partial_products_polys(), + common_data.num_quotient_polys(), + ]; + + ProofTarget { + wires_cap: self.add_virtual_cap(cap_height), + plonk_zs_partial_products_cap: self.add_virtual_cap(cap_height), + quotient_polys_cap: self.add_virtual_cap(cap_height), + openings: self.add_opening_set(common_data), + opening_proof: self.add_virtual_fri_proof(num_leaves_per_oracle, fri_params), + } + } + + fn add_opening_set>( + &mut self, + common_data: &CommonCircuitData, + ) -> OpeningSetTarget { + let config = &common_data.config; + let num_challenges = config.num_challenges; + let total_partial_products = num_challenges * common_data.num_partial_products; + OpeningSetTarget { + constants: self.add_virtual_extension_targets(common_data.num_constants), + plonk_sigmas: self.add_virtual_extension_targets(config.num_routed_wires), + wires: self.add_virtual_extension_targets(config.num_wires), + plonk_zs: self.add_virtual_extension_targets(num_challenges), + plonk_zs_right: self.add_virtual_extension_targets(num_challenges), + partial_products: self.add_virtual_extension_targets(total_partial_products), + quotient_polys: self.add_virtual_extension_targets(common_data.num_quotient_polys()), + } + } +} + +#[cfg(test)] +mod tests { + use anyhow::Result; + use itertools::Itertools; + use log::{info, Level}; + + use super::*; + use crate::fri::reduction_strategies::FriReductionStrategy; + use crate::fri::FriConfig; + use crate::gates::noop::NoopGate; + use crate::iop::witness::{PartialWitness, Witness}; + use crate::plonk::circuit_data::VerifierOnlyCircuitData; + use crate::plonk::config::{ + GMiMCGoldilocksConfig, GenericConfig, KeccakGoldilocksConfig, PoseidonGoldilocksConfig, + }; + use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs}; + use crate::plonk::prover::prove; + use crate::util::timing::TimingTree; + // Set the targets in a `ProofTarget` to their corresponding values in a `Proof`. fn set_proof_target, C: GenericConfig, const D: usize>( proof: &ProofWithPublicInputs, @@ -272,7 +238,7 @@ mod tests { } = pt; // Set public inputs. - for (&pi_t, &pi) in pi_targets.iter().zip(public_inputs) { + for (&pi_t, &pi) in pi_targets.iter().zip_eq(public_inputs) { pw.set_target(pi_t, pi); } @@ -283,28 +249,33 @@ mod tests { ); pw.set_cap_target(&pt.quotient_polys_cap, &proof.quotient_polys_cap); - for (&t, &x) in pt.openings.wires.iter().zip(&proof.openings.wires) { + for (&t, &x) in pt.openings.wires.iter().zip_eq(&proof.openings.wires) { pw.set_extension_target(t, x); } - for (&t, &x) in pt.openings.constants.iter().zip(&proof.openings.constants) { + for (&t, &x) in pt + .openings + .constants + .iter() + .zip_eq(&proof.openings.constants) + { pw.set_extension_target(t, x); } for (&t, &x) in pt .openings .plonk_sigmas .iter() - .zip(&proof.openings.plonk_sigmas) + .zip_eq(&proof.openings.plonk_sigmas) { pw.set_extension_target(t, x); } - for (&t, &x) in pt.openings.plonk_zs.iter().zip(&proof.openings.plonk_zs) { + for (&t, &x) in pt.openings.plonk_zs.iter().zip_eq(&proof.openings.plonk_zs) { pw.set_extension_target(t, x); } for (&t, &x) in pt .openings .plonk_zs_right .iter() - .zip(&proof.openings.plonk_zs_right) + .zip_eq(&proof.openings.plonk_zs_right) { pw.set_extension_target(t, x); } @@ -312,7 +283,7 @@ mod tests { .openings .partial_products .iter() - .zip(&proof.openings.partial_products) + .zip_eq(&proof.openings.partial_products) { pw.set_extension_target(t, x); } @@ -320,7 +291,7 @@ mod tests { .openings .quotient_polys .iter() - .zip(&proof.openings.quotient_polys) + .zip_eq(&proof.openings.quotient_polys) { pw.set_extension_target(t, x); } @@ -330,14 +301,14 @@ mod tests { pw.set_target(fpt.pow_witness, fri_proof.pow_witness); - for (&t, &x) in fpt.final_poly.0.iter().zip(&fri_proof.final_poly.coeffs) { + for (&t, &x) in fpt.final_poly.0.iter().zip_eq(&fri_proof.final_poly.coeffs) { pw.set_extension_target(t, x); } for (t, x) in fpt .commit_phase_merkle_caps .iter() - .zip(&fri_proof.commit_phase_merkle_caps) + .zip_eq(&fri_proof.commit_phase_merkle_caps) { pw.set_cap_target(t, x); } @@ -345,31 +316,31 @@ mod tests { for (qt, q) in fpt .query_round_proofs .iter() - .zip(&fri_proof.query_round_proofs) + .zip_eq(&fri_proof.query_round_proofs) { for (at, a) in qt .initial_trees_proof .evals_proofs .iter() - .zip(&q.initial_trees_proof.evals_proofs) + .zip_eq(&q.initial_trees_proof.evals_proofs) { - for (&t, &x) in at.0.iter().zip(&a.0) { + for (&t, &x) in at.0.iter().zip_eq(&a.0) { pw.set_target(t, x); } - for (&t, &x) in at.1.siblings.iter().zip(&a.1.siblings) { + for (&t, &x) in at.1.siblings.iter().zip_eq(&a.1.siblings) { pw.set_hash_target(t, x); } } - for (st, s) in qt.steps.iter().zip(&q.steps) { - for (&t, &x) in st.evals.iter().zip(&s.evals) { + for (st, s) in qt.steps.iter().zip_eq(&q.steps) { + for (&t, &x) in st.evals.iter().zip_eq(&s.evals) { pw.set_extension_target(t, x); } for (&t, &x) in st .merkle_proof .siblings .iter() - .zip(&s.merkle_proof.siblings) + .zip_eq(&s.merkle_proof.siblings) { pw.set_hash_target(t, x); } @@ -582,7 +553,7 @@ mod tests { { let mut builder = CircuitBuilder::::new(config.clone()); let mut pw = PartialWitness::new(); - let pt = proof_to_proof_target(&inner_proof, &mut builder); + let pt = builder.add_virtual_proof_with_pis(&inner_cd); set_proof_target(&inner_proof, &pt, &mut pw); let inner_data = VerifierCircuitTarget { @@ -593,7 +564,7 @@ mod tests { &inner_vd.constants_sigmas_cap, ); - builder.add_recursive_verifier(pt, inner_config, &inner_data, &inner_cd); + builder.verify_proof_with_pis(pt, inner_config, &inner_data, &inner_cd); if print_gate_counts { builder.print_gate_counts(0); diff --git a/plonky2/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs index e612a1c9..cbaec6d9 100644 --- a/plonky2/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -30,6 +30,10 @@ pub(crate) fn verify_with_challenges< verifier_data: &VerifierOnlyCircuitData, common_data: &CommonCircuitData, ) -> Result<()> { + assert_eq!( + proof_with_pis.public_inputs.len(), + common_data.num_public_inputs + ); let public_inputs_hash = &proof_with_pis.get_public_inputs_hash(); let ProofWithPublicInputs { proof, .. } = proof_with_pis;