Merge branch 'main' into partial_witness_vec

This commit is contained in:
wborgeaud 2021-08-09 09:23:17 +02:00
commit 4f4839dcbe
8 changed files with 102 additions and 145 deletions

View File

@ -24,6 +24,13 @@ anyhow = "1.0.40"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_cbor = "0.11.1" serde_cbor = "0.11.1"
[dev-dependencies]
criterion = "0.3.5"
[[bench]]
name = "field_arithmetic"
harness = false
[profile.release] [profile.release]
opt-level = 3 opt-level = 3
#lto = "fat" #lto = "fat"

View File

@ -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<F: Field>(c: &mut Criterion) {
c.bench_function(&format!("{} mul", type_name::<F>()), |b| {
b.iter_batched(
|| (F::rand(), F::rand()),
|(x, y)| x * y,
BatchSize::SmallInput,
)
});
c.bench_function(&format!("{} try_inverse", type_name::<F>()), |b| {
b.iter_batched(|| F::rand(), |x| x.try_inverse(), BatchSize::SmallInput)
});
}
fn criterion_benchmark(c: &mut Criterion) {
bench_field::<CrandallField>(c);
bench_field::<QuarticCrandallField>(c);
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

View File

@ -1,25 +1,20 @@
use anyhow::Result;
use rayon::prelude::*; use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable; use crate::field::extension_field::Extendable;
use crate::field::field_types::Field; 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::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::hash::merkle_tree::MerkleTree;
use crate::iop::challenger::{Challenger, RecursiveChallenger}; use crate::iop::challenger::Challenger;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::plonk_common::PlonkPolynomials; 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::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
use crate::timed; use crate::timed;
use crate::util::reducing::ReducingFactor; use crate::util::reducing::ReducingFactor;
use crate::util::timing::TimingTree; use crate::util::timing::TimingTree;
use crate::util::{log2_ceil, log2_strict, reverse_bits, reverse_index_bits_in_place, transpose}; use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place, transpose};
use crate::with_context;
/// Two (~64 bit) field elements gives ~128 bit security. /// Two (~64 bit) field elements gives ~128 bit security.
pub const SALT_SIZE: usize = 2; pub const SALT_SIZE: usize = 2;
@ -78,8 +73,6 @@ impl<F: Field> PolynomialBatchCommitment<F> {
blinding: bool, blinding: bool,
timing: &mut TimingTree, timing: &mut TimingTree,
) -> Self { ) -> 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)); let mut leaves = timed!(timing, "transpose LDEs", transpose(&lde_values));
reverse_index_bits_in_place(&mut leaves); 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, false));
@ -131,7 +124,7 @@ impl<F: Field> PolynomialBatchCommitment<F> {
challenger: &mut Challenger<F>, challenger: &mut Challenger<F>,
common_data: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
timing: &mut TimingTree, timing: &mut TimingTree,
) -> (OpeningProof<F, D>, OpeningSet<F, D>) ) -> (FriProof<F, D>, OpeningSet<F, D>)
where where
F: Extendable<D>, F: Extendable<D>,
{ {
@ -223,13 +216,7 @@ impl<F: Field> PolynomialBatchCommitment<F> {
timing, timing,
); );
( (fri_proof, os)
OpeningProof {
fri_proof,
quotient_degree: final_poly.len(),
},
os,
)
} }
/// Given `points=(x_i)`, `evals=(y_i)` and `poly=P` with `P(x_i)=y_i`, computes the polynomial /// Given `points=(x_i)`, `evals=(y_i)` and `poly=P` with `P(x_i)=y_i`, computes the polynomial
@ -260,75 +247,6 @@ impl<F: Field> PolynomialBatchCommitment<F> {
} }
} }
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "")]
pub struct OpeningProof<F: Extendable<D>, const D: usize> {
pub(crate) fri_proof: FriProof<F, D>,
// TODO: Get the degree from `CommonCircuitData` instead.
quotient_degree: usize,
}
impl<F: Extendable<D>, const D: usize> OpeningProof<F, D> {
pub fn verify(
&self,
zeta: F::Extension,
os: &OpeningSet<F, D>,
merkle_roots: &[HashOut<F>],
challenger: &mut Challenger<F>,
common_data: &CommonCircuitData<F, D>,
) -> 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<const D: usize> {
pub(crate) fri_proof: FriProofTarget<D>,
}
impl<const D: usize> OpeningProofTarget<D> {
pub fn verify<F: Extendable<D>>(
&self,
zeta: ExtensionTarget<D>,
os: &OpeningSetTarget<D>,
merkle_roots: &[HashOutTarget],
challenger: &mut RecursiveChallenger,
common_data: &CommonCircuitData<F, D>,
builder: &mut CircuitBuilder<F, D>,
) {
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)] #[cfg(test)]
mod tests { mod tests {
use anyhow::Result; use anyhow::Result;
@ -363,7 +281,7 @@ mod tests {
fn check_batch_polynomial_commitment<F: Field + Extendable<D>, const D: usize>() -> Result<()> { fn check_batch_polynomial_commitment<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
let ks = [10, 2, 10, 8]; let ks = [10, 2, 10, 8];
let degree_log = 11; let degree_bits = 11;
let fri_config = FriConfig { let fri_config = FriConfig {
proof_of_work_bits: 2, proof_of_work_bits: 2,
reduction_arity_bits: vec![2, 3, 1, 2], reduction_arity_bits: vec![2, 3, 1, 2],
@ -376,7 +294,7 @@ mod tests {
num_routed_wires: 6, num_routed_wires: 6,
..CircuitConfig::large_config() ..CircuitConfig::large_config()
}, },
degree_bits: 0, degree_bits,
gates: vec![], gates: vec![],
quotient_degree_factor: 0, quotient_degree_factor: 0,
num_gate_constraints: 0, num_gate_constraints: 0,
@ -389,7 +307,7 @@ mod tests {
let lpcs = (0..4) let lpcs = (0..4)
.map(|i| { .map(|i| {
PolynomialBatchCommitment::<F>::new( PolynomialBatchCommitment::<F>::new(
gen_random_test_case(ks[i], degree_log), gen_random_test_case(ks[i], degree_bits),
common_data.config.rate_bits, common_data.config.rate_bits,
PlonkPolynomials::polynomials(i).blinding, PlonkPolynomials::polynomials(i).blinding,
&mut TimingTree::default(), &mut TimingTree::default(),
@ -397,7 +315,7 @@ mod tests {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let zeta = gen_random_point::<F, D>(degree_log); let zeta = gen_random_point::<F, D>(degree_bits);
let (proof, os) = PolynomialBatchCommitment::open_plonk::<D>( let (proof, os) = PolynomialBatchCommitment::open_plonk::<D>(
&[&lpcs[0], &lpcs[1], &lpcs[2], &lpcs[3]], &[&lpcs[0], &lpcs[1], &lpcs[2], &lpcs[3]],
zeta, zeta,
@ -406,15 +324,18 @@ mod tests {
&mut TimingTree::default(), &mut TimingTree::default(),
); );
proof.verify( let merkle_roots = &[
zeta, lpcs[0].merkle_tree.root,
lpcs[1].merkle_tree.root,
lpcs[2].merkle_tree.root,
lpcs[3].merkle_tree.root,
];
verify_fri_proof(
&os, &os,
&[ zeta,
lpcs[0].merkle_tree.root, merkle_roots,
lpcs[1].merkle_tree.root, &proof,
lpcs[2].merkle_tree.root,
lpcs[3].merkle_tree.root,
],
&mut Challenger::new(), &mut Challenger::new(),
&common_data, &common_data,
) )

View File

@ -70,13 +70,10 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn verify_fri_proof( pub fn verify_fri_proof(
&mut self, &mut self,
purported_degree_log: usize,
// Openings of the PLONK polynomials. // Openings of the PLONK polynomials.
os: &OpeningSetTarget<D>, os: &OpeningSetTarget<D>,
// Point at which the PLONK polynomials are opened. // Point at which the PLONK polynomials are opened.
zeta: ExtensionTarget<D>, zeta: ExtensionTarget<D>,
// Scaling factor to combine polynomials.
alpha: ExtensionTarget<D>,
initial_merkle_roots: &[HashOutTarget], initial_merkle_roots: &[HashOutTarget],
proof: &FriProofTarget<D>, proof: &FriProofTarget<D>,
challenger: &mut RecursiveChallenger, challenger: &mut RecursiveChallenger,
@ -85,7 +82,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let config = &common_data.config; let config = &common_data.config;
let total_arities = config.fri_config.reduction_arity_bits.iter().sum::<usize>(); let total_arities = config.fri_config.reduction_arity_bits.iter().sum::<usize>();
debug_assert_eq!( debug_assert_eq!(
purported_degree_log, common_data.degree_bits,
log2_strict(proof.final_poly.len()) + total_arities, log2_strict(proof.final_poly.len()) + total_arities,
"Final polynomial has wrong degree." "Final polynomial has wrong degree."
); );
@ -93,6 +90,11 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// Size of the LDE domain. // Size of the LDE domain.
let n = proof.final_poly.len() << (total_arities + config.rate_bits); 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!( let betas = with_context!(
self, self,
"recover the random betas used in the FRI reductions.", "recover the random betas used in the FRI reductions.",

View File

@ -69,13 +69,10 @@ fn fri_verify_proof_of_work<F: Field + Extendable<D>, const D: usize>(
} }
pub fn verify_fri_proof<F: Field + Extendable<D>, const D: usize>( pub fn verify_fri_proof<F: Field + Extendable<D>, const D: usize>(
purported_degree_log: usize,
// Openings of the PLONK polynomials. // Openings of the PLONK polynomials.
os: &OpeningSet<F, D>, os: &OpeningSet<F, D>,
// Point at which the PLONK polynomials are opened. // Point at which the PLONK polynomials are opened.
zeta: F::Extension, zeta: F::Extension,
// Scaling factor to combine polynomials.
alpha: F::Extension,
initial_merkle_roots: &[HashOut<F>], initial_merkle_roots: &[HashOut<F>],
proof: &FriProof<F, D>, proof: &FriProof<F, D>,
challenger: &mut Challenger<F>, challenger: &mut Challenger<F>,
@ -84,10 +81,15 @@ pub fn verify_fri_proof<F: Field + Extendable<D>, const D: usize>(
let config = &common_data.config; let config = &common_data.config;
let total_arities = config.fri_config.reduction_arity_bits.iter().sum::<usize>(); let total_arities = config.fri_config.reduction_arity_bits.iter().sum::<usize>();
ensure!( 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." "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. // Size of the LDE domain.
let n = proof.final_poly.len() << (total_arities + config.rate_bits); let n = proof.final_poly.len() << (total_arities + config.rate_bits);

View File

@ -3,7 +3,8 @@ use serde::{Deserialize, Serialize};
use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable; 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::hash::hash_types::{HashOut, HashOutTarget};
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::circuit_data::CommonCircuitData;
@ -19,8 +20,8 @@ pub struct Proof<F: Extendable<D>, const D: usize> {
pub quotient_polys_root: HashOut<F>, pub quotient_polys_root: HashOut<F>,
/// Purported values of each polynomial at the challenge point. /// Purported values of each polynomial at the challenge point.
pub openings: OpeningSet<F, D>, pub openings: OpeningSet<F, D>,
/// A FRI argument for each FRI query. /// A batch FRI argument for all openings.
pub opening_proof: OpeningProof<F, D>, pub opening_proof: FriProof<F, D>,
} }
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
@ -35,7 +36,7 @@ pub struct ProofTarget<const D: usize> {
pub plonk_zs_partial_products_root: HashOutTarget, pub plonk_zs_partial_products_root: HashOutTarget,
pub quotient_polys_root: HashOutTarget, pub quotient_polys_root: HashOutTarget,
pub openings: OpeningSetTarget<D>, pub openings: OpeningSetTarget<D>,
pub opening_proof: OpeningProofTarget<D>, pub opening_proof: FriProofTarget<D>,
} }
pub struct ProofWithPublicInputsTarget<const D: usize> { pub struct ProofWithPublicInputsTarget<const D: usize> {

View File

@ -114,13 +114,17 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
proof.quotient_polys_root, proof.quotient_polys_root,
]; ];
proof.opening_proof.verify( with_context!(
zeta,
&proof.openings,
merkle_roots,
&mut challenger,
inner_common_data,
self, 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 super::*;
use crate::field::crandall_field::CrandallField; use crate::field::crandall_field::CrandallField;
use crate::fri::commitment::OpeningProofTarget;
use crate::fri::proof::{ use crate::fri::proof::{
FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget, FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget,
}; };
@ -153,7 +156,7 @@ mod tests {
}, },
steps: vec![], 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 .initial_trees_proof
.evals_proofs .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 { query_round.steps.push(FriQueryStepTarget {
evals: builder.add_virtual_extension_targets(step.evals.len()), evals: builder.add_virtual_extension_targets(step.evals.len()),
merkle_proof: MerkleProofTarget { merkle_proof: MerkleProofTarget {
@ -201,27 +204,20 @@ mod tests {
quotient_polys: builder quotient_polys: builder
.add_virtual_extension_targets(proof.openings.quotient_polys.len()), .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)) .map(|_| get_fri_query_round(proof, builder))
.collect(); .collect();
let commit_phase_merkle_roots = (0..proof let commit_phase_merkle_roots = (0..proof.opening_proof.commit_phase_merkle_roots.len())
.opening_proof
.fri_proof
.commit_phase_merkle_roots
.len())
.map(|_| builder.add_virtual_hash()) .map(|_| builder.add_virtual_hash())
.collect(); .collect();
let opening_proof = let opening_proof = FriProofTarget {
OpeningProofTarget { commit_phase_merkle_roots,
fri_proof: FriProofTarget { query_round_proofs,
commit_phase_merkle_roots, final_poly: PolynomialCoeffsExtTarget(
query_round_proofs, builder.add_virtual_extension_targets(proof.opening_proof.final_poly.len()),
final_poly: PolynomialCoeffsExtTarget(builder.add_virtual_extension_targets( ),
proof.opening_proof.fri_proof.final_poly.len(), pow_witness: builder.add_virtual_target(),
)), };
pow_witness: builder.add_virtual_target(),
},
};
let proof = ProofTarget { let proof = ProofTarget {
wires_root, wires_root,
@ -307,8 +303,8 @@ mod tests {
pw.set_extension_target(t, x); pw.set_extension_target(t, x);
} }
let fri_proof = &proof.opening_proof.fri_proof; let fri_proof = &proof.opening_proof;
let fpt = &pt.opening_proof.fri_proof; let fpt = &pt.opening_proof;
pw.set_target(fpt.pow_witness, fri_proof.pow_witness); pw.set_target(fpt.pow_witness, fri_proof.pow_witness);

View File

@ -2,6 +2,7 @@ use anyhow::{ensure, Result};
use crate::field::extension_field::Extendable; use crate::field::extension_field::Extendable;
use crate::field::field_types::Field; use crate::field::field_types::Field;
use crate::fri::verifier::verify_fri_proof;
use crate::hash::hashing::hash_n_to_hash; use crate::hash::hashing::hash_n_to_hash;
use crate::iop::challenger::Challenger; use crate::iop::challenger::Challenger;
use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData};
@ -82,8 +83,6 @@ pub(crate) fn verify<F: Extendable<D>, const D: usize>(
ensure!(vanishing_polys_zeta[i] == z_h_zeta * reduce_with_powers(chunk, zeta_pow_deg)); ensure!(vanishing_polys_zeta[i] == z_h_zeta * reduce_with_powers(chunk, zeta_pow_deg));
} }
let evaluations = proof.openings.clone();
let merkle_roots = &[ let merkle_roots = &[
verifier_data.constants_sigmas_root, verifier_data.constants_sigmas_root,
proof.wires_root, proof.wires_root,
@ -91,10 +90,11 @@ pub(crate) fn verify<F: Extendable<D>, const D: usize>(
proof.quotient_polys_root, proof.quotient_polys_root,
]; ];
proof.opening_proof.verify( verify_fri_proof(
&proof.openings,
zeta, zeta,
&evaluations,
merkle_roots, merkle_roots,
&proof.opening_proof,
&mut challenger, &mut challenger,
common_data, common_data,
)?; )?;