From ce71b536bf7aec8599d037fd8626ca76b0df44f8 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 10 Aug 2021 13:33:44 +0200 Subject: [PATCH] First pass --- src/bin/bench_recursion.rs | 2 + src/fri/commitment.rs | 26 +- src/fri/mod.rs | 2 + src/fri/proof.rs | 7 +- src/fri/prover.rs | 6 +- src/fri/recursive_verifier.rs | 14 +- src/fri/verifier.rs | 13 +- src/hash/hash_types.rs | 3 + src/hash/merkle_proofs.rs | 58 ++- src/hash/merkle_tree.rs | 21 +- src/iop/challenger.rs | 15 +- src/iop/witness.rs | 9 +- src/plonk/circuit_builder.rs | 18 +- src/plonk/circuit_data.rs | 12 +- src/plonk/proof.rs | 15 +- src/plonk/prover.rs | 9 +- src/plonk/recursive_verifier.rs | 712 ++++++++++++++++---------------- src/plonk/verifier.rs | 8 +- 18 files changed, 519 insertions(+), 431 deletions(-) diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index 3b71c6f4..7067bd49 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -27,10 +27,12 @@ fn bench_prove, const D: usize>() -> Result<()> { rate_bits: 3, num_challenges: 3, zero_knowledge: false, + cap_height: 1, fri_config: FriConfig { proof_of_work_bits: 20, reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], num_query_rounds: 35, + cap_height: 1, }, }; diff --git a/src/fri/commitment.rs b/src/fri/commitment.rs index 79efceb7..e2ca88e7 100644 --- a/src/fri/commitment.rs +++ b/src/fri/commitment.rs @@ -34,6 +34,7 @@ impl PolynomialBatchCommitment { values: Vec>, rate_bits: usize, blinding: bool, + cap_height: usize, timing: &mut TimingTree, ) -> Self { let coeffs = timed!( @@ -42,7 +43,7 @@ impl PolynomialBatchCommitment { values.par_iter().map(|v| v.ifft()).collect::>() ); - Self::from_coeffs(coeffs, rate_bits, blinding, timing) + Self::from_coeffs(coeffs, rate_bits, blinding, cap_height, timing) } /// Creates a list polynomial commitment for the polynomials `polynomials`. @@ -50,6 +51,7 @@ impl PolynomialBatchCommitment { polynomials: Vec>, rate_bits: usize, blinding: bool, + cap_height: usize, timing: &mut TimingTree, ) -> Self { let degree = polynomials[0].len(); @@ -61,7 +63,11 @@ impl PolynomialBatchCommitment { 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)); + let merkle_tree = timed!( + timing, + "build Merkle tree", + MerkleTree::new(leaves, cap_height, false) + ); Self { polynomials, @@ -250,7 +256,8 @@ mod tests { let degree = 1 << degree_log; (0..k) - .map(|_| PolynomialValues::new(F::rand_vec(degree))) + // .map(|_| PolynomialValues::new(F::rand_vec(degree))) + .map(|_| PolynomialValues::new((1..=degree).map(F::from_canonical_usize).collect())) .collect() } @@ -274,6 +281,7 @@ mod tests { proof_of_work_bits: 2, reduction_arity_bits: vec![2, 3, 1, 2], num_query_rounds: 3, + cap_height: 0, }; // We only care about `fri_config, num_constants`, and `num_routed_wires` here. let common_data = CommonCircuitData { @@ -297,13 +305,15 @@ mod tests { PolynomialBatchCommitment::::from_values( gen_random_test_case(ks[i], degree_bits), common_data.config.rate_bits, - PlonkPolynomials::polynomials(i).blinding, + false, + common_data.config.cap_height, &mut TimingTree::default(), ) }) .collect::>(); let zeta = gen_random_point::(degree_bits); + let zeta = F::Extension::MULTIPLICATIVE_GROUP_GENERATOR; let (proof, os) = PolynomialBatchCommitment::open_plonk::( &[&lpcs[0], &lpcs[1], &lpcs[2], &lpcs[3]], zeta, @@ -313,10 +323,10 @@ mod tests { ); let merkle_roots = &[ - lpcs[0].merkle_tree.root, - lpcs[1].merkle_tree.root, - lpcs[2].merkle_tree.root, - lpcs[3].merkle_tree.root, + lpcs[0].merkle_tree.root.clone(), + lpcs[1].merkle_tree.root.clone(), + lpcs[2].merkle_tree.root.clone(), + lpcs[3].merkle_tree.root.clone(), ]; verify_fri_proof( diff --git a/src/fri/mod.rs b/src/fri/mod.rs index c2f081d2..29d99d61 100644 --- a/src/fri/mod.rs +++ b/src/fri/mod.rs @@ -20,6 +20,8 @@ pub struct FriConfig { /// Number of query rounds to perform. pub num_query_rounds: usize, + + pub cap_height: usize, } fn fri_delta(rate_log: usize, conjecture: bool) -> f64 { diff --git a/src/fri/proof.rs b/src/fri/proof.rs index 0216d355..d5ef1ec9 100644 --- a/src/fri/proof.rs +++ b/src/fri/proof.rs @@ -4,8 +4,9 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; -use crate::hash::hash_types::{HashOut, HashOutTarget}; +use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; use crate::hash::merkle_proofs::{MerkleProof, MerkleProofTarget}; +use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::Target; use crate::plonk::plonk_common::PolynomialsIndexBlinding; use crate::polynomial::polynomial::PolynomialCoeffs; @@ -77,7 +78,7 @@ pub struct FriQueryRoundTarget { #[serde(bound = "")] pub struct FriProof, const D: usize> { /// A Merkle root for each reduced polynomial in the commit phase. - pub commit_phase_merkle_roots: Vec>, + pub commit_phase_merkle_roots: Vec>, /// Query rounds proofs pub query_round_proofs: Vec>, /// The final polynomial in coefficient form. @@ -87,7 +88,7 @@ pub struct FriProof, const D: usize> { } pub struct FriProofTarget { - pub commit_phase_merkle_roots: Vec, + pub commit_phase_merkle_roots: Vec, pub query_round_proofs: Vec>, pub final_poly: PolynomialCoeffsExtTarget, pub pow_witness: Target, diff --git a/src/fri/prover.rs b/src/fri/prover.rs index c4445b31..340f749b 100644 --- a/src/fri/prover.rs +++ b/src/fri/prover.rs @@ -53,7 +53,7 @@ pub fn fri_proof, const D: usize>( fri_prover_query_rounds(initial_merkle_trees, &trees, challenger, n, config); FriProof { - commit_phase_merkle_roots: trees.iter().map(|t| t.root).collect(), + commit_phase_merkle_roots: trees.iter().map(|t| t.root.clone()).collect(), query_round_proofs, final_poly: final_coeffs, pow_witness, @@ -80,10 +80,11 @@ fn fri_committed_trees, const D: usize>( .par_chunks(arity) .map(|chunk: &[F::Extension]| flatten(chunk)) .collect(), + config.cap_height, false, ); - challenger.observe_hash(&tree.root); + challenger.observe_cap(&tree.root); trees.push(tree); let beta = challenger.get_extension_challenge(); @@ -155,6 +156,7 @@ fn fri_prover_query_round, const D: usize>( let arity_bits = config.reduction_arity_bits[i]; let arity = 1 << arity_bits; let mut evals = unflatten(tree.get(x_index >> arity_bits)); + dbg!(&evals); evals.remove(x_index & (arity - 1)); let merkle_proof = tree.prove(x_index >> arity_bits); diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index 0ee786f7..26846e70 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -3,7 +3,7 @@ use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::fri::proof::{FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget}; use crate::fri::FriConfig; -use crate::hash::hash_types::HashOutTarget; +use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget}; use crate::iop::challenger::RecursiveChallenger; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; @@ -83,7 +83,7 @@ impl, const D: usize> CircuitBuilder { os: &OpeningSetTarget, // Point at which the PLONK polynomials are opened. zeta: ExtensionTarget, - initial_merkle_roots: &[HashOutTarget], + initial_merkle_roots: &[MerkleCapTarget], proof: &FriProofTarget, challenger: &mut RecursiveChallenger, common_data: &CommonCircuitData, @@ -111,7 +111,7 @@ impl, const D: usize> CircuitBuilder { .commit_phase_merkle_roots .iter() .map(|root| { - challenger.observe_hash(root); + challenger.observe_cap(root); challenger.get_extension_challenge(self) }) .collect::>() @@ -176,9 +176,9 @@ impl, const D: usize> CircuitBuilder { &mut self, x_index_bits: &[Target], proof: &FriInitialTreeProofTarget, - initial_merkle_roots: &[HashOutTarget], + initial_merkle_roots: &[MerkleCapTarget], ) { - for (i, ((evals, merkle_proof), &root)) in proof + for (i, ((evals, merkle_proof), root)) in proof .evals_proofs .iter() .zip(initial_merkle_roots) @@ -270,7 +270,7 @@ impl, const D: usize> CircuitBuilder { zeta: ExtensionTarget, alpha: ExtensionTarget, precomputed_reduced_evals: PrecomputedReducedEvalsTarget, - initial_merkle_roots: &[HashOutTarget], + initial_merkle_roots: &[MerkleCapTarget], proof: &FriProofTarget, challenger: &mut RecursiveChallenger, n: usize, @@ -347,7 +347,7 @@ impl, const D: usize> CircuitBuilder { self.verify_merkle_proof( flatten_target(&evals), &high_x_index_bits, - proof.commit_phase_merkle_roots[i], + &proof.commit_phase_merkle_roots[i], &round_proof.steps[i].merkle_proof, ) ); diff --git a/src/fri/verifier.rs b/src/fri/verifier.rs index ab877352..d0a16c95 100644 --- a/src/fri/verifier.rs +++ b/src/fri/verifier.rs @@ -8,6 +8,7 @@ use crate::fri::FriConfig; use crate::hash::hash_types::HashOut; use crate::hash::hashing::hash_n_to_1; use crate::hash::merkle_proofs::verify_merkle_proof; +use crate::hash::merkle_tree::MerkleCap; use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::plonk_common::PlonkPolynomials; @@ -73,7 +74,7 @@ pub fn verify_fri_proof, const D: usize>( os: &OpeningSet, // Point at which the PLONK polynomials are opened. zeta: F::Extension, - initial_merkle_roots: &[HashOut], + initial_merkle_roots: &[MerkleCap], proof: &FriProof, challenger: &mut Challenger, common_data: &CommonCircuitData, @@ -98,7 +99,7 @@ pub fn verify_fri_proof, const D: usize>( .commit_phase_merkle_roots .iter() .map(|root| { - challenger.observe_hash(root); + challenger.observe_cap(root); challenger.get_extension_challenge() }) .collect::>(); @@ -139,9 +140,9 @@ pub fn verify_fri_proof, const D: usize>( fn fri_verify_initial_proof( x_index: usize, proof: &FriInitialTreeProof, - initial_merkle_roots: &[HashOut], + initial_merkle_roots: &[MerkleCap], ) -> Result<()> { - for ((evals, merkle_proof), &root) in proof.evals_proofs.iter().zip(initial_merkle_roots) { + for ((evals, merkle_proof), root) in proof.evals_proofs.iter().zip(initial_merkle_roots) { verify_merkle_proof(evals.clone(), x_index, root, merkle_proof, false)?; } @@ -244,7 +245,7 @@ fn fri_verifier_query_round, const D: usize>( zeta: F::Extension, alpha: F::Extension, precomputed_reduced_evals: PrecomputedReducedEvals, - initial_merkle_roots: &[HashOut], + initial_merkle_roots: &[MerkleCap], proof: &FriProof, challenger: &mut Challenger, n: usize, @@ -297,7 +298,7 @@ fn fri_verifier_query_round, const D: usize>( verify_merkle_proof( flatten(&evals), x_index >> arity_bits, - proof.commit_phase_merkle_roots[i], + &proof.commit_phase_merkle_roots[i], &round_proof.steps[i].merkle_proof, false, )?; diff --git a/src/hash/hash_types.rs b/src/hash/hash_types.rs index 663b8cd1..e6cb274a 100644 --- a/src/hash/hash_types.rs +++ b/src/hash/hash_types.rs @@ -61,3 +61,6 @@ impl HashOutTarget { } } } + +#[derive(Clone, Debug)] +pub struct MerkleCapTarget(pub Vec); diff --git a/src/hash/merkle_proofs.rs b/src/hash/merkle_proofs.rs index 30391a98..fb303775 100644 --- a/src/hash/merkle_proofs.rs +++ b/src/hash/merkle_proofs.rs @@ -1,11 +1,15 @@ +use std::convert::TryInto; + use anyhow::{ensure, Result}; 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::gates::gmimc::GMiMCGate; -use crate::hash::hash_types::{HashOut, HashOutTarget}; +use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; use crate::hash::hashing::{compress, hash_or_noop, GMIMC_ROUNDS}; +use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::plonk::circuit_builder::CircuitBuilder; @@ -28,30 +32,29 @@ pub struct MerkleProofTarget { pub(crate) fn verify_merkle_proof( leaf_data: Vec, leaf_index: usize, - merkle_root: HashOut, + merkle_cap: &MerkleCap, proof: &MerkleProof, reverse_bits: bool, ) -> Result<()> { - ensure!( - leaf_index >> proof.siblings.len() == 0, - "Merkle leaf index is too large." - ); - - let index = if reverse_bits { + let mut index = if reverse_bits { crate::util::reverse_bits(leaf_index, proof.siblings.len()) } else { leaf_index }; let mut current_digest = hash_or_noop(leaf_data); - for (i, &sibling_digest) in proof.siblings.iter().enumerate() { - let bit = (index >> i & 1) == 1; - current_digest = if bit { + for &sibling_digest in proof.siblings.iter() { + let bit = index & 1; + index >>= 1; + current_digest = if bit == 1 { compress(sibling_digest, current_digest) } else { compress(current_digest, sibling_digest) } } - ensure!(current_digest == merkle_root, "Invalid Merkle proof."); + ensure!( + current_digest == merkle_cap.0[index], + "Invalid Merkle proof." + ); Ok(()) } @@ -63,7 +66,7 @@ impl, const D: usize> CircuitBuilder { &mut self, leaf_data: Vec, leaf_index_bits: &[Target], - merkle_root: HashOutTarget, + merkle_root: &MerkleCapTarget, proof: &MerkleProofTarget, ) { let zero = self.zero(); @@ -108,7 +111,25 @@ impl, const D: usize> CircuitBuilder { ) } - self.named_assert_hashes_equal(state, merkle_root, "check Merkle root".into()) + let index = self.le_sum(leaf_index_bits[proof.siblings.len()..].to_vec().into_iter()); + let mut state_ext = [zero; D]; + for i in 0..D { + state_ext[i] = state.elements[i]; + } + let state_ext = ExtensionTarget(state_ext); + let cap_ext = merkle_root + .0 + .iter() + .map(|h| { + let mut tmp = [zero; D]; + for i in 0..D { + tmp[i] = h.elements[i]; + } + ExtensionTarget(tmp) + }) + .collect(); + self.random_access(index, state_ext, cap_ext); + // self.named_assert_hashes_equal(state, merkle_root, "check Merkle root".into()) } pub(crate) fn assert_hashes_equal(&mut self, x: HashOutTarget, y: HashOutTarget) { @@ -159,8 +180,9 @@ mod tests { let log_n = 8; let n = 1 << log_n; + let cap_height = 1; let leaves = random_data::(n, 7); - let tree = MerkleTree::new(leaves, false); + let tree = MerkleTree::new(leaves, cap_height, false); let i: usize = thread_rng().gen_range(0..n); let proof = tree.prove(i); @@ -171,8 +193,8 @@ mod tests { pw.set_hash_target(proof_t.siblings[i], proof.siblings[i]); } - let root_t = builder.add_virtual_hash(); - pw.set_hash_target(root_t, tree.root); + let root_t = builder.add_virtual_cap(cap_height); + pw.set_cap_target(&root_t, &tree.root); let i_c = builder.constant(F::from_canonical_usize(i)); let i_bits = builder.split_le(i_c, log_n); @@ -182,7 +204,7 @@ mod tests { pw.set_target(data[j], tree.leaves[i][j]); } - builder.verify_merkle_proof(data, &i_bits, root_t, &proof_t); + builder.verify_merkle_proof(data, &i_bits, &root_t, &proof_t); let data = builder.build(); let proof = data.prove(pw)?; diff --git a/src/hash/merkle_tree.rs b/src/hash/merkle_tree.rs index c4e2a194..6accd451 100644 --- a/src/hash/merkle_tree.rs +++ b/src/hash/merkle_tree.rs @@ -1,4 +1,5 @@ use rayon::prelude::*; +use serde::{Deserialize, Serialize}; use crate::field::field_types::Field; use crate::hash::hash_types::HashOut; @@ -6,6 +7,10 @@ use crate::hash::hashing::{compress, hash_or_noop}; use crate::hash::merkle_proofs::MerkleProof; use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place}; +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound = "")] +pub struct MerkleCap(pub Vec>); + #[derive(Clone, Debug)] pub struct MerkleTree { /// The data in the leaves of the Merkle tree. @@ -14,8 +19,8 @@ pub struct MerkleTree { /// The layers of hashes in the tree. The first layer is the one at the bottom. pub layers: Vec>>, - /// The Merkle root. - pub root: HashOut, + /// The Merkle cap. + pub root: MerkleCap, /// If true, the indices are in bit-reversed form, so that the leaf at index `i` /// contains the leaf originally at index `reverse_bits(i)`. @@ -23,7 +28,7 @@ pub struct MerkleTree { } impl MerkleTree { - pub fn new(mut leaves: Vec>, reverse_bits: bool) -> Self { + pub fn new(mut leaves: Vec>, cap_height: usize, reverse_bits: bool) -> Self { if reverse_bits { reverse_index_bits_in_place(&mut leaves); } @@ -32,7 +37,7 @@ impl MerkleTree { .map(|l| hash_or_noop(l.clone())) .collect::>()]; while let Some(l) = layers.last() { - if l.len() == 1 { + if l.len() == 1 << cap_height { break; } let next_layer = l @@ -41,11 +46,11 @@ impl MerkleTree { .collect::>(); layers.push(next_layer); } - let root = layers.pop().unwrap()[0]; + let cap = layers.pop().unwrap(); Self { leaves, layers, - root, + root: MerkleCap(cap), reverse_bits, } } @@ -97,10 +102,10 @@ mod tests { n: usize, reverse_bits: bool, ) -> Result<()> { - let tree = MerkleTree::new(leaves.clone(), reverse_bits); + let tree = MerkleTree::new(leaves.clone(), 1, reverse_bits); for i in 0..n { let proof = tree.prove(i); - verify_merkle_proof(leaves[i].clone(), i, tree.root, &proof, reverse_bits)?; + verify_merkle_proof(leaves[i].clone(), i, &tree.root, &proof, reverse_bits)?; } Ok(()) } diff --git a/src/iop/challenger.rs b/src/iop/challenger.rs index 1e41ecea..70c7e310 100644 --- a/src/iop/challenger.rs +++ b/src/iop/challenger.rs @@ -3,8 +3,9 @@ use std::convert::TryInto; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; -use crate::hash::hash_types::{HashOut, HashOutTarget}; +use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; use crate::hash::hashing::{permute, SPONGE_RATE, SPONGE_WIDTH}; +use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::proof::{OpeningSet, OpeningSetTarget}; @@ -93,6 +94,12 @@ impl Challenger { self.observe_elements(&hash.elements) } + pub fn observe_cap(&mut self, cap: &MerkleCap) { + for hash in &cap.0 { + self.observe_elements(&hash.elements) + } + } + pub fn get_challenge(&mut self) -> F { self.absorb_buffered_inputs(); @@ -239,6 +246,12 @@ impl RecursiveChallenger { self.observe_elements(&hash.elements) } + pub fn observe_cap(&mut self, cap: &MerkleCapTarget) { + for hash in &cap.0 { + self.observe_hash(hash) + } + } + pub fn observe_extension_element(&mut self, element: ExtensionTarget) { self.observe_elements(&element.0); } diff --git a/src/iop/witness.rs b/src/iop/witness.rs index 0c9828a3..f2c0d453 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -6,8 +6,9 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; use crate::gates::gate::GateInstance; -use crate::hash::hash_types::HashOut; use crate::hash::hash_types::HashOutTarget; +use crate::hash::hash_types::{HashOut, MerkleCapTarget}; +use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::plonk::copy_constraint::CopyConstraint; @@ -147,6 +148,12 @@ impl PartialWitness { .for_each(|(&t, x)| self.set_target(t, x)); } + pub fn set_cap_target(&mut self, ct: &MerkleCapTarget, value: &MerkleCap) { + for (ht, h) in ct.0.iter().zip(&value.0) { + self.set_hash_target(*ht, *h); + } + } + pub fn set_extension_target( &mut self, et: ExtensionTarget, diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 0a6c0d06..646de78d 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -13,8 +13,9 @@ use crate::gates::gate::{Gate, GateInstance, GateRef, PrefixedGate}; use crate::gates::gate_tree::Tree; use crate::gates::noop::NoopGate; use crate::gates::public_input::PublicInputGate; -use crate::hash::hash_types::HashOutTarget; +use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget}; use crate::hash::hashing::hash_n_to_hash; +use crate::hash::merkle_tree::MerkleCap; use crate::iop::generator::{CopyGenerator, RandomValueGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -111,6 +112,10 @@ impl, const D: usize> CircuitBuilder { HashOutTarget::from_vec(self.add_virtual_targets(4)) } + pub fn add_virtual_cap(&mut self, cap_height: usize) -> MerkleCapTarget { + MerkleCapTarget(self.add_virtual_hashes(1 << cap_height)) + } + pub fn add_virtual_hashes(&mut self, n: usize) -> Vec { (0..n).map(|_i| self.add_virtual_hash()).collect() } @@ -561,12 +566,13 @@ impl, const D: usize> CircuitBuilder { constants_sigmas_vecs, self.config.rate_bits, self.config.zero_knowledge & PlonkPolynomials::CONSTANTS_SIGMAS.blinding, + self.config.cap_height, &mut timing, ); - let constants_sigmas_root = constants_sigmas_commitment.merkle_tree.root; + let constants_sigmas_root = constants_sigmas_commitment.merkle_tree.root.clone(); let verifier_only = VerifierOnlyCircuitData { - constants_sigmas_root, + constants_sigmas_root: constants_sigmas_root.clone(), }; let prover_only = ProverOnlyCircuitData { @@ -597,7 +603,11 @@ impl, const D: usize> CircuitBuilder { // TODO: This should also include an encoding of gate constraints. let circuit_digest_parts = [ - constants_sigmas_root.elements.to_vec(), + constants_sigmas_root + .0 + .into_iter() + .flat_map(|h| h.elements) + .collect::>(), vec![/* Add other circuit data here */], ]; let circuit_digest = hash_n_to_hash(circuit_digest_parts.concat(), false); diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index 48ec13be..9476b6f1 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -7,7 +7,8 @@ use crate::field::field_types::Field; use crate::fri::commitment::PolynomialBatchCommitment; use crate::fri::FriConfig; use crate::gates::gate::{GateInstance, PrefixedGate}; -use crate::hash::hash_types::{HashOut, HashOutTarget}; +use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; +use crate::hash::merkle_tree::MerkleCap; use crate::iop::generator::WitnessGenerator; use crate::iop::target::Target; use crate::iop::witness::PartialWitness; @@ -27,6 +28,7 @@ pub struct CircuitConfig { /// `degree / |F|`. pub num_challenges: usize, pub zero_knowledge: bool, + pub cap_height: usize, // TODO: Find a better place for this. pub fri_config: FriConfig, @@ -41,10 +43,12 @@ impl Default for CircuitConfig { rate_bits: 3, num_challenges: 3, zero_knowledge: true, + cap_height: 1, fri_config: FriConfig { proof_of_work_bits: 1, reduction_arity_bits: vec![1, 1, 1, 1], num_query_rounds: 1, + cap_height: 1, }, } } @@ -63,10 +67,12 @@ impl CircuitConfig { rate_bits: 3, num_challenges: 3, zero_knowledge: true, + cap_height: 1, fri_config: FriConfig { proof_of_work_bits: 1, reduction_arity_bits: vec![1, 1, 1, 1], num_query_rounds: 1, + cap_height: 0, }, } } @@ -143,7 +149,7 @@ pub(crate) struct ProverOnlyCircuitData, const D: usize> { /// Circuit data required by the verifier, but not the prover. pub(crate) struct VerifierOnlyCircuitData { /// A commitment to each constant polynomial and each permutation polynomial. - pub(crate) constants_sigmas_root: HashOut, + pub(crate) constants_sigmas_root: MerkleCap, } /// Circuit data required by both the prover and the verifier. @@ -233,5 +239,5 @@ impl, const D: usize> CommonCircuitData { /// dynamic, at least not without setting a maximum wire count and paying for the worst case. pub struct VerifierCircuitTarget { /// A commitment to each constant polynomial and each permutation polynomial. - pub(crate) constants_sigmas_root: HashOutTarget, + pub(crate) constants_sigmas_root: MerkleCapTarget, } diff --git a/src/plonk/proof.rs b/src/plonk/proof.rs index 300210f2..514f83f7 100644 --- a/src/plonk/proof.rs +++ b/src/plonk/proof.rs @@ -5,7 +5,8 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::fri::commitment::PolynomialBatchCommitment; use crate::fri::proof::{FriProof, FriProofTarget}; -use crate::hash::hash_types::{HashOut, HashOutTarget}; +use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; +use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::Target; use crate::plonk::circuit_data::CommonCircuitData; @@ -13,11 +14,11 @@ use crate::plonk::circuit_data::CommonCircuitData; #[serde(bound = "")] pub struct Proof, const D: usize> { /// Merkle root of LDEs of wire values. - pub wires_root: HashOut, + pub wires_root: MerkleCap, /// Merkle root of LDEs of Z, in the context of Plonk's permutation argument. - pub plonk_zs_partial_products_root: HashOut, + pub plonk_zs_partial_products_root: MerkleCap, /// Merkle root of LDEs of the quotient polynomial components. - pub quotient_polys_root: HashOut, + pub quotient_polys_root: MerkleCap, /// Purported values of each polynomial at the challenge point. pub openings: OpeningSet, /// A batch FRI argument for all openings. @@ -32,9 +33,9 @@ pub struct ProofWithPublicInputs, const D: usize> { } pub struct ProofTarget { - pub wires_root: HashOutTarget, - pub plonk_zs_partial_products_root: HashOutTarget, - pub quotient_polys_root: HashOutTarget, + pub wires_root: MerkleCapTarget, + pub plonk_zs_partial_products_root: MerkleCapTarget, + pub quotient_polys_root: MerkleCapTarget, pub openings: OpeningSetTarget, pub opening_proof: FriProofTarget, } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 27ba31c5..56484c8a 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -85,6 +85,7 @@ pub(crate) fn prove, const D: usize>( wires_values, config.rate_bits, config.zero_knowledge & PlonkPolynomials::WIRES.blinding, + config.cap_height, &mut timing, ) ); @@ -95,7 +96,7 @@ pub(crate) fn prove, const D: usize>( challenger.observe_hash(&common_data.circuit_digest); challenger.observe_hash(&public_inputs_hash); - challenger.observe_hash(&wires_commitment.merkle_tree.root); + challenger.observe_cap(&wires_commitment.merkle_tree.root); let betas = challenger.get_n_challenges(num_challenges); let gammas = challenger.get_n_challenges(num_challenges); @@ -129,11 +130,12 @@ pub(crate) fn prove, const D: usize>( zs_partial_products, config.rate_bits, config.zero_knowledge & PlonkPolynomials::ZS_PARTIAL_PRODUCTS.blinding, + config.cap_height, &mut timing, ) ); - challenger.observe_hash(&zs_partial_products_commitment.merkle_tree.root); + challenger.observe_cap(&zs_partial_products_commitment.merkle_tree.root); let alphas = challenger.get_n_challenges(num_challenges); @@ -177,11 +179,12 @@ pub(crate) fn prove, const D: usize>( all_quotient_poly_chunks, config.rate_bits, config.zero_knowledge & PlonkPolynomials::QUOTIENT.blinding, + config.cap_height, &mut timing ) ); - challenger.observe_hash("ient_polys_commitment.merkle_tree.root); + challenger.observe_cap("ient_polys_commitment.merkle_tree.root); let zeta = challenger.get_extension_challenge(); diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index ee5f82b9..7fc909e5 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -44,14 +44,14 @@ impl, const D: usize> CircuitBuilder { challenger.observe_hash(&digest); challenger.observe_hash(&public_inputs_hash); - challenger.observe_hash(&proof.wires_root); + challenger.observe_cap(&proof.wires_root); let betas = challenger.get_n_challenges(self, num_challenges); let gammas = challenger.get_n_challenges(self, num_challenges); - challenger.observe_hash(&proof.plonk_zs_partial_products_root); + challenger.observe_cap(&proof.plonk_zs_partial_products_root); let alphas = challenger.get_n_challenges(self, num_challenges); - challenger.observe_hash(&proof.quotient_polys_root); + challenger.observe_cap(&proof.quotient_polys_root); let zeta = challenger.get_extension_challenge(self); (betas, gammas, alphas, zeta) @@ -108,7 +108,7 @@ impl, const D: usize> CircuitBuilder { }); let merkle_roots = &[ - inner_verifier_data.constants_sigmas_root, + inner_verifier_data.constants_sigmas_root.clone(), proof.wires_root, proof.plonk_zs_partial_products_root, proof.quotient_polys_root, @@ -129,355 +129,355 @@ impl, const D: usize> CircuitBuilder { } } -#[cfg(test)] -mod tests { - use anyhow::Result; - - use super::*; - use crate::field::crandall_field::CrandallField; - use crate::fri::proof::{ - FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget, - }; - use crate::fri::FriConfig; - use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; - use crate::hash::merkle_proofs::MerkleProofTarget; - use crate::iop::witness::PartialWitness; - use crate::plonk::proof::{OpeningSetTarget, Proof, ProofTarget, ProofWithPublicInputs}; - use crate::plonk::verifier::verify; - - // Construct a `FriQueryRoundTarget` with the same dimensions as the ones in `proof`. - fn get_fri_query_round, const D: usize>( - proof: &Proof, - builder: &mut CircuitBuilder, - ) -> FriQueryRoundTarget { - 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, const D: usize>( - proof_with_pis: &ProofWithPublicInputs, - builder: &mut CircuitBuilder, - ) -> ProofWithPublicInputsTarget { - let ProofWithPublicInputs { - proof, - public_inputs, - } = proof_with_pis; - - let wires_root = builder.add_virtual_hash(); - let plonk_zs_root = builder.add_virtual_hash(); - let quotient_polys_root = builder.add_virtual_hash(); - - let openings = OpeningSetTarget { - constants: builder.add_virtual_extension_targets(proof.openings.constants.len()), - plonk_sigmas: builder.add_virtual_extension_targets(proof.openings.plonk_sigmas.len()), - wires: builder.add_virtual_extension_targets(proof.openings.wires.len()), - plonk_zs: builder.add_virtual_extension_targets(proof.openings.plonk_zs.len()), - plonk_zs_right: builder - .add_virtual_extension_targets(proof.openings.plonk_zs_right.len()), - partial_products: builder - .add_virtual_extension_targets(proof.openings.partial_products.len()), - quotient_polys: builder - .add_virtual_extension_targets(proof.openings.quotient_polys.len()), - }; - let query_round_proofs = (0..proof.opening_proof.query_round_proofs.len()) - .map(|_| get_fri_query_round(proof, builder)) - .collect(); - let commit_phase_merkle_roots = (0..proof.opening_proof.commit_phase_merkle_roots.len()) - .map(|_| builder.add_virtual_hash()) - .collect(); - 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, - plonk_zs_partial_products_root: plonk_zs_root, - quotient_polys_root, - 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, const D: usize>( - proof: &ProofWithPublicInputs, - pt: &ProofWithPublicInputsTarget, - pw: &mut PartialWitness, - ) { - 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); - } - - pw.set_hash_target(pt.wires_root, proof.wires_root); - pw.set_hash_target( - pt.plonk_zs_partial_products_root, - proof.plonk_zs_partial_products_root, - ); - pw.set_hash_target(pt.quotient_polys_root, proof.quotient_polys_root); - - 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 - .commit_phase_merkle_roots - .iter() - .zip(&fri_proof.commit_phase_merkle_roots) - { - pw.set_hash_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<()> { - env_logger::init(); - type F = CrandallField; - const D: usize = 4; - let config = CircuitConfig { - num_wires: 126, - num_routed_wires: 33, - security_bits: 128, - rate_bits: 3, - num_challenges: 3, - zero_knowledge: false, - fri_config: FriConfig { - proof_of_work_bits: 1, - reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], - num_query_rounds: 40, - }, - }; - let (proof_with_pis, vd, cd) = { - let mut builder = CircuitBuilder::::new(config.clone()); - let _two = builder.two(); - let _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; - for _ in 0..10000 { - let _two = builder.mul(_two, _two); - } - let data = builder.build(); - ( - data.prove(PartialWitness::new(config.num_wires))?, - data.verifier_only, - data.common, - ) - }; - verify(proof_with_pis.clone(), &vd, &cd)?; - - let mut builder = CircuitBuilder::::new(config.clone()); - let mut pw = PartialWitness::new(config.num_wires); - let pt = proof_to_proof_target(&proof_with_pis, &mut builder); - set_proof_target(&proof_with_pis, &pt, &mut pw); - - let inner_data = VerifierCircuitTarget { - constants_sigmas_root: builder.add_virtual_hash(), - }; - pw.set_hash_target(inner_data.constants_sigmas_root, vd.constants_sigmas_root); - - builder.add_recursive_verifier(pt, &config, &inner_data, &cd); - - builder.print_gate_counts(0); - let data = builder.build(); - let recursive_proof = data.prove(pw)?; - - verify(recursive_proof, &data.verifier_only, &data.common) - } - - #[test] - #[ignore] - fn test_recursive_recursive_verifier() -> Result<()> { - env_logger::init(); - type F = CrandallField; - const D: usize = 4; - let config = CircuitConfig { - num_wires: 126, - num_routed_wires: 33, - security_bits: 128, - rate_bits: 3, - num_challenges: 3, - zero_knowledge: false, - fri_config: FriConfig { - proof_of_work_bits: 1, - reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], - num_query_rounds: 40, - }, - }; - let (proof_with_pis, vd, cd) = { - let (proof_with_pis, vd, cd) = { - let mut builder = CircuitBuilder::::new(config.clone()); - let _two = builder.two(); - let _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; - for _ in 0..10000 { - let _two = builder.mul(_two, _two); - } - let data = builder.build(); - ( - data.prove(PartialWitness::new(config.num_wires))?, - data.verifier_only, - data.common, - ) - }; - verify(proof_with_pis.clone(), &vd, &cd)?; - - let mut builder = CircuitBuilder::::new(config.clone()); - let mut pw = PartialWitness::new(config.num_wires); - let pt = proof_to_proof_target(&proof_with_pis, &mut builder); - set_proof_target(&proof_with_pis, &pt, &mut pw); - - let inner_data = VerifierCircuitTarget { - constants_sigmas_root: builder.add_virtual_hash(), - }; - pw.set_hash_target(inner_data.constants_sigmas_root, vd.constants_sigmas_root); - - builder.add_recursive_verifier(pt, &config, &inner_data, &cd); - - let data = builder.build(); - let recursive_proof = data.prove(pw)?; - (recursive_proof, data.verifier_only, data.common) - }; - - verify(proof_with_pis.clone(), &vd, &cd)?; - let mut builder = CircuitBuilder::::new(config.clone()); - let mut pw = PartialWitness::new(config.num_wires); - let pt = proof_to_proof_target(&proof_with_pis, &mut builder); - set_proof_target(&proof_with_pis, &pt, &mut pw); - - let inner_data = VerifierCircuitTarget { - constants_sigmas_root: builder.add_virtual_hash(), - }; - pw.set_hash_target(inner_data.constants_sigmas_root, vd.constants_sigmas_root); - - builder.add_recursive_verifier(pt, &config, &inner_data, &cd); - - builder.print_gate_counts(0); - let data = builder.build(); - let recursive_proof = data.prove(pw)?; - verify(recursive_proof, &data.verifier_only, &data.common) - } -} +// #[cfg(test)] +// mod tests { +// use anyhow::Result; +// +// use super::*; +// use crate::field::crandall_field::CrandallField; +// use crate::fri::proof::{ +// FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget, +// }; +// use crate::fri::FriConfig; +// use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; +// use crate::hash::merkle_proofs::MerkleProofTarget; +// use crate::iop::witness::PartialWitness; +// use crate::plonk::proof::{OpeningSetTarget, Proof, ProofTarget, ProofWithPublicInputs}; +// use crate::plonk::verifier::verify; +// +// // Construct a `FriQueryRoundTarget` with the same dimensions as the ones in `proof`. +// fn get_fri_query_round, const D: usize>( +// proof: &Proof, +// builder: &mut CircuitBuilder, +// ) -> FriQueryRoundTarget { +// 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, const D: usize>( +// proof_with_pis: &ProofWithPublicInputs, +// builder: &mut CircuitBuilder, +// ) -> ProofWithPublicInputsTarget { +// let ProofWithPublicInputs { +// proof, +// public_inputs, +// } = proof_with_pis; +// +// let wires_root = builder.add_virtual_hash(); +// let plonk_zs_root = builder.add_virtual_hash(); +// let quotient_polys_root = builder.add_virtual_hash(); +// +// let openings = OpeningSetTarget { +// constants: builder.add_virtual_extension_targets(proof.openings.constants.len()), +// plonk_sigmas: builder.add_virtual_extension_targets(proof.openings.plonk_sigmas.len()), +// wires: builder.add_virtual_extension_targets(proof.openings.wires.len()), +// plonk_zs: builder.add_virtual_extension_targets(proof.openings.plonk_zs.len()), +// plonk_zs_right: builder +// .add_virtual_extension_targets(proof.openings.plonk_zs_right.len()), +// partial_products: builder +// .add_virtual_extension_targets(proof.openings.partial_products.len()), +// quotient_polys: builder +// .add_virtual_extension_targets(proof.openings.quotient_polys.len()), +// }; +// let query_round_proofs = (0..proof.opening_proof.query_round_proofs.len()) +// .map(|_| get_fri_query_round(proof, builder)) +// .collect(); +// let commit_phase_merkle_roots = (0..proof.opening_proof.commit_phase_merkle_roots.len()) +// .map(|_| builder.add_virtual_hash()) +// .collect(); +// 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, +// plonk_zs_partial_products_root: plonk_zs_root, +// quotient_polys_root, +// 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, const D: usize>( +// proof: &ProofWithPublicInputs, +// pt: &ProofWithPublicInputsTarget, +// pw: &mut PartialWitness, +// ) { +// 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); +// } +// +// pw.set_hash_target(pt.wires_root, proof.wires_root); +// pw.set_hash_target( +// pt.plonk_zs_partial_products_root, +// proof.plonk_zs_partial_products_root, +// ); +// pw.set_hash_target(pt.quotient_polys_root, proof.quotient_polys_root); +// +// 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 +// .commit_phase_merkle_roots +// .iter() +// .zip(&fri_proof.commit_phase_merkle_roots) +// { +// pw.set_hash_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<()> { +// env_logger::init(); +// type F = CrandallField; +// const D: usize = 4; +// let config = CircuitConfig { +// num_wires: 126, +// num_routed_wires: 33, +// security_bits: 128, +// rate_bits: 3, +// num_challenges: 3, +// zero_knowledge: false, +// fri_config: FriConfig { +// proof_of_work_bits: 1, +// reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], +// num_query_rounds: 40, +// }, +// }; +// let (proof_with_pis, vd, cd) = { +// let mut builder = CircuitBuilder::::new(config.clone()); +// let _two = builder.two(); +// let _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; +// for _ in 0..10000 { +// let _two = builder.mul(_two, _two); +// } +// let data = builder.build(); +// ( +// data.prove(PartialWitness::new(config.num_wires))?, +// data.verifier_only, +// data.common, +// ) +// }; +// verify(proof_with_pis.clone(), &vd, &cd)?; +// +// let mut builder = CircuitBuilder::::new(config.clone()); +// let mut pw = PartialWitness::new(config.num_wires); +// let pt = proof_to_proof_target(&proof_with_pis, &mut builder); +// set_proof_target(&proof_with_pis, &pt, &mut pw); +// +// let inner_data = VerifierCircuitTarget { +// constants_sigmas_root: builder.add_virtual_hash(), +// }; +// pw.set_hash_target(inner_data.constants_sigmas_root, vd.constants_sigmas_root); +// +// builder.add_recursive_verifier(pt, &config, &inner_data, &cd); +// +// builder.print_gate_counts(0); +// let data = builder.build(); +// let recursive_proof = data.prove(pw)?; +// +// verify(recursive_proof, &data.verifier_only, &data.common) +// } +// +// #[test] +// #[ignore] +// fn test_recursive_recursive_verifier() -> Result<()> { +// env_logger::init(); +// type F = CrandallField; +// const D: usize = 4; +// let config = CircuitConfig { +// num_wires: 126, +// num_routed_wires: 33, +// security_bits: 128, +// rate_bits: 3, +// num_challenges: 3, +// zero_knowledge: false, +// fri_config: FriConfig { +// proof_of_work_bits: 1, +// reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], +// num_query_rounds: 40, +// }, +// }; +// let (proof_with_pis, vd, cd) = { +// let (proof_with_pis, vd, cd) = { +// let mut builder = CircuitBuilder::::new(config.clone()); +// let _two = builder.two(); +// let _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; +// for _ in 0..10000 { +// let _two = builder.mul(_two, _two); +// } +// let data = builder.build(); +// ( +// data.prove(PartialWitness::new(config.num_wires))?, +// data.verifier_only, +// data.common, +// ) +// }; +// verify(proof_with_pis.clone(), &vd, &cd)?; +// +// let mut builder = CircuitBuilder::::new(config.clone()); +// let mut pw = PartialWitness::new(config.num_wires); +// let pt = proof_to_proof_target(&proof_with_pis, &mut builder); +// set_proof_target(&proof_with_pis, &pt, &mut pw); +// +// let inner_data = VerifierCircuitTarget { +// constants_sigmas_root: builder.add_virtual_hash(), +// }; +// pw.set_hash_target(inner_data.constants_sigmas_root, vd.constants_sigmas_root); +// +// builder.add_recursive_verifier(pt, &config, &inner_data, &cd); +// +// let data = builder.build(); +// let recursive_proof = data.prove(pw)?; +// (recursive_proof, data.verifier_only, data.common) +// }; +// +// verify(proof_with_pis.clone(), &vd, &cd)?; +// let mut builder = CircuitBuilder::::new(config.clone()); +// let mut pw = PartialWitness::new(config.num_wires); +// let pt = proof_to_proof_target(&proof_with_pis, &mut builder); +// set_proof_target(&proof_with_pis, &pt, &mut pw); +// +// let inner_data = VerifierCircuitTarget { +// constants_sigmas_root: builder.add_virtual_hash(), +// }; +// pw.set_hash_target(inner_data.constants_sigmas_root, vd.constants_sigmas_root); +// +// builder.add_recursive_verifier(pt, &config, &inner_data, &cd); +// +// builder.print_gate_counts(0); +// let data = builder.build(); +// let recursive_proof = data.prove(pw)?; +// verify(recursive_proof, &data.verifier_only, &data.common) +// } +// } diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index ad6623c3..98736044 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -31,14 +31,14 @@ pub(crate) fn verify, const D: usize>( challenger.observe_hash(&common_data.circuit_digest); challenger.observe_hash(&public_inputs_hash); - challenger.observe_hash(&proof.wires_root); + challenger.observe_cap(&proof.wires_root); let betas = challenger.get_n_challenges(num_challenges); let gammas = challenger.get_n_challenges(num_challenges); - challenger.observe_hash(&proof.plonk_zs_partial_products_root); + challenger.observe_cap(&proof.plonk_zs_partial_products_root); let alphas = challenger.get_n_challenges(num_challenges); - challenger.observe_hash(&proof.quotient_polys_root); + challenger.observe_cap(&proof.quotient_polys_root); let zeta = challenger.get_extension_challenge(); let local_constants = &proof.openings.constants; @@ -84,7 +84,7 @@ pub(crate) fn verify, const D: usize>( } let merkle_roots = &[ - verifier_data.constants_sigmas_root, + verifier_data.constants_sigmas_root.clone(), proof.wires_root, proof.plonk_zs_partial_products_root, proof.quotient_polys_root,