diff --git a/field/src/lib.rs b/field/src/lib.rs index f190bcbc..2c89aab3 100644 --- a/field/src/lib.rs +++ b/field/src/lib.rs @@ -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; diff --git a/field/src/zero_poly_coset.rs b/field/src/zero_poly_coset.rs new file mode 100644 index 00000000..0b7452f5 --- /dev/null +++ b/field/src/zero_poly_coset.rs @@ -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 { + /// `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, + /// Holds the multiplicative inverses of `evals`. + inverses: Vec, +} + +impl ZeroPolyOnCoset { + 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::>(); + 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() + } +} diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index c016f0ee..0922962a 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -127,7 +127,7 @@ impl, C: GenericConfig, const D: usize> } /// Produces a batch opening proof. - pub(crate) fn prove_openings( + pub fn prove_openings( instance: &FriInstanceInfo, oracles: &[&Self], challenger: &mut Challenger, diff --git a/plonky2/src/plonk/plonk_common.rs b/plonky2/src/plonk/plonk_common.rs index 92c4168d..74495198 100644 --- a/plonky2/src/plonk/plonk_common.rs +++ b/plonky2/src/plonk/plonk_common.rs @@ -63,52 +63,6 @@ pub(crate) fn eval_zero_poly(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 { - /// `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, - /// Holds the multiplicative inverses of `evals`. - inverses: Vec, -} - -impl ZeroPolyOnCoset { - 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::>(); - 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(n: usize, x: F) -> F { diff --git a/plonky2/src/plonk/prover.rs b/plonky2/src/plonk/prover.rs index 2a11e4c0..09caf81e 100644 --- a/plonky2/src/plonk/prover.rs +++ b/plonky2/src/plonk/prover.rs @@ -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; diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 74e0fab3..70de5833 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -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; diff --git a/starky/src/constraint_consumer.rs b/starky/src/constraint_consumer.rs index 09b5397f..adb88e41 100644 --- a/starky/src/constraint_consumer.rs +++ b/starky/src/constraint_consumer.rs @@ -8,26 +8,45 @@ use plonky2::iop::target::Target; use plonky2::plonk::circuit_builder::CircuitBuilder; pub struct ConstraintConsumer { - /// A random value used to combine multiple constraints into one. - alpha: P::Scalar, + /// Random values used to combine multiple constraints into one. + alphas: Vec, - /// A running sum of constraints that have been emitted so far, scaled by powers of alpha. - constraint_acc: P, + /// Running sums of constraints that have been emitted so far, scaled by powers of alpha. + constraint_accs: Vec

, /// The evaluation of the Lagrange basis polynomial which is nonzero at the point associated /// with the first trace row, and zero at other points in the subgroup. - lagrange_basis_first: P::Scalar, + lagrange_basis_first: P, /// The evaluation of the Lagrange basis polynomial which is nonzero at the point associated /// with the last trace row, and zero at other points in the subgroup. - lagrange_basis_last: P::Scalar, + lagrange_basis_last: P, } impl ConstraintConsumer

{ + pub fn new(alphas: Vec, lagrange_basis_first: P, lagrange_basis_last: P) -> Self { + Self { + constraint_accs: vec![P::ZEROS; alphas.len()], + alphas, + lagrange_basis_first, + lagrange_basis_last, + } + } + + // TODO: Do this correctly. + pub fn accumulators(self) -> Vec { + self.constraint_accs + .into_iter() + .map(|acc| acc.as_slice()[0]) + .collect() + } + /// Add one constraint. pub fn one(&mut self, constraint: P) { - self.constraint_acc *= self.alpha; - self.constraint_acc += constraint; + for (&alpha, acc) in self.alphas.iter().zip(&mut self.constraint_accs) { + *acc *= alpha; + *acc += constraint; + } } /// Add a series of constraints. diff --git a/starky/src/fibonacci_stark.rs b/starky/src/fibonacci_stark.rs new file mode 100644 index 00000000..ea834e99 --- /dev/null +++ b/starky/src/fibonacci_stark.rs @@ -0,0 +1,123 @@ +use std::marker::PhantomData; + +use plonky2::field::extension_field::{Extendable, FieldExtension}; +use plonky2::field::packed_field::PackedField; +use plonky2::hash::hash_types::RichField; +use plonky2::plonk::circuit_builder::CircuitBuilder; + +use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; +use crate::stark::Stark; +use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars}; + +/// Toy STARK system used for testing. +/// Computes a Fibonacci sequence with state `[x0, x1]` using the state transition +/// `x0 <- x1, x1 <- x0 + x1`. +struct FibonacciStark, const D: usize> { + num_rows: usize, + _phantom: PhantomData, +} + +impl, const D: usize> FibonacciStark { + // The first public input is `x0`. + const PI_INDEX_X0: usize = 0; + // The second public input is `x1`. + const PI_INDEX_X1: usize = 1; + // The third public input is the second element of the last row, which should be equal to the + // `num_rows`-th Fibonacci number. + const PI_INDEX_RES: usize = 2; + + fn new(num_rows: usize) -> Self { + Self { + num_rows, + _phantom: PhantomData, + } + } + + /// Generate the trace using `x0, x1` as inital state values. + fn generate_trace(&self, x0: F, x1: F) -> Vec<[F; Self::COLUMNS]> { + (0..self.num_rows) + .scan([x0, x1], |acc, _| { + let tmp = *acc; + acc[0] = tmp[1]; + acc[1] = tmp[0] + tmp[1]; + Some(tmp) + }) + .collect() + } +} + +impl, const D: usize> Stark for FibonacciStark { + const COLUMNS: usize = 2; + const PUBLIC_INPUTS: usize = 3; + + fn eval_packed_generic( + &self, + vars: StarkEvaluationVars, + yield_constr: &mut ConstraintConsumer

, + ) where + FE: FieldExtension, + P: PackedField, + { + // Check public inputs. + yield_constr.one_first_row(vars.local_values[0] - vars.public_inputs[Self::PI_INDEX_X0]); + yield_constr.one_first_row(vars.local_values[1] - vars.public_inputs[Self::PI_INDEX_X1]); + yield_constr.one_last_row(vars.local_values[1] - vars.public_inputs[Self::PI_INDEX_RES]); + + // x0 <- x1 + yield_constr.one(vars.next_values[0] - vars.local_values[1]); + // x1 <- x0 + x1 + yield_constr.one(vars.next_values[1] - vars.local_values[0] - vars.local_values[1]); + } + + fn eval_ext_recursively( + &self, + builder: &mut CircuitBuilder, + vars: StarkEvaluationTargets, + yield_constr: &mut RecursiveConstraintConsumer, + ) { + todo!() + } +} + +#[cfg(test)] +mod tests { + use anyhow::Result; + use plonky2::field::field_types::Field; + use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + use plonky2::util::timing::TimingTree; + + use crate::config::StarkConfig; + use crate::fibonacci_stark::FibonacciStark; + use crate::prover::prove; + + fn fibonacci(n: usize, x0: usize, x1: usize) -> usize { + (0..n).fold((0, 1), |x, _| (x.1, x.0 + x.1)).1 + } + + #[test] + fn test_fibonacci_stark() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + type S = FibonacciStark; + + let config = StarkConfig::standard_fast_config(); + let num_rows = 1 << 5; + let public_inputs = [ + F::ZERO, + F::ONE, + F::from_canonical_usize(fibonacci(num_rows - 1, 0, 1)), + ]; + let stark = S::new(num_rows); + let trace = stark.generate_trace(public_inputs[0], public_inputs[1]); + prove::( + stark, + config, + trace, + public_inputs, + &mut TimingTree::default(), + )?; + + Ok(()) + } +} diff --git a/starky/src/lib.rs b/starky/src/lib.rs index be28a01e..541950ab 100644 --- a/starky/src/lib.rs +++ b/starky/src/lib.rs @@ -12,3 +12,6 @@ pub mod proof; pub mod prover; pub mod stark; pub mod vars; + +#[cfg(test)] +pub mod fibonacci_stark; diff --git a/starky/src/proof.rs b/starky/src/proof.rs index 1cdbbd3c..4218e71f 100644 --- a/starky/src/proof.rs +++ b/starky/src/proof.rs @@ -1,8 +1,10 @@ use plonky2::field::extension_field::Extendable; +use plonky2::fri::oracle::PolynomialBatch; use plonky2::fri::proof::{CompressedFriProof, FriProof}; use plonky2::hash::hash_types::RichField; use plonky2::hash::merkle_tree::MerkleCap; use plonky2::plonk::config::GenericConfig; +use rayon::prelude::*; pub struct StarkProof, C: GenericConfig, const D: usize> { /// Merkle cap of LDEs of trace values. @@ -33,3 +35,25 @@ pub struct StarkOpeningSet, const D: usize> { pub permutation_zs: Vec, pub quotient_polys: Vec, } + +impl, const D: usize> StarkOpeningSet { + pub fn new>( + zeta: F::Extension, + g: F::Extension, + trace_commitment: &PolynomialBatch, + quotient_commitment: &PolynomialBatch, + ) -> Self { + let eval_commitment = |z: F::Extension, c: &PolynomialBatch| { + c.polynomials + .par_iter() + .map(|p| p.to_extension().eval(z)) + .collect::>() + }; + Self { + local_values: eval_commitment(zeta, trace_commitment), + next_values: eval_commitment(zeta * g, trace_commitment), + permutation_zs: vec![/*TODO*/], + quotient_polys: eval_commitment(zeta, quotient_commitment), + } + } +} diff --git a/starky/src/prover.rs b/starky/src/prover.rs index bda478e5..e0652b24 100644 --- a/starky/src/prover.rs +++ b/starky/src/prover.rs @@ -1,8 +1,10 @@ +use anyhow::{ensure, Result}; use itertools::Itertools; use plonky2::field::extension_field::Extendable; -use plonky2::field::polynomial::PolynomialValues; +use plonky2::field::field_types::Field; +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::config::GenericConfig; @@ -13,22 +15,28 @@ use plonky2_util::log2_strict; use rayon::prelude::*; use crate::config::StarkConfig; -use crate::proof::StarkProof; +use crate::constraint_consumer::ConstraintConsumer; +use crate::proof::{StarkOpeningSet, StarkProof}; use crate::stark::Stark; +use crate::vars::StarkEvaluationVars; +// TODO: Deal with public inputs. pub fn prove( stark: S, config: StarkConfig, trace: Vec<[F; S::COLUMNS]>, + public_inputs: [F; S::PUBLIC_INPUTS], timing: &mut TimingTree, -) -> StarkProof +) -> Result> where F: RichField + Extendable, C: GenericConfig, S: Stark, [(); S::COLUMNS]:, + [(); S::PUBLIC_INPUTS]:, { - let degree_bits = log2_strict(trace.len()); + let degree = trace.len(); + let degree_bits = log2_strict(degree); let trace_vecs = trace.into_iter().map(|row| row.to_vec()).collect_vec(); let trace_col_major: Vec> = transpose(&trace_vecs); @@ -57,27 +65,148 @@ where ) ); - let trace_cap = trace_commitment.merkle_tree.cap; - let openings = todo!(); - - let initial_merkle_trees = todo!(); - let lde_polynomial_coeffs = todo!(); - let lde_polynomial_values = todo!(); + 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_polys = compute_quotient_polys::( + &stark, + &trace_commitment, + public_inputs, + alphas, + degree_bits, + rate_bits, + ); + let all_quotient_chunks = quotient_polys + .into_par_iter() + .flat_map(|mut quotient_poly| { + quotient_poly.trim(); + quotient_poly + .pad(degree << rate_bits) + .expect("Quotient has failed, the vanishing polynomial is not divisible by `Z_H"); + // Split quotient into degree-n chunks. + quotient_poly.chunks(degree) + }) + .collect(); + let quotient_commitment = timed!( + timing, + "compute quotient commitment", + PolynomialBatch::from_coeffs( + all_quotient_chunks, + rate_bits, + false, + config.fri_config.cap_height, + timing, + None, + ) + ); + challenger.observe_cap("ient_commitment.merkle_tree.cap); + + let zeta = challenger.get_extension_challenge::(); + // To avoid leaking witness data, we want to ensure that our opening locations, `zeta` and + // `g * zeta`, are not in our subgroup `H`. It suffices to check `zeta` only, since + // `(g * zeta)^n = zeta^n`, where `n` is the order of `g`. + let g = F::Extension::primitive_root_of_unity(degree_bits); + ensure!( + zeta.exp_power_of_2(degree_bits) != F::Extension::ONE, + "Opening point is in the subgroup." + ); + let openings = StarkOpeningSet::new(zeta, g, &trace_commitment, "ient_commitment); + + // TODO: Add permuation checks + let initial_merkle_trees = &[&trace_commitment, "ient_commitment]; let fri_params = config.fri_params(degree_bits); - let opening_proof = fri_proof::( - initial_merkle_trees, - lde_polynomial_coeffs, - lde_polynomial_values, - &mut challenger, - &fri_params, + let opening_proof = timed!( timing, + "compute openings proof", + PolynomialBatch::prove_openings( + &S::fri_instance(zeta, g, rate_bits), + initial_merkle_trees, + &mut challenger, + &fri_params, + timing, + ) ); - StarkProof { + Ok(StarkProof { trace_cap, openings, opening_proof, - } + }) +} + +/// Computes the quotient polynomials `(sum alpha^i C_i(x)) / Z_H(x)` for `alpha` in `alphas`, +/// where the `C_i`s are the Stark constraints. +// TODO: This won't work for the Fibonacci example because the constraints wrap around the subgroup. +// The denominator should be the vanishing polynomial of `H` without its last element. +fn compute_quotient_polys( + stark: &S, + trace_commitment: &PolynomialBatch, + public_inputs: [F; S::PUBLIC_INPUTS], + alphas: Vec, + degree_bits: usize, + rate_bits: usize, +) -> Vec> +where + F: RichField + Extendable, + C: GenericConfig, + S: Stark, + [(); S::COLUMNS]:, + [(); S::PUBLIC_INPUTS]:, +{ + let degree = 1 << degree_bits; + let points = F::two_adic_subgroup(degree_bits + rate_bits); + + // Evaluation of the first Lagrange polynomial on the LDE domain. + let lagrange_first = { + let mut evals = PolynomialValues::new(vec![F::ZERO; degree]); + evals.values[0] = F::ONE; + evals.lde(rate_bits) + }; + // Evaluation of the last Lagrange polynomial on the LDE domain. + 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); + + // Retrieve the LDE values at index `i`. + let get_at_index = |comm: &PolynomialBatch, i: usize| -> [F; S::COLUMNS] { + comm.get_lde_values(i).try_into().unwrap() + }; + + let quotient_values = (0..degree << rate_bits) + .into_par_iter() + .map(|i| { + // TODO: Set `P` to a genuine `PackedField` here. + let mut consumer = ConstraintConsumer::::new( + alphas.clone(), + lagrange_first.values[i], + lagrange_last.values[i], + ); + let vars = StarkEvaluationVars:: { + local_values: &get_at_index(trace_commitment, i), + next_values: &get_at_index(trace_commitment, (i + 1) % (degree << rate_bits)), + public_inputs: &public_inputs, + }; + stark.eval_packed_base(vars, &mut consumer); + // TODO: Fix this once we a genuine `PackedField`. + let mut constraints_evals = consumer.accumulators(); + let denominator_inv = z_h_on_coset.eval_inverse(i); + for eval in &mut constraints_evals { + *eval *= denominator_inv; + } + constraints_evals + }) + .collect::>(); + + transpose("ient_values) + .into_par_iter() + .map(PolynomialValues::new) + .map(|values| values.coset_ifft(F::coset_shift())) + .collect() } diff --git a/starky/src/stark.rs b/starky/src/stark.rs index 8d6abb69..f91d4fdd 100644 --- a/starky/src/stark.rs +++ b/starky/src/stark.rs @@ -1,5 +1,6 @@ use plonky2::field::extension_field::{Extendable, FieldExtension}; use plonky2::field::packed_field::PackedField; +use plonky2::fri::structure::{FriBatchInfo, FriInstanceInfo, FriOracleInfo, FriPolynomialInfo}; use plonky2::hash::hash_types::RichField; use plonky2::plonk::circuit_builder::CircuitBuilder; @@ -8,7 +9,7 @@ use crate::vars::StarkEvaluationTargets; use crate::vars::StarkEvaluationVars; /// Represents a STARK system. -pub trait Stark, const D: usize> { +pub trait Stark, const D: usize>: Sync { /// The total number of columns in the trace. const COLUMNS: usize; /// The number of public inputs. @@ -59,4 +60,28 @@ pub trait Stark, const D: usize> { vars: StarkEvaluationTargets, yield_constr: &mut RecursiveConstraintConsumer, ); + + /// Computes the FRI instance used to prove this Stark. + // TODO: Permutation polynomials. + fn fri_instance( + zeta: F::Extension, + g: F::Extension, + rate_bits: usize, + ) -> FriInstanceInfo { + let no_blinding_oracle = FriOracleInfo { blinding: false }; + let trace_info = FriPolynomialInfo::from_range(0, 0..Self::COLUMNS); + let quotient_info = FriPolynomialInfo::from_range(1, 0..1 << rate_bits); + let zeta_batch = FriBatchInfo { + point: zeta, + polynomials: [trace_info.clone(), quotient_info].concat(), + }; + let zeta_right_batch = FriBatchInfo:: { + point: zeta * g, + polynomials: trace_info, + }; + FriInstanceInfo { + oracles: vec![no_blinding_oracle; 3], + batches: vec![zeta_batch], + } + } } diff --git a/system_zero/src/system_zero.rs b/system_zero/src/system_zero.rs index a16fb699..49e25e6c 100644 --- a/system_zero/src/system_zero.rs +++ b/system_zero/src/system_zero.rs @@ -83,27 +83,33 @@ impl, const D: usize> Stark for SystemZero Result<()> { type F = GoldilocksField; type C = PoseidonGoldilocksConfig; const D: usize = 2; type S = SystemZero; let system = S::default(); + let public_inputs = [F::ZERO; S::PUBLIC_INPUTS]; let config = StarkConfig::standard_fast_config(); let mut timing = TimingTree::new("prove", Level::Debug); let trace = system.generate_trace(); - prove::(system, config, trace, &mut timing); + prove::(system, config, trace, public_inputs, &mut timing)?; + + Ok(()) } } diff --git a/util/src/lib.rs b/util/src/lib.rs index f760cfba..61677ff0 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -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 {