plonky2/starky/src/proof.rs

217 lines
7.6 KiB
Rust
Raw Normal View History

use alloc::vec;
use alloc::vec::Vec;
use itertools::Itertools;
use plonky2::field::extension::{Extendable, FieldExtension};
2022-01-27 12:58:56 +01:00
use plonky2::fri::oracle::PolynomialBatch;
2022-02-08 18:16:33 +01:00
use plonky2::fri::proof::{
CompressedFriProof, FriChallenges, FriChallengesTarget, FriProof, FriProofTarget,
};
use plonky2::fri::structure::{
FriOpeningBatch, FriOpeningBatchTarget, FriOpenings, FriOpeningsTarget,
};
2022-02-07 10:41:52 +01:00
use plonky2::hash::hash_types::{MerkleCapTarget, RichField};
use plonky2::hash::merkle_tree::MerkleCap;
2022-02-07 10:41:52 +01:00
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::target::Target;
use plonky2::plonk::config::GenericConfig;
2023-01-30 08:51:33 -08:00
use plonky2_maybe_rayon::*;
2022-02-08 18:16:33 +01:00
use crate::config::StarkConfig;
use crate::permutation::PermutationChallengeSet;
2022-02-08 18:16:33 +01:00
2022-02-14 09:53:33 +01:00
#[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::HCO, C::Hasher>,
/// Merkle cap of LDEs of permutation Z values.
pub permutation_zs_cap: Option<MerkleCap<F, C::HCO, C::Hasher>>,
2022-01-29 12:49:00 +01:00
/// Merkle cap of LDEs of trace values.
pub quotient_polys_cap: MerkleCap<F, C::HCO, 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::HCO, C::Hasher, D>,
}
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> StarkProof<F, C, D> {
2022-02-23 09:36:28 +01:00
/// Recover the length of the trace from a STARK proof and a STARK config.
2022-04-29 10:50:02 +02:00
pub fn recover_degree_bits(&self, config: &StarkConfig) -> usize {
2022-02-08 18:16:33 +01:00
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();
2022-02-11 10:37:17 +01:00
lde_bits - config.fri_config.rate_bits
2022-02-08 18:16:33 +01:00
}
}
2022-02-07 10:41:52 +01:00
pub struct StarkProofTarget<const D: usize> {
pub trace_cap: MerkleCapTarget,
pub permutation_zs_cap: Option<MerkleCapTarget>,
2022-02-07 10:41:52 +01:00
pub quotient_polys_cap: MerkleCapTarget,
pub openings: StarkOpeningSetTarget<D>,
pub opening_proof: FriProofTarget<D>,
}
2022-02-08 18:16:33 +01:00
impl<const D: usize> StarkProofTarget<D> {
2022-02-23 09:36:28 +01:00
/// Recover the length of the trace from a STARK proof and a STARK config.
pub fn recover_degree_bits(&self, config: &StarkConfig) -> usize {
2022-02-08 18:16:33 +01:00
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();
2022-02-11 10:37:17 +01:00
lde_bits - config.fri_config.rate_bits
2022-02-08 18:16:33 +01:00
}
}
2022-02-14 09:53:33 +01:00
#[derive(Debug, Clone)]
2022-01-29 12:49:00 +01:00
pub struct StarkProofWithPublicInputs<
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F>,
2022-01-29 12:49:00 +01:00
const D: usize,
> {
pub proof: StarkProof<F, C, D>,
2022-02-01 17:34:03 +01:00
// TODO: Maybe make it generic over a `S: Stark` and replace with `[F; S::PUBLIC_INPUTS]`.
2022-01-29 12:49:00 +01:00
pub public_inputs: Vec<F>,
}
2022-02-07 10:41:52 +01:00
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::HCO, 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::HCO, C::Hasher, D>,
}
2022-01-29 12:49:00 +01:00
pub struct CompressedStarkProofWithPublicInputs<
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F>,
2022-01-29 12:49:00 +01:00
const D: usize,
> {
pub proof: CompressedStarkProof<F, C, D>,
2022-01-29 12:49:00 +01:00
pub public_inputs: Vec<F>,
}
pub(crate) struct StarkProofChallenges<F: RichField + Extendable<D>, const D: usize> {
/// Randomness used in any permutation arguments.
2022-02-22 17:00:08 +01:00
pub permutation_challenge_sets: Option<Vec<PermutationChallengeSet<F>>>,
2022-02-03 11:49:44 +01:00
/// Random values used to combine STARK constraints.
2022-01-29 12:49:00 +01:00
pub stark_alphas: Vec<F>,
2022-02-03 11:49:44 +01:00
/// Point at which the STARK polynomials are opened.
2022-01-29 12:49:00 +01:00
pub stark_zeta: F::Extension,
2022-01-31 18:00:07 +01:00
pub fri_challenges: FriChallenges<F, D>,
2022-01-29 12:49:00 +01:00
}
2022-02-08 18:16:33 +01:00
pub(crate) struct StarkProofChallengesTarget<const D: usize> {
2022-02-22 17:00:08 +01:00
pub permutation_challenge_sets: Option<Vec<PermutationChallengeSet<Target>>>,
2022-02-08 18:16:33 +01:00
pub stark_alphas: Vec<Target>,
pub stark_zeta: ExtensionTarget<D>,
pub fri_challenges: FriChallengesTarget<D>,
}
/// Purported values of each polynomial at the challenge point.
2022-02-14 09:53:33 +01:00
#[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>>,
2022-06-02 23:55:56 +02:00
pub permutation_zs_next: Option<Vec<F::Extension>>,
pub quotient_polys: Vec<F::Extension>,
}
2022-01-27 12:58:56 +01:00
impl<F: RichField + Extendable<D>, const D: usize> StarkOpeningSet<F, D> {
pub fn new<C: GenericConfig<D, F = F>>(
2022-01-27 12:58:56 +01:00
zeta: F::Extension,
2022-02-08 18:16:33 +01:00
g: F,
trace_commitment: &PolynomialBatch<F, C, D>,
permutation_zs_commitment: Option<&PolynomialBatch<F, C, D>>,
quotient_commitment: &PolynomialBatch<F, C, D>,
2022-01-27 12:58:56 +01:00
) -> Self {
let eval_commitment = |z: F::Extension, c: &PolynomialBatch<F, C, D>| {
2022-01-27 12:58:56 +01:00
c.polynomials
.par_iter()
.map(|p| p.to_extension().eval(z))
.collect::<Vec<_>>()
};
2022-06-02 23:55:56 +02:00
let zeta_next = zeta.scalar_mul(g);
2022-01-27 12:58:56 +01:00
Self {
local_values: eval_commitment(zeta, trace_commitment),
2022-06-02 23:55:56 +02:00
next_values: eval_commitment(zeta_next, trace_commitment),
permutation_zs: permutation_zs_commitment.map(|c| eval_commitment(zeta, c)),
2022-06-02 23:55:56 +02:00
permutation_zs_next: permutation_zs_commitment.map(|c| eval_commitment(zeta_next, c)),
2022-01-27 12:58:56 +01:00
quotient_polys: eval_commitment(zeta, quotient_commitment),
}
}
2022-01-29 12:49:00 +01:00
2022-01-31 18:00:07 +01:00
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(),
2022-01-31 18:00:07 +01:00
};
2022-06-02 23:55:56 +02:00
let zeta_next_batch = FriOpeningBatch {
values: self
.next_values
.iter()
2022-06-02 23:55:56 +02:00
.chain(self.permutation_zs_next.iter().flatten())
.copied()
.collect_vec(),
2022-01-31 18:00:07 +01:00
};
FriOpenings {
2022-06-02 23:55:56 +02:00
batches: vec![zeta_batch, zeta_next_batch],
2022-01-31 18:00:07 +01:00
}
}
2022-01-27 12:58:56 +01:00
}
2022-02-07 10:41:52 +01:00
pub struct StarkOpeningSetTarget<const D: usize> {
pub local_values: Vec<ExtensionTarget<D>>,
pub next_values: Vec<ExtensionTarget<D>>,
2022-02-22 11:44:24 +01:00
pub permutation_zs: Option<Vec<ExtensionTarget<D>>>,
2022-06-02 23:55:56 +02:00
pub permutation_zs_next: Option<Vec<ExtensionTarget<D>>>,
2022-02-07 10:41:52 +01:00
pub quotient_polys: Vec<ExtensionTarget<D>>,
}
2022-02-08 18:16:33 +01:00
impl<const D: usize> StarkOpeningSetTarget<D> {
pub(crate) fn to_fri_openings(&self) -> FriOpeningsTarget<D> {
let zeta_batch = FriOpeningBatchTarget {
2022-02-22 11:44:24 +01:00
values: self
.local_values
.iter()
.chain(self.permutation_zs.iter().flatten())
.chain(&self.quotient_polys)
.copied()
.collect_vec(),
2022-02-08 18:16:33 +01:00
};
2022-06-02 23:55:56 +02:00
let zeta_next_batch = FriOpeningBatchTarget {
2022-02-22 11:44:24 +01:00
values: self
.next_values
.iter()
2022-06-02 23:55:56 +02:00
.chain(self.permutation_zs_next.iter().flatten())
2022-02-22 11:44:24 +01:00
.copied()
.collect_vec(),
2022-02-08 18:16:33 +01:00
};
FriOpeningsTarget {
2022-06-02 23:55:56 +02:00
batches: vec![zeta_batch, zeta_next_batch],
2022-02-08 18:16:33 +01:00
}
}
}