Finish making FRI generic (#422)

* Finish making FRI generic

* fix quotient poly factor

* Bound quotient degree factor
This commit is contained in:
Daniel Lubarov 2022-01-06 23:04:33 -08:00 committed by GitHub
parent 4e532f04fa
commit f48d8c92bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 91 additions and 125 deletions

View File

@ -1,8 +1,6 @@
use anyhow::Result;
use env_logger::Env;
use log::info;
use plonky2::fri::reduction_strategies::FriReductionStrategy;
use plonky2::fri::FriConfig;
use plonky2::hash::hashing::SPONGE_WIDTH;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
@ -20,22 +18,7 @@ fn main() -> Result<()> {
}
fn bench_prove<C: GenericConfig<D>, const D: usize>() -> Result<()> {
let config = CircuitConfig {
num_wires: 126,
num_routed_wires: 33,
constant_gate_size: 6,
use_base_arithmetic_gate: false,
security_bits: 128,
num_challenges: 3,
zero_knowledge: false,
fri_config: FriConfig {
rate_bits: 3,
cap_height: 1,
proof_of_work_bits: 15,
reduction_strategy: FriReductionStrategy::ConstantArityBits(3, 5),
num_query_rounds: 35,
},
};
let config = CircuitConfig::standard_recursion_config();
let inputs = PartialWitness::new();
let mut builder = CircuitBuilder::<C::F, D>::new(config);

View File

@ -24,6 +24,12 @@ pub struct FriConfig {
pub num_query_rounds: usize,
}
impl FriConfig {
pub fn rate(&self) -> f64 {
1.0 / ((1 << self.rate_bits) as f64)
}
}
/// FRI parameters, including generated parameters which are specific to an instance size, in
/// contrast to `FriConfig` which is user-specified and independent of instance size.
#[derive(Debug)]
@ -31,6 +37,9 @@ pub struct FriParams {
/// User-specified FRI configuration.
pub config: FriConfig,
/// Whether to use a hiding variant of Merkle trees (where random salts are added to leaves).
pub hiding: bool,
/// The degree of the purported codeword, measured in bits.
pub degree_bits: usize,

View File

@ -8,10 +8,10 @@ use rayon::prelude::*;
use crate::fri::proof::FriProof;
use crate::fri::prover::fri_proof;
use crate::fri::structure::{FriBatchInfo, FriInstanceInfo};
use crate::fri::FriParams;
use crate::hash::hash_types::RichField;
use crate::hash::merkle_tree::MerkleTree;
use crate::iop::challenger::Challenger;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::config::GenericConfig;
use crate::timed;
use crate::util::reducing::ReducingFactor;
@ -131,7 +131,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
instance: &FriInstanceInfo<F, D>,
oracles: &[&Self],
challenger: &mut Challenger<F, C::Hasher>,
common_data: &CommonCircuitData<F, C, D>,
fri_params: &FriParams,
timing: &mut TimingTree,
) -> FriProof<F, C::Hasher, D> {
assert!(D > 1, "Not implemented for D=1.");
@ -155,7 +155,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
final_poly += quotient;
}
let lde_final_poly = final_poly.lde(common_data.config.fri_config.rate_bits);
let lde_final_poly = final_poly.lde(fri_params.config.rate_bits);
let lde_final_values = timed!(
timing,
&format!("perform final FFT {}", lde_final_poly.len()),
@ -170,7 +170,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
lde_final_poly,
lde_final_values,
challenger,
&common_data.fri_params,
fri_params,
timing,
);

View File

@ -5,6 +5,7 @@ use plonky2_field::extension_field::{flatten, unflatten, Extendable};
use plonky2_field::polynomial::PolynomialCoeffs;
use serde::{Deserialize, Serialize};
use crate::fri::FriParams;
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
use crate::hash::hash_types::MerkleCapTarget;
use crate::hash::hash_types::RichField;
@ -13,7 +14,6 @@ use crate::hash::merkle_tree::MerkleCap;
use crate::hash::path_compression::{compress_merkle_proofs, decompress_merkle_proofs};
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::target::Target;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::config::{GenericConfig, Hasher};
use crate::plonk::plonk_common::salt_size;
use crate::plonk::proof::{FriInferredElements, ProofChallenges};
@ -136,7 +136,7 @@ impl<F: RichField + Extendable<D>, H: Hasher<F>, const D: usize> FriProof<F, H,
pub fn compress<C: GenericConfig<D, F = F, Hasher = H>>(
self,
indices: &[usize],
common_data: &CommonCircuitData<F, C, D>,
params: &FriParams,
) -> CompressedFriProof<F, H, D> {
let FriProof {
commit_phase_merkle_caps,
@ -145,8 +145,8 @@ impl<F: RichField + Extendable<D>, H: Hasher<F>, const D: usize> FriProof<F, H,
pow_witness,
..
} = self;
let cap_height = common_data.config.fri_config.cap_height;
let reduction_arity_bits = &common_data.fri_params.reduction_arity_bits;
let cap_height = params.config.cap_height;
let reduction_arity_bits = &params.reduction_arity_bits;
let num_reductions = reduction_arity_bits.len();
let num_initial_trees = query_round_proofs[0].initial_trees_proof.evals_proofs.len();
@ -243,7 +243,7 @@ impl<F: RichField + Extendable<D>, H: Hasher<F>, const D: usize> CompressedFriPr
self,
challenges: &ProofChallenges<F, D>,
fri_inferred_elements: FriInferredElements<F, D>,
common_data: &CommonCircuitData<F, C, D>,
params: &FriParams,
) -> FriProof<F, H, D> {
let CompressedFriProof {
commit_phase_merkle_caps,
@ -257,8 +257,8 @@ impl<F: RichField + Extendable<D>, H: Hasher<F>, const D: usize> CompressedFriPr
..
} = challenges;
let mut fri_inferred_elements = fri_inferred_elements.0.into_iter();
let cap_height = common_data.config.fri_config.cap_height;
let reduction_arity_bits = &common_data.fri_params.reduction_arity_bits;
let cap_height = params.config.cap_height;
let reduction_arity_bits = &params.reduction_arity_bits;
let num_reductions = reduction_arity_bits.len();
let num_initial_trees = query_round_proofs
.initial_trees_proofs
@ -275,7 +275,7 @@ impl<F: RichField + Extendable<D>, H: Hasher<F>, const D: usize> CompressedFriPr
let mut steps_indices = vec![vec![]; num_reductions];
let mut steps_evals = vec![vec![]; num_reductions];
let mut steps_proofs = vec![vec![]; num_reductions];
let height = common_data.degree_bits + common_data.config.fri_config.rate_bits;
let height = params.degree_bits + params.config.rate_bits;
let heights = reduction_arity_bits
.iter()
.scan(height, |acc, &bits| {
@ -285,10 +285,8 @@ impl<F: RichField + Extendable<D>, H: Hasher<F>, const D: usize> CompressedFriPr
.collect::<Vec<_>>();
// Holds the `evals` vectors that have already been reconstructed at each reduction depth.
let mut evals_by_depth = vec![
HashMap::<usize, Vec<_>>::new();
common_data.fri_params.reduction_arity_bits.len()
];
let mut evals_by_depth =
vec![HashMap::<usize, Vec<_>>::new(); params.reduction_arity_bits.len()];
for &(mut index) in indices {
let initial_trees_proof = query_round_proofs.initial_trees_proofs[&index].clone();
for (i, (leaves_data, proof)) in

View File

@ -4,7 +4,7 @@ use plonky2_util::{log2_strict, reverse_index_bits_in_place};
use crate::fri::proof::{FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget};
use crate::fri::structure::{FriBatchInfoTarget, FriInstanceInfoTarget, FriOpeningsTarget};
use crate::fri::FriConfig;
use crate::fri::{FriConfig, FriParams};
use crate::gadgets::interpolation::InterpolationGate;
use crate::gates::gate::Gate;
use crate::gates::interpolation::HighDegreeInterpolationGate;
@ -16,7 +16,6 @@ use crate::iop::challenger::RecursiveChallenger;
use crate::iop::ext_target::{flatten_target, ExtensionTarget};
use crate::iop::target::{BoolTarget, Target};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
use crate::plonk::config::{AlgebraicConfig, AlgebraicHasher, GenericConfig};
use crate::plonk::proof::OpeningSetTarget;
use crate::util::reducing::ReducingFactorTarget;
@ -32,7 +31,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
arity_bits: usize,
evals: &[ExtensionTarget<D>],
beta: ExtensionTarget<D>,
common_data: &CommonCircuitData<F, C, D>,
) -> ExtensionTarget<D> {
let arity = 1 << arity_bits;
debug_assert_eq!(evals.len(), arity);
@ -51,7 +49,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// The answer is gotten by interpolating {(x*g^i, P(x*g^i))} and evaluating at beta.
// `HighDegreeInterpolationGate` has degree `arity`, so we use the low-degree gate if
// the arity is too large.
if arity > common_data.quotient_degree_factor {
if arity > self.config.max_quotient_degree_factor {
self.interpolate_coset::<LowDegreeInterpolationGate<F, D>>(
arity_bits,
coset_start,
@ -71,17 +69,13 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Make sure we have enough wires and routed wires to do the FRI checks efficiently. This check
/// isn't required -- without it we'd get errors elsewhere in the stack -- but just gives more
/// helpful errors.
fn check_recursion_config<C: GenericConfig<D, F = F>>(
&self,
max_fri_arity_bits: usize,
common_data: &CommonCircuitData<F, C, D>,
) {
fn check_recursion_config<C: GenericConfig<D, F = F>>(&self, max_fri_arity_bits: usize) {
let random_access = RandomAccessGate::<F, D>::new_from_config(
&self.config,
max_fri_arity_bits.max(self.config.fri_config.cap_height),
);
let (interpolation_wires, interpolation_routed_wires) =
if 1 << max_fri_arity_bits > common_data.quotient_degree_factor {
if 1 << max_fri_arity_bits > self.config.max_quotient_degree_factor {
let gate = LowDegreeInterpolationGate::<F, D>::new(max_fri_arity_bits);
(gate.num_wires(), gate.num_routed_wires())
} else {
@ -133,22 +127,20 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
initial_merkle_caps: &[MerkleCapTarget],
proof: &FriProofTarget<D>,
challenger: &mut RecursiveChallenger<F, C::Hasher, D>,
common_data: &CommonCircuitData<F, C, D>,
params: &FriParams,
) {
let config = &common_data.config;
if let Some(max_arity_bits) = common_data.fri_params.max_arity_bits() {
self.check_recursion_config(max_arity_bits, common_data);
if let Some(max_arity_bits) = params.max_arity_bits() {
self.check_recursion_config::<C>(max_arity_bits);
}
debug_assert_eq!(
common_data.fri_params.final_poly_len(),
params.final_poly_len(),
proof.final_poly.len(),
"Final polynomial has wrong degree."
);
// Size of the LDE domain.
let n = common_data.lde_size();
let n = params.lde_size();
challenger.observe_opening_set(os);
@ -172,12 +164,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
with_context!(
self,
"check PoW",
self.fri_verify_proof_of_work::<C::Hasher>(proof, challenger, &config.fri_config)
self.fri_verify_proof_of_work::<C::Hasher>(proof, challenger, &params.config)
);
// Check that parameters are coherent.
debug_assert_eq!(
config.fri_config.num_query_rounds,
params.config.num_query_rounds,
proof.query_round_proofs.len(),
"Number of query rounds does not match config."
);
@ -203,7 +195,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self,
level,
&format!("verify one (of {}) query rounds", num_queries),
self.fri_verifier_query_round(
self.fri_verifier_query_round::<C>(
instance,
alpha,
&precomputed_reduced_evals,
@ -213,7 +205,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
n,
&betas,
round_proof,
common_data,
params,
)
);
}
@ -253,15 +245,14 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
alpha: ExtensionTarget<D>,
subgroup_x: Target,
precomputed_reduced_evals: &PrecomputedReducedOpeningsTarget<D>,
common_data: &CommonCircuitData<F, C, D>,
params: &FriParams,
) -> ExtensionTarget<D> {
assert!(D > 1, "Not implemented for D=1.");
let config = &common_data.config;
let degree_log = common_data.degree_bits;
let degree_log = params.degree_bits;
debug_assert_eq!(
degree_log,
common_data.config.fri_config.cap_height + proof.evals_proofs[0].1.siblings.len()
- config.fri_config.rate_bits
params.config.cap_height + proof.evals_proofs[0].1.siblings.len()
- params.config.rate_bits
);
let subgroup_x = self.convert_to_ext(subgroup_x);
let mut alpha = ReducingFactorTarget::new(alpha);
@ -277,7 +268,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
.iter()
.map(|p| {
let poly_blinding = instance.oracles[p.oracle_index].blinding;
let salted = config.zero_knowledge && poly_blinding;
let salted = params.hiding && poly_blinding;
proof.unsalted_eval(p.oracle_index, p.polynomial_index, salted)
})
.collect_vec();
@ -302,19 +293,18 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
n: usize,
betas: &[ExtensionTarget<D>],
round_proof: &FriQueryRoundTarget<D>,
common_data: &CommonCircuitData<F, C, D>,
params: &FriParams,
) {
let n_log = log2_strict(n);
// Note that this `low_bits` decomposition permits non-canonical binary encodings. Here we
// verify that this has a negligible impact on soundness error.
Self::assert_noncanonical_indices_ok(&common_data.config);
Self::assert_noncanonical_indices_ok(&params.config);
let x_index = challenger.get_challenge(self);
let mut x_index_bits = self.low_bits(x_index, n_log, F::BITS);
let cap_index = self.le_sum(
x_index_bits[x_index_bits.len() - common_data.config.fri_config.cap_height..].iter(),
);
let cap_index =
self.le_sum(x_index_bits[x_index_bits.len() - params.config.cap_height..].iter());
with_context!(
self,
"check FRI initial proof",
@ -340,22 +330,17 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let mut old_eval = with_context!(
self,
"combine initial oracles",
self.fri_combine_initial(
self.fri_combine_initial::<C>(
instance,
&round_proof.initial_trees_proof,
alpha,
subgroup_x,
precomputed_reduced_evals,
common_data,
params,
)
);
for (i, &arity_bits) in common_data
.fri_params
.reduction_arity_bits
.iter()
.enumerate()
{
for (i, &arity_bits) in params.reduction_arity_bits.iter().enumerate() {
let evals = &round_proof.steps[i].evals;
// Split x_index into the index of the coset x is in, and the index of x within that coset.
@ -370,13 +355,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
old_eval = with_context!(
self,
"infer evaluation using interpolation",
self.compute_evaluation(
self.compute_evaluation::<C>(
subgroup_x,
x_index_within_coset_bits,
arity_bits,
evals,
betas[i],
common_data
)
);
@ -423,7 +407,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Thus ambiguous elements contribute a negligible amount to soundness error.
///
/// Here we compare the probabilities as a sanity check, to verify the claim above.
fn assert_noncanonical_indices_ok(config: &CircuitConfig) {
fn assert_noncanonical_indices_ok(config: &FriConfig) {
let num_ambiguous_elems = u64::MAX - F::ORDER + 1;
let query_error = config.rate();
let p_ambiguous = (num_ambiguous_elems as f64) / (F::ORDER as f64);

View File

@ -6,11 +6,10 @@ use plonky2_util::{log2_strict, reverse_index_bits_in_place};
use crate::fri::proof::{FriInitialTreeProof, FriProof, FriQueryRound};
use crate::fri::structure::{FriBatchInfo, FriInstanceInfo, FriOpenings};
use crate::fri::FriConfig;
use crate::fri::{FriConfig, FriParams};
use crate::hash::hash_types::RichField;
use crate::hash::merkle_proofs::verify_merkle_proof;
use crate::hash::merkle_tree::MerkleCap;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::config::{GenericConfig, Hasher};
use crate::plonk::proof::{OpeningSet, ProofChallenges};
use crate::util::reducing::ReducingFactor;
@ -69,23 +68,22 @@ pub(crate) fn verify_fri_proof<
challenges: &ProofChallenges<F, D>,
initial_merkle_caps: &[MerkleCap<F, C::Hasher>],
proof: &FriProof<F, C::Hasher, D>,
common_data: &CommonCircuitData<F, C, D>,
params: &FriParams,
) -> Result<()> {
let config = &common_data.config;
ensure!(
common_data.fri_params.final_poly_len() == proof.final_poly.len(),
params.final_poly_len() == proof.final_poly.len(),
"Final polynomial has wrong degree."
);
// Size of the LDE domain.
let n = common_data.lde_size();
let n = params.lde_size();
// Check PoW.
fri_verify_proof_of_work(challenges.fri_pow_response, &config.fri_config)?;
fri_verify_proof_of_work(challenges.fri_pow_response, &params.config)?;
// Check that parameters are coherent.
ensure!(
config.fri_config.num_query_rounds == proof.query_round_proofs.len(),
params.config.num_query_rounds == proof.query_round_proofs.len(),
"Number of query rounds does not match config."
);
@ -105,7 +103,7 @@ pub(crate) fn verify_fri_proof<
x_index,
n,
round_proof,
common_data,
params,
)?;
}
@ -134,9 +132,8 @@ pub(crate) fn fri_combine_initial<
alpha: F::Extension,
subgroup_x: F,
precomputed_reduced_evals: &PrecomputedReducedOpenings<F, D>,
common_data: &CommonCircuitData<F, C, D>,
params: &FriParams,
) -> F::Extension {
let config = &common_data.config;
assert!(D > 1, "Not implemented for D=1.");
let subgroup_x = F::Extension::from_basefield(subgroup_x);
let mut alpha = ReducingFactor::new(alpha);
@ -152,7 +149,7 @@ pub(crate) fn fri_combine_initial<
.iter()
.map(|p| {
let poly_blinding = instance.oracles[p.oracle_index].blinding;
let salted = config.zero_knowledge && poly_blinding;
let salted = params.hiding && poly_blinding;
proof.unsalted_eval(p.oracle_index, p.polynomial_index, salted)
})
.map(F::Extension::from_basefield);
@ -179,7 +176,7 @@ fn fri_verifier_query_round<
mut x_index: usize,
n: usize,
round_proof: &FriQueryRound<F, C::Hasher, D>,
common_data: &CommonCircuitData<F, C, D>,
params: &FriParams,
) -> Result<()> {
fri_verify_initial_proof::<F, C::Hasher>(
x_index,
@ -193,21 +190,16 @@ fn fri_verifier_query_round<
// old_eval is the last derived evaluation; it will be checked for consistency with its
// committed "parent" value in the next iteration.
let mut old_eval = fri_combine_initial(
let mut old_eval = fri_combine_initial::<F, C, D>(
instance,
&round_proof.initial_trees_proof,
challenges.fri_alpha,
subgroup_x,
precomputed_reduced_evals,
common_data,
params,
);
for (i, &arity_bits) in common_data
.fri_params
.reduction_arity_bits
.iter()
.enumerate()
{
for (i, &arity_bits) in params.reduction_arity_bits.iter().enumerate() {
let arity = 1 << arity_bits;
let evals = &round_proof.steps[i].evals;

View File

@ -377,6 +377,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
);
FriParams {
config: fri_config.clone(),
hiding: self.config.zero_knowledge,
degree_bits,
reduction_arity_bits,
}
@ -588,6 +589,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn build<C: GenericConfig<D, F = F>>(mut self) -> CircuitData<F, C, D> {
let mut timing = TimingTree::new("preprocess", Level::Trace);
let start = Instant::now();
let rate_bits = self.config.fri_config.rate_bits;
self.fill_batched_gates();
@ -620,14 +622,16 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let gates = self.gates.iter().cloned().collect();
let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates);
let prefixed_gates = PrefixedGate::from_tree(gate_tree);
// `quotient_degree_factor` has to be between `max_filtered_constraint_degree-1` and `1<<rate_bits`.
// We find the value that minimizes `num_partial_product + quotient_degree_factor`.
let rate_bits = self.config.fri_config.rate_bits;
let quotient_degree_factor = (max_filtered_constraint_degree - 1..=1 << rate_bits)
let min_quotient_degree_factor = max_filtered_constraint_degree - 1;
let max_quotient_degree_factor = self.config.max_quotient_degree_factor.min(1 << rate_bits);
let quotient_degree_factor = (min_quotient_degree_factor..=max_quotient_degree_factor)
.min_by_key(|&q| num_partial_products(self.config.num_routed_wires, q).0 + q)
.unwrap();
debug!("Quotient degree factor set to: {}.", quotient_degree_factor);
let prefixed_gates = PrefixedGate::from_tree(gate_tree);
let subgroup = F::two_adic_subgroup(degree_bits);

View File

@ -41,7 +41,9 @@ pub struct CircuitConfig {
/// `degree / |F|`.
pub num_challenges: usize,
pub zero_knowledge: bool,
/// A cap on the quotient polynomial's degree factor. The actual degree factor is derived
/// systematically, but will never exceed this value.
pub max_quotient_degree_factor: usize,
pub fri_config: FriConfig,
}
@ -52,10 +54,6 @@ impl Default for CircuitConfig {
}
impl CircuitConfig {
pub fn rate(&self) -> f64 {
1.0 / ((1 << self.fri_config.rate_bits) as f64)
}
pub fn num_advice_wires(&self) -> usize {
self.num_wires - self.num_routed_wires
}
@ -70,6 +68,7 @@ impl CircuitConfig {
security_bits: 100,
num_challenges: 2,
zero_knowledge: false,
max_quotient_degree_factor: 8,
fri_config: FriConfig {
rate_bits: 3,
cap_height: 4,

View File

@ -197,7 +197,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
for &(mut x_index) in fri_query_indices {
let mut subgroup_x = F::MULTIPLICATIVE_GROUP_GENERATOR
* F::primitive_root_of_unity(log_n).exp_u64(reverse_bits(x_index, log_n) as u64);
let mut old_eval = fri_combine_initial(
let mut old_eval = fri_combine_initial::<F, C, D>(
&common_data.get_fri_instance(*plonk_zeta),
&self
.proof
@ -207,7 +207,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
*fri_alpha,
subgroup_x,
&precomputed_reduced_evals,
common_data,
&common_data.fri_params,
);
for (i, &arity_bits) in common_data
.fri_params

View File

@ -7,6 +7,7 @@ use crate::fri::proof::{CompressedFriProof, FriProof, FriProofTarget};
use crate::fri::structure::{
FriOpeningBatch, FriOpeningBatchTarget, FriOpenings, FriOpeningsTarget,
};
use crate::fri::FriParams;
use crate::hash::hash_types::{MerkleCapTarget, RichField};
use crate::hash::merkle_tree::MerkleCap;
use crate::iop::ext_target::ExtensionTarget;
@ -41,11 +42,7 @@ pub struct ProofTarget<const D: usize> {
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> Proof<F, C, D> {
/// Compress the proof.
pub fn compress(
self,
indices: &[usize],
common_data: &CommonCircuitData<F, C, D>,
) -> CompressedProof<F, C, D> {
pub fn compress(self, indices: &[usize], params: &FriParams) -> CompressedProof<F, C, D> {
let Proof {
wires_cap,
plonk_zs_partial_products_cap,
@ -59,7 +56,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> P
plonk_zs_partial_products_cap,
quotient_polys_cap,
openings,
opening_proof: opening_proof.compress(indices, common_data),
opening_proof: opening_proof.compress::<C>(indices, params),
}
}
}
@ -83,7 +80,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
common_data: &CommonCircuitData<F, C, D>,
) -> anyhow::Result<CompressedProofWithPublicInputs<F, C, D>> {
let indices = self.fri_query_indices(common_data)?;
let compressed_proof = self.proof.compress(&indices, common_data);
let compressed_proof = self.proof.compress(&indices, &common_data.fri_params);
Ok(CompressedProofWithPublicInputs {
public_inputs: self.public_inputs,
proof: compressed_proof,
@ -136,7 +133,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
self,
challenges: &ProofChallenges<F, D>,
fri_inferred_elements: FriInferredElements<F, D>,
common_data: &CommonCircuitData<F, C, D>,
params: &FriParams,
) -> Proof<F, C, D> {
let CompressedProof {
wires_cap,
@ -151,7 +148,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
plonk_zs_partial_products_cap,
quotient_polys_cap,
openings,
opening_proof: opening_proof.decompress(challenges, fri_inferred_elements, common_data),
opening_proof: opening_proof.decompress::<C>(challenges, fri_inferred_elements, params),
}
}
}
@ -178,7 +175,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
let fri_inferred_elements = self.get_inferred_elements(&challenges, common_data);
let decompressed_proof =
self.proof
.decompress(&challenges, fri_inferred_elements, common_data);
.decompress(&challenges, fri_inferred_elements, &common_data.fri_params);
Ok(ProofWithPublicInputs {
public_inputs: self.public_inputs,
proof: decompressed_proof,
@ -194,7 +191,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
let fri_inferred_elements = self.get_inferred_elements(&challenges, common_data);
let decompressed_proof =
self.proof
.decompress(&challenges, fri_inferred_elements, common_data);
.decompress(&challenges, fri_inferred_elements, &common_data.fri_params);
verify_with_challenges(
ProofWithPublicInputs {
public_inputs: self.public_inputs,

View File

@ -209,7 +209,7 @@ pub(crate) fn prove<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, co
&quotient_polys_commitment,
],
&mut challenger,
common_data,
&common_data.fri_params,
timing,
)
);

View File

@ -30,7 +30,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let public_inputs_hash = &self.hash_n_to_hash::<C::InnerHasher>(public_inputs, true);
let mut challenger = RecursiveChallenger::new(self);
let mut challenger = RecursiveChallenger::<F, C::Hasher, D>::new(self);
let (betas, gammas, alphas, zeta) =
with_context!(self, "observe proof and generates challenges", {
@ -111,13 +111,13 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
with_context!(
self,
"verify FRI proof",
self.verify_fri_proof(
self.verify_fri_proof::<C>(
&fri_instance,
&proof.openings,
merkle_caps,
&proof.opening_proof,
&mut challenger,
inner_common_data,
&inner_common_data.fri_params,
)
);
}

View File

@ -85,13 +85,13 @@ pub(crate) fn verify_with_challenges<
proof.quotient_polys_cap,
];
verify_fri_proof(
verify_fri_proof::<F, C, D>(
&common_data.get_fri_instance(challenges.plonk_zeta),
&proof.openings,
&challenges,
merkle_caps,
&proof.opening_proof,
common_data,
&common_data.fri_params,
)?;
Ok(())