Bit of refactoring in FRI code (#162)

* Bit of refactoring in FRI code

- Inline `OpeningSet[Target]` and their `verify` methods, as they had become fairly trivial wrappers
- Have the challenger observe the openings and generate alpha inside `verify_fri_proof`. Conceptually I think of it as part of the batch-FRI protocol, and it minimizes redundancy.

* Fix tests
This commit is contained in:
Daniel Lubarov 2021-08-08 09:14:07 -07:00 committed by GitHub
parent 30bedbb18e
commit 97c2b6b9a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 143 deletions

View File

@ -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;
@ -131,7 +126,7 @@ impl<F: Field> PolynomialBatchCommitment<F> {
challenger: &mut Challenger<F>,
common_data: &CommonCircuitData<F, D>,
timing: &mut TimingTree,
) -> (OpeningProof<F, D>, OpeningSet<F, D>)
) -> (FriProof<F, D>, OpeningSet<F, D>)
where
F: Extendable<D>,
{
@ -223,13 +218,7 @@ impl<F: Field> PolynomialBatchCommitment<F> {
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 +249,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)]
mod tests {
use anyhow::Result;
@ -363,7 +283,7 @@ mod tests {
fn check_batch_polynomial_commitment<F: Field + Extendable<D>, 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 +296,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 +309,7 @@ mod tests {
let lpcs = (0..4)
.map(|i| {
PolynomialBatchCommitment::<F>::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 +317,7 @@ mod tests {
})
.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>(
&[&lpcs[0], &lpcs[1], &lpcs[2], &lpcs[3]],
zeta,
@ -406,15 +326,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,
)

View File

@ -70,13 +70,10 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn verify_fri_proof(
&mut self,
purported_degree_log: usize,
// Openings of the PLONK polynomials.
os: &OpeningSetTarget<D>,
// Point at which the PLONK polynomials are opened.
zeta: ExtensionTarget<D>,
// Scaling factor to combine polynomials.
alpha: ExtensionTarget<D>,
initial_merkle_roots: &[HashOutTarget],
proof: &FriProofTarget<D>,
challenger: &mut RecursiveChallenger,
@ -85,7 +82,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let config = &common_data.config;
let total_arities = config.fri_config.reduction_arity_bits.iter().sum::<usize>();
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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// 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.",

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>(
purported_degree_log: usize,
// Openings of the PLONK polynomials.
os: &OpeningSet<F, D>,
// Point at which the PLONK polynomials are opened.
zeta: F::Extension,
// Scaling factor to combine polynomials.
alpha: F::Extension,
initial_merkle_roots: &[HashOut<F>],
proof: &FriProof<F, D>,
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 total_arities = config.fri_config.reduction_arity_bits.iter().sum::<usize>();
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);

View File

@ -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<F: Extendable<D>, const D: usize> {
pub quotient_polys_root: HashOut<F>,
/// Purported values of each polynomial at the challenge point.
pub openings: OpeningSet<F, D>,
/// A FRI argument for each FRI query.
pub opening_proof: OpeningProof<F, D>,
/// A batch FRI argument for all openings.
pub opening_proof: FriProof<F, D>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
@ -35,7 +36,7 @@ pub struct ProofTarget<const D: usize> {
pub plonk_zs_partial_products_root: HashOutTarget,
pub quotient_polys_root: HashOutTarget,
pub openings: OpeningSetTarget<D>,
pub opening_proof: OpeningProofTarget<D>,
pub opening_proof: FriProofTarget<D>,
}
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.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);

View File

@ -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<F: Extendable<D>, 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<F: Extendable<D>, 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,
)?;