From f7b4e62f2e4a0b70efc102f5b739796a41ac53aa Mon Sep 17 00:00:00 2001 From: Balazs Komuves Date: Thu, 30 Jan 2025 14:20:56 +0100 Subject: [PATCH] add rudimentary hash counting statistics --- plonky2/Cargo.toml | 2 + plonky2/examples/bench_recursion.rs | 9 +++- plonky2/examples/fibonacci.rs | 8 ++- plonky2/examples/lookup_example.rs | 2 + plonky2/examples/multi_lookup_example.rs | 2 + plonky2/src/fri/oracle.rs | 3 ++ plonky2/src/fri/prover.rs | 17 ++++++- plonky2/src/fri/verifier.rs | 24 ++++++++- plonky2/src/hash/hashing.rs | 65 ++++++++++++++++++++++++ plonky2/src/hash/poseidon.rs | 2 + plonky2/src/plonk/circuit_data.rs | 8 ++- plonky2/src/plonk/proof.rs | 3 +- plonky2/src/plonk/prover.rs | 36 +++++++++++-- plonky2/src/plonk/verifier.rs | 56 +++++++++++++++++++- 14 files changed, 224 insertions(+), 13 deletions(-) diff --git a/plonky2/Cargo.toml b/plonky2/Cargo.toml index 1136e775..0a6d1d3f 100644 --- a/plonky2/Cargo.toml +++ b/plonky2/Cargo.toml @@ -33,6 +33,8 @@ serde_json = { workspace = true } static_assertions = { workspace = true } unroll = { workspace = true } web-time = { version = "1.0.0", optional = true } +strum = "0.26" +strum_macros = "0.26" # Local dependencies plonky2_field = { version = "1.0.0", path = "../field", default-features = false } diff --git a/plonky2/examples/bench_recursion.rs b/plonky2/examples/bench_recursion.rs index 2b054d54..a85f0048 100644 --- a/plonky2/examples/bench_recursion.rs +++ b/plonky2/examples/bench_recursion.rs @@ -28,7 +28,8 @@ use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{CircuitConfig, CommonCircuitData, VerifierOnlyCircuitData}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, PoseidonGoldilocksConfig}; use plonky2::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs}; -use plonky2::plonk::prover::{prove,prove_with_options,ProverOptions}; +use plonky2::plonk::prover::{prove, prove_with_options, ProverOptions}; +use plonky2::plonk::verifier::{VerifierOptions, HashStatisticsPrintLevel}; use plonky2::util::serialization::DefaultGateSerializer; use plonky2::util::timing::TimingTree; use plonky2_field::extension::Extendable; @@ -245,6 +246,7 @@ where let prover_opts = ProverOptions { export_witness: Some(format!("{}_witness.json",name)), + print_hash_statistics: HashStatisticsPrintLevel::Summary, // ::None, }; let mut timing = TimingTree::new("prove", Level::Debug); @@ -261,7 +263,10 @@ where fs::write(format!("recursion_{}_proof.json" , name), proof_serialized ).expect("Unable to write file"); */ - data.verify(proof.clone())?; + let verifier_opts = VerifierOptions { + print_hash_statistics: HashStatisticsPrintLevel::Summary, + }; + data.verify_with_options(proof.clone(), &verifier_opts)?; Ok((proof, data.verifier_only, data.common)) } diff --git a/plonky2/examples/fibonacci.rs b/plonky2/examples/fibonacci.rs index f28522c9..22d2beb0 100644 --- a/plonky2/examples/fibonacci.rs +++ b/plonky2/examples/fibonacci.rs @@ -5,6 +5,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::CircuitConfig; use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use plonky2::plonk::prover::ProverOptions; +use plonky2::plonk::verifier::{VerifierOptions, HashStatisticsPrintLevel}; /// An example of using Plonky2 to prove a statement of the form /// "I know the 100th element of the Fibonacci sequence, starting with constants a and b." @@ -42,6 +43,7 @@ fn main() -> Result<()> { let prover_opts = ProverOptions { export_witness: Some(String::from("fibonacci_witness.json")), + print_hash_statistics: HashStatisticsPrintLevel::Info, }; let proof = data.prove_with_options(pw, &prover_opts)?; @@ -51,5 +53,9 @@ fn main() -> Result<()> { proof.public_inputs[0], proof.public_inputs[1], proof.public_inputs[2] ); - data.verify(proof) + let verifier_opts = VerifierOptions { + print_hash_statistics: HashStatisticsPrintLevel::Summary, + }; + data.verify_with_options(proof, &verifier_opts) + } diff --git a/plonky2/examples/lookup_example.rs b/plonky2/examples/lookup_example.rs index 3dfd16a8..4571a89f 100644 --- a/plonky2/examples/lookup_example.rs +++ b/plonky2/examples/lookup_example.rs @@ -10,6 +10,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{CircuitConfig,CircuitData}; use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use plonky2::plonk::prover::ProverOptions; +use plonky2::plonk::verifier::{VerifierOptions, HashStatisticsPrintLevel}; //use plonky2::gadgets::lookup; @@ -142,6 +143,7 @@ fn main() -> Result<()> { let prover_opts = ProverOptions { export_witness: Some(String::from("lookup_witness.json")), + print_hash_statistics: HashStatisticsPrintLevel::None, }; let proof = data.prove_with_options(pw, &prover_opts)?; diff --git a/plonky2/examples/multi_lookup_example.rs b/plonky2/examples/multi_lookup_example.rs index e7404093..7f83747d 100644 --- a/plonky2/examples/multi_lookup_example.rs +++ b/plonky2/examples/multi_lookup_example.rs @@ -13,6 +13,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{CircuitConfig,CircuitData}; use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use plonky2::plonk::prover::ProverOptions; +use plonky2::plonk::verifier::{VerifierOptions, HashStatisticsPrintLevel}; //use plonky2::gadgets::lookup; @@ -87,6 +88,7 @@ fn main() -> Result<()> { let prover_opts = ProverOptions { export_witness: Some(String::from("multi_lookup_witness.json")), + print_hash_statistics: HashStatisticsPrintLevel::None, }; let proof = data.prove_with_options(pw, &prover_opts)?; diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index e413071a..931ff28f 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -17,6 +17,7 @@ use crate::hash::hash_types::RichField; use crate::hash::merkle_tree::MerkleTree; use crate::iop::challenger::Challenger; use crate::plonk::config::GenericConfig; +use crate::plonk::prover::ProverOptions; use crate::timed; use crate::util::reducing::ReducingFactor; use crate::util::timing::TimingTree; @@ -181,6 +182,7 @@ impl, C: GenericConfig, const D: usize> final_poly_coeff_len: Option, max_num_query_steps: Option, timing: &mut TimingTree, + prover_options: &ProverOptions, ) -> FriProof { assert!(D > 1, "Not implemented for D=1."); let alpha = challenger.get_extension_challenge::(); @@ -231,6 +233,7 @@ impl, C: GenericConfig, const D: usize> final_poly_coeff_len, max_num_query_steps, timing, + prover_options, ); fri_proof diff --git a/plonky2/src/fri/prover.rs b/plonky2/src/fri/prover.rs index 24c88ced..d478ae5d 100644 --- a/plonky2/src/fri/prover.rs +++ b/plonky2/src/fri/prover.rs @@ -11,11 +11,13 @@ use crate::field::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::fri::proof::{FriInitialTreeProof, FriProof, FriQueryRound, FriQueryStep}; use crate::fri::{FriConfig, FriParams}; use crate::hash::hash_types::{RichField, NUM_HASH_OUT_ELTS}; -use crate::hash::hashing::PlonkyPermutation; +use crate::hash::hashing::*; use crate::hash::merkle_tree::MerkleTree; use crate::iop::challenger::Challenger; use crate::plonk::config::GenericConfig; use crate::plonk::plonk_common::reduce_with_powers; +use crate::plonk::prover::ProverOptions; +use crate::plonk::verifier::HashStatisticsPrintLevel; use crate::timed; use crate::util::reverse_index_bits_in_place; use crate::util::timing::TimingTree; @@ -32,6 +34,7 @@ pub fn fri_proof, C: GenericConfig, const final_poly_coeff_len: Option, max_num_query_steps: Option, timing: &mut TimingTree, + prover_options: &ProverOptions, ) -> FriProof { let n = lde_polynomial_values.len(); assert_eq!(lde_polynomial_coeffs.len(), n); @@ -50,6 +53,10 @@ pub fn fri_proof, C: GenericConfig, const ) ); + if prover_options.print_hash_statistics >= HashStatisticsPrintLevel::Debug { + print_hash_counters("after commit phase"); + } + // PoW phase let pow_witness = timed!( timing, @@ -57,6 +64,10 @@ pub fn fri_proof, C: GenericConfig, const fri_proof_of_work::(challenger, &fri_params.config) ); + if prover_options.print_hash_statistics >= HashStatisticsPrintLevel::Debug { + print_hash_counters("after PoW grinding"); + } + // Query phase let query_round_proofs = fri_prover_query_rounds::(initial_merkle_trees, &trees, challenger, n, fri_params); @@ -180,6 +191,8 @@ pub(crate) fn fri_proof_of_work< let witness_input_pos = challenger.input_buffer.len(); duplex_intermediate_state.set_from_iter(challenger.input_buffer.clone(), 0); + // println!("duplex_intermediate_state = {:?}", duplex_intermediate_state); + let pow_witness = (0..=F::NEG_ONE.to_canonical_u64()) .into_par_iter() .find_any(|&candidate| { @@ -193,6 +206,8 @@ pub(crate) fn fri_proof_of_work< .map(F::from_canonical_u64) .expect("Proof of work failed. This is highly unlikely!"); + // println!("pow_witness = {:?}",pow_witness); + // Recompute pow_response using our normal Challenger code, and make sure it matches. challenger.observe_element(pow_witness); let pow_response = challenger.get_challenge(); diff --git a/plonky2/src/fri/verifier.rs b/plonky2/src/fri/verifier.rs index 89faa0f6..b5bdc514 100644 --- a/plonky2/src/fri/verifier.rs +++ b/plonky2/src/fri/verifier.rs @@ -13,9 +13,11 @@ use crate::fri::{FriConfig, FriParams}; use crate::hash::hash_types::RichField; use crate::hash::merkle_proofs::verify_merkle_proof_to_cap; use crate::hash::merkle_tree::MerkleCap; +use crate::hash::hashing::*; use crate::plonk::config::{GenericConfig, Hasher}; use crate::util::reducing::ReducingFactor; use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place}; +use crate::plonk::verifier::{VerifierOptions, HashStatisticsPrintLevel}; /// Computes P'(x^arity) from {P(x*g^i)}_(i=0..arity), where g is a `arity`-th root of unity /// and P' is the FRI reduced polynomial. @@ -70,6 +72,7 @@ pub fn verify_fri_proof< initial_merkle_caps: &[MerkleCap], proof: &FriProof, params: &FriParams, + verify_options: &VerifierOptions, ) -> Result<()> { validate_fri_proof_shape::(proof, instance, params)?; @@ -87,10 +90,11 @@ pub fn verify_fri_proof< let precomputed_reduced_evals = PrecomputedReducedOpenings::from_os_and_alpha(openings, challenges.fri_alpha); - for (&x_index, round_proof) in challenges + for (round_counter,(&x_index, round_proof)) in challenges .fri_query_indices .iter() .zip(&proof.query_round_proofs) + .enumerate() { fri_verifier_query_round::( instance, @@ -102,7 +106,14 @@ pub fn verify_fri_proof< n, round_proof, params, + verify_options, )?; + + if verify_options.print_hash_statistics >= HashStatisticsPrintLevel::Debug { + let s = format!("after query round #{}",round_counter); + print_hash_counters(&s); + } + } Ok(()) @@ -175,6 +186,7 @@ fn fri_verifier_query_round< n: usize, round_proof: &FriQueryRound, params: &FriParams, + verify_options: &VerifierOptions, ) -> Result<()> { fri_verify_initial_proof::( x_index, @@ -197,6 +209,11 @@ fn fri_verifier_query_round< params, ); + if verify_options.print_hash_statistics >= HashStatisticsPrintLevel::Debug { + let s = format!("after combine_initial"); + print_hash_counters(&s); + } + for (i, &arity_bits) in params.reduction_arity_bits.iter().enumerate() { let arity = 1 << arity_bits; let evals = &round_proof.steps[i].evals; @@ -224,6 +241,11 @@ fn fri_verifier_query_round< &round_proof.steps[i].merkle_proof, )?; + if verify_options.print_hash_statistics >= HashStatisticsPrintLevel::Debug { + let s = format!("after folding step #{}",i); + print_hash_counters(&s); + } + // Update the point x to x^arity. subgroup_x = subgroup_x.exp_power_of_2(arity_bits); diff --git a/plonky2/src/hash/hashing.rs b/plonky2/src/hash/hashing.rs index 75b35a93..1dc3ae39 100644 --- a/plonky2/src/hash/hashing.rs +++ b/plonky2/src/hash/hashing.rs @@ -10,6 +10,71 @@ use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::config::AlgebraicHasher; +use strum_macros::FromRepr; +use std::sync::atomic::{AtomicUsize,Ordering}; + +//------------------------------------------------------------------------------ +// hash usage statistics + +#[derive(Copy, Clone, Debug, FromRepr)] +pub enum HashUsage { + Permutation, + Compress, +// Sponge, +// Duplex, +} + +impl HashUsage { + pub fn from_usize(v: usize) -> HashUsage { + HashUsage::from_repr(v.try_into().unwrap()).unwrap() + } +} + +const ATOMIC_ORDER: Ordering = Ordering::SeqCst; + +#[derive(Debug)] +pub struct HashCounter { + current_usage: AtomicUsize, + count_permute: AtomicUsize, + count_compress: AtomicUsize, +} + +static the_hash_counters: HashCounter = HashCounter { + current_usage: AtomicUsize::new(HashUsage::Permutation as usize), + count_permute: AtomicUsize::new(0), + count_compress: AtomicUsize::new(0), +}; + +pub fn reset_hash_counters() { + the_hash_counters.current_usage .store(HashUsage::Permutation as usize, ATOMIC_ORDER); + the_hash_counters.count_permute .store(0, ATOMIC_ORDER ); + the_hash_counters.count_compress.store(0, ATOMIC_ORDER ); +} + +pub fn set_current_hash_usage(what: HashUsage) { + the_hash_counters.current_usage.store(what as usize, ATOMIC_ORDER); +} + +pub fn increment_given_hash_counter(which: HashUsage) { + let _ = match which { + HashUsage::Permutation => the_hash_counters.count_permute .fetch_add(1, ATOMIC_ORDER), + HashUsage::Compress => the_hash_counters.count_compress.fetch_add(1, ATOMIC_ORDER), + }; +} + +pub fn increment_current_hash_counter() { + let cur = the_hash_counters.current_usage.load(ATOMIC_ORDER); + increment_given_hash_counter(HashUsage::from_usize(cur)); +} + +pub fn print_hash_counters(msg: &str) { + let nperms = the_hash_counters.count_permute.load(ATOMIC_ORDER); + println!("hash statistic ({})",msg); + println!(" - number of permutations = {}",nperms); +} + +//------------------------------------------------------------------------------ + impl, const D: usize> CircuitBuilder { pub fn hash_or_noop>(&mut self, inputs: Vec) -> HashOutTarget { let zero = self.zero(); diff --git a/plonky2/src/hash/poseidon.rs b/plonky2/src/hash/poseidon.rs index a7c76325..aa7936ee 100644 --- a/plonky2/src/hash/poseidon.rs +++ b/plonky2/src/hash/poseidon.rs @@ -15,6 +15,7 @@ use crate::gates::poseidon::PoseidonGate; use crate::gates::poseidon_mds::PoseidonMdsGate; use crate::hash::hash_types::{HashOut, RichField}; use crate::hash::hashing::{compress, hash_n_to_hash_no_pad, PlonkyPermutation}; +use crate::hash::hashing::{HashUsage, increment_given_hash_counter}; use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; @@ -862,6 +863,7 @@ impl PlonkyPermutation< fn permute(&mut self) { self.state = T::permute(self.state); + increment_given_hash_counter(HashUsage::Permutation); } fn squeeze(&self) -> &[T] { diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index 64e50297..52bc653c 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -46,8 +46,8 @@ use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::plonk_common::PlonkOracle; use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs}; -use crate::plonk::prover::{prove,prove_with_options,ProverOptions}; -use crate::plonk::verifier::verify; +use crate::plonk::prover::{prove, prove_with_options, ProverOptions}; +use crate::plonk::verifier::{verify, verify_with_options, VerifierOptions}; use crate::util::serialization::{ Buffer, GateSerializer, IoResult, Read, WitnessGeneratorSerializer, Write, }; @@ -213,6 +213,10 @@ impl, C: GenericConfig, const D: usize> verify::(proof_with_pis, &self.verifier_only, &self.common) } + pub fn verify_with_options(&self, proof_with_pis: ProofWithPublicInputs, verifier_options: &VerifierOptions) -> Result<()> { + verify_with_options::(proof_with_pis, &self.verifier_only, &self.common, verifier_options) + } + pub fn verify_compressed( &self, compressed_proof_with_pis: CompressedProofWithPublicInputs, diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index 8cb8911a..c76c3112 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -26,7 +26,7 @@ use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; use crate::plonk::config::{GenericConfig, Hasher}; -use crate::plonk::verifier::verify_with_challenges; +use crate::plonk::verifier::{verify_with_challenges, DEFAULT_VERIFIER_OPTIONS}; use crate::util::serialization::{Buffer, Read, Write}; #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] @@ -227,6 +227,7 @@ impl, C: GenericConfig, const D: usize> challenges, verifier_data, common_data, + &DEFAULT_VERIFIER_OPTIONS, ) } diff --git a/plonky2/src/plonk/prover.rs b/plonky2/src/plonk/prover.rs index 0cea8af5..80c02dc2 100644 --- a/plonky2/src/plonk/prover.rs +++ b/plonky2/src/plonk/prover.rs @@ -23,6 +23,7 @@ use crate::gates::lookup::LookupGate; use crate::gates::lookup_table::LookupTableGate; use crate::gates::selectors::{LookupSelectors}; use crate::hash::hash_types::RichField; +use crate::hash::hashing::*; use crate::iop::challenger::Challenger; use crate::iop::generator::generate_partial_witness; use crate::iop::target::Target; @@ -33,6 +34,7 @@ use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::plonk_common::PlonkOracle; use crate::plonk::proof::{OpeningSet, Proof, ProofWithPublicInputs}; use crate::plonk::vanishing_poly::{eval_vanishing_poly_base_batch, get_lut_poly}; +use crate::plonk::verifier::HashStatisticsPrintLevel; use crate::plonk::vars::EvaluationVarsBaseBatch; use crate::timed; use crate::util::partial_products::{partial_products_and_z_gx, quotient_chunk_products}; @@ -121,10 +123,12 @@ pub fn set_lookup_wires< #[derive(Debug,Clone)] pub struct ProverOptions { pub export_witness: Option, // export the full witness into the given file + pub print_hash_statistics: HashStatisticsPrintLevel, } pub const DEFAULT_PROVER_OPTIONS: ProverOptions = ProverOptions { - export_witness: None, + export_witness: None, + print_hash_statistics: HashStatisticsPrintLevel::None, }; // things we want to export to be used by third party tooling @@ -223,14 +227,23 @@ pub fn prove_with_options, C: GenericConfig, C::InnerHasher: Hasher, + { + reset_hash_counters(); + let partition_witness = timed!( timing, &format!("run {} generators", prover_data.generators.len()), generate_partial_witness(inputs, prover_data, common_data)? ); - prove_with_partition_witness(prover_data, common_data, partition_witness, timing, prover_options) + let result = prove_with_partition_witness(prover_data, common_data, partition_witness, timing, prover_options); + + if prover_options.print_hash_statistics >= HashStatisticsPrintLevel::Summary { + print_hash_counters("prover total"); + } + + result } pub fn prove_with_partition_witness< @@ -288,6 +301,10 @@ where ) ); + if prover_options.print_hash_statistics >= HashStatisticsPrintLevel::Info { + print_hash_counters("after wires commitment"); + } + // export witness etc for third party tooling match &prover_options.export_witness { None => (), @@ -366,6 +383,10 @@ where ) ); + if prover_options.print_hash_statistics >= HashStatisticsPrintLevel::Info { + print_hash_counters("after partial product and lookup commitment"); + } + challenger.observe_cap::(&partial_products_zs_and_lookup_commitment.merkle_tree.cap); let alphas = challenger.get_n_challenges(num_challenges); @@ -414,6 +435,10 @@ where ) ); + if prover_options.print_hash_statistics >= HashStatisticsPrintLevel::Info { + print_hash_counters("after quotient poly commitment"); + } + challenger.observe_cap::("ient_polys_commitment.merkle_tree.cap); let zeta = challenger.get_extension_challenge::(); @@ -436,12 +461,16 @@ where &wires_commitment, &partial_products_zs_and_lookup_commitment, "ient_polys_commitment, - common_data + common_data, ) ); challenger.observe_openings(&openings.to_fri_openings()); let instance = common_data.get_fri_instance(zeta); + if prover_options.print_hash_statistics >= HashStatisticsPrintLevel::Info { + print_hash_counters("before FRI opening proof"); + } + let opening_proof = timed!( timing, "compute opening proofs", @@ -458,6 +487,7 @@ where None, None, timing, + prover_options, ) ); diff --git a/plonky2/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs index fa1bc14b..f1292bfb 100644 --- a/plonky2/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -6,6 +6,7 @@ use crate::field::extension::Extendable; use crate::field::types::Field; use crate::fri::verifier::verify_fri_proof; use crate::hash::hash_types::RichField; +use crate::hash::hashing::*; use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::plonk_common::reduce_with_powers; @@ -14,27 +15,76 @@ use crate::plonk::validate_shape::validate_proof_with_pis_shape; use crate::plonk::vanishing_poly::eval_vanishing_poly; use crate::plonk::vars::EvaluationVars; +// debugging features in the verifier +#[derive(Debug,Clone,PartialEq,PartialOrd)] +pub enum HashStatisticsPrintLevel { + None, + Summary, + Info, + Debug, +} + +#[derive(Debug,Clone)] +pub struct VerifierOptions { + pub print_hash_statistics: HashStatisticsPrintLevel, +} + +pub const DEFAULT_VERIFIER_OPTIONS: VerifierOptions = VerifierOptions { + print_hash_statistics: HashStatisticsPrintLevel::None, +}; + pub(crate) fn verify, C: GenericConfig, const D: usize>( proof_with_pis: ProofWithPublicInputs, verifier_data: &VerifierOnlyCircuitData, common_data: &CommonCircuitData, ) -> Result<()> { + verify_with_options( + proof_with_pis, + verifier_data, + common_data, + &DEFAULT_VERIFIER_OPTIONS, + ) +} +pub(crate) fn verify_with_options, C: GenericConfig, const D: usize>( + proof_with_pis: ProofWithPublicInputs, + verifier_data: &VerifierOnlyCircuitData, + common_data: &CommonCircuitData, + verifier_options: &VerifierOptions, +) -> Result<()> { + + reset_hash_counters(); + validate_proof_with_pis_shape(&proof_with_pis, common_data)?; let public_inputs_hash = proof_with_pis.get_public_inputs_hash(); + + if verifier_options.print_hash_statistics >= HashStatisticsPrintLevel::Info { + print_hash_counters("after PI"); + } + let challenges = proof_with_pis.get_challenges( public_inputs_hash, &verifier_data.circuit_digest, common_data, )?; - verify_with_challenges::( + if verifier_options.print_hash_statistics >= HashStatisticsPrintLevel::Info { + print_hash_counters("after challenges"); + } + + let result = verify_with_challenges::( proof_with_pis.proof, public_inputs_hash, challenges, verifier_data, common_data, - ) + verifier_options + ); + + if verifier_options.print_hash_statistics >= HashStatisticsPrintLevel::Summary { + print_hash_counters("verify total"); + } + result } pub(crate) fn verify_with_challenges< @@ -47,6 +97,7 @@ pub(crate) fn verify_with_challenges< challenges: ProofChallenges, verifier_data: &VerifierOnlyCircuitData, common_data: &CommonCircuitData, + verifier_options: &VerifierOptions, ) -> Result<()> { let local_constants = &proof.openings.constants; let local_wires = &proof.openings.wires; @@ -112,6 +163,7 @@ pub(crate) fn verify_with_challenges< merkle_caps, &proof.opening_proof, &common_data.fri_params, + &verifier_options, )?; Ok(())