mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 07:13:08 +00:00
Merge branch 'main' of github.com:mir-protocol/plonky2 into ripeMD
This commit is contained in:
commit
d5f04cbfb4
@ -16,6 +16,10 @@ use crate::permutation::PermutationPair;
|
||||
use crate::vars::StarkEvaluationTargets;
|
||||
use crate::vars::StarkEvaluationVars;
|
||||
|
||||
const TRACE_ORACLE_INDEX: usize = 0;
|
||||
const PERMUTATION_CTL_ORACLE_INDEX: usize = 1;
|
||||
const QUOTIENT_ORACLE_INDEX: usize = 2;
|
||||
|
||||
/// Represents a STARK system.
|
||||
pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
/// The total number of columns in the trace.
|
||||
@ -72,6 +76,10 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
1.max(self.constraint_degree() - 1)
|
||||
}
|
||||
|
||||
fn num_quotient_polys(&self, config: &StarkConfig) -> usize {
|
||||
self.quotient_degree_factor() * config.num_challenges
|
||||
}
|
||||
|
||||
/// Computes the FRI instance used to prove this Stark.
|
||||
fn fri_instance(
|
||||
&self,
|
||||
@ -81,28 +89,35 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
num_ctl_zs: usize,
|
||||
config: &StarkConfig,
|
||||
) -> FriInstanceInfo<F, D> {
|
||||
let no_blinding_oracle = FriOracleInfo { blinding: false };
|
||||
let mut oracle_indices = 0..;
|
||||
|
||||
let trace_info =
|
||||
FriPolynomialInfo::from_range(oracle_indices.next().unwrap(), 0..Self::COLUMNS);
|
||||
let trace_oracle = FriOracleInfo {
|
||||
num_polys: Self::COLUMNS,
|
||||
blinding: false,
|
||||
};
|
||||
let trace_info = FriPolynomialInfo::from_range(TRACE_ORACLE_INDEX, 0..Self::COLUMNS);
|
||||
|
||||
let num_permutation_batches = self.num_permutation_batches(config);
|
||||
let permutation_ctl_index = oracle_indices.next().unwrap();
|
||||
let num_perutation_ctl_polys = num_permutation_batches + num_ctl_zs;
|
||||
let permutation_ctl_oracle = FriOracleInfo {
|
||||
num_polys: num_perutation_ctl_polys,
|
||||
blinding: false,
|
||||
};
|
||||
let permutation_ctl_zs_info = FriPolynomialInfo::from_range(
|
||||
permutation_ctl_index,
|
||||
0..num_permutation_batches + num_ctl_zs,
|
||||
PERMUTATION_CTL_ORACLE_INDEX,
|
||||
0..num_perutation_ctl_polys,
|
||||
);
|
||||
|
||||
let ctl_zs_info = FriPolynomialInfo::from_range(
|
||||
permutation_ctl_index,
|
||||
PERMUTATION_CTL_ORACLE_INDEX,
|
||||
num_permutation_batches..num_permutation_batches + num_ctl_zs,
|
||||
);
|
||||
|
||||
let quotient_info = FriPolynomialInfo::from_range(
|
||||
oracle_indices.next().unwrap(),
|
||||
0..self.quotient_degree_factor() * config.num_challenges,
|
||||
);
|
||||
let num_quotient_polys = self.num_quotient_polys(config);
|
||||
let quotient_oracle = FriOracleInfo {
|
||||
num_polys: num_quotient_polys,
|
||||
blinding: false,
|
||||
};
|
||||
let quotient_info =
|
||||
FriPolynomialInfo::from_range(QUOTIENT_ORACLE_INDEX, 0..num_quotient_polys);
|
||||
|
||||
let zeta_batch = FriBatchInfo {
|
||||
point: zeta,
|
||||
@ -122,7 +137,7 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
polynomials: ctl_zs_info,
|
||||
};
|
||||
FriInstanceInfo {
|
||||
oracles: vec![no_blinding_oracle; oracle_indices.next().unwrap()],
|
||||
oracles: vec![trace_oracle, permutation_ctl_oracle, quotient_oracle],
|
||||
batches: vec![zeta_batch, zeta_next_batch, ctl_last_batch],
|
||||
}
|
||||
}
|
||||
@ -137,28 +152,35 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
num_ctl_zs: usize,
|
||||
inner_config: &StarkConfig,
|
||||
) -> FriInstanceInfoTarget<D> {
|
||||
let no_blinding_oracle = FriOracleInfo { blinding: false };
|
||||
let mut oracle_indices = 0..;
|
||||
|
||||
let trace_info =
|
||||
FriPolynomialInfo::from_range(oracle_indices.next().unwrap(), 0..Self::COLUMNS);
|
||||
let trace_oracle = FriOracleInfo {
|
||||
num_polys: Self::COLUMNS,
|
||||
blinding: false,
|
||||
};
|
||||
let trace_info = FriPolynomialInfo::from_range(TRACE_ORACLE_INDEX, 0..Self::COLUMNS);
|
||||
|
||||
let num_permutation_batches = self.num_permutation_batches(inner_config);
|
||||
let permutation_ctl_index = oracle_indices.next().unwrap();
|
||||
let num_perutation_ctl_polys = num_permutation_batches + num_ctl_zs;
|
||||
let permutation_ctl_oracle = FriOracleInfo {
|
||||
num_polys: num_perutation_ctl_polys,
|
||||
blinding: false,
|
||||
};
|
||||
let permutation_ctl_zs_info = FriPolynomialInfo::from_range(
|
||||
permutation_ctl_index,
|
||||
0..num_permutation_batches + num_ctl_zs,
|
||||
PERMUTATION_CTL_ORACLE_INDEX,
|
||||
0..num_perutation_ctl_polys,
|
||||
);
|
||||
|
||||
let ctl_zs_info = FriPolynomialInfo::from_range(
|
||||
permutation_ctl_index,
|
||||
PERMUTATION_CTL_ORACLE_INDEX,
|
||||
num_permutation_batches..num_permutation_batches + num_ctl_zs,
|
||||
);
|
||||
|
||||
let quotient_info = FriPolynomialInfo::from_range(
|
||||
oracle_indices.next().unwrap(),
|
||||
0..self.quotient_degree_factor() * inner_config.num_challenges,
|
||||
);
|
||||
let num_quotient_polys = self.num_quotient_polys(inner_config);
|
||||
let quotient_oracle = FriOracleInfo {
|
||||
num_polys: num_quotient_polys,
|
||||
blinding: false,
|
||||
};
|
||||
let quotient_info =
|
||||
FriPolynomialInfo::from_range(QUOTIENT_ORACLE_INDEX, 0..num_quotient_polys);
|
||||
|
||||
let zeta_batch = FriBatchInfoTarget {
|
||||
point: zeta,
|
||||
@ -180,7 +202,7 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
polynomials: ctl_zs_info,
|
||||
};
|
||||
FriInstanceInfoTarget {
|
||||
oracles: vec![no_blinding_oracle; oracle_indices.next().unwrap()],
|
||||
oracles: vec![trace_oracle, permutation_ctl_oracle, quotient_oracle],
|
||||
batches: vec![zeta_batch, zeta_next_batch, ctl_last_batch],
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,6 +119,7 @@ where
|
||||
[(); S::COLUMNS]:,
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
{
|
||||
validate_proof_shape(&stark, proof, config, ctl_vars.len())?;
|
||||
let StarkOpeningSet {
|
||||
local_values,
|
||||
next_values,
|
||||
@ -204,6 +205,57 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_proof_shape<F, C, S, const D: usize>(
|
||||
stark: &S,
|
||||
proof: &StarkProof<F, C, D>,
|
||||
config: &StarkConfig,
|
||||
num_ctl_zs: usize,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
S: Stark<F, D>,
|
||||
[(); S::COLUMNS]:,
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
{
|
||||
let StarkProof {
|
||||
trace_cap,
|
||||
permutation_ctl_zs_cap,
|
||||
quotient_polys_cap,
|
||||
openings,
|
||||
// The shape of the opening proof will be checked in the FRI verifier (see
|
||||
// validate_fri_proof_shape), so we ignore it here.
|
||||
opening_proof: _,
|
||||
} = proof;
|
||||
|
||||
let StarkOpeningSet {
|
||||
local_values,
|
||||
next_values,
|
||||
permutation_ctl_zs,
|
||||
permutation_ctl_zs_next,
|
||||
ctl_zs_last,
|
||||
quotient_polys,
|
||||
} = openings;
|
||||
|
||||
let degree_bits = proof.recover_degree_bits(config);
|
||||
let fri_params = config.fri_params(degree_bits);
|
||||
let cap_height = fri_params.config.cap_height;
|
||||
let num_zs = num_ctl_zs + stark.num_permutation_batches(config);
|
||||
|
||||
ensure!(trace_cap.height() == cap_height);
|
||||
ensure!(permutation_ctl_zs_cap.height() == cap_height);
|
||||
ensure!(quotient_polys_cap.height() == cap_height);
|
||||
|
||||
ensure!(local_values.len() == S::COLUMNS);
|
||||
ensure!(next_values.len() == S::COLUMNS);
|
||||
ensure!(permutation_ctl_zs.len() == num_zs);
|
||||
ensure!(permutation_ctl_zs_next.len() == num_zs);
|
||||
ensure!(ctl_zs_last.len() == num_ctl_zs);
|
||||
ensure!(quotient_polys.len() == stark.num_quotient_polys(config));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Evaluate the Lagrange polynomials `L_0` and `L_(n-1)` at a point `x`.
|
||||
/// `L_0(x) = (x^n - 1)/(n * (x - 1))`
|
||||
/// `L_(n-1)(x) = (x^n - 1)/(n * (g * x - 1))`, with `g` the first element of the subgroup.
|
||||
|
||||
@ -7,6 +7,7 @@ pub mod prover;
|
||||
pub mod recursive_verifier;
|
||||
pub mod reduction_strategies;
|
||||
pub mod structure;
|
||||
mod validate_shape;
|
||||
pub mod verifier;
|
||||
pub mod witness_util;
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ pub struct FriInstanceInfoTarget<const D: usize> {
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct FriOracleInfo {
|
||||
pub num_polys: usize,
|
||||
pub blinding: bool,
|
||||
}
|
||||
|
||||
|
||||
67
plonky2/src/fri/validate_shape.rs
Normal file
67
plonky2/src/fri/validate_shape.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use anyhow::ensure;
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
use crate::fri::proof::{FriProof, FriQueryRound, FriQueryStep};
|
||||
use crate::fri::structure::FriInstanceInfo;
|
||||
use crate::fri::FriParams;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::plonk::config::GenericConfig;
|
||||
use crate::plonk::plonk_common::salt_size;
|
||||
|
||||
pub(crate) fn validate_fri_proof_shape<F, C, const D: usize>(
|
||||
proof: &FriProof<F, C::Hasher, D>,
|
||||
instance: &FriInstanceInfo<F, D>,
|
||||
params: &FriParams,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
{
|
||||
let FriProof {
|
||||
commit_phase_merkle_caps,
|
||||
query_round_proofs,
|
||||
final_poly,
|
||||
pow_witness: _pow_witness,
|
||||
} = proof;
|
||||
|
||||
let cap_height = params.config.cap_height;
|
||||
for cap in commit_phase_merkle_caps {
|
||||
ensure!(cap.height() == cap_height);
|
||||
}
|
||||
|
||||
for query_round in query_round_proofs {
|
||||
let FriQueryRound {
|
||||
initial_trees_proof,
|
||||
steps,
|
||||
} = query_round;
|
||||
|
||||
ensure!(initial_trees_proof.evals_proofs.len() == instance.oracles.len());
|
||||
for ((leaf, merkle_proof), oracle) in initial_trees_proof
|
||||
.evals_proofs
|
||||
.iter()
|
||||
.zip(&instance.oracles)
|
||||
{
|
||||
ensure!(leaf.len() == oracle.num_polys + salt_size(oracle.blinding && params.hiding));
|
||||
ensure!(merkle_proof.len() + cap_height == params.lde_bits());
|
||||
}
|
||||
|
||||
ensure!(steps.len() == params.reduction_arity_bits.len());
|
||||
let mut codeword_len_bits = params.lde_bits();
|
||||
for (step, arity_bits) in steps.iter().zip(¶ms.reduction_arity_bits) {
|
||||
let FriQueryStep {
|
||||
evals,
|
||||
merkle_proof,
|
||||
} = step;
|
||||
|
||||
let arity = 1 << arity_bits;
|
||||
codeword_len_bits -= arity_bits;
|
||||
|
||||
ensure!(evals.len() == arity);
|
||||
ensure!(merkle_proof.len() + cap_height == codeword_len_bits);
|
||||
}
|
||||
}
|
||||
|
||||
ensure!(final_poly.len() == params.final_poly_len());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -6,6 +6,7 @@ use plonky2_util::{log2_strict, reverse_index_bits_in_place};
|
||||
|
||||
use crate::fri::proof::{FriChallenges, FriInitialTreeProof, FriProof, FriQueryRound};
|
||||
use crate::fri::structure::{FriBatchInfo, FriInstanceInfo, FriOpenings};
|
||||
use crate::fri::validate_shape::validate_fri_proof_shape;
|
||||
use crate::fri::{FriConfig, FriParams};
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::hash::merkle_proofs::verify_merkle_proof_to_cap;
|
||||
@ -67,10 +68,7 @@ pub fn verify_fri_proof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>
|
||||
where
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
{
|
||||
ensure!(
|
||||
params.final_poly_len() == proof.final_poly.len(),
|
||||
"Final polynomial has wrong degree."
|
||||
);
|
||||
validate_fri_proof_shape::<F, C, D>(proof, instance, params)?;
|
||||
|
||||
// Size of the LDE domain.
|
||||
let n = params.lde_size();
|
||||
|
||||
@ -17,6 +17,12 @@ pub struct MerkleProof<F: RichField, H: Hasher<F>> {
|
||||
pub siblings: Vec<H::Hash>,
|
||||
}
|
||||
|
||||
impl<F: RichField, H: Hasher<F>> MerkleProof<F, H> {
|
||||
pub fn len(&self) -> usize {
|
||||
self.siblings.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MerkleProofTarget {
|
||||
/// The Merkle digest of each sibling subtree, staying from the bottommost layer.
|
||||
|
||||
@ -21,6 +21,10 @@ impl<F: RichField, H: Hasher<F>> MerkleCap<F, H> {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
pub fn height(&self) -> usize {
|
||||
log2_strict(self.len())
|
||||
}
|
||||
|
||||
pub fn flatten(&self) -> Vec<F> {
|
||||
self.0.iter().flat_map(|&h| h.to_vec()).collect()
|
||||
}
|
||||
|
||||
@ -9,7 +9,8 @@ use crate::field::types::Field;
|
||||
use crate::fri::oracle::PolynomialBatch;
|
||||
use crate::fri::reduction_strategies::FriReductionStrategy;
|
||||
use crate::fri::structure::{
|
||||
FriBatchInfo, FriBatchInfoTarget, FriInstanceInfo, FriInstanceInfoTarget, FriPolynomialInfo,
|
||||
FriBatchInfo, FriBatchInfoTarget, FriInstanceInfo, FriInstanceInfoTarget, FriOracleInfo,
|
||||
FriPolynomialInfo,
|
||||
};
|
||||
use crate::fri::{FriConfig, FriParams};
|
||||
use crate::gates::gate::GateRef;
|
||||
@ -22,7 +23,7 @@ use crate::iop::target::Target;
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::config::{GenericConfig, Hasher};
|
||||
use crate::plonk::plonk_common::{PlonkOracle, FRI_ORACLES};
|
||||
use crate::plonk::plonk_common::PlonkOracle;
|
||||
use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs};
|
||||
use crate::plonk::prover::prove;
|
||||
use crate::plonk::verifier::verify;
|
||||
@ -342,7 +343,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
|
||||
let openings = vec![zeta_batch, zeta_next_batch];
|
||||
FriInstanceInfo {
|
||||
oracles: FRI_ORACLES.to_vec(),
|
||||
oracles: self.fri_oracles(),
|
||||
batches: openings,
|
||||
}
|
||||
}
|
||||
@ -368,11 +369,32 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
|
||||
let openings = vec![zeta_batch, zeta_next_batch];
|
||||
FriInstanceInfoTarget {
|
||||
oracles: FRI_ORACLES.to_vec(),
|
||||
oracles: self.fri_oracles(),
|
||||
batches: openings,
|
||||
}
|
||||
}
|
||||
|
||||
fn fri_oracles(&self) -> Vec<FriOracleInfo> {
|
||||
vec![
|
||||
FriOracleInfo {
|
||||
num_polys: self.num_preprocessed_polys(),
|
||||
blinding: PlonkOracle::CONSTANTS_SIGMAS.blinding,
|
||||
},
|
||||
FriOracleInfo {
|
||||
num_polys: self.config.num_wires,
|
||||
blinding: PlonkOracle::WIRES.blinding,
|
||||
},
|
||||
FriOracleInfo {
|
||||
num_polys: self.num_zs_partial_products_polys(),
|
||||
blinding: PlonkOracle::ZS_PARTIAL_PRODUCTS.blinding,
|
||||
},
|
||||
FriOracleInfo {
|
||||
num_polys: self.num_quotient_polys(),
|
||||
blinding: PlonkOracle::QUOTIENT.blinding,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn fri_preprocessed_polys(&self) -> Vec<FriPolynomialInfo> {
|
||||
FriPolynomialInfo::from_range(
|
||||
PlonkOracle::CONSTANTS_SIGMAS.index,
|
||||
|
||||
@ -8,6 +8,7 @@ pub mod plonk_common;
|
||||
pub mod proof;
|
||||
pub mod prover;
|
||||
pub mod recursive_verifier;
|
||||
mod validate_shape;
|
||||
pub(crate) mod vanishing_poly;
|
||||
pub mod vars;
|
||||
pub mod verifier;
|
||||
|
||||
@ -3,7 +3,6 @@ use plonky2_field::packed::PackedField;
|
||||
use plonky2_field::types::Field;
|
||||
|
||||
use crate::fri::oracle::SALT_SIZE;
|
||||
use crate::fri::structure::FriOracleInfo;
|
||||
use crate::gates::arithmetic_base::ArithmeticGate;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
@ -11,13 +10,6 @@ use crate::iop::target::Target;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::util::reducing::ReducingFactorTarget;
|
||||
|
||||
pub(crate) const FRI_ORACLES: [FriOracleInfo; 4] = [
|
||||
PlonkOracle::CONSTANTS_SIGMAS.as_fri_oracle(),
|
||||
PlonkOracle::WIRES.as_fri_oracle(),
|
||||
PlonkOracle::ZS_PARTIAL_PRODUCTS.as_fri_oracle(),
|
||||
PlonkOracle::QUOTIENT.as_fri_oracle(),
|
||||
];
|
||||
|
||||
/// Holds the Merkle tree index and blinding flag of a set of polynomials used in FRI.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PlonkOracle {
|
||||
@ -42,12 +34,6 @@ impl PlonkOracle {
|
||||
index: 3,
|
||||
blinding: true,
|
||||
};
|
||||
|
||||
pub(crate) const fn as_fri_oracle(&self) -> FriOracleInfo {
|
||||
FriOracleInfo {
|
||||
blinding: self.blinding,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn salt_size(salted: bool) -> usize {
|
||||
|
||||
77
plonky2/src/plonk/validate_shape.rs
Normal file
77
plonky2/src/plonk/validate_shape.rs
Normal file
@ -0,0 +1,77 @@
|
||||
use anyhow::ensure;
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::plonk::circuit_data::CommonCircuitData;
|
||||
use crate::plonk::config::{GenericConfig, Hasher};
|
||||
use crate::plonk::proof::{OpeningSet, Proof, ProofWithPublicInputs};
|
||||
|
||||
pub(crate) fn validate_proof_with_pis_shape<F, C, const D: usize>(
|
||||
proof_with_pis: &ProofWithPublicInputs<F, C, D>,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
{
|
||||
let ProofWithPublicInputs {
|
||||
proof,
|
||||
public_inputs,
|
||||
} = proof_with_pis;
|
||||
|
||||
validate_proof_shape(proof, common_data)?;
|
||||
|
||||
ensure!(
|
||||
public_inputs.len() == common_data.num_public_inputs,
|
||||
"Number of public inputs doesn't match circuit data."
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_proof_shape<F, C, const D: usize>(
|
||||
proof: &Proof<F, C, D>,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
{
|
||||
let config = &common_data.config;
|
||||
let Proof {
|
||||
wires_cap,
|
||||
plonk_zs_partial_products_cap,
|
||||
quotient_polys_cap,
|
||||
openings,
|
||||
// The shape of the opening proof will be checked in the FRI verifier (see
|
||||
// validate_fri_proof_shape), so we ignore it here.
|
||||
opening_proof: _,
|
||||
} = proof;
|
||||
|
||||
let OpeningSet {
|
||||
constants,
|
||||
plonk_sigmas,
|
||||
wires,
|
||||
plonk_zs,
|
||||
plonk_zs_next,
|
||||
partial_products,
|
||||
quotient_polys,
|
||||
} = openings;
|
||||
|
||||
let cap_height = common_data.fri_params.config.cap_height;
|
||||
ensure!(wires_cap.height() == cap_height);
|
||||
ensure!(plonk_zs_partial_products_cap.height() == cap_height);
|
||||
ensure!(quotient_polys_cap.height() == cap_height);
|
||||
|
||||
ensure!(constants.len() == common_data.num_constants);
|
||||
ensure!(plonk_sigmas.len() == config.num_routed_wires);
|
||||
ensure!(wires.len() == config.num_wires);
|
||||
ensure!(plonk_zs.len() == config.num_challenges);
|
||||
ensure!(plonk_zs_next.len() == config.num_challenges);
|
||||
ensure!(partial_products.len() == config.num_challenges * common_data.num_partial_products);
|
||||
ensure!(quotient_polys.len() == common_data.num_quotient_polys());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -8,6 +8,7 @@ use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData};
|
||||
use crate::plonk::config::{GenericConfig, Hasher};
|
||||
use crate::plonk::plonk_common::reduce_with_powers;
|
||||
use crate::plonk::proof::{Proof, ProofChallenges, ProofWithPublicInputs};
|
||||
use crate::plonk::validate_shape::validate_proof_with_pis_shape;
|
||||
use crate::plonk::vanishing_poly::eval_vanishing_poly;
|
||||
use crate::plonk::vars::EvaluationVars;
|
||||
|
||||
@ -19,10 +20,8 @@ pub(crate) fn verify<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, c
|
||||
where
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
{
|
||||
ensure!(
|
||||
proof_with_pis.public_inputs.len() == common_data.num_public_inputs,
|
||||
"Number of public inputs doesn't match circuit data."
|
||||
);
|
||||
validate_proof_with_pis_shape(&proof_with_pis, common_data)?;
|
||||
|
||||
let public_inputs_hash = proof_with_pis.get_public_inputs_hash();
|
||||
let challenges = proof_with_pis.get_challenges(public_inputs_hash, common_data)?;
|
||||
|
||||
|
||||
@ -78,6 +78,10 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
1.max(self.constraint_degree() - 1)
|
||||
}
|
||||
|
||||
fn num_quotient_polys(&self, config: &StarkConfig) -> usize {
|
||||
self.quotient_degree_factor() * config.num_challenges
|
||||
}
|
||||
|
||||
/// Computes the FRI instance used to prove this Stark.
|
||||
fn fri_instance(
|
||||
&self,
|
||||
@ -85,25 +89,32 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
g: F,
|
||||
config: &StarkConfig,
|
||||
) -> FriInstanceInfo<F, D> {
|
||||
let no_blinding_oracle = FriOracleInfo { blinding: false };
|
||||
let mut oracle_indices = 0..;
|
||||
let mut oracles = vec![];
|
||||
|
||||
let trace_info =
|
||||
FriPolynomialInfo::from_range(oracle_indices.next().unwrap(), 0..Self::COLUMNS);
|
||||
let trace_info = FriPolynomialInfo::from_range(oracles.len(), 0..Self::COLUMNS);
|
||||
oracles.push(FriOracleInfo {
|
||||
num_polys: Self::COLUMNS,
|
||||
blinding: false,
|
||||
});
|
||||
|
||||
let permutation_zs_info = if self.uses_permutation_args() {
|
||||
FriPolynomialInfo::from_range(
|
||||
oracle_indices.next().unwrap(),
|
||||
0..self.num_permutation_batches(config),
|
||||
)
|
||||
let num_z_polys = self.num_permutation_batches(config);
|
||||
let polys = FriPolynomialInfo::from_range(oracles.len(), 0..num_z_polys);
|
||||
oracles.push(FriOracleInfo {
|
||||
num_polys: num_z_polys,
|
||||
blinding: false,
|
||||
});
|
||||
polys
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let quotient_info = FriPolynomialInfo::from_range(
|
||||
oracle_indices.next().unwrap(),
|
||||
0..self.quotient_degree_factor() * config.num_challenges,
|
||||
);
|
||||
let num_quotient_polys = self.quotient_degree_factor() * config.num_challenges;
|
||||
let quotient_info = FriPolynomialInfo::from_range(oracles.len(), 0..num_quotient_polys);
|
||||
oracles.push(FriOracleInfo {
|
||||
num_polys: num_quotient_polys,
|
||||
blinding: false,
|
||||
});
|
||||
|
||||
let zeta_batch = FriBatchInfo {
|
||||
point: zeta,
|
||||
@ -118,10 +129,9 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
point: zeta.scalar_mul(g),
|
||||
polynomials: [trace_info, permutation_zs_info].concat(),
|
||||
};
|
||||
FriInstanceInfo {
|
||||
oracles: vec![no_blinding_oracle; oracle_indices.next().unwrap()],
|
||||
batches: vec![zeta_batch, zeta_next_batch],
|
||||
}
|
||||
let batches = vec![zeta_batch, zeta_next_batch];
|
||||
|
||||
FriInstanceInfo { oracles, batches }
|
||||
}
|
||||
|
||||
/// Computes the FRI instance used to prove this Stark.
|
||||
@ -132,25 +142,32 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
g: F,
|
||||
config: &StarkConfig,
|
||||
) -> FriInstanceInfoTarget<D> {
|
||||
let no_blinding_oracle = FriOracleInfo { blinding: false };
|
||||
let mut oracle_indices = 0..;
|
||||
let mut oracles = vec![];
|
||||
|
||||
let trace_info =
|
||||
FriPolynomialInfo::from_range(oracle_indices.next().unwrap(), 0..Self::COLUMNS);
|
||||
let trace_info = FriPolynomialInfo::from_range(oracles.len(), 0..Self::COLUMNS);
|
||||
oracles.push(FriOracleInfo {
|
||||
num_polys: Self::COLUMNS,
|
||||
blinding: false,
|
||||
});
|
||||
|
||||
let permutation_zs_info = if self.uses_permutation_args() {
|
||||
FriPolynomialInfo::from_range(
|
||||
oracle_indices.next().unwrap(),
|
||||
0..self.num_permutation_batches(config),
|
||||
)
|
||||
let num_z_polys = self.num_permutation_batches(config);
|
||||
let polys = FriPolynomialInfo::from_range(oracles.len(), 0..num_z_polys);
|
||||
oracles.push(FriOracleInfo {
|
||||
num_polys: num_z_polys,
|
||||
blinding: false,
|
||||
});
|
||||
polys
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let quotient_info = FriPolynomialInfo::from_range(
|
||||
oracle_indices.next().unwrap(),
|
||||
0..self.quotient_degree_factor() * config.num_challenges,
|
||||
);
|
||||
let num_quotient_polys = self.quotient_degree_factor() * config.num_challenges;
|
||||
let quotient_info = FriPolynomialInfo::from_range(oracles.len(), 0..num_quotient_polys);
|
||||
oracles.push(FriOracleInfo {
|
||||
num_polys: num_quotient_polys,
|
||||
blinding: false,
|
||||
});
|
||||
|
||||
let zeta_batch = FriBatchInfoTarget {
|
||||
point: zeta,
|
||||
@ -166,10 +183,9 @@ pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
||||
point: zeta_next,
|
||||
polynomials: [trace_info, permutation_zs_info].concat(),
|
||||
};
|
||||
FriInstanceInfoTarget {
|
||||
oracles: vec![no_blinding_oracle; oracle_indices.next().unwrap()],
|
||||
batches: vec![zeta_batch, zeta_next_batch],
|
||||
}
|
||||
let batches = vec![zeta_batch, zeta_next_batch];
|
||||
|
||||
FriInstanceInfoTarget { oracles, batches }
|
||||
}
|
||||
|
||||
/// Pairs of lists of columns that should be permutations of one another. A permutation argument
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::iter::once;
|
||||
|
||||
use anyhow::{ensure, Result};
|
||||
use anyhow::{anyhow, ensure, Result};
|
||||
use itertools::Itertools;
|
||||
use plonky2::field::extension::{Extendable, FieldExtension};
|
||||
use plonky2::field::types::Field;
|
||||
@ -12,7 +12,7 @@ use plonky2::plonk::plonk_common::reduce_with_powers;
|
||||
use crate::config::StarkConfig;
|
||||
use crate::constraint_consumer::ConstraintConsumer;
|
||||
use crate::permutation::PermutationCheckVars;
|
||||
use crate::proof::{StarkOpeningSet, StarkProofChallenges, StarkProofWithPublicInputs};
|
||||
use crate::proof::{StarkOpeningSet, StarkProof, StarkProofChallenges, StarkProofWithPublicInputs};
|
||||
use crate::stark::Stark;
|
||||
use crate::vanishing_poly::eval_vanishing_poly;
|
||||
use crate::vars::StarkEvaluationVars;
|
||||
@ -55,6 +55,7 @@ where
|
||||
[(); S::PUBLIC_INPUTS]:,
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
{
|
||||
validate_proof_shape(&stark, &proof_with_pis, config)?;
|
||||
check_permutation_options(&stark, &proof_with_pis, &challenges)?;
|
||||
let StarkProofWithPublicInputs {
|
||||
proof,
|
||||
@ -144,6 +145,78 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_proof_shape<F, C, S, const D: usize>(
|
||||
stark: &S,
|
||||
proof_with_pis: &StarkProofWithPublicInputs<F, C, D>,
|
||||
config: &StarkConfig,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
S: Stark<F, D>,
|
||||
[(); S::COLUMNS]:,
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
{
|
||||
let StarkProofWithPublicInputs {
|
||||
proof,
|
||||
public_inputs,
|
||||
} = proof_with_pis;
|
||||
let degree_bits = proof.recover_degree_bits(config);
|
||||
|
||||
let StarkProof {
|
||||
trace_cap,
|
||||
permutation_zs_cap,
|
||||
quotient_polys_cap,
|
||||
openings,
|
||||
// The shape of the opening proof will be checked in the FRI verifier (see
|
||||
// validate_fri_proof_shape), so we ignore it here.
|
||||
opening_proof: _,
|
||||
} = proof;
|
||||
|
||||
let StarkOpeningSet {
|
||||
local_values,
|
||||
next_values,
|
||||
permutation_zs,
|
||||
permutation_zs_next,
|
||||
quotient_polys,
|
||||
} = openings;
|
||||
|
||||
ensure!(public_inputs.len() == S::PUBLIC_INPUTS);
|
||||
|
||||
let fri_params = config.fri_params(degree_bits);
|
||||
let cap_height = fri_params.config.cap_height;
|
||||
let num_zs = stark.num_permutation_batches(config);
|
||||
|
||||
ensure!(trace_cap.height() == cap_height);
|
||||
ensure!(quotient_polys_cap.height() == cap_height);
|
||||
|
||||
ensure!(local_values.len() == S::COLUMNS);
|
||||
ensure!(next_values.len() == S::COLUMNS);
|
||||
ensure!(quotient_polys.len() == stark.num_quotient_polys(config));
|
||||
|
||||
if stark.uses_permutation_args() {
|
||||
let permutation_zs_cap = permutation_zs_cap
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("Missing Zs cap"))?;
|
||||
let permutation_zs = permutation_zs
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("Missing permutation_zs"))?;
|
||||
let permutation_zs_next = permutation_zs_next
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("Missing permutation_zs_next"))?;
|
||||
|
||||
ensure!(permutation_zs_cap.height() == cap_height);
|
||||
ensure!(permutation_zs.len() == num_zs);
|
||||
ensure!(permutation_zs_next.len() == num_zs);
|
||||
} else {
|
||||
ensure!(permutation_zs_cap.is_none());
|
||||
ensure!(permutation_zs.is_none());
|
||||
ensure!(permutation_zs_next.is_none());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Evaluate the Lagrange polynomials `L_0` and `L_(n-1)` at a point `x`.
|
||||
/// `L_0(x) = (x^n - 1)/(n * (x - 1))`
|
||||
/// `L_(n-1)(x) = (x^n - 1)/(n * (g * x - 1))`, with `g` the first element of the subgroup.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user