diff --git a/Cargo.toml b/Cargo.toml index 8c4968ec..fa22a769 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,13 @@ anyhow = "1.0.40" serde = { version = "1.0", features = ["derive"] } serde_cbor = "0.11.1" +[dev-dependencies] +criterion = "0.3.5" + +[[bench]] +name = "field_arithmetic" +harness = false + [profile.release] opt-level = 3 #lto = "fat" diff --git a/benches/field_arithmetic.rs b/benches/field_arithmetic.rs new file mode 100644 index 00000000..e5ec13ab --- /dev/null +++ b/benches/field_arithmetic.rs @@ -0,0 +1,28 @@ +use std::any::type_name; + +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use plonky2::field::crandall_field::CrandallField; +use plonky2::field::extension_field::quartic::QuarticCrandallField; +use plonky2::field::field_types::Field; + +pub(crate) fn bench_field(c: &mut Criterion) { + c.bench_function(&format!("{} mul", type_name::()), |b| { + b.iter_batched( + || (F::rand(), F::rand()), + |(x, y)| x * y, + BatchSize::SmallInput, + ) + }); + + c.bench_function(&format!("{} try_inverse", type_name::()), |b| { + b.iter_batched(|| F::rand(), |x| x.try_inverse(), BatchSize::SmallInput) + }); +} + +fn criterion_benchmark(c: &mut Criterion) { + bench_field::(c); + bench_field::(c); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/src/fri/commitment.rs b/src/fri/commitment.rs index c57d42f5..ee7c2717 100644 --- a/src/fri/commitment.rs +++ b/src/fri/commitment.rs @@ -1,25 +1,20 @@ -use anyhow::Result; use rayon::prelude::*; -use serde::{Deserialize, Serialize}; -use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; -use crate::fri::proof::{FriProof, FriProofTarget}; +use crate::fri::proof::FriProof; use crate::fri::{prover::fri_proof, verifier::verify_fri_proof}; -use crate::hash::hash_types::{HashOut, HashOutTarget}; +use crate::hash::hash_types::HashOut; use crate::hash::merkle_tree::MerkleTree; -use crate::iop::challenger::{Challenger, RecursiveChallenger}; -use crate::plonk::circuit_builder::CircuitBuilder; +use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::plonk_common::PlonkPolynomials; -use crate::plonk::proof::{OpeningSet, OpeningSetTarget}; +use crate::plonk::proof::OpeningSet; use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::timed; use crate::util::reducing::ReducingFactor; use crate::util::timing::TimingTree; -use crate::util::{log2_ceil, log2_strict, reverse_bits, reverse_index_bits_in_place, transpose}; -use crate::with_context; +use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place, transpose}; /// Two (~64 bit) field elements gives ~128 bit security. pub const SALT_SIZE: usize = 2; @@ -78,8 +73,6 @@ impl PolynomialBatchCommitment { blinding: bool, timing: &mut TimingTree, ) -> Self { - // TODO: Could try parallelizing the transpose, or not doing it explicitly, instead having - // MerkleTree do it implicitly. let mut leaves = timed!(timing, "transpose LDEs", transpose(&lde_values)); reverse_index_bits_in_place(&mut leaves); let merkle_tree = timed!(timing, "build Merkle tree", MerkleTree::new(leaves, false)); @@ -131,7 +124,7 @@ impl PolynomialBatchCommitment { challenger: &mut Challenger, common_data: &CommonCircuitData, timing: &mut TimingTree, - ) -> (OpeningProof, OpeningSet) + ) -> (FriProof, OpeningSet) where F: Extendable, { @@ -223,13 +216,7 @@ impl PolynomialBatchCommitment { timing, ); - ( - OpeningProof { - fri_proof, - quotient_degree: final_poly.len(), - }, - os, - ) + (fri_proof, os) } /// Given `points=(x_i)`, `evals=(y_i)` and `poly=P` with `P(x_i)=y_i`, computes the polynomial @@ -260,75 +247,6 @@ impl PolynomialBatchCommitment { } } -#[derive(Serialize, Deserialize, Clone, Debug)] -#[serde(bound = "")] -pub struct OpeningProof, const D: usize> { - pub(crate) fri_proof: FriProof, - // TODO: Get the degree from `CommonCircuitData` instead. - quotient_degree: usize, -} - -impl, const D: usize> OpeningProof { - pub fn verify( - &self, - zeta: F::Extension, - os: &OpeningSet, - merkle_roots: &[HashOut], - challenger: &mut Challenger, - common_data: &CommonCircuitData, - ) -> Result<()> { - challenger.observe_opening_set(os); - - let alpha = challenger.get_extension_challenge(); - - verify_fri_proof( - log2_strict(self.quotient_degree), - &os, - zeta, - alpha, - merkle_roots, - &self.fri_proof, - challenger, - common_data, - ) - } -} - -pub struct OpeningProofTarget { - pub(crate) fri_proof: FriProofTarget, -} - -impl OpeningProofTarget { - pub fn verify>( - &self, - zeta: ExtensionTarget, - os: &OpeningSetTarget, - merkle_roots: &[HashOutTarget], - challenger: &mut RecursiveChallenger, - common_data: &CommonCircuitData, - builder: &mut CircuitBuilder, - ) { - challenger.observe_opening_set(os); - - let alpha = challenger.get_extension_challenge(builder); - - with_context!( - builder, - "verify FRI proof", - builder.verify_fri_proof( - log2_ceil(common_data.degree()), - &os, - zeta, - alpha, - merkle_roots, - &self.fri_proof, - challenger, - common_data, - ) - ); - } -} - #[cfg(test)] mod tests { use anyhow::Result; @@ -363,7 +281,7 @@ mod tests { fn check_batch_polynomial_commitment, const D: usize>() -> Result<()> { let ks = [10, 2, 10, 8]; - let degree_log = 11; + let degree_bits = 11; let fri_config = FriConfig { proof_of_work_bits: 2, reduction_arity_bits: vec![2, 3, 1, 2], @@ -376,7 +294,7 @@ mod tests { num_routed_wires: 6, ..CircuitConfig::large_config() }, - degree_bits: 0, + degree_bits, gates: vec![], quotient_degree_factor: 0, num_gate_constraints: 0, @@ -389,7 +307,7 @@ mod tests { let lpcs = (0..4) .map(|i| { PolynomialBatchCommitment::::new( - gen_random_test_case(ks[i], degree_log), + gen_random_test_case(ks[i], degree_bits), common_data.config.rate_bits, PlonkPolynomials::polynomials(i).blinding, &mut TimingTree::default(), @@ -397,7 +315,7 @@ mod tests { }) .collect::>(); - let zeta = gen_random_point::(degree_log); + let zeta = gen_random_point::(degree_bits); let (proof, os) = PolynomialBatchCommitment::open_plonk::( &[&lpcs[0], &lpcs[1], &lpcs[2], &lpcs[3]], zeta, @@ -406,15 +324,18 @@ mod tests { &mut TimingTree::default(), ); - proof.verify( - zeta, + let merkle_roots = &[ + lpcs[0].merkle_tree.root, + lpcs[1].merkle_tree.root, + lpcs[2].merkle_tree.root, + lpcs[3].merkle_tree.root, + ]; + + verify_fri_proof( &os, - &[ - lpcs[0].merkle_tree.root, - lpcs[1].merkle_tree.root, - lpcs[2].merkle_tree.root, - lpcs[3].merkle_tree.root, - ], + zeta, + merkle_roots, + &proof, &mut Challenger::new(), &common_data, ) diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index 7135cc4c..d771e884 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -70,13 +70,10 @@ impl, const D: usize> CircuitBuilder { pub fn verify_fri_proof( &mut self, - purported_degree_log: usize, // Openings of the PLONK polynomials. os: &OpeningSetTarget, // Point at which the PLONK polynomials are opened. zeta: ExtensionTarget, - // Scaling factor to combine polynomials. - alpha: ExtensionTarget, initial_merkle_roots: &[HashOutTarget], proof: &FriProofTarget, challenger: &mut RecursiveChallenger, @@ -85,7 +82,7 @@ impl, const D: usize> CircuitBuilder { let config = &common_data.config; let total_arities = config.fri_config.reduction_arity_bits.iter().sum::(); debug_assert_eq!( - purported_degree_log, + common_data.degree_bits, log2_strict(proof.final_poly.len()) + total_arities, "Final polynomial has wrong degree." ); @@ -93,6 +90,11 @@ impl, const D: usize> CircuitBuilder { // Size of the LDE domain. let n = proof.final_poly.len() << (total_arities + config.rate_bits); + challenger.observe_opening_set(&os); + + // Scaling factor to combine polynomials. + let alpha = challenger.get_extension_challenge(self); + let betas = with_context!( self, "recover the random betas used in the FRI reductions.", diff --git a/src/fri/verifier.rs b/src/fri/verifier.rs index 6e814cac..ab877352 100644 --- a/src/fri/verifier.rs +++ b/src/fri/verifier.rs @@ -69,13 +69,10 @@ fn fri_verify_proof_of_work, const D: usize>( } pub fn verify_fri_proof, const D: usize>( - purported_degree_log: usize, // Openings of the PLONK polynomials. os: &OpeningSet, // Point at which the PLONK polynomials are opened. zeta: F::Extension, - // Scaling factor to combine polynomials. - alpha: F::Extension, initial_merkle_roots: &[HashOut], proof: &FriProof, challenger: &mut Challenger, @@ -84,10 +81,15 @@ pub fn verify_fri_proof, const D: usize>( let config = &common_data.config; let total_arities = config.fri_config.reduction_arity_bits.iter().sum::(); ensure!( - purported_degree_log == log2_strict(proof.final_poly.len()) + total_arities, + common_data.degree_bits == log2_strict(proof.final_poly.len()) + total_arities, "Final polynomial has wrong degree." ); + challenger.observe_opening_set(os); + + // Scaling factor to combine polynomials. + let alpha = challenger.get_extension_challenge(); + // Size of the LDE domain. let n = proof.final_poly.len() << (total_arities + config.rate_bits); diff --git a/src/plonk/proof.rs b/src/plonk/proof.rs index 5999e882..300210f2 100644 --- a/src/plonk/proof.rs +++ b/src/plonk/proof.rs @@ -3,7 +3,8 @@ use serde::{Deserialize, Serialize}; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::fri::commitment::{OpeningProof, OpeningProofTarget, PolynomialBatchCommitment}; +use crate::fri::commitment::PolynomialBatchCommitment; +use crate::fri::proof::{FriProof, FriProofTarget}; use crate::hash::hash_types::{HashOut, HashOutTarget}; use crate::iop::target::Target; use crate::plonk::circuit_data::CommonCircuitData; @@ -19,8 +20,8 @@ pub struct Proof, const D: usize> { pub quotient_polys_root: HashOut, /// Purported values of each polynomial at the challenge point. pub openings: OpeningSet, - /// A FRI argument for each FRI query. - pub opening_proof: OpeningProof, + /// A batch FRI argument for all openings. + pub opening_proof: FriProof, } #[derive(Serialize, Deserialize, Clone, Debug)] @@ -35,7 +36,7 @@ pub struct ProofTarget { pub plonk_zs_partial_products_root: HashOutTarget, pub quotient_polys_root: HashOutTarget, pub openings: OpeningSetTarget, - pub opening_proof: OpeningProofTarget, + pub opening_proof: FriProofTarget, } pub struct ProofWithPublicInputsTarget { diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index a52020d9..64175a20 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -114,13 +114,17 @@ impl, const D: usize> CircuitBuilder { proof.quotient_polys_root, ]; - proof.opening_proof.verify( - zeta, - &proof.openings, - merkle_roots, - &mut challenger, - inner_common_data, + with_context!( self, + "verify FRI proof", + self.verify_fri_proof( + &proof.openings, + zeta, + merkle_roots, + &proof.opening_proof, + &mut challenger, + inner_common_data, + ) ); } } @@ -131,7 +135,6 @@ mod tests { use super::*; use crate::field::crandall_field::CrandallField; - use crate::fri::commitment::OpeningProofTarget; use crate::fri::proof::{ FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget, }; @@ -153,7 +156,7 @@ mod tests { }, steps: vec![], }; - for (v, merkle_proof) in &proof.opening_proof.fri_proof.query_round_proofs[0] + for (v, merkle_proof) in &proof.opening_proof.query_round_proofs[0] .initial_trees_proof .evals_proofs { @@ -164,7 +167,7 @@ mod tests { }, )); } - for step in &proof.opening_proof.fri_proof.query_round_proofs[0].steps { + 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 { @@ -201,27 +204,20 @@ mod tests { quotient_polys: builder .add_virtual_extension_targets(proof.openings.quotient_polys.len()), }; - let query_round_proofs = (0..proof.opening_proof.fri_proof.query_round_proofs.len()) + let query_round_proofs = (0..proof.opening_proof.query_round_proofs.len()) .map(|_| get_fri_query_round(proof, builder)) .collect(); - let commit_phase_merkle_roots = (0..proof - .opening_proof - .fri_proof - .commit_phase_merkle_roots - .len()) + let commit_phase_merkle_roots = (0..proof.opening_proof.commit_phase_merkle_roots.len()) .map(|_| builder.add_virtual_hash()) .collect(); - let opening_proof = - OpeningProofTarget { - fri_proof: FriProofTarget { - commit_phase_merkle_roots, - query_round_proofs, - final_poly: PolynomialCoeffsExtTarget(builder.add_virtual_extension_targets( - proof.opening_proof.fri_proof.final_poly.len(), - )), - pow_witness: builder.add_virtual_target(), - }, - }; + let opening_proof = FriProofTarget { + commit_phase_merkle_roots, + query_round_proofs, + final_poly: PolynomialCoeffsExtTarget( + builder.add_virtual_extension_targets(proof.opening_proof.final_poly.len()), + ), + pow_witness: builder.add_virtual_target(), + }; let proof = ProofTarget { wires_root, @@ -307,8 +303,8 @@ mod tests { pw.set_extension_target(t, x); } - let fri_proof = &proof.opening_proof.fri_proof; - let fpt = &pt.opening_proof.fri_proof; + let fri_proof = &proof.opening_proof; + let fpt = &pt.opening_proof; pw.set_target(fpt.pow_witness, fri_proof.pow_witness); diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index fe86a24b..ad6623c3 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -2,6 +2,7 @@ use anyhow::{ensure, Result}; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; +use crate::fri::verifier::verify_fri_proof; use crate::hash::hashing::hash_n_to_hash; use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; @@ -82,8 +83,6 @@ pub(crate) fn verify, const D: usize>( ensure!(vanishing_polys_zeta[i] == z_h_zeta * reduce_with_powers(chunk, zeta_pow_deg)); } - let evaluations = proof.openings.clone(); - let merkle_roots = &[ verifier_data.constants_sigmas_root, proof.wires_root, @@ -91,10 +90,11 @@ pub(crate) fn verify, const D: usize>( proof.quotient_polys_root, ]; - proof.opening_proof.verify( + verify_fri_proof( + &proof.openings, zeta, - &evaluations, merkle_roots, + &proof.opening_proof, &mut challenger, common_data, )?;