2022-01-26 00:09:29 -08:00
|
|
|
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 starky::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
|
|
|
|
use starky::stark::Stark;
|
|
|
|
|
use starky::vars::StarkEvaluationTargets;
|
|
|
|
|
use starky::vars::StarkEvaluationVars;
|
|
|
|
|
|
|
|
|
|
use crate::column_layout::NUM_COLUMNS;
|
|
|
|
|
use crate::memory::TransactionMemory;
|
|
|
|
|
use crate::public_input_layout::NUM_PUBLIC_INPUTS;
|
|
|
|
|
|
|
|
|
|
/// We require at least 2^16 rows as it helps support efficient 16-bit range checks.
|
|
|
|
|
const MIN_TRACE_ROWS: usize = 1 << 16;
|
|
|
|
|
|
2022-02-01 17:34:03 +01:00
|
|
|
#[derive(Copy, Clone)]
|
2022-01-26 00:09:29 -08:00
|
|
|
pub struct SystemZero<F: RichField + Extendable<D>, const D: usize> {
|
|
|
|
|
_phantom: PhantomData<F>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<F: RichField + Extendable<D>, const D: usize> SystemZero<F, D> {
|
|
|
|
|
fn generate_trace(&self) -> Vec<[F; NUM_COLUMNS]> {
|
|
|
|
|
let memory = TransactionMemory::default();
|
|
|
|
|
|
|
|
|
|
let mut row = [F::ZERO; NUM_COLUMNS];
|
|
|
|
|
self.generate_first_row_core_registers(&mut row);
|
2022-02-04 16:50:57 -08:00
|
|
|
Self::generate_permutation_unit(&mut row);
|
2022-01-26 00:09:29 -08:00
|
|
|
|
|
|
|
|
let mut trace = Vec::with_capacity(MIN_TRACE_ROWS);
|
|
|
|
|
|
|
|
|
|
loop {
|
|
|
|
|
let mut next_row = [F::ZERO; NUM_COLUMNS];
|
|
|
|
|
self.generate_next_row_core_registers(&row, &mut next_row);
|
2022-02-04 16:50:57 -08:00
|
|
|
Self::generate_permutation_unit(&mut next_row);
|
2022-01-26 00:09:29 -08:00
|
|
|
|
|
|
|
|
trace.push(row);
|
|
|
|
|
row = next_row;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trace.push(row);
|
|
|
|
|
trace
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<F: RichField + Extendable<D>, const D: usize> Default for SystemZero<F, D> {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
_phantom: PhantomData,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for SystemZero<F, D> {
|
|
|
|
|
const COLUMNS: usize = NUM_COLUMNS;
|
|
|
|
|
const PUBLIC_INPUTS: usize = NUM_PUBLIC_INPUTS;
|
|
|
|
|
|
|
|
|
|
fn eval_packed_generic<FE, P, const D2: usize>(
|
|
|
|
|
&self,
|
|
|
|
|
vars: StarkEvaluationVars<FE, P, NUM_COLUMNS, NUM_PUBLIC_INPUTS>,
|
|
|
|
|
yield_constr: &mut ConstraintConsumer<P>,
|
|
|
|
|
) where
|
|
|
|
|
FE: FieldExtension<D2, BaseField = F>,
|
|
|
|
|
P: PackedField<Scalar = FE>,
|
|
|
|
|
{
|
|
|
|
|
self.eval_core_registers(vars, yield_constr);
|
2022-02-04 16:50:57 -08:00
|
|
|
Self::eval_permutation_unit(vars, yield_constr);
|
2022-01-26 00:09:29 -08:00
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn eval_ext_recursively(
|
|
|
|
|
&self,
|
|
|
|
|
builder: &mut CircuitBuilder<F, D>,
|
|
|
|
|
vars: StarkEvaluationTargets<D, NUM_COLUMNS, NUM_PUBLIC_INPUTS>,
|
|
|
|
|
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
|
|
|
|
|
) {
|
|
|
|
|
self.eval_core_registers_recursively(builder, vars, yield_constr);
|
2022-02-04 16:50:57 -08:00
|
|
|
Self::eval_permutation_unit_recursively(builder, vars, yield_constr);
|
2022-01-26 00:09:29 -08:00
|
|
|
todo!()
|
|
|
|
|
}
|
2022-02-04 15:56:59 +01:00
|
|
|
|
2022-02-04 17:16:18 +01:00
|
|
|
fn constraint_degree(&self) -> usize {
|
2022-02-04 15:56:59 +01:00
|
|
|
3
|
|
|
|
|
}
|
2022-01-26 00:09:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
2022-01-28 05:02:31 +01:00
|
|
|
use anyhow::Result;
|
2022-01-26 00:09:29 -08:00
|
|
|
use log::Level;
|
2022-01-28 05:02:31 +01:00
|
|
|
use plonky2::field::field_types::Field;
|
2022-01-26 00:09:29 -08:00
|
|
|
use plonky2::field::goldilocks_field::GoldilocksField;
|
|
|
|
|
use plonky2::plonk::config::PoseidonGoldilocksConfig;
|
|
|
|
|
use plonky2::util::timing::TimingTree;
|
|
|
|
|
use starky::config::StarkConfig;
|
|
|
|
|
use starky::prover::prove;
|
2022-01-28 05:02:31 +01:00
|
|
|
use starky::stark::Stark;
|
2022-02-04 16:02:45 +01:00
|
|
|
use starky::stark_testing::test_stark_low_degree;
|
2022-02-01 17:34:03 +01:00
|
|
|
use starky::verifier::verify;
|
2022-01-26 00:09:29 -08:00
|
|
|
|
|
|
|
|
use crate::system_zero::SystemZero;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
#[ignore] // TODO
|
2022-01-28 05:02:31 +01:00
|
|
|
fn run() -> Result<()> {
|
2022-01-26 00:09:29 -08:00
|
|
|
type F = GoldilocksField;
|
|
|
|
|
type C = PoseidonGoldilocksConfig;
|
|
|
|
|
const D: usize = 2;
|
|
|
|
|
|
|
|
|
|
type S = SystemZero<F, D>;
|
|
|
|
|
let system = S::default();
|
2022-01-28 05:02:31 +01:00
|
|
|
let public_inputs = [F::ZERO; S::PUBLIC_INPUTS];
|
2022-01-26 00:09:29 -08:00
|
|
|
let config = StarkConfig::standard_fast_config();
|
|
|
|
|
let mut timing = TimingTree::new("prove", Level::Debug);
|
|
|
|
|
let trace = system.generate_trace();
|
2022-02-01 17:34:03 +01:00
|
|
|
let proof = prove::<F, C, S, D>(system, &config, trace, public_inputs, &mut timing)?;
|
2022-01-28 05:02:31 +01:00
|
|
|
|
2022-02-01 17:34:03 +01:00
|
|
|
verify(system, proof, &config)
|
2022-01-26 00:09:29 -08:00
|
|
|
}
|
2022-02-04 16:02:45 +01:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
#[ignore] // TODO
|
|
|
|
|
fn degree() -> Result<()> {
|
|
|
|
|
type F = GoldilocksField;
|
|
|
|
|
type C = PoseidonGoldilocksConfig;
|
|
|
|
|
const D: usize = 2;
|
|
|
|
|
|
|
|
|
|
type S = SystemZero<F, D>;
|
|
|
|
|
let system = S::default();
|
|
|
|
|
test_stark_low_degree(system)
|
|
|
|
|
}
|
2022-01-26 00:09:29 -08:00
|
|
|
}
|