Merge branch 'main' of github.com:mir-protocol/plonky2 into ripeMD

This commit is contained in:
Dmitry Vagner 2022-09-20 10:19:50 -07:00
commit d5f04cbfb4
15 changed files with 413 additions and 88 deletions

View File

@ -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],
}
}

View File

@ -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.

View File

@ -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;

View File

@ -25,6 +25,7 @@ pub struct FriInstanceInfoTarget<const D: usize> {
#[derive(Copy, Clone)]
pub struct FriOracleInfo {
pub num_polys: usize,
pub blinding: bool,
}

View 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(&params.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(())
}

View File

@ -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();

View File

@ -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.

View File

@ -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()
}

View File

@ -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,

View File

@ -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;

View File

@ -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 {

View 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(())
}

View File

@ -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)?;

View File

@ -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

View File

@ -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.