First try

This commit is contained in:
wborgeaud 2022-01-26 16:08:04 +01:00
parent c0ac79e2e1
commit d54cc9a7c8
9 changed files with 157 additions and 52 deletions

View File

@ -24,6 +24,7 @@ pub mod packed_field;
pub mod polynomial;
pub mod secp256k1_base;
pub mod secp256k1_scalar;
pub mod zero_poly_coset;
#[cfg(test)]
mod field_testing;

View File

@ -0,0 +1,47 @@
use crate::field_types::Field;
/// Precomputations of the evaluation of `Z_H(X) = X^n - 1` on a coset `gK` with `H <= K`.
pub struct ZeroPolyOnCoset<F: Field> {
/// `n = |H|`.
n: F,
/// `rate = |K|/|H|`.
rate: usize,
/// Holds `g^n * (w^n)^i - 1 = g^n * v^i - 1` for `i in 0..rate`, with `w` a generator of `K` and `v` a
/// `rate`-primitive root of unity.
evals: Vec<F>,
/// Holds the multiplicative inverses of `evals`.
inverses: Vec<F>,
}
impl<F: Field> ZeroPolyOnCoset<F> {
pub fn new(n_log: usize, rate_bits: usize) -> Self {
let g_pow_n = F::coset_shift().exp_power_of_2(n_log);
let evals = F::two_adic_subgroup(rate_bits)
.into_iter()
.map(|x| g_pow_n * x - F::ONE)
.collect::<Vec<_>>();
let inverses = F::batch_multiplicative_inverse(&evals);
Self {
n: F::from_canonical_usize(1 << n_log),
rate: 1 << rate_bits,
evals,
inverses,
}
}
/// Returns `Z_H(g * w^i)`.
pub fn eval(&self, i: usize) -> F {
self.evals[i % self.rate]
}
/// Returns `1 / Z_H(g * w^i)`.
pub fn eval_inverse(&self, i: usize) -> F {
self.inverses[i % self.rate]
}
/// Returns `L_1(x) = Z_H(x)/(n * (x - 1))` with `x = w^i`.
pub fn eval_l1(&self, i: usize, x: F) -> F {
// Could also precompute the inverses using Montgomery.
self.eval(i) * (self.n * (x - F::ONE)).inverse()
}
}

View File

@ -63,52 +63,6 @@ pub(crate) fn eval_zero_poly<F: Field>(n: usize, x: F) -> F {
x.exp_u64(n as u64) - F::ONE
}
/// Precomputations of the evaluation of `Z_H(X) = X^n - 1` on a coset `gK` with `H <= K`.
pub(crate) struct ZeroPolyOnCoset<F: Field> {
/// `n = |H|`.
n: F,
/// `rate = |K|/|H|`.
rate: usize,
/// Holds `g^n * (w^n)^i - 1 = g^n * v^i - 1` for `i in 0..rate`, with `w` a generator of `K` and `v` a
/// `rate`-primitive root of unity.
evals: Vec<F>,
/// Holds the multiplicative inverses of `evals`.
inverses: Vec<F>,
}
impl<F: Field> ZeroPolyOnCoset<F> {
pub fn new(n_log: usize, rate_bits: usize) -> Self {
let g_pow_n = F::coset_shift().exp_power_of_2(n_log);
let evals = F::two_adic_subgroup(rate_bits)
.into_iter()
.map(|x| g_pow_n * x - F::ONE)
.collect::<Vec<_>>();
let inverses = F::batch_multiplicative_inverse(&evals);
Self {
n: F::from_canonical_usize(1 << n_log),
rate: 1 << rate_bits,
evals,
inverses,
}
}
/// Returns `Z_H(g * w^i)`.
pub fn eval(&self, i: usize) -> F {
self.evals[i % self.rate]
}
/// Returns `1 / Z_H(g * w^i)`.
pub fn eval_inverse(&self, i: usize) -> F {
self.inverses[i % self.rate]
}
/// Returns `L_1(x) = Z_H(x)/(n * (x - 1))` with `x = w^i`.
pub fn eval_l1(&self, i: usize, x: F) -> F {
// Could also precompute the inverses using Montgomery.
self.eval(i) * (self.n * (x - F::ONE)).inverse()
}
}
/// Evaluate the Lagrange basis `L_1` with `L_1(1) = 1`, and `L_1(x) = 0` for other members of an
/// order `n` multiplicative subgroup.
pub(crate) fn eval_l_1<F: Field>(n: usize, x: F) -> F {

View File

@ -4,6 +4,7 @@ use anyhow::ensure;
use anyhow::Result;
use plonky2_field::extension_field::Extendable;
use plonky2_field::polynomial::{PolynomialCoeffs, PolynomialValues};
use plonky2_field::zero_poly_coset::ZeroPolyOnCoset;
use plonky2_util::log2_ceil;
use rayon::prelude::*;
@ -15,7 +16,7 @@ use crate::iop::generator::generate_partial_witness;
use crate::iop::witness::{MatrixWitness, PartialWitness, Witness};
use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData};
use crate::plonk::config::{GenericConfig, Hasher};
use crate::plonk::plonk_common::{PlonkOracle, ZeroPolyOnCoset};
use crate::plonk::plonk_common::PlonkOracle;
use crate::plonk::proof::OpeningSet;
use crate::plonk::proof::{Proof, ProofWithPublicInputs};
use crate::plonk::vanishing_poly::eval_vanishing_poly_base_batch;

View File

@ -1,6 +1,7 @@
use plonky2_field::batch_util::batch_add_inplace;
use plonky2_field::extension_field::{Extendable, FieldExtension};
use plonky2_field::field_types::Field;
use plonky2_field::zero_poly_coset::ZeroPolyOnCoset;
use crate::gates::gate::PrefixedGate;
use crate::hash::hash_types::RichField;
@ -10,7 +11,7 @@ use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::config::GenericConfig;
use crate::plonk::plonk_common;
use crate::plonk::plonk_common::{eval_l_1_recursively, ZeroPolyOnCoset};
use crate::plonk::plonk_common::eval_l_1_recursively;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch};
use crate::util::partial_products::{check_partial_products, check_partial_products_recursively};
use crate::util::reducing::ReducingFactorTarget;

View File

@ -1,6 +1,7 @@
use std::marker::PhantomData;
use plonky2::field::extension_field::Extendable;
use plonky2::field::field_types::Field;
use plonky2::field::packed_field::PackedField;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
@ -24,6 +25,24 @@ pub struct ConstraintConsumer<P: PackedField> {
}
impl<P: PackedField> ConstraintConsumer<P> {
pub fn new(
alpha: P::Scalar,
lagrange_basis_first: P::Scalar,
lagrange_basis_last: P::Scalar,
) -> Self {
Self {
alpha,
constraint_acc: P::ZEROS,
lagrange_basis_first,
lagrange_basis_last,
}
}
// TODO: Do this correctly.
pub fn accumulator(&self) -> P::Scalar {
self.constraint_acc.as_slice()[0]
}
/// Add one constraint.
pub fn one(&mut self, constraint: P) {
self.constraint_acc *= self.alpha;

View File

@ -1,10 +1,12 @@
use itertools::Itertools;
use plonky2::field::extension_field::Extendable;
use plonky2::field::polynomial::PolynomialValues;
use plonky2::field::polynomial::{PolynomialCoeffs, PolynomialValues};
use plonky2::field::zero_poly_coset::ZeroPolyOnCoset;
use plonky2::fri::oracle::PolynomialBatch;
use plonky2::fri::prover::fri_proof;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::challenger::Challenger;
use plonky2::plonk::circuit_data::CommonCircuitData;
use plonky2::plonk::config::GenericConfig;
use plonky2::timed;
use plonky2::util::timing::TimingTree;
@ -13,8 +15,10 @@ use plonky2_util::log2_strict;
use rayon::prelude::*;
use crate::config::StarkConfig;
use crate::constraint_consumer::ConstraintConsumer;
use crate::proof::StarkProof;
use crate::stark::Stark;
use crate::vars::StarkEvaluationVars;
pub fn prove<F, C, S, const D: usize>(
stark: S,
@ -27,6 +31,7 @@ where
C: GenericConfig<D, F = F>,
S: Stark<F, D>,
[(); S::COLUMNS]:,
[(); S::PUBLIC_INPUTS]:,
{
let degree_bits = log2_strict(trace.len());
@ -57,13 +62,23 @@ where
)
);
let trace_cap = trace_commitment.merkle_tree.cap;
let trace_cap = trace_commitment.merkle_tree.cap.clone();
let mut challenger = Challenger::new();
challenger.observe_cap(&trace_cap);
let alphas = challenger.get_n_challenges(config.num_challenges);
let quotient = compute_quotient_polys::<F, C, S, D>(
&stark,
&trace_commitment,
&alphas,
degree_bits,
rate_bits,
);
let openings = todo!();
let initial_merkle_trees = todo!();
let lde_polynomial_coeffs = todo!();
let lde_polynomial_values = todo!();
let mut challenger = Challenger::new();
let fri_params = config.fri_params(degree_bits);
let opening_proof = fri_proof::<F, C, D>(
@ -81,3 +96,69 @@ where
opening_proof,
}
}
fn compute_quotient_polys<F, C, S, const D: usize>(
stark: &S,
trace_commitment: &PolynomialBatch<F, C, D>,
alphas: &[F],
degree_bits: usize,
rate_bits: usize,
) -> Vec<PolynomialCoeffs<F>>
where
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F>,
S: Stark<F, D>,
[(); S::COLUMNS]:,
[(); S::PUBLIC_INPUTS]:,
{
let degree = 1 << degree_bits;
let points = F::two_adic_subgroup(degree_bits + rate_bits);
let lagrange_first = {
let mut evals = PolynomialValues::new(vec![F::ZERO; degree]);
evals.values[0] = F::ONE;
evals.lde(rate_bits)
};
let lagrange_last = {
let mut evals = PolynomialValues::new(vec![F::ZERO; degree]);
evals.values[degree - 1] = F::ONE;
evals.lde(rate_bits)
};
let z_h_on_coset = ZeroPolyOnCoset::new(degree_bits, rate_bits);
alphas
.iter()
.map(|&alpha| {
let quotient_evals = PolynomialValues::new(
(0..degree << rate_bits)
.into_par_iter()
.map(|i| {
let mut consumer = ConstraintConsumer::<F>::new(
alpha,
lagrange_first.values[i],
lagrange_last.values[i],
);
let vars =
StarkEvaluationVars::<F, F, { S::COLUMNS }, { S::PUBLIC_INPUTS }> {
local_values: trace_commitment
.get_lde_values(i)
.try_into()
.unwrap(),
next_values: trace_commitment
.get_lde_values((i + 1) % (degree << rate_bits))
.try_into()
.unwrap(),
public_inputs: &[F::ZERO; S::PUBLIC_INPUTS],
};
stark.eval_packed_base(vars, &mut consumer);
let constraints_eval = consumer.accumulator();
let denominator_inv = z_h_on_coset.eval_inverse(i);
constraints_eval * denominator_inv
})
.collect(),
);
quotient_evals.coset_ifft(F::coset_shift())
})
.collect()
}

View File

@ -8,7 +8,7 @@ use crate::vars::StarkEvaluationTargets;
use crate::vars::StarkEvaluationVars;
/// Represents a STARK system.
pub trait Stark<F: RichField + Extendable<D>, const D: usize> {
pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
/// The total number of columns in the trace.
const COLUMNS: usize;
/// The number of public inputs.

View File

@ -11,6 +11,7 @@ use std::mem::size_of;
use std::ptr::{swap, swap_nonoverlapping};
mod transpose_util;
use crate::transpose_util::transpose_in_place_square;
pub fn bits_u64(n: u64) -> usize {