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
This commit is contained in:
Daniel Lubarov 2022-01-23 23:27:26 -08:00 committed by GitHub
parent 04fbb05d7c
commit a6e64d1c7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 246 additions and 163 deletions

View File

@ -26,7 +26,7 @@ pub struct FriQueryStep<F: RichField + Extendable<D>, H: Hasher<F>, const D: usi
pub merkle_proof: MerkleProof<F, H>,
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct FriQueryStepTarget<const D: usize> {
pub evals: Vec<ExtensionTarget<D>>,
pub merkle_proof: MerkleProofTarget,
@ -51,7 +51,7 @@ impl<F: RichField, H: Hasher<F>> FriInitialTreeProof<F, H> {
}
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct FriInitialTreeProofTarget {
pub evals_proofs: Vec<(Vec<Target>, MerkleProofTarget)>,
}
@ -80,7 +80,7 @@ pub struct FriQueryRound<F: RichField + Extendable<D>, H: Hasher<F>, const D: us
pub steps: Vec<FriQueryStep<F, H, D>>,
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct FriQueryRoundTarget<const D: usize> {
pub initial_trees_proof: FriInitialTreeProofTarget,
pub steps: Vec<FriQueryStepTarget<D>>,
@ -111,6 +111,7 @@ pub struct FriProof<F: RichField + Extendable<D>, H: Hasher<F>, const D: usize>
pub pow_witness: F,
}
#[derive(Debug)]
pub struct FriProofTarget<const D: usize> {
pub commit_phase_merkle_caps: Vec<MerkleCapTarget>,
pub query_round_proofs: Vec<FriQueryRoundTarget<D>>,

View File

@ -72,9 +72,8 @@ fn fri_committed_trees<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>,
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

View File

@ -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<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
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<D> {
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<D> {
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 &params.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<D> {
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

View File

@ -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<const D: usize>(pub Vec<ExtensionTarget<D>>);
impl<const D: usize> PolynomialCoeffsExtTarget<D> {

View File

@ -17,7 +17,7 @@ pub struct MerkleProof<F: RichField, H: Hasher<F>> {
pub siblings: Vec<H::Hash>,
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct MerkleProofTarget {
/// The Merkle digest of each sibling subtree, staying from the bottommost layer.
pub siblings: Vec<HashOutTarget>,

View File

@ -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<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
(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<D> {
ExtensionTarget(self.add_virtual_targets(D).try_into().unwrap())
}
@ -182,6 +190,14 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
.collect()
}
pub(crate) fn add_virtual_poly_coeff_ext(
&mut self,
num_coeffs: usize,
) -> PolynomialCoeffsExtTarget<D> {
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<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// 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::<C::InnerHasher>(self.public_inputs.clone(), true);
let pi_gate = self.add_gate(PublicInputGate, vec![]);
@ -736,6 +753,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
num_gate_constraints,
num_constants,
num_virtual_targets: self.virtual_target_index,
num_public_inputs,
k_is,
num_partial_products,
circuit_digest,

View File

@ -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<F>,
@ -341,34 +343,42 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
}
fn fri_preprocessed_polys(&self) -> Vec<FriPolynomialInfo> {
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<FriPolynomialInfo> {
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<FriPolynomialInfo> {
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> {
FriPolynomialInfo::from_range(PlonkOracle::ZS_PARTIAL_PRODUCTS.index, self.zs_range())
}
fn fri_quotient_polys(&self) -> Vec<FriPolynomialInfo> {
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<FriPolynomialInfo> {

View File

@ -32,6 +32,7 @@ pub struct Proof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const
pub opening_proof: FriProof<F, C::Hasher, D>,
}
#[derive(Debug)]
pub struct ProofTarget<const D: usize> {
pub wires_cap: MerkleCapTarget,
pub plonk_zs_partial_products_cap: MerkleCapTarget,
@ -255,6 +256,7 @@ pub(crate) struct FriInferredElements<F: RichField + Extendable<D>, const D: usi
pub Vec<F::Extension>,
);
#[derive(Debug)]
pub struct ProofWithPublicInputsTarget<const D: usize> {
pub proof: ProofTarget<D>,
pub public_inputs: Vec<Target>,

View File

@ -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<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Recursively verifies an inner proof.
pub fn add_recursive_verifier<C: GenericConfig<D, F = F>>(
pub fn verify_proof_with_pis<C: GenericConfig<D, F = F>>(
&mut self,
proof_with_pis: ProofWithPublicInputsTarget<D>,
inner_config: &CircuitConfig,
@ -26,12 +26,34 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
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::<C::InnerHasher>(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<C: GenericConfig<D, F = F>>(
&mut self,
proof: ProofTarget<D>,
public_inputs_hash: HashOutTarget,
inner_config: &CircuitConfig,
inner_verifier_data: &VerifierCircuitTarget,
inner_common_data: &CommonCircuitData<F, C, D>,
) where
C::Hasher: AlgebraicHasher<F>,
{
let one = self.one_extension();
let num_challenges = inner_config.num_challenges;
let public_inputs_hash = &self.hash_n_to_hash::<C::InnerHasher>(public_inputs, true);
let mut challenger = RecursiveChallenger::<F, C::Hasher, D>::new(self);
let (betas, gammas, alphas, zeta) =
@ -41,7 +63,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
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<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
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<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
)
);
}
}
#[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<D>,
C: GenericConfig<D, F = F>,
const D: usize,
>(
proof: &Proof<F, C, D>,
builder: &mut CircuitBuilder<F, D>,
) -> FriQueryRoundTarget<D> {
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<D>,
C: GenericConfig<D, F = F>,
const D: usize,
>(
proof_with_pis: &ProofWithPublicInputs<F, C, D>,
builder: &mut CircuitBuilder<F, D>,
pub fn add_virtual_proof_with_pis<InnerC: GenericConfig<D, F = F>>(
&mut self,
common_data: &CommonCircuitData<F, InnerC, D>,
) -> ProofWithPublicInputsTarget<D> {
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<InnerC: GenericConfig<D, F = F>>(
&mut self,
common_data: &CommonCircuitData<F, InnerC, D>,
) -> ProofTarget<D> {
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<InnerC: GenericConfig<D, F = F>>(
&mut self,
common_data: &CommonCircuitData<F, InnerC, D>,
) -> OpeningSetTarget<D> {
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<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(
proof: &ProofWithPublicInputs<F, C, D>,
@ -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::<F, D>::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);

View File

@ -30,6 +30,10 @@ pub(crate) fn verify_with_challenges<
verifier_data: &VerifierOnlyCircuitData<C, D>,
common_data: &CommonCircuitData<F, C, D>,
) -> 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;