mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-08 08:43:06 +00:00
Add FRI challenges
This commit is contained in:
parent
851455a26a
commit
d24d26e5c0
@ -16,7 +16,7 @@ use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::target::Target;
|
||||
use crate::plonk::config::{GenericConfig, Hasher};
|
||||
use crate::plonk::plonk_common::salt_size;
|
||||
use crate::plonk::proof::{FriInferredElements, ProofChallenges};
|
||||
use crate::plonk::proof::{FriChallenges, FriInferredElements, ProofChallenges};
|
||||
|
||||
/// Evaluations and Merkle proof produced by the prover in a FRI query step.
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
|
||||
@ -253,10 +253,10 @@ impl<F: RichField + Extendable<D>, H: Hasher<F>, const D: usize> CompressedFriPr
|
||||
pow_witness,
|
||||
..
|
||||
} = self;
|
||||
let ProofChallenges {
|
||||
let FriChallenges {
|
||||
fri_query_indices: indices,
|
||||
..
|
||||
} = challenges;
|
||||
} = &challenges.fri_challenges;
|
||||
let mut fri_inferred_elements = fri_inferred_elements.0.into_iter();
|
||||
let cap_height = params.config.cap_height;
|
||||
let reduction_arity_bits = ¶ms.reduction_arity_bits;
|
||||
|
||||
@ -11,7 +11,7 @@ use crate::hash::hash_types::RichField;
|
||||
use crate::hash::merkle_proofs::verify_merkle_proof;
|
||||
use crate::hash::merkle_tree::MerkleCap;
|
||||
use crate::plonk::config::{GenericConfig, Hasher};
|
||||
use crate::plonk::proof::{OpeningSet, ProofChallenges};
|
||||
use crate::plonk::proof::{FriChallenges, OpeningSet, ProofChallenges};
|
||||
use crate::util::reducing::ReducingFactor;
|
||||
use crate::util::reverse_bits;
|
||||
|
||||
@ -57,7 +57,7 @@ pub(crate) fn fri_verify_proof_of_work<F: RichField + Extendable<D>, const D: us
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn verify_fri_proof<
|
||||
pub fn verify_fri_proof<
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
const D: usize,
|
||||
@ -65,7 +65,7 @@ pub(crate) fn verify_fri_proof<
|
||||
instance: &FriInstanceInfo<F, D>,
|
||||
// Openings of the PLONK polynomials.
|
||||
os: &OpeningSet<F, D>,
|
||||
challenges: &ProofChallenges<F, D>,
|
||||
challenges: &FriChallenges<F, D>,
|
||||
initial_merkle_caps: &[MerkleCap<F, C::Hasher>],
|
||||
proof: &FriProof<F, C::Hasher, D>,
|
||||
params: &FriParams,
|
||||
@ -171,7 +171,7 @@ fn fri_verifier_query_round<
|
||||
const D: usize,
|
||||
>(
|
||||
instance: &FriInstanceInfo<F, D>,
|
||||
challenges: &ProofChallenges<F, D>,
|
||||
challenges: &FriChallenges<F, D>,
|
||||
precomputed_reduced_evals: &PrecomputedReducedOpenings<F, D>,
|
||||
initial_merkle_caps: &[MerkleCap<F, C::Hasher>],
|
||||
proof: &FriProof<F, C::Hasher, D>,
|
||||
|
||||
@ -12,8 +12,8 @@ use crate::iop::challenger::Challenger;
|
||||
use crate::plonk::circuit_data::CommonCircuitData;
|
||||
use crate::plonk::config::{GenericConfig, Hasher};
|
||||
use crate::plonk::proof::{
|
||||
CompressedProof, CompressedProofWithPublicInputs, FriInferredElements, OpeningSet, Proof,
|
||||
ProofChallenges, ProofWithPublicInputs,
|
||||
CompressedProof, CompressedProofWithPublicInputs, FriChallenges, FriInferredElements,
|
||||
OpeningSet, Proof, ProofChallenges, ProofWithPublicInputs,
|
||||
};
|
||||
use crate::util::reverse_bits;
|
||||
|
||||
@ -86,10 +86,12 @@ fn get_challenges<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, cons
|
||||
plonk_gammas,
|
||||
plonk_alphas,
|
||||
plonk_zeta,
|
||||
fri_alpha,
|
||||
fri_betas,
|
||||
fri_pow_response,
|
||||
fri_query_indices,
|
||||
fri_challenges: FriChallenges {
|
||||
fri_alpha,
|
||||
fri_betas,
|
||||
fri_pow_response,
|
||||
fri_query_indices,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -100,7 +102,10 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
&self,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> anyhow::Result<Vec<usize>> {
|
||||
Ok(self.get_challenges(common_data)?.fri_query_indices)
|
||||
Ok(self
|
||||
.get_challenges(common_data)?
|
||||
.fri_challenges
|
||||
.fri_query_indices)
|
||||
}
|
||||
|
||||
/// Computes all Fiat-Shamir challenges used in the Plonk proof.
|
||||
@ -179,9 +184,13 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
) -> FriInferredElements<F, D> {
|
||||
let ProofChallenges {
|
||||
plonk_zeta,
|
||||
fri_alpha,
|
||||
fri_betas,
|
||||
fri_query_indices,
|
||||
fri_challenges:
|
||||
FriChallenges {
|
||||
fri_alpha,
|
||||
fri_betas,
|
||||
fri_query_indices,
|
||||
..
|
||||
},
|
||||
..
|
||||
} = challenges;
|
||||
let mut fri_inferred_elements = Vec::new();
|
||||
|
||||
@ -4,7 +4,7 @@ pub mod config;
|
||||
pub(crate) mod copy_constraint;
|
||||
mod get_challenges;
|
||||
pub(crate) mod permutation_argument;
|
||||
pub(crate) mod plonk_common;
|
||||
pub mod plonk_common;
|
||||
pub mod proof;
|
||||
pub mod prover;
|
||||
pub mod recursive_verifier;
|
||||
|
||||
@ -125,7 +125,7 @@ pub(crate) fn reduce_with_powers_multi<
|
||||
cumul
|
||||
}
|
||||
|
||||
pub(crate) fn reduce_with_powers<'a, P: PackedField, T: IntoIterator<Item = &'a P>>(
|
||||
pub fn reduce_with_powers<'a, P: PackedField, T: IntoIterator<Item = &'a P>>(
|
||||
terms: T,
|
||||
alpha: P::Scalar,
|
||||
) -> P
|
||||
|
||||
@ -239,6 +239,10 @@ pub(crate) struct ProofChallenges<F: RichField + Extendable<D>, const D: usize>
|
||||
// Point at which the PLONK polynomials are opened.
|
||||
pub plonk_zeta: F::Extension,
|
||||
|
||||
pub fri_challenges: FriChallenges<F, D>,
|
||||
}
|
||||
|
||||
pub struct FriChallenges<F: RichField + Extendable<D>, const D: usize> {
|
||||
// Scaling factor to combine polynomials.
|
||||
pub fri_alpha: F::Extension,
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@ pub(crate) fn verify_with_challenges<
|
||||
verify_fri_proof::<F, C, D>(
|
||||
&common_data.get_fri_instance(challenges.plonk_zeta),
|
||||
&proof.openings,
|
||||
&challenges,
|
||||
&challenges.fri_challenges,
|
||||
merkle_caps,
|
||||
&proof.opening_proof,
|
||||
&common_data.fri_params,
|
||||
|
||||
@ -77,14 +77,19 @@ fn get_challenges<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, cons
|
||||
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
StarkProofWithPublicInputs<F, C, D>
|
||||
{
|
||||
pub(crate) fn fri_query_indices(&self, config: &StarkConfig) -> anyhow::Result<Vec<usize>> {
|
||||
Ok(self.get_challenges(config)?.fri_query_indices)
|
||||
pub(crate) fn fri_query_indices(
|
||||
&self,
|
||||
config: &StarkConfig,
|
||||
degree_bits: usize,
|
||||
) -> anyhow::Result<Vec<usize>> {
|
||||
Ok(self.get_challenges(config, degree_bits)?.fri_query_indices)
|
||||
}
|
||||
|
||||
/// Computes all Fiat-Shamir challenges used in the Plonk proof.
|
||||
pub(crate) fn get_challenges(
|
||||
&self,
|
||||
config: &StarkConfig,
|
||||
degree_bits: usize,
|
||||
) -> Result<StarkProofChallenges<F, D>> {
|
||||
let StarkProof {
|
||||
trace_cap,
|
||||
@ -99,7 +104,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
},
|
||||
} = &self.proof;
|
||||
|
||||
get_challenges(
|
||||
get_challenges::<F, C, D>(
|
||||
trace_cap,
|
||||
quotient_polys_cap,
|
||||
openings,
|
||||
@ -107,6 +112,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
final_poly,
|
||||
*pow_witness,
|
||||
config,
|
||||
degree_bits,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ impl<F: RichField + Extendable<D>, const D: usize> StarkOpeningSet<F, D> {
|
||||
quotient_polys,
|
||||
} = self;
|
||||
for v in &[local_values, next_values, permutation_zs, quotient_polys] {
|
||||
self.observe_extension_elements(v);
|
||||
challenger.observe_extension_elements(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ where
|
||||
)
|
||||
);
|
||||
let quotient_polys_cap = quotient_commitment.merkle_tree.cap;
|
||||
challenger.observe_cap(quotient_polys_cap);
|
||||
challenger.observe_cap("ient_polys_cap);
|
||||
|
||||
let zeta = challenger.get_extension_challenge::<D>();
|
||||
// To avoid leaking witness data, we want to ensure that our opening locations, `zeta` and
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use anyhow::{ensure, Result};
|
||||
use plonky2::field::extension_field::Extendable;
|
||||
use plonky2::field::extension_field::{Extendable, FieldExtension};
|
||||
use plonky2::field::field_types::Field;
|
||||
use plonky2::fri::verifier::verify_fri_proof;
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::plonk::circuit_data::CommonCircuitData;
|
||||
use plonky2::plonk::config::GenericConfig;
|
||||
use plonky2::plonk::plonk_common::reduce_with_powers;
|
||||
use plonky2::plonk::proof::ProofWithPublicInputs;
|
||||
use plonky2_util::log2_strict;
|
||||
|
||||
@ -19,11 +21,17 @@ pub(crate) fn verify<
|
||||
S: Stark<F, D>,
|
||||
const D: usize,
|
||||
>(
|
||||
stark: S,
|
||||
proof_with_pis: StarkProofWithPublicInputs<F, C, D>,
|
||||
config: &StarkConfig,
|
||||
) -> Result<()> {
|
||||
let challenges = proof_with_pis.get_challenges(config)?;
|
||||
verify_with_challenges(proof_with_pis, challenges, verifier_data, common_data)
|
||||
degree_bits: usize,
|
||||
) -> Result<()>
|
||||
where
|
||||
[(); S::COLUMNS]:,
|
||||
[(); S::PUBLIC_INPUTS]:,
|
||||
{
|
||||
let challenges = proof_with_pis.get_challenges(config, degree_bits)?;
|
||||
verify_with_challenges(stark, proof_with_pis, challenges, config)
|
||||
}
|
||||
|
||||
pub(crate) fn verify_with_challenges<
|
||||
@ -36,15 +44,18 @@ pub(crate) fn verify_with_challenges<
|
||||
proof_with_pis: StarkProofWithPublicInputs<F, C, D>,
|
||||
challenges: StarkProofChallenges<F, D>,
|
||||
config: &StarkConfig,
|
||||
) -> Result<()> {
|
||||
) -> Result<()>
|
||||
where
|
||||
[(); S::COLUMNS]:,
|
||||
[(); S::PUBLIC_INPUTS]:,
|
||||
{
|
||||
let StarkProofWithPublicInputs {
|
||||
proof,
|
||||
public_inputs,
|
||||
} = proof_with_pis;
|
||||
let degree = recover_degree(&proof, config);
|
||||
let degree_log = log2_strict(degree);
|
||||
let degree_bits = log2_strict(degree);
|
||||
|
||||
let local_constants = &proof.openings.constants;
|
||||
let local_values = &proof.openings.local_values;
|
||||
let next_values = &proof.openings.local_values;
|
||||
let StarkOpeningSet {
|
||||
@ -54,24 +65,32 @@ pub(crate) fn verify_with_challenges<
|
||||
quotient_polys,
|
||||
} = &proof.openings;
|
||||
let vars = StarkEvaluationVars {
|
||||
local_values,
|
||||
next_values,
|
||||
public_inputs: &public_inputs,
|
||||
local_values: &local_values.to_vec().try_into().unwrap(),
|
||||
next_values: &next_values.to_vec().try_into().unwrap(),
|
||||
public_inputs: &public_inputs
|
||||
.into_iter()
|
||||
.map(F::Extension::from_basefield)
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
let (l_1, l_last) = eval_l_1_and_l_last(degree_bits, challenges.stark_zeta);
|
||||
let mut consumer = ConstraintConsumer::<F::Extension>::new(
|
||||
challenges.stark_alphas,
|
||||
lagrange_first.values[i],
|
||||
lagrange_last.values[i],
|
||||
challenges
|
||||
.stark_alphas
|
||||
.iter()
|
||||
.map(|&alpha| F::Extension::from_basefield(alpha))
|
||||
.collect::<Vec<_>>(),
|
||||
l_1.into(),
|
||||
l_last.into(),
|
||||
);
|
||||
let (l_1, l_n) = eval_l_1_and_l_last(degree_log, challenges.stark_zeta);
|
||||
stark.eval_ext()
|
||||
stark.eval_ext(vars, &mut consumer);
|
||||
let acc = consumer.accumulators();
|
||||
|
||||
// Check each polynomial identity, of the form `vanishing(x) = Z_H(x) quotient(x)`, at zeta.
|
||||
let quotient_polys_zeta = &proof.openings.quotient_polys;
|
||||
let zeta_pow_deg = challenges
|
||||
.plonk_zeta
|
||||
.exp_power_of_2(common_data.degree_bits);
|
||||
let zeta_pow_deg = challenges.stark_zeta.exp_power_of_2(degree_bits);
|
||||
let z_h_zeta = zeta_pow_deg - F::Extension::ONE;
|
||||
// `quotient_polys_zeta` holds `num_challenges * quotient_degree_factor` evaluations.
|
||||
// Each chunk of `quotient_degree_factor` holds the evaluations of `t_0(zeta),...,t_{quotient_degree_factor-1}(zeta)`
|
||||
@ -79,41 +98,52 @@ pub(crate) fn verify_with_challenges<
|
||||
// So to reconstruct `t(zeta)` we can compute `reduce_with_powers(chunk, zeta^n)` for each
|
||||
// `quotient_degree_factor`-sized chunk of the original evaluations.
|
||||
for (i, chunk) in quotient_polys_zeta
|
||||
.chunks(common_data.quotient_degree_factor)
|
||||
.chunks(config.fri_config.rate_bits)
|
||||
.enumerate()
|
||||
{
|
||||
ensure!(vanishing_polys_zeta[i] == z_h_zeta * reduce_with_powers(chunk, zeta_pow_deg));
|
||||
ensure!(acc[i] == z_h_zeta * reduce_with_powers(chunk, zeta_pow_deg));
|
||||
}
|
||||
|
||||
let merkle_caps = &[
|
||||
verifier_data.constants_sigmas_cap.clone(),
|
||||
proof.wires_cap,
|
||||
proof.plonk_zs_partial_products_cap,
|
||||
proof.quotient_polys_cap,
|
||||
];
|
||||
let merkle_caps = &[proof.trace_cap, proof.quotient_polys_cap];
|
||||
|
||||
verify_fri_proof::<F, C, D>(
|
||||
&common_data.get_fri_instance(challenges.plonk_zeta),
|
||||
&S::fri_instance(
|
||||
challenges.stark_zeta,
|
||||
F::primitive_root_of_unity(degree_bits).into(),
|
||||
config.fri_config.rate_bits,
|
||||
),
|
||||
&proof.openings,
|
||||
&challenges,
|
||||
merkle_caps,
|
||||
&proof.opening_proof,
|
||||
&common_data.fri_params,
|
||||
&config.fri_params(degree_bits),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Evaluate the Lagrange basis `L_1` and `L_n` at a point `x`.
|
||||
fn eval_l_1_and_l_last<F: Field>(log_n: usize, x: F) -> (F,F) {
|
||||
fn eval_l_1_and_l_last<F: Field>(log_n: usize, x: F) -> (F, F) {
|
||||
let n = 1 << log_n;
|
||||
let g = F::primitive_root_of_unity(log_n);
|
||||
let z_x = x.exp_power_of_2(log_n);
|
||||
let invs = F::batch_multiplicative_inverse(&[F::from_canonical_usize(n) * (x - F::ONE), F::from_canonical_usize(n) * (g*x - F::ONE)]);
|
||||
let invs = F::batch_multiplicative_inverse(&[
|
||||
F::from_canonical_usize(n) * (x - F::ONE),
|
||||
F::from_canonical_usize(n) * (g * x - F::ONE),
|
||||
]);
|
||||
|
||||
(z_x * invs[0], z_x * invs[1])
|
||||
}
|
||||
|
||||
fn recover_degree<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(proof: &StarkProof<F, C,D>, config: &StarkConfig) -> usize {
|
||||
1<<(proof.opening_proof.query_round_proofs[0].initial_trees_proof.evals_proofs[0].1.siblings.len() + config.fri_config.cap_height)
|
||||
}
|
||||
fn recover_degree<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(
|
||||
proof: &StarkProof<F, C, D>,
|
||||
config: &StarkConfig,
|
||||
) -> usize {
|
||||
1 << (proof.opening_proof.query_round_proofs[0]
|
||||
.initial_trees_proof
|
||||
.evals_proofs[0]
|
||||
.1
|
||||
.siblings
|
||||
.len()
|
||||
+ config.fri_config.cap_height)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user