Merge branch 'generate_dummy_proof' into cyclic_recursion

# Conflicts:
#	plonky2/src/fri/mod.rs
#	plonky2/src/plonk/circuit_data.rs
This commit is contained in:
wborgeaud 2022-10-12 17:45:07 +02:00
commit f497fc652c
13 changed files with 192 additions and 72 deletions

View File

@ -586,6 +586,7 @@ where
VerifierCircuitTarget {
constants_sigmas_cap: builder
.constant_merkle_cap(&verifier_data.verifier_only.constants_sigmas_cap),
circuit_digest: builder.add_virtual_hash(),
}
});
RecursiveAllProofTargetWithData {

View File

@ -117,11 +117,9 @@ where
let inner_data = VerifierCircuitTarget {
constants_sigmas_cap: builder.add_virtual_cap(inner_cd.config.fri_config.cap_height),
circuit_digest: builder.add_virtual_hash(),
};
pw.set_cap_target(
&inner_data.constants_sigmas_cap,
&inner_vd.constants_sigmas_cap,
);
pw.set_verifier_data_target(&inner_data, inner_vd);
builder.verify_proof(pt, &inner_data, inner_cd);
builder.print_gate_counts(0);
@ -151,6 +149,7 @@ where
/// Test serialization and print some size info.
fn test_serialization<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(
proof: &ProofWithPublicInputs<F, C, D>,
vd: &VerifierOnlyCircuitData<C, D>,
cd: &CommonCircuitData<F, C, D>,
) -> Result<()>
where
@ -162,8 +161,10 @@ where
assert_eq!(proof, &proof_from_bytes);
let now = std::time::Instant::now();
let compressed_proof = proof.clone().compress(cd)?;
let decompressed_compressed_proof = compressed_proof.clone().decompress(cd)?;
let compressed_proof = proof.clone().compress(&vd.circuit_digest, cd)?;
let decompressed_compressed_proof = compressed_proof
.clone()
.decompress(&vd.circuit_digest, cd)?;
info!("{:.4}s to compress proof", now.elapsed().as_secs_f64());
assert_eq!(proof, &decompressed_compressed_proof);
@ -204,14 +205,14 @@ fn benchmark(config: &CircuitConfig, log2_inner_size: usize) -> Result<()> {
// Add a second layer of recursion to shrink the proof size further
let outer = recursive_proof::<F, C, C, D>(&middle, config, None)?;
let (proof, _, cd) = &outer;
let (proof, vd, cd) = &outer;
info!(
"Double recursion proof degree {} = 2^{}",
cd.degree(),
cd.degree_bits
);
test_serialization(proof, cd)?;
test_serialization(proof, vd, cd)?;
Ok(())
}

View File

@ -54,7 +54,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, Clone)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct FriParams {
/// User-specified FRI configuration.
pub config: FriConfig,

View File

@ -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<usize>,
pub(crate) groups: Vec<Range<usize>>,

View File

@ -13,6 +13,7 @@ use crate::hash::merkle_tree::MerkleCap;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::target::{BoolTarget, Target};
use crate::iop::wire::Wire;
use crate::plonk::circuit_data::{VerifierCircuitTarget, VerifierOnlyCircuitData};
use crate::plonk::config::{AlgebraicHasher, GenericConfig};
use crate::plonk::proof::{Proof, ProofTarget, ProofWithPublicInputs, ProofWithPublicInputsTarget};
@ -197,6 +198,18 @@ pub trait Witness<F: Field> {
}
}
fn set_verifier_data_target<C: GenericConfig<D, F = F>, const D: usize>(
&mut self,
vdt: &VerifierCircuitTarget,
vd: &VerifierOnlyCircuitData<C, D>,
) where
F: RichField + Extendable<D>,
C::Hasher: AlgebraicHasher<F>,
{
self.set_cap_target(&vdt.constants_sigmas_cap, &vd.constants_sigmas_cap);
self.set_hash_target(vdt.circuit_digest, vd.circuit_digest);
}
fn set_wire(&mut self, wire: Wire, value: F) {
self.set_target(Target::Wire(wire), value)
}

View File

@ -271,6 +271,10 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
);
}
pub fn add_gate_to_gate_set(&mut self, gate: GateRef<F, D>) {
self.gates.insert(gate);
}
pub fn connect_extension(&mut self, src: ExtensionTarget<D>, dst: ExtensionTarget<D>) {
for i in 0..D {
self.connect(src.0[i], dst.0[i]);
@ -751,11 +755,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
Some(&fft_root_table),
);
let constants_sigmas_cap = constants_sigmas_commitment.merkle_tree.cap.clone();
let verifier_only = VerifierOnlyCircuitData {
constants_sigmas_cap: constants_sigmas_cap.clone(),
};
// Map between gates where not all generators are used and the gate's number of used generators.
let incomplete_gates = self
.current_slots
@ -796,17 +795,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
indices.shrink_to_fit();
}
let prover_only = ProverOnlyCircuitData {
generators: self.generators,
generator_indices_by_watches,
constants_sigmas_commitment,
sigmas: transpose_poly_values(sigma_vecs),
subgroup,
public_inputs: self.public_inputs,
representative_map: forest.parents,
fft_root_table: Some(fft_root_table),
};
let num_gate_constraints = gates
.iter()
.map(|gate| gate.0.num_constraints())
@ -816,6 +804,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let num_partial_products =
num_partial_products(self.config.num_routed_wires, quotient_degree_factor);
let constants_sigmas_cap = constants_sigmas_commitment.merkle_tree.cap.clone();
// TODO: This should also include an encoding of gate constraints.
let circuit_digest_parts = [
constants_sigmas_cap.flatten(),
@ -838,6 +827,22 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
num_public_inputs,
k_is,
num_partial_products,
};
let prover_only = ProverOnlyCircuitData {
generators: self.generators,
generator_indices_by_watches,
constants_sigmas_commitment,
sigmas: transpose_poly_values(sigma_vecs),
subgroup,
public_inputs: self.public_inputs,
representative_map: forest.parents,
fft_root_table: Some(fft_root_table),
circuit_digest,
};
let verifier_only = VerifierOnlyCircuitData {
constants_sigmas_cap,
circuit_digest,
};

View File

@ -15,7 +15,7 @@ use crate::fri::structure::{
use crate::fri::{FriConfig, FriParams};
use crate::gates::gate::GateRef;
use crate::gates::selectors::SelectorsInfo;
use crate::hash::hash_types::{MerkleCapTarget, RichField};
use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField};
use crate::hash::merkle_tree::MerkleCap;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::WitnessGenerator;
@ -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,
@ -141,6 +141,23 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
compressed_proof_with_pis.verify(&self.verifier_only, &self.common)
}
pub fn compress(
&self,
proof: ProofWithPublicInputs<F, C, D>,
) -> Result<CompressedProofWithPublicInputs<F, C, D>> {
proof.compress(&self.verifier_only.circuit_digest, &self.common)
}
pub fn decompress(
&self,
proof: CompressedProofWithPublicInputs<F, C, D>,
) -> Result<ProofWithPublicInputs<F, C, D>>
where
[(); C::Hasher::HASH_SIZE]:,
{
proof.decompress(&self.verifier_only.circuit_digest, &self.common)
}
pub fn verifier_data(self) -> VerifierCircuitData<F, C, D> {
let CircuitData {
verifier_only,
@ -253,6 +270,9 @@ pub struct ProverOnlyCircuitData<
pub representative_map: Vec<usize>,
/// Pre-computed roots for faster FFT.
pub fft_root_table: Option<FftRootTable<F>>,
/// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to
/// seed Fiat-Shamir.
pub circuit_digest: <<C as GenericConfig<D>>::Hasher as Hasher<F>>::Hash,
}
/// Circuit data required by the verifier, but not the prover.
@ -260,10 +280,13 @@ pub struct ProverOnlyCircuitData<
pub struct VerifierOnlyCircuitData<C: GenericConfig<D>, const D: usize> {
/// A commitment to each constant polynomial and each permutation polynomial.
pub constants_sigmas_cap: MerkleCap<C::F, C::Hasher>,
/// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to
/// seed Fiat-Shamir.
pub circuit_digest: <<C as GenericConfig<D>>::Hasher as Hasher<C::F>>::Hash,
}
/// Circuit data required by both the prover and the verifier.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct CommonCircuitData<
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F>,
@ -276,7 +299,7 @@ pub struct CommonCircuitData<
pub degree_bits: usize,
/// The types of gates used in this circuit, along with their prefixes.
pub(crate) gates: Vec<GateRef<F, D>>,
pub(crate) gates: Vec<GateRef<C::F, D>>,
/// Information on the circuit's selector polynomials.
pub(crate) selectors_info: SelectorsInfo,
@ -293,14 +316,10 @@ pub struct CommonCircuitData<
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>,
pub(crate) k_is: Vec<C::F>,
/// The number of partial products needed to compute the `Z` polynomials.
pub(crate) num_partial_products: usize,
/// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to
/// seed Fiat-Shamir.
pub(crate) circuit_digest: <<C as GenericConfig<D>>::Hasher as Hasher<F>>::Hash,
}
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
@ -476,4 +495,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
pub struct VerifierCircuitTarget {
/// A commitment to each constant polynomial and each permutation polynomial.
pub constants_sigmas_cap: MerkleCapTarget,
/// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to
/// seed Fiat-Shamir.
pub circuit_digest: HashOutTarget,
}

View File

@ -1,20 +1,65 @@
use anyhow::{ensure, Result};
use itertools::Itertools;
use plonky2_field::extension::Extendable;
use plonky2_util::ceil_div_usize;
use crate::fri::proof::{
FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget,
};
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
use crate::gates::noop::NoopGate;
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::iop::witness::{PartialWitness, Witness};
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::plonk::circuit_data::{CircuitData, CommonCircuitData, VerifierCircuitTarget};
use crate::plonk::config::{AlgebraicHasher, GenericConfig, Hasher};
use crate::plonk::proof::{
OpeningSetTarget, ProofTarget, ProofWithPublicInputs, ProofWithPublicInputsTarget,
};
use crate::with_context;
/// Generate a proof having a given `CommonCircuitData`.
pub fn dummy_proof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(
common_data: &CommonCircuitData<F, C, D>,
) -> Result<(ProofWithPublicInputs<F, C, D>, CircuitData<F, C, D>)>
where
[(); C::Hasher::HASH_SIZE]:,
{
let config = common_data.config.clone();
let mut pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, D>::new(config);
ensure!(
!common_data.config.zero_knowledge,
"Degree calculation can be off if zero-knowledge is on."
);
let degree = 1 << common_data.degree_bits;
// Number of `NoopGate`s to add to get a circuit of size `degree` in the end.
// Need to account for public input hashing, a `PublicInputGate` and a `ConstantGate`.
let num_noop_gate = degree - ceil_div_usize(common_data.num_public_inputs, 8) - 2;
for _ in 0..num_noop_gate {
builder.add_gate(NoopGate, vec![]);
}
for gate in &common_data.gates {
builder.add_gate_to_gate_set(gate.clone());
}
for _ in 0..common_data.num_public_inputs {
let t = builder.add_virtual_public_input();
pw.set_target(t, F::ZERO);
}
let data = builder.build::<C>();
assert_eq!(&data.common, common_data);
let proof = data.prove(pw)?;
Ok((proof, data))
}
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Verify `proof0` if `condition` else verify `proof1`.
/// `proof0` and `proof1` are assumed to use the same `CommonCircuitData`.
@ -82,6 +127,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
inner_verifier_data0.constants_sigmas_cap.clone(),
inner_verifier_data1.constants_sigmas_cap.clone(),
),
circuit_digest: self.select_hash(
condition,
inner_verifier_data0.circuit_digest,
inner_verifier_data1.circuit_digest,
),
};
self.verify_proof(selected_proof, &selected_verifier_data, inner_common_data);
@ -297,6 +347,7 @@ mod tests {
type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_recursion_config();
// Generate proof.
let mut builder = CircuitBuilder::<F, D>::new(config.clone());
let mut pw = PartialWitness::new();
let t = builder.add_virtual_target();
@ -310,27 +361,26 @@ mod tests {
let proof = data.prove(pw)?;
data.verify(proof.clone())?;
// Generate dummy proof with the same `CommonCircuitData`.
let (dummy_proof, dummy_data) = dummy_proof(&data.common)?;
// Conditionally verify the two proofs.
let mut builder = CircuitBuilder::<F, D>::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);
pw.set_proof_with_pis_target(&dummy_pt, &dummy_proof);
let inner_data = VerifierCircuitTarget {
constants_sigmas_cap: builder.add_virtual_cap(data.common.config.fri_config.cap_height),
circuit_digest: builder.add_virtual_hash(),
};
pw.set_cap_target(
&inner_data.constants_sigmas_cap,
&data.verifier_only.constants_sigmas_cap,
);
pw.set_verifier_data_target(&inner_data, &data.verifier_only);
let dummy_inner_data = VerifierCircuitTarget {
constants_sigmas_cap: builder.add_virtual_cap(data.common.config.fri_config.cap_height),
circuit_digest: builder.add_virtual_hash(),
};
pw.set_cap_target(
&dummy_inner_data.constants_sigmas_cap,
&data.verifier_only.constants_sigmas_cap,
);
pw.set_verifier_data_target(&dummy_inner_data, &dummy_data.verifier_only);
let b = builder.constant_bool(F::rand().0 % 2 == 0);
builder.conditionally_verify_proof(
b,

View File

@ -29,6 +29,7 @@ fn get_challenges<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, cons
commit_phase_merkle_caps: &[MerkleCap<F, C::Hasher>],
final_poly: &PolynomialCoeffs<F::Extension>,
pow_witness: F,
circuit_digest: &<<C as GenericConfig<D>>::Hasher as Hasher<C::F>>::Hash,
common_data: &CommonCircuitData<F, C, D>,
) -> anyhow::Result<ProofChallenges<F, D>> {
let config = &common_data.config;
@ -37,7 +38,7 @@ fn get_challenges<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, cons
let mut challenger = Challenger::<F, C::Hasher>::new();
// Observe the instance.
challenger.observe_hash::<C::Hasher>(common_data.circuit_digest);
challenger.observe_hash::<C::Hasher>(*circuit_digest);
challenger.observe_hash::<C::InnerHasher>(public_inputs_hash);
challenger.observe_cap(wires_cap);
@ -72,10 +73,11 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
{
pub(crate) fn fri_query_indices(
&self,
circuit_digest: &<<C as GenericConfig<D>>::Hasher as Hasher<C::F>>::Hash,
common_data: &CommonCircuitData<F, C, D>,
) -> anyhow::Result<Vec<usize>> {
Ok(self
.get_challenges(self.get_public_inputs_hash(), common_data)?
.get_challenges(self.get_public_inputs_hash(), circuit_digest, common_data)?
.fri_challenges
.fri_query_indices)
}
@ -84,6 +86,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
pub(crate) fn get_challenges(
&self,
public_inputs_hash: <<C as GenericConfig<D>>::InnerHasher as Hasher<F>>::Hash,
circuit_digest: &<<C as GenericConfig<D>>::Hasher as Hasher<C::F>>::Hash,
common_data: &CommonCircuitData<F, C, D>,
) -> anyhow::Result<ProofChallenges<F, D>> {
let Proof {
@ -109,6 +112,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
commit_phase_merkle_caps,
final_poly,
*pow_witness,
circuit_digest,
common_data,
)
}
@ -121,6 +125,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
pub(crate) fn get_challenges(
&self,
public_inputs_hash: <<C as GenericConfig<D>>::InnerHasher as Hasher<F>>::Hash,
circuit_digest: &<<C as GenericConfig<D>>::Hasher as Hasher<C::F>>::Hash,
common_data: &CommonCircuitData<F, C, D>,
) -> anyhow::Result<ProofChallenges<F, D>> {
let CompressedProof {
@ -146,6 +151,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
commit_phase_merkle_caps,
final_poly,
*pow_witness,
circuit_digest,
common_data,
)
}
@ -237,6 +243,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
commit_phase_merkle_caps: &[MerkleCapTarget],
final_poly: &PolynomialCoeffsExtTarget<D>,
pow_witness: Target,
inner_circuit_digest: HashOutTarget,
inner_common_data: &CommonCircuitData<F, C, D>,
) -> ProofChallengesTarget<D>
where
@ -248,9 +255,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let mut challenger = RecursiveChallenger::<F, C::Hasher, D>::new(self);
// Observe the instance.
let digest =
HashOutTarget::from_vec(self.constants(&inner_common_data.circuit_digest.elements));
challenger.observe_hash(&digest);
challenger.observe_hash(&inner_circuit_digest);
challenger.observe_hash(&public_inputs_hash);
challenger.observe_cap(wires_cap);
@ -286,6 +291,7 @@ impl<const D: usize> ProofWithPublicInputsTarget<D> {
&self,
builder: &mut CircuitBuilder<F, D>,
public_inputs_hash: HashOutTarget,
inner_circuit_digest: HashOutTarget,
inner_common_data: &CommonCircuitData<F, C, D>,
) -> ProofChallengesTarget<D>
where
@ -314,6 +320,7 @@ impl<const D: usize> ProofWithPublicInputsTarget<D> {
commit_phase_merkle_caps,
final_poly,
*pow_witness,
inner_circuit_digest,
inner_common_data,
)
}

View File

@ -81,9 +81,10 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
{
pub fn compress(
self,
circuit_digest: &<<C as GenericConfig<D>>::Hasher as Hasher<C::F>>::Hash,
common_data: &CommonCircuitData<F, C, D>,
) -> anyhow::Result<CompressedProofWithPublicInputs<F, C, D>> {
let indices = self.fri_query_indices(common_data)?;
let indices = self.fri_query_indices(circuit_digest, common_data)?;
let compressed_proof = self.proof.compress(&indices, &common_data.fri_params);
Ok(CompressedProofWithPublicInputs {
public_inputs: self.public_inputs,
@ -176,12 +177,14 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
{
pub fn decompress(
self,
circuit_digest: &<<C as GenericConfig<D>>::Hasher as Hasher<C::F>>::Hash,
common_data: &CommonCircuitData<F, C, D>,
) -> anyhow::Result<ProofWithPublicInputs<F, C, D>>
where
[(); C::Hasher::HASH_SIZE]:,
{
let challenges = self.get_challenges(self.get_public_inputs_hash(), common_data)?;
let challenges =
self.get_challenges(self.get_public_inputs_hash(), circuit_digest, common_data)?;
let fri_inferred_elements = self.get_inferred_elements(&challenges, common_data);
let decompressed_proof =
self.proof
@ -205,7 +208,11 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
"Number of public inputs doesn't match circuit data."
);
let public_inputs_hash = self.get_public_inputs_hash();
let challenges = self.get_challenges(public_inputs_hash, common_data)?;
let challenges = self.get_challenges(
public_inputs_hash,
&verifier_data.circuit_digest,
common_data,
)?;
let fri_inferred_elements = self.get_inferred_elements(&challenges, common_data);
let decompressed_proof =
self.proof
@ -418,8 +425,8 @@ mod tests {
verify(proof.clone(), &data.verifier_only, &data.common)?;
// Verify that `decompress ∘ compress = identity`.
let compressed_proof = proof.clone().compress(&data.common)?;
let decompressed_compressed_proof = compressed_proof.clone().decompress(&data.common)?;
let compressed_proof = data.compress(proof.clone())?;
let decompressed_compressed_proof = data.decompress(compressed_proof.clone())?;
assert_eq!(proof, decompressed_compressed_proof);
verify(proof, &data.verifier_only, &data.common)?;

View File

@ -81,7 +81,7 @@ where
let mut challenger = Challenger::<F, C::Hasher>::new();
// Observe the instance.
challenger.observe_hash::<C::Hasher>(common_data.circuit_digest);
challenger.observe_hash::<C::Hasher>(prover_data.circuit_digest);
challenger.observe_hash::<C::InnerHasher>(public_inputs_hash);
challenger.observe_cap(&wires_commitment.merkle_tree.cap);

View File

@ -29,7 +29,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
);
let public_inputs_hash =
self.hash_n_to_hash_no_pad::<C::InnerHasher>(proof_with_pis.public_inputs.clone());
let challenges = proof_with_pis.get_challenges(self, public_inputs_hash, inner_common_data);
let challenges = proof_with_pis.get_challenges(
self,
public_inputs_hash,
inner_verifier_data.circuit_digest,
inner_common_data,
);
self.verify_proof_with_challenges(
proof_with_pis.proof,
@ -205,9 +210,9 @@ mod tests {
let config = CircuitConfig::standard_recursion_zk_config();
let (proof, vd, cd) = dummy_proof::<F, C, D>(&config, 4_000)?;
let (proof, _vd, cd) =
let (proof, vd, cd) =
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, None, true, true)?;
test_serialization(&proof, &cd)?;
test_serialization(&proof, &vd, &cd)?;
Ok(())
}
@ -231,11 +236,11 @@ mod tests {
assert_eq!(cd.degree_bits, 13);
// Shrink it to 2^12.
let (proof, _vd, cd) =
let (proof, vd, cd) =
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, None, true, true)?;
assert_eq!(cd.degree_bits, 12);
test_serialization(&proof, &cd)?;
test_serialization(&proof, &vd, &cd)?;
Ok(())
}
@ -287,11 +292,11 @@ mod tests {
},
..high_rate_config
};
let (proof, _vd, cd) =
let (proof, vd, cd) =
recursive_proof::<F, KC, C, D>(proof, vd, cd, &final_config, None, true, true)?;
assert_eq!(cd.degree_bits, 12, "final proof too large");
test_serialization(&proof, &cd)?;
test_serialization(&proof, &vd, &cd)?;
Ok(())
}
@ -309,11 +314,11 @@ mod tests {
let (proof, vd, cd) =
recursive_proof::<F, PC, PC, D>(proof, vd, cd, &config, None, false, false)?;
test_serialization(&proof, &cd)?;
test_serialization(&proof, &vd, &cd)?;
let (proof, _vd, cd) =
let (proof, vd, cd) =
recursive_proof::<F, KC, PC, D>(proof, vd, cd, &config, None, false, false)?;
test_serialization(&proof, &cd)?;
test_serialization(&proof, &vd, &cd)?;
Ok(())
}
@ -372,11 +377,13 @@ mod tests {
let inner_data = VerifierCircuitTarget {
constants_sigmas_cap: builder.add_virtual_cap(inner_cd.config.fri_config.cap_height),
circuit_digest: builder.add_virtual_hash(),
};
pw.set_cap_target(
&inner_data.constants_sigmas_cap,
&inner_vd.constants_sigmas_cap,
);
pw.set_hash_target(inner_data.circuit_digest, inner_vd.circuit_digest);
builder.verify_proof(pt, &inner_data, &inner_cd);
@ -414,6 +421,7 @@ mod tests {
const D: usize,
>(
proof: &ProofWithPublicInputs<F, C, D>,
vd: &VerifierOnlyCircuitData<C, D>,
cd: &CommonCircuitData<F, C, D>,
) -> Result<()>
where
@ -425,8 +433,10 @@ mod tests {
assert_eq!(proof, &proof_from_bytes);
let now = std::time::Instant::now();
let compressed_proof = proof.clone().compress(cd)?;
let decompressed_compressed_proof = compressed_proof.clone().decompress(cd)?;
let compressed_proof = proof.clone().compress(&vd.circuit_digest, cd)?;
let decompressed_compressed_proof = compressed_proof
.clone()
.decompress(&vd.circuit_digest, cd)?;
info!("{:.4}s to compress proof", now.elapsed().as_secs_f64());
assert_eq!(proof, &decompressed_compressed_proof);

View File

@ -23,7 +23,11 @@ where
validate_proof_with_pis_shape(&proof_with_pis, common_data)?;
let public_inputs_hash = proof_with_pis.get_public_inputs_hash();
let challenges = proof_with_pis.get_challenges(public_inputs_hash, common_data)?;
let challenges = proof_with_pis.get_challenges(
public_inputs_hash,
&verifier_data.circuit_digest,
common_data,
)?;
verify_with_challenges(
proof_with_pis.proof,