mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 08:13:11 +00:00
214 lines
7.6 KiB
Rust
214 lines
7.6 KiB
Rust
|
|
use itertools::Itertools;
|
||
|
|
use plonky2::field::extension_field::{Extendable, FieldExtension};
|
||
|
|
use plonky2::fri::oracle::PolynomialBatch;
|
||
|
|
use plonky2::fri::proof::{
|
||
|
|
CompressedFriProof, FriChallenges, FriChallengesTarget, FriProof, FriProofTarget,
|
||
|
|
};
|
||
|
|
use plonky2::fri::structure::{
|
||
|
|
FriOpeningBatch, FriOpeningBatchTarget, FriOpenings, FriOpeningsTarget,
|
||
|
|
};
|
||
|
|
use plonky2::hash::hash_types::{MerkleCapTarget, RichField};
|
||
|
|
use plonky2::hash::merkle_tree::MerkleCap;
|
||
|
|
use plonky2::iop::ext_target::ExtensionTarget;
|
||
|
|
use plonky2::iop::target::Target;
|
||
|
|
use plonky2::plonk::config::GenericConfig;
|
||
|
|
use rayon::prelude::*;
|
||
|
|
|
||
|
|
use crate::config::StarkConfig;
|
||
|
|
use crate::permutation::PermutationChallengeSet;
|
||
|
|
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
pub struct StarkProof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> {
|
||
|
|
/// Merkle cap of LDEs of trace values.
|
||
|
|
pub trace_cap: MerkleCap<F, C::Hasher>,
|
||
|
|
/// Merkle cap of LDEs of permutation Z values.
|
||
|
|
pub permutation_zs_cap: Option<MerkleCap<F, C::Hasher>>,
|
||
|
|
/// Merkle cap of LDEs of trace values.
|
||
|
|
pub quotient_polys_cap: MerkleCap<F, C::Hasher>,
|
||
|
|
/// Purported values of each polynomial at the challenge point.
|
||
|
|
pub openings: StarkOpeningSet<F, D>,
|
||
|
|
/// A batch FRI argument for all openings.
|
||
|
|
pub opening_proof: FriProof<F, C::Hasher, D>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> StarkProof<F, C, D> {
|
||
|
|
/// Recover the length of the trace from a STARK proof and a STARK config.
|
||
|
|
pub fn recover_degree_bits(&self, config: &StarkConfig) -> usize {
|
||
|
|
let initial_merkle_proof = &self.opening_proof.query_round_proofs[0]
|
||
|
|
.initial_trees_proof
|
||
|
|
.evals_proofs[0]
|
||
|
|
.1;
|
||
|
|
let lde_bits = config.fri_config.cap_height + initial_merkle_proof.siblings.len();
|
||
|
|
lde_bits - config.fri_config.rate_bits
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub struct StarkProofTarget<const D: usize> {
|
||
|
|
pub trace_cap: MerkleCapTarget,
|
||
|
|
pub permutation_zs_cap: Option<MerkleCapTarget>,
|
||
|
|
pub quotient_polys_cap: MerkleCapTarget,
|
||
|
|
pub openings: StarkOpeningSetTarget<D>,
|
||
|
|
pub opening_proof: FriProofTarget<D>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<const D: usize> StarkProofTarget<D> {
|
||
|
|
/// Recover the length of the trace from a STARK proof and a STARK config.
|
||
|
|
pub fn recover_degree_bits(&self, config: &StarkConfig) -> usize {
|
||
|
|
let initial_merkle_proof = &self.opening_proof.query_round_proofs[0]
|
||
|
|
.initial_trees_proof
|
||
|
|
.evals_proofs[0]
|
||
|
|
.1;
|
||
|
|
let lde_bits = config.fri_config.cap_height + initial_merkle_proof.siblings.len();
|
||
|
|
lde_bits - config.fri_config.rate_bits
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
pub struct StarkProofWithPublicInputs<
|
||
|
|
F: RichField + Extendable<D>,
|
||
|
|
C: GenericConfig<D, F = F>,
|
||
|
|
const D: usize,
|
||
|
|
> {
|
||
|
|
pub proof: StarkProof<F, C, D>,
|
||
|
|
// TODO: Maybe make it generic over a `S: Stark` and replace with `[F; S::PUBLIC_INPUTS]`.
|
||
|
|
pub public_inputs: Vec<F>,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub struct StarkProofWithPublicInputsTarget<const D: usize> {
|
||
|
|
pub proof: StarkProofTarget<D>,
|
||
|
|
pub public_inputs: Vec<Target>,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub struct CompressedStarkProof<
|
||
|
|
F: RichField + Extendable<D>,
|
||
|
|
C: GenericConfig<D, F = F>,
|
||
|
|
const D: usize,
|
||
|
|
> {
|
||
|
|
/// Merkle cap of LDEs of trace values.
|
||
|
|
pub trace_cap: MerkleCap<F, C::Hasher>,
|
||
|
|
/// Purported values of each polynomial at the challenge point.
|
||
|
|
pub openings: StarkOpeningSet<F, D>,
|
||
|
|
/// A batch FRI argument for all openings.
|
||
|
|
pub opening_proof: CompressedFriProof<F, C::Hasher, D>,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub struct CompressedStarkProofWithPublicInputs<
|
||
|
|
F: RichField + Extendable<D>,
|
||
|
|
C: GenericConfig<D, F = F>,
|
||
|
|
const D: usize,
|
||
|
|
> {
|
||
|
|
pub proof: CompressedStarkProof<F, C, D>,
|
||
|
|
pub public_inputs: Vec<F>,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub(crate) struct StarkProofChallenges<F: RichField + Extendable<D>, const D: usize> {
|
||
|
|
/// Randomness used in any permutation arguments.
|
||
|
|
pub permutation_challenge_sets: Option<Vec<PermutationChallengeSet<F>>>,
|
||
|
|
|
||
|
|
/// Random values used to combine STARK constraints.
|
||
|
|
pub stark_alphas: Vec<F>,
|
||
|
|
|
||
|
|
/// Point at which the STARK polynomials are opened.
|
||
|
|
pub stark_zeta: F::Extension,
|
||
|
|
|
||
|
|
pub fri_challenges: FriChallenges<F, D>,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub(crate) struct StarkProofChallengesTarget<const D: usize> {
|
||
|
|
pub permutation_challenge_sets: Option<Vec<PermutationChallengeSet<Target>>>,
|
||
|
|
pub stark_alphas: Vec<Target>,
|
||
|
|
pub stark_zeta: ExtensionTarget<D>,
|
||
|
|
pub fri_challenges: FriChallengesTarget<D>,
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Purported values of each polynomial at the challenge point.
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
pub struct StarkOpeningSet<F: RichField + Extendable<D>, const D: usize> {
|
||
|
|
pub local_values: Vec<F::Extension>,
|
||
|
|
pub next_values: Vec<F::Extension>,
|
||
|
|
pub permutation_zs: Option<Vec<F::Extension>>,
|
||
|
|
pub permutation_zs_right: Option<Vec<F::Extension>>,
|
||
|
|
pub quotient_polys: Vec<F::Extension>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<F: RichField + Extendable<D>, const D: usize> StarkOpeningSet<F, D> {
|
||
|
|
pub fn new<C: GenericConfig<D, F = F>>(
|
||
|
|
zeta: F::Extension,
|
||
|
|
g: F,
|
||
|
|
trace_commitment: &PolynomialBatch<F, C, D>,
|
||
|
|
permutation_zs_commitment: Option<&PolynomialBatch<F, C, D>>,
|
||
|
|
quotient_commitment: &PolynomialBatch<F, C, D>,
|
||
|
|
) -> Self {
|
||
|
|
let eval_commitment = |z: F::Extension, c: &PolynomialBatch<F, C, D>| {
|
||
|
|
c.polynomials
|
||
|
|
.par_iter()
|
||
|
|
.map(|p| p.to_extension().eval(z))
|
||
|
|
.collect::<Vec<_>>()
|
||
|
|
};
|
||
|
|
let zeta_right = zeta.scalar_mul(g);
|
||
|
|
Self {
|
||
|
|
local_values: eval_commitment(zeta, trace_commitment),
|
||
|
|
next_values: eval_commitment(zeta_right, trace_commitment),
|
||
|
|
permutation_zs: permutation_zs_commitment.map(|c| eval_commitment(zeta, c)),
|
||
|
|
permutation_zs_right: permutation_zs_commitment.map(|c| eval_commitment(zeta_right, c)),
|
||
|
|
quotient_polys: eval_commitment(zeta, quotient_commitment),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub(crate) fn to_fri_openings(&self) -> FriOpenings<F, D> {
|
||
|
|
let zeta_batch = FriOpeningBatch {
|
||
|
|
values: self
|
||
|
|
.local_values
|
||
|
|
.iter()
|
||
|
|
.chain(self.permutation_zs.iter().flatten())
|
||
|
|
.chain(&self.quotient_polys)
|
||
|
|
.copied()
|
||
|
|
.collect_vec(),
|
||
|
|
};
|
||
|
|
let zeta_right_batch = FriOpeningBatch {
|
||
|
|
values: self
|
||
|
|
.next_values
|
||
|
|
.iter()
|
||
|
|
.chain(self.permutation_zs_right.iter().flatten())
|
||
|
|
.copied()
|
||
|
|
.collect_vec(),
|
||
|
|
};
|
||
|
|
FriOpenings {
|
||
|
|
batches: vec![zeta_batch, zeta_right_batch],
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub struct StarkOpeningSetTarget<const D: usize> {
|
||
|
|
pub local_values: Vec<ExtensionTarget<D>>,
|
||
|
|
pub next_values: Vec<ExtensionTarget<D>>,
|
||
|
|
pub permutation_zs: Option<Vec<ExtensionTarget<D>>>,
|
||
|
|
pub permutation_zs_right: Option<Vec<ExtensionTarget<D>>>,
|
||
|
|
pub quotient_polys: Vec<ExtensionTarget<D>>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<const D: usize> StarkOpeningSetTarget<D> {
|
||
|
|
pub(crate) fn to_fri_openings(&self) -> FriOpeningsTarget<D> {
|
||
|
|
let zeta_batch = FriOpeningBatchTarget {
|
||
|
|
values: self
|
||
|
|
.local_values
|
||
|
|
.iter()
|
||
|
|
.chain(self.permutation_zs.iter().flatten())
|
||
|
|
.chain(&self.quotient_polys)
|
||
|
|
.copied()
|
||
|
|
.collect_vec(),
|
||
|
|
};
|
||
|
|
let zeta_right_batch = FriOpeningBatchTarget {
|
||
|
|
values: self
|
||
|
|
.next_values
|
||
|
|
.iter()
|
||
|
|
.chain(self.permutation_zs_right.iter().flatten())
|
||
|
|
.copied()
|
||
|
|
.collect_vec(),
|
||
|
|
};
|
||
|
|
FriOpeningsTarget {
|
||
|
|
batches: vec![zeta_batch, zeta_right_batch],
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|