plonky2/src/plonk/recursive_verifier.rs

515 lines
18 KiB
Rust
Raw Normal View History

use crate::field::extension_field::Extendable;
use crate::field::field_types::RichField;
use crate::hash::hash_types::HashOutTarget;
use crate::iop::challenger::RecursiveChallenger;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData, VerifierCircuitTarget};
use crate::plonk::proof::ProofWithPublicInputsTarget;
use crate::plonk::vanishing_poly::eval_vanishing_poly_recursively;
use crate::plonk::vars::EvaluationTargets;
2021-07-23 17:31:00 +02:00
use crate::util::reducing::ReducingFactorTarget;
Reduce noise in FRI logging (#129) * Reduce noise in FRI logging Previously, all logs related to gate counts were at the `Debug` log level. This PR gives us more flexibility to adjust the log levels of particular scopes. In particular, our circuit checks 40 FRI queries, and we log a bunch of steps for each query, creating a lot of noise. With this change, we log just a single FRI query at the `Debug` level, and demote others to the `Trace` level. With `RUST_LOG=debug`, our logs now look like ``` [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] 17631 gates to root [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 8 gates to observe proof and generates challenges [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 4150 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 3184 gates to evaluate gate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 227 gates to evaluate InterpolationGate { num_points: 4, _phantom: PhantomData }<D=4> constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 867 gates to evaluate <R=101> GMiMCGate { ... } constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 576 gates to evaluate BaseSumGate { num_limbs: 63 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 78 gates to evaluate ArithmeticExtensionGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 288 gates to evaluate BaseSumGate { num_limbs: 31 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 115 gates to evaluate InsertionGate { vec_size: 3, _phantom: PhantomData }<D=4> constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 26 gates to evaluate BaseSumGate { num_limbs: 2 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 633 gates to evaluate ReducingGate { num_coeffs: 21 } constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 4 gates to evaluate ConstantGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to evaluate PublicInputGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 2 gates to evaluate NoopGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 16 gates to check vanishing and quotient polynomials. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 13336 gates to verify FRI proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 6 gates to recover the random betas used in the FRI reductions. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 4 gates to check PoW [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 104 gates to precompute reduced evaluations [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 95 gates to check FRI initial proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 22 gates to verify 0'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 33 gates to verify 1'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 2'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 3'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 34 gates to compute x from its index [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 32 gates to combine initial oracles [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 17 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 15 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 13 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 9 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 7 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer final evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 8 gates to evaluate final polynomial ``` This bit corresponds to the single FRI query being shown: ``` [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds ``` * Minor cleanup * Address feedback
2021-07-26 16:21:14 -07:00
use crate::with_context;
2021-02-26 13:18:41 -08:00
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
2021-07-08 17:16:26 +02:00
/// Recursively verifies an inner proof.
pub fn add_recursive_verifier(
&mut self,
proof_with_pis: ProofWithPublicInputsTarget<D>,
2021-07-09 10:01:58 +02:00
inner_config: &CircuitConfig,
2021-07-12 14:25:28 +02:00
inner_verifier_data: &VerifierCircuitTarget,
inner_common_data: &CommonCircuitData<F, D>,
2021-07-08 17:16:26 +02:00
) {
let ProofWithPublicInputsTarget {
proof,
public_inputs,
} = proof_with_pis;
2021-07-12 14:25:28 +02:00
let one = self.one_extension();
let num_challenges = inner_config.num_challenges;
let public_inputs_hash = &self.hash_n_to_hash(public_inputs, true);
2021-07-12 14:25:28 +02:00
let mut challenger = RecursiveChallenger::new(self);
Tree of scopes (#106) * Tree of scopes This is an extension of the context concept. Earlier I was planning to store a simple stack of contexts, but I ended up storing the whole history, in a tree structure. This gives us more control over the output, i.e. we can print the gate count of a parent scope before those of its child scopes, which seems more user-friendly. Sample gate count output: [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] 27829 gates to root [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 2373 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 1284 gates to evaluate gate constraints [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 25312 gates to verify FRI proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 650 gates to verify 0'th FRI query [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 96 gates to check FRI initial proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 65 gates to compute x from its index [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 233 gates to combine initial oracles ... Sample copy constraint failure: Error: Copy constraint 'root > verify FRI proof > verify 0'th FRI query > check FRI initial proof > verify 0'th initial Merkle proof > check Merkle root: 0-th hash element' between wire 12 of gate #2550 [...] and wire 0 of gate #0 [...] is not satisfied. Got values of 6861386743364621393 and 0 respectively. * No min * info -> debug * Move to its own file
2021-07-19 12:22:18 -07:00
let (betas, gammas, alphas, zeta) =
Reduce noise in FRI logging (#129) * Reduce noise in FRI logging Previously, all logs related to gate counts were at the `Debug` log level. This PR gives us more flexibility to adjust the log levels of particular scopes. In particular, our circuit checks 40 FRI queries, and we log a bunch of steps for each query, creating a lot of noise. With this change, we log just a single FRI query at the `Debug` level, and demote others to the `Trace` level. With `RUST_LOG=debug`, our logs now look like ``` [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] 17631 gates to root [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 8 gates to observe proof and generates challenges [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 4150 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 3184 gates to evaluate gate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 227 gates to evaluate InterpolationGate { num_points: 4, _phantom: PhantomData }<D=4> constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 867 gates to evaluate <R=101> GMiMCGate { ... } constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 576 gates to evaluate BaseSumGate { num_limbs: 63 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 78 gates to evaluate ArithmeticExtensionGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 288 gates to evaluate BaseSumGate { num_limbs: 31 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 115 gates to evaluate InsertionGate { vec_size: 3, _phantom: PhantomData }<D=4> constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 26 gates to evaluate BaseSumGate { num_limbs: 2 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 633 gates to evaluate ReducingGate { num_coeffs: 21 } constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 4 gates to evaluate ConstantGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to evaluate PublicInputGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 2 gates to evaluate NoopGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 16 gates to check vanishing and quotient polynomials. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 13336 gates to verify FRI proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 6 gates to recover the random betas used in the FRI reductions. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 4 gates to check PoW [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 104 gates to precompute reduced evaluations [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 95 gates to check FRI initial proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 22 gates to verify 0'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 33 gates to verify 1'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 2'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 3'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 34 gates to compute x from its index [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 32 gates to combine initial oracles [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 17 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 15 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 13 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 9 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 7 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer final evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 8 gates to evaluate final polynomial ``` This bit corresponds to the single FRI query being shown: ``` [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds ``` * Minor cleanup * Address feedback
2021-07-26 16:21:14 -07:00
with_context!(self, "observe proof and generates challenges", {
// Observe the instance.
let digest = HashOutTarget::from_vec(
Tree of scopes (#106) * Tree of scopes This is an extension of the context concept. Earlier I was planning to store a simple stack of contexts, but I ended up storing the whole history, in a tree structure. This gives us more control over the output, i.e. we can print the gate count of a parent scope before those of its child scopes, which seems more user-friendly. Sample gate count output: [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] 27829 gates to root [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 2373 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 1284 gates to evaluate gate constraints [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 25312 gates to verify FRI proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 650 gates to verify 0'th FRI query [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 96 gates to check FRI initial proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 65 gates to compute x from its index [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 233 gates to combine initial oracles ... Sample copy constraint failure: Error: Copy constraint 'root > verify FRI proof > verify 0'th FRI query > check FRI initial proof > verify 0'th initial Merkle proof > check Merkle root: 0-th hash element' between wire 12 of gate #2550 [...] and wire 0 of gate #0 [...] is not satisfied. Got values of 6861386743364621393 and 0 respectively. * No min * info -> debug * Move to its own file
2021-07-19 12:22:18 -07:00
self.constants(&inner_common_data.circuit_digest.elements),
);
challenger.observe_hash(&digest);
2021-08-16 10:41:12 +02:00
challenger.observe_hash(public_inputs_hash);
2021-07-12 14:25:28 +02:00
2021-08-10 15:53:27 +02:00
challenger.observe_cap(&proof.wires_cap);
Tree of scopes (#106) * Tree of scopes This is an extension of the context concept. Earlier I was planning to store a simple stack of contexts, but I ended up storing the whole history, in a tree structure. This gives us more control over the output, i.e. we can print the gate count of a parent scope before those of its child scopes, which seems more user-friendly. Sample gate count output: [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] 27829 gates to root [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 2373 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 1284 gates to evaluate gate constraints [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 25312 gates to verify FRI proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 650 gates to verify 0'th FRI query [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 96 gates to check FRI initial proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 65 gates to compute x from its index [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 233 gates to combine initial oracles ... Sample copy constraint failure: Error: Copy constraint 'root > verify FRI proof > verify 0'th FRI query > check FRI initial proof > verify 0'th initial Merkle proof > check Merkle root: 0-th hash element' between wire 12 of gate #2550 [...] and wire 0 of gate #0 [...] is not satisfied. Got values of 6861386743364621393 and 0 respectively. * No min * info -> debug * Move to its own file
2021-07-19 12:22:18 -07:00
let betas = challenger.get_n_challenges(self, num_challenges);
let gammas = challenger.get_n_challenges(self, num_challenges);
2021-07-12 14:25:28 +02:00
2021-08-10 15:53:27 +02:00
challenger.observe_cap(&proof.plonk_zs_partial_products_cap);
Tree of scopes (#106) * Tree of scopes This is an extension of the context concept. Earlier I was planning to store a simple stack of contexts, but I ended up storing the whole history, in a tree structure. This gives us more control over the output, i.e. we can print the gate count of a parent scope before those of its child scopes, which seems more user-friendly. Sample gate count output: [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] 27829 gates to root [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 2373 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 1284 gates to evaluate gate constraints [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 25312 gates to verify FRI proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 650 gates to verify 0'th FRI query [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 96 gates to check FRI initial proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 65 gates to compute x from its index [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 233 gates to combine initial oracles ... Sample copy constraint failure: Error: Copy constraint 'root > verify FRI proof > verify 0'th FRI query > check FRI initial proof > verify 0'th initial Merkle proof > check Merkle root: 0-th hash element' between wire 12 of gate #2550 [...] and wire 0 of gate #0 [...] is not satisfied. Got values of 6861386743364621393 and 0 respectively. * No min * info -> debug * Move to its own file
2021-07-19 12:22:18 -07:00
let alphas = challenger.get_n_challenges(self, num_challenges);
2021-07-08 17:16:26 +02:00
2021-08-10 15:53:27 +02:00
challenger.observe_cap(&proof.quotient_polys_cap);
Tree of scopes (#106) * Tree of scopes This is an extension of the context concept. Earlier I was planning to store a simple stack of contexts, but I ended up storing the whole history, in a tree structure. This gives us more control over the output, i.e. we can print the gate count of a parent scope before those of its child scopes, which seems more user-friendly. Sample gate count output: [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] 27829 gates to root [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 2373 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 1284 gates to evaluate gate constraints [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 25312 gates to verify FRI proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 650 gates to verify 0'th FRI query [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 96 gates to check FRI initial proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 65 gates to compute x from its index [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 233 gates to combine initial oracles ... Sample copy constraint failure: Error: Copy constraint 'root > verify FRI proof > verify 0'th FRI query > check FRI initial proof > verify 0'th initial Merkle proof > check Merkle root: 0-th hash element' between wire 12 of gate #2550 [...] and wire 0 of gate #0 [...] is not satisfied. Got values of 6861386743364621393 and 0 respectively. * No min * info -> debug * Move to its own file
2021-07-19 12:22:18 -07:00
let zeta = challenger.get_extension_challenge(self);
(betas, gammas, alphas, zeta)
});
2021-07-12 14:25:28 +02:00
let local_constants = &proof.openings.constants;
let local_wires = &proof.openings.wires;
let vars = EvaluationTargets {
local_constants,
local_wires,
public_inputs_hash,
2021-07-12 14:25:28 +02:00
};
let local_zs = &proof.openings.plonk_zs;
let next_zs = &proof.openings.plonk_zs_right;
let s_sigmas = &proof.openings.plonk_sigmas;
let partial_products = &proof.openings.partial_products;
let zeta_pow_deg = self.exp_power_of_2_extension(zeta, inner_common_data.degree_bits);
Reduce noise in FRI logging (#129) * Reduce noise in FRI logging Previously, all logs related to gate counts were at the `Debug` log level. This PR gives us more flexibility to adjust the log levels of particular scopes. In particular, our circuit checks 40 FRI queries, and we log a bunch of steps for each query, creating a lot of noise. With this change, we log just a single FRI query at the `Debug` level, and demote others to the `Trace` level. With `RUST_LOG=debug`, our logs now look like ``` [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] 17631 gates to root [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 8 gates to observe proof and generates challenges [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 4150 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 3184 gates to evaluate gate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 227 gates to evaluate InterpolationGate { num_points: 4, _phantom: PhantomData }<D=4> constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 867 gates to evaluate <R=101> GMiMCGate { ... } constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 576 gates to evaluate BaseSumGate { num_limbs: 63 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 78 gates to evaluate ArithmeticExtensionGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 288 gates to evaluate BaseSumGate { num_limbs: 31 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 115 gates to evaluate InsertionGate { vec_size: 3, _phantom: PhantomData }<D=4> constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 26 gates to evaluate BaseSumGate { num_limbs: 2 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 633 gates to evaluate ReducingGate { num_coeffs: 21 } constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 4 gates to evaluate ConstantGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to evaluate PublicInputGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 2 gates to evaluate NoopGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 16 gates to check vanishing and quotient polynomials. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 13336 gates to verify FRI proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 6 gates to recover the random betas used in the FRI reductions. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 4 gates to check PoW [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 104 gates to precompute reduced evaluations [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 95 gates to check FRI initial proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 22 gates to verify 0'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 33 gates to verify 1'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 2'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 3'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 34 gates to compute x from its index [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 32 gates to combine initial oracles [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 17 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 15 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 13 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 9 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 7 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer final evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 8 gates to evaluate final polynomial ``` This bit corresponds to the single FRI query being shown: ``` [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds ``` * Minor cleanup * Address feedback
2021-07-26 16:21:14 -07:00
let vanishing_polys_zeta = with_context!(
2021-07-12 14:25:28 +02:00
self,
Tree of scopes (#106) * Tree of scopes This is an extension of the context concept. Earlier I was planning to store a simple stack of contexts, but I ended up storing the whole history, in a tree structure. This gives us more control over the output, i.e. we can print the gate count of a parent scope before those of its child scopes, which seems more user-friendly. Sample gate count output: [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] 27829 gates to root [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 2373 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 1284 gates to evaluate gate constraints [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 25312 gates to verify FRI proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 650 gates to verify 0'th FRI query [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 96 gates to check FRI initial proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 65 gates to compute x from its index [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 233 gates to combine initial oracles ... Sample copy constraint failure: Error: Copy constraint 'root > verify FRI proof > verify 0'th FRI query > check FRI initial proof > verify 0'th initial Merkle proof > check Merkle root: 0-th hash element' between wire 12 of gate #2550 [...] and wire 0 of gate #0 [...] is not satisfied. Got values of 6861386743364621393 and 0 respectively. * No min * info -> debug * Move to its own file
2021-07-19 12:22:18 -07:00
"evaluate the vanishing polynomial at our challenge point, zeta.",
eval_vanishing_poly_recursively(
self,
inner_common_data,
zeta,
zeta_pow_deg,
vars,
local_zs,
next_zs,
partial_products,
s_sigmas,
&betas,
&gammas,
&alphas,
)
2021-07-12 14:25:28 +02:00
);
Reduce noise in FRI logging (#129) * Reduce noise in FRI logging Previously, all logs related to gate counts were at the `Debug` log level. This PR gives us more flexibility to adjust the log levels of particular scopes. In particular, our circuit checks 40 FRI queries, and we log a bunch of steps for each query, creating a lot of noise. With this change, we log just a single FRI query at the `Debug` level, and demote others to the `Trace` level. With `RUST_LOG=debug`, our logs now look like ``` [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] 17631 gates to root [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 8 gates to observe proof and generates challenges [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 4150 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 3184 gates to evaluate gate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 227 gates to evaluate InterpolationGate { num_points: 4, _phantom: PhantomData }<D=4> constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 867 gates to evaluate <R=101> GMiMCGate { ... } constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 576 gates to evaluate BaseSumGate { num_limbs: 63 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 78 gates to evaluate ArithmeticExtensionGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 288 gates to evaluate BaseSumGate { num_limbs: 31 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 115 gates to evaluate InsertionGate { vec_size: 3, _phantom: PhantomData }<D=4> constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 26 gates to evaluate BaseSumGate { num_limbs: 2 } + Base: 2 constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 633 gates to evaluate ReducingGate { num_coeffs: 21 } constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 4 gates to evaluate ConstantGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to evaluate PublicInputGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 2 gates to evaluate NoopGate constraints [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 16 gates to check vanishing and quotient polynomials. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 13336 gates to verify FRI proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 6 gates to recover the random betas used in the FRI reductions. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 4 gates to check PoW [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 104 gates to precompute reduced evaluations [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 95 gates to check FRI initial proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 22 gates to verify 0'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 33 gates to verify 1'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 2'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 3'th initial Merkle proof [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 34 gates to compute x from its index [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 32 gates to combine initial oracles [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 17 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 15 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 13 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 9 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 7 gates to verify FRI round Merkle proof. [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer final evaluation using interpolation [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 8 gates to evaluate final polynomial ``` This bit corresponds to the single FRI query being shown: ``` [2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds ``` * Minor cleanup * Address feedback
2021-07-26 16:21:14 -07:00
with_context!(self, "check vanishing and quotient polynomials.", {
Tree of scopes (#106) * Tree of scopes This is an extension of the context concept. Earlier I was planning to store a simple stack of contexts, but I ended up storing the whole history, in a tree structure. This gives us more control over the output, i.e. we can print the gate count of a parent scope before those of its child scopes, which seems more user-friendly. Sample gate count output: [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] 27829 gates to root [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 2373 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 1284 gates to evaluate gate constraints [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 25312 gates to verify FRI proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 650 gates to verify 0'th FRI query [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 96 gates to check FRI initial proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 65 gates to compute x from its index [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 233 gates to combine initial oracles ... Sample copy constraint failure: Error: Copy constraint 'root > verify FRI proof > verify 0'th FRI query > check FRI initial proof > verify 0'th initial Merkle proof > check Merkle root: 0-th hash element' between wire 12 of gate #2550 [...] and wire 0 of gate #0 [...] is not satisfied. Got values of 6861386743364621393 and 0 respectively. * No min * info -> debug * Move to its own file
2021-07-19 12:22:18 -07:00
let quotient_polys_zeta = &proof.openings.quotient_polys;
let mut scale = ReducingFactorTarget::new(zeta_pow_deg);
let z_h_zeta = self.sub_extension(zeta_pow_deg, one);
for (i, chunk) in quotient_polys_zeta
.chunks(inner_common_data.quotient_degree_factor)
.enumerate()
{
let recombined_quotient = scale.reduce(chunk, self);
let computed_vanishing_poly = self.mul_extension(z_h_zeta, recombined_quotient);
2021-08-24 18:20:47 +02:00
self.connect_extension(vanishing_polys_zeta[i], computed_vanishing_poly);
Tree of scopes (#106) * Tree of scopes This is an extension of the context concept. Earlier I was planning to store a simple stack of contexts, but I ended up storing the whole history, in a tree structure. This gives us more control over the output, i.e. we can print the gate count of a parent scope before those of its child scopes, which seems more user-friendly. Sample gate count output: [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] 27829 gates to root [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 2373 gates to evaluate the vanishing polynomial at our challenge point, zeta. [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 1284 gates to evaluate gate constraints [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | 25312 gates to verify FRI proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | 650 gates to verify 0'th FRI query [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 96 gates to check FRI initial proof [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 65 gates to compute x from its index [2021-07-19T18:09:24Z INFO plonky2::circuit_builder] | | | 233 gates to combine initial oracles ... Sample copy constraint failure: Error: Copy constraint 'root > verify FRI proof > verify 0'th FRI query > check FRI initial proof > verify 0'th initial Merkle proof > check Merkle root: 0-th hash element' between wire 12 of gate #2550 [...] and wire 0 of gate #0 [...] is not satisfied. Got values of 6861386743364621393 and 0 respectively. * No min * info -> debug * Move to its own file
2021-07-19 12:22:18 -07:00
}
});
2021-07-13 09:44:35 +02:00
2021-08-10 15:53:27 +02:00
let merkle_caps = &[
inner_verifier_data.constants_sigmas_cap.clone(),
proof.wires_cap,
proof.plonk_zs_partial_products_cap,
proof.quotient_polys_cap,
2021-07-13 09:44:35 +02:00
];
with_context!(
2021-07-13 09:44:35 +02:00
self,
"verify FRI proof",
self.verify_fri_proof(
&proof.openings,
zeta,
2021-08-10 15:53:27 +02:00
merkle_caps,
&proof.opening_proof,
&mut challenger,
inner_common_data,
)
2021-07-13 09:44:35 +02:00
);
2021-07-08 17:16:26 +02:00
}
}
2021-08-10 14:19:12 +02:00
#[cfg(test)]
mod tests {
use anyhow::Result;
2021-08-10 15:28:41 +02:00
use log::info;
2021-08-10 14:19:12 +02:00
use super::*;
use crate::field::goldilocks_field::GoldilocksField;
2021-08-10 14:19:12 +02:00
use crate::fri::proof::{
FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget,
};
use crate::fri::reduction_strategies::FriReductionStrategy;
2021-08-10 14:19:12 +02:00
use crate::fri::FriConfig;
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
use crate::hash::merkle_proofs::MerkleProofTarget;
2021-08-20 09:50:07 +02:00
use crate::iop::witness::{PartialWitness, Witness};
use crate::plonk::circuit_data::VerifierOnlyCircuitData;
2021-10-01 16:54:14 +02:00
use crate::plonk::proof::{
CompressedProofWithPublicInputs, OpeningSetTarget, Proof, ProofTarget,
ProofWithPublicInputs,
};
2021-08-10 14:19:12 +02:00
use crate::util::log2_strict;
// Construct a `FriQueryRoundTarget` with the same dimensions as the ones in `proof`.
fn get_fri_query_round<F: RichField + Extendable<D>, const D: usize>(
2021-08-10 14:19:12 +02:00
proof: &Proof<F, 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>, const D: usize>(
2021-08-10 14:19:12 +02:00
proof_with_pis: &ProofWithPublicInputs<F, D>,
builder: &mut CircuitBuilder<F, D>,
) -> ProofWithPublicInputsTarget<D> {
let ProofWithPublicInputs {
proof,
public_inputs,
} = proof_with_pis;
2021-08-10 15:53:27 +02:00
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()));
2021-08-10 14:19:12 +02:00
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();
2021-08-10 15:53:27 +02:00
let commit_phase_merkle_caps = proof
2021-08-10 14:19:12 +02:00
.opening_proof
2021-08-10 15:53:27 +02:00
.commit_phase_merkle_caps
2021-08-10 14:19:12 +02:00
.iter()
.map(|r| builder.add_virtual_cap(log2_strict(r.0.len())))
.collect();
let opening_proof = FriProofTarget {
2021-08-10 15:53:27 +02:00
commit_phase_merkle_caps,
2021-08-10 14:19:12 +02:00
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 {
2021-08-10 15:53:27 +02:00
wires_cap,
plonk_zs_partial_products_cap: plonk_zs_cap,
quotient_polys_cap,
2021-08-10 14:19:12 +02:00
openings,
opening_proof,
};
let public_inputs = builder.add_virtual_targets(public_inputs.len());
ProofWithPublicInputsTarget {
proof,
public_inputs,
}
}
// Set the targets in a `ProofTarget` to their corresponding values in a `Proof`.
fn set_proof_target<F: RichField + Extendable<D>, const D: usize>(
2021-08-10 14:19:12 +02:00
proof: &ProofWithPublicInputs<F, D>,
pt: &ProofWithPublicInputsTarget<D>,
pw: &mut PartialWitness<F>,
) {
let ProofWithPublicInputs {
proof,
public_inputs,
} = proof;
let ProofWithPublicInputsTarget {
proof: pt,
public_inputs: pi_targets,
} = pt;
// Set public inputs.
for (&pi_t, &pi) in pi_targets.iter().zip(public_inputs) {
pw.set_target(pi_t, pi);
}
2021-08-10 15:53:27 +02:00
pw.set_cap_target(&pt.wires_cap, &proof.wires_cap);
2021-08-10 14:19:12 +02:00
pw.set_cap_target(
2021-08-10 15:53:27 +02:00
&pt.plonk_zs_partial_products_cap,
&proof.plonk_zs_partial_products_cap,
2021-08-10 14:19:12 +02:00
);
2021-08-10 15:53:27 +02:00
pw.set_cap_target(&pt.quotient_polys_cap, &proof.quotient_polys_cap);
2021-08-10 14:19:12 +02:00
for (&t, &x) in pt.openings.wires.iter().zip(&proof.openings.wires) {
pw.set_extension_target(t, x);
}
for (&t, &x) in pt.openings.constants.iter().zip(&proof.openings.constants) {
pw.set_extension_target(t, x);
}
for (&t, &x) in pt
.openings
.plonk_sigmas
.iter()
.zip(&proof.openings.plonk_sigmas)
{
pw.set_extension_target(t, x);
}
for (&t, &x) in pt.openings.plonk_zs.iter().zip(&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)
{
pw.set_extension_target(t, x);
}
for (&t, &x) in pt
.openings
.partial_products
.iter()
.zip(&proof.openings.partial_products)
{
pw.set_extension_target(t, x);
}
for (&t, &x) in pt
.openings
.quotient_polys
.iter()
.zip(&proof.openings.quotient_polys)
{
pw.set_extension_target(t, x);
}
let fri_proof = &proof.opening_proof;
let fpt = &pt.opening_proof;
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) {
pw.set_extension_target(t, x);
}
for (t, x) in fpt
2021-08-10 15:53:27 +02:00
.commit_phase_merkle_caps
2021-08-10 14:19:12 +02:00
.iter()
2021-08-10 15:53:27 +02:00
.zip(&fri_proof.commit_phase_merkle_caps)
2021-08-10 14:19:12 +02:00
{
pw.set_cap_target(t, x);
}
for (qt, q) in fpt
.query_round_proofs
.iter()
.zip(&fri_proof.query_round_proofs)
{
for (at, a) in qt
.initial_trees_proof
.evals_proofs
.iter()
.zip(&q.initial_trees_proof.evals_proofs)
{
for (&t, &x) in at.0.iter().zip(&a.0) {
pw.set_target(t, x);
}
for (&t, &x) in at.1.siblings.iter().zip(&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) {
pw.set_extension_target(t, x);
}
for (&t, &x) in st
.merkle_proof
.siblings
.iter()
.zip(&s.merkle_proof.siblings)
{
pw.set_hash_target(t, x);
}
}
}
}
#[test]
#[ignore]
fn test_recursive_verifier() -> Result<()> {
init_logger();
type F = GoldilocksField;
2021-08-10 14:19:12 +02:00
const D: usize = 4;
let config = CircuitConfig::standard_recursion_config();
2021-08-10 14:19:12 +02:00
let (proof, vd, cd) = dummy_proof::<F, D>(&config, 8_000)?;
let (proof, _vd, cd) = recursive_proof(proof, vd, cd, &config, &config, true)?;
test_serialization(&proof, &cd)?;
2021-08-10 14:19:12 +02:00
Ok(())
}
#[test]
#[ignore]
fn test_recursive_recursive_verifier() -> Result<()> {
init_logger();
type F = GoldilocksField;
const D: usize = 4;
2021-08-10 14:19:12 +02:00
let config = CircuitConfig::standard_recursion_config();
2021-08-10 14:19:12 +02:00
let (proof, vd, cd) = dummy_proof::<F, D>(&config, 8_000)?;
let (proof, vd, cd) = recursive_proof(proof, vd, cd, &config, &config, false)?;
let (proof, _vd, cd) = recursive_proof(proof, vd, cd, &config, &config, true)?;
2021-08-10 14:19:12 +02:00
test_serialization(&proof, &cd)?;
Ok(())
2021-08-10 14:19:12 +02:00
}
/// Creates a chain of recursive proofs where the last proof is made as small as reasonably
/// possible, using a high rate, high PoW bits, etc.
2021-08-10 14:19:12 +02:00
#[test]
#[ignore]
fn test_size_optimized_recursion() -> Result<()> {
init_logger();
type F = GoldilocksField;
2021-08-10 14:19:12 +02:00
const D: usize = 4;
let normal_config = CircuitConfig::standard_recursion_config();
let final_config = CircuitConfig {
rate_bits: 7,
cap_height: 0,
2021-08-10 14:19:12 +02:00
fri_config: FriConfig {
proof_of_work_bits: 23,
2021-10-05 16:33:08 -07:00
reduction_strategy: FriReductionStrategy::MinSize(None),
num_query_rounds: 11,
2021-08-10 14:19:12 +02:00
},
..normal_config
2021-08-10 14:19:12 +02:00
};
let (proof, vd, cd) = dummy_proof::<F, D>(&normal_config, 8_000)?;
let (proof, vd, cd) =
recursive_proof(proof, vd, cd, &normal_config, &normal_config, false)?;
let (proof, _vd, cd) = recursive_proof(proof, vd, cd, &normal_config, &final_config, true)?;
test_serialization(&proof, &cd)?;
Ok(())
}
fn dummy_proof<F: RichField + Extendable<D>, const D: usize>(
config: &CircuitConfig,
num_dummy_gates: u64,
) -> Result<(
ProofWithPublicInputs<F, D>,
VerifierOnlyCircuitData<F>,
CommonCircuitData<F, D>,
)> {
let mut builder = CircuitBuilder::<F, D>::new(config.clone());
for i in 0..num_dummy_gates {
builder.constant(F::from_canonical_u64(i));
}
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
data.verify(proof.clone())?;
Ok((proof, data.verifier_only, data.common))
}
fn recursive_proof<F: RichField + Extendable<D>, const D: usize>(
inner_proof: ProofWithPublicInputs<F, D>,
inner_vd: VerifierOnlyCircuitData<F>,
inner_cd: CommonCircuitData<F, D>,
inner_config: &CircuitConfig,
config: &CircuitConfig,
print_gate_counts: bool,
) -> Result<(
ProofWithPublicInputs<F, D>,
VerifierOnlyCircuitData<F>,
CommonCircuitData<F, D>,
)> {
2021-08-10 14:19:12 +02:00
let mut builder = CircuitBuilder::<F, D>::new(config.clone());
2021-08-20 11:56:57 +02:00
let mut pw = PartialWitness::new();
let pt = proof_to_proof_target(&inner_proof, &mut builder);
set_proof_target(&inner_proof, &pt, &mut pw);
2021-08-10 14:19:12 +02:00
let inner_data = VerifierCircuitTarget {
constants_sigmas_cap: builder.add_virtual_cap(inner_config.cap_height),
2021-08-10 14:19:12 +02:00
};
pw.set_cap_target(
&inner_data.constants_sigmas_cap,
&inner_vd.constants_sigmas_cap,
);
builder.add_recursive_verifier(pt, &inner_config, &inner_data, &inner_cd);
2021-08-10 14:19:12 +02:00
if print_gate_counts {
builder.print_gate_counts(0);
}
2021-08-10 14:19:12 +02:00
let data = builder.build();
let proof = data.prove(pw)?;
data.verify(proof.clone())?;
Ok((proof, data.verifier_only, data.common))
}
/// Test serialization and print some size info.
fn test_serialization<F: RichField + Extendable<D>, const D: usize>(
proof: &ProofWithPublicInputs<F, D>,
cd: &CommonCircuitData<F, D>,
) -> Result<()> {
let proof_bytes = proof.to_bytes()?;
2021-10-01 16:54:14 +02:00
info!("Proof length: {} bytes", proof_bytes.len());
let proof_from_bytes = ProofWithPublicInputs::from_bytes(proof_bytes, &cd)?;
assert_eq!(proof, &proof_from_bytes);
2021-09-20 17:34:52 +02:00
let now = std::time::Instant::now();
let compressed_proof = proof.clone().compress(&cd)?;
let decompressed_compressed_proof = compressed_proof.clone().decompress(&cd)?;
info!("{:.4}s to compress proof", now.elapsed().as_secs_f64());
assert_eq!(proof, &decompressed_compressed_proof);
let compressed_proof_bytes = compressed_proof.to_bytes()?;
2021-09-20 17:34:52 +02:00
info!(
"Compressed proof length: {} bytes",
compressed_proof_bytes.len()
);
2021-10-02 10:46:02 +02:00
let compressed_proof_from_bytes =
CompressedProofWithPublicInputs::from_bytes(compressed_proof_bytes, &cd)?;
assert_eq!(compressed_proof, compressed_proof_from_bytes);
Ok(())
}
fn init_logger() {
let _ = env_logger::builder().format_timestamp(None).try_init();
2021-08-10 14:19:12 +02:00
}
}