Skip to content

Commit

Permalink
Remove generic_const_exprs feature from EVM crate (#1246)
Browse files Browse the repository at this point in the history
* Remove const_generic_exprs feature from EVM crate

* Get a generic impl of StarkFrame
  • Loading branch information
Nashtare authored Sep 22, 2023
1 parent 6618cfa commit d6be2b9
Show file tree
Hide file tree
Showing 22 changed files with 469 additions and 451 deletions.
25 changes: 17 additions & 8 deletions evm/src/arithmetic/arithmetic_stark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@ use plonky2::field::packed::PackedField;
use plonky2::field::polynomial::PolynomialValues;
use plonky2::field::types::Field;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::util::transpose;
use static_assertions::const_assert;

use super::columns::NUM_ARITH_COLUMNS;
use crate::all_stark::Table;
use crate::arithmetic::{addcy, byte, columns, divmod, modular, mul, Operation};
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
use crate::cross_table_lookup::{Column, TableWithColumns};
use crate::evaluation_frame::{StarkEvaluationFrame, StarkFrame};
use crate::lookup::{eval_lookups, eval_lookups_circuit, permuted_cols};
use crate::permutation::PermutationPair;
use crate::stark::Stark;
use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars};

/// Link the 16-bit columns of the arithmetic table, split into groups
/// of N_LIMBS at a time in `regs`, with the corresponding 32-bit
Expand Down Expand Up @@ -168,11 +170,16 @@ impl<F: RichField, const D: usize> ArithmeticStark<F, D> {
}

impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for ArithmeticStark<F, D> {
const COLUMNS: usize = columns::NUM_ARITH_COLUMNS;
type EvaluationFrame<FE, P, const D2: usize> = StarkFrame<P, NUM_ARITH_COLUMNS>
where
FE: FieldExtension<D2, BaseField = F>,
P: PackedField<Scalar = FE>;

type EvaluationFrameTarget = StarkFrame<ExtensionTarget<D>, NUM_ARITH_COLUMNS>;

fn eval_packed_generic<FE, P, const D2: usize>(
&self,
vars: StarkEvaluationVars<FE, P, { Self::COLUMNS }>,
vars: &Self::EvaluationFrame<FE, P, D2>,
yield_constr: &mut ConstraintConsumer<P>,
) where
FE: FieldExtension<D2, BaseField = F>,
Expand All @@ -183,8 +190,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for ArithmeticSta
eval_lookups(vars, yield_constr, col, col + 1);
}

let lv = vars.local_values;
let nv = vars.next_values;
let lv: &[P; NUM_ARITH_COLUMNS] = vars.get_local_values().try_into().unwrap();
let nv: &[P; NUM_ARITH_COLUMNS] = vars.get_next_values().try_into().unwrap();

// Check the range column: First value must be 0, last row
// must be 2^16-1, and intermediate rows must increment by 0
Expand All @@ -207,16 +214,18 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for ArithmeticSta
fn eval_ext_circuit(
&self,
builder: &mut CircuitBuilder<F, D>,
vars: StarkEvaluationTargets<D, { Self::COLUMNS }>,
vars: &Self::EvaluationFrameTarget,
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
) {
// Range check all the columns
for col in columns::RC_COLS.step_by(2) {
eval_lookups_circuit(builder, vars, yield_constr, col, col + 1);
}

let lv = vars.local_values;
let nv = vars.next_values;
let lv: &[ExtensionTarget<D>; NUM_ARITH_COLUMNS] =
vars.get_local_values().try_into().unwrap();
let nv: &[ExtensionTarget<D>; NUM_ARITH_COLUMNS] =
vars.get_next_values().try_into().unwrap();

let rc1 = lv[columns::RANGE_COUNTER];
let rc2 = nv[columns::RANGE_COUNTER];
Expand Down
122 changes: 63 additions & 59 deletions evm/src/byte_packing/byte_packing_stark.rs

Large diffs are not rendered by default.

21 changes: 8 additions & 13 deletions evm/src/cpu/bootstrap_kernel.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
//! The initial phase of execution, where the kernel code is hashed while being written to memory.
//! The hash is then checked against a precomputed kernel hash.
use std::borrow::Borrow;

use itertools::Itertools;
use plonky2::field::extension::Extendable;
use plonky2::field::packed::PackedField;
use plonky2::field::types::Field;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::plonk::circuit_builder::CircuitBuilder;

use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
use crate::cpu::columns::{CpuColumnsView, NUM_CPU_COLUMNS};
use crate::cpu::columns::CpuColumnsView;
use crate::cpu::kernel::aggregator::KERNEL;
use crate::cpu::membus::NUM_GP_CHANNELS;
use crate::generation::state::GenerationState;
use crate::memory::segments::Segment;
use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars};
use crate::witness::memory::MemoryAddress;
use crate::witness::util::{keccak_sponge_log, mem_write_gp_log_and_fill};

Expand Down Expand Up @@ -58,13 +56,11 @@ pub(crate) fn generate_bootstrap_kernel<F: Field>(state: &mut GenerationState<F>
log::info!("Bootstrapping took {} cycles", state.traces.clock());
}

pub(crate) fn eval_bootstrap_kernel<F: Field, P: PackedField<Scalar = F>>(
vars: StarkEvaluationVars<F, P, NUM_CPU_COLUMNS>,
pub(crate) fn eval_bootstrap_kernel_packed<F: Field, P: PackedField<Scalar = F>>(
local_values: &CpuColumnsView<P>,
next_values: &CpuColumnsView<P>,
yield_constr: &mut ConstraintConsumer<P>,
) {
let local_values: &CpuColumnsView<_> = vars.local_values.borrow();
let next_values: &CpuColumnsView<_> = vars.next_values.borrow();

// IS_BOOTSTRAP_KERNEL must have an init value of 1, a final value of 0, and a delta in {0, -1}.
let local_is_bootstrap = local_values.is_bootstrap_kernel;
let next_is_bootstrap = next_values.is_bootstrap_kernel;
Expand Down Expand Up @@ -103,13 +99,12 @@ pub(crate) fn eval_bootstrap_kernel<F: Field, P: PackedField<Scalar = F>>(
}
}

pub(crate) fn eval_bootstrap_kernel_circuit<F: RichField + Extendable<D>, const D: usize>(
pub(crate) fn eval_bootstrap_kernel_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
vars: StarkEvaluationTargets<D, NUM_CPU_COLUMNS>,
local_values: &CpuColumnsView<ExtensionTarget<D>>,
next_values: &CpuColumnsView<ExtensionTarget<D>>,
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
) {
let local_values: &CpuColumnsView<_> = vars.local_values.borrow();
let next_values: &CpuColumnsView<_> = vars.next_values.borrow();
let one = builder.one_extension();

// IS_BOOTSTRAP_KERNEL must have an init value of 1, a final value of 0, and a delta in {0, -1}.
Expand Down
43 changes: 33 additions & 10 deletions evm/src/cpu/cpu_stark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use plonky2::field::extension::{Extendable, FieldExtension};
use plonky2::field::packed::PackedField;
use plonky2::field::types::Field;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;

use super::halt;
use crate::all_stark::Table;
Expand All @@ -18,10 +19,10 @@ use crate::cpu::{
modfp254, pc, push0, shift, simple_logic, stack, stack_bounds, syscalls_exceptions,
};
use crate::cross_table_lookup::{Column, TableWithColumns};
use crate::evaluation_frame::{StarkEvaluationFrame, StarkFrame};
use crate::memory::segments::Segment;
use crate::memory::{NUM_CHANNELS, VALUE_LIMBS};
use crate::stark::Stark;
use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars};

pub fn ctl_data_keccak_sponge<F: Field>() -> Vec<Column<F>> {
// When executing KECCAK_GENERAL, the GP memory channels are used as follows:
Expand Down Expand Up @@ -227,19 +228,29 @@ impl<F: RichField, const D: usize> CpuStark<F, D> {
}

impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for CpuStark<F, D> {
const COLUMNS: usize = NUM_CPU_COLUMNS;
type EvaluationFrame<FE, P, const D2: usize> = StarkFrame<P, NUM_CPU_COLUMNS>
where
FE: FieldExtension<D2, BaseField = F>,
P: PackedField<Scalar = FE>;

type EvaluationFrameTarget = StarkFrame<ExtensionTarget<D>, NUM_CPU_COLUMNS>;

fn eval_packed_generic<FE, P, const D2: usize>(
&self,
vars: StarkEvaluationVars<FE, P, { Self::COLUMNS }>,
vars: &Self::EvaluationFrame<FE, P, D2>,
yield_constr: &mut ConstraintConsumer<P>,
) where
FE: FieldExtension<D2, BaseField = F>,
P: PackedField<Scalar = FE>,
{
let local_values = vars.local_values.borrow();
let next_values = vars.next_values.borrow();
bootstrap_kernel::eval_bootstrap_kernel(vars, yield_constr);
let local_values =
TryInto::<[P; NUM_CPU_COLUMNS]>::try_into(vars.get_local_values()).unwrap();
let local_values: &CpuColumnsView<P> = local_values.borrow();
let next_values =
TryInto::<[P; NUM_CPU_COLUMNS]>::try_into(vars.get_next_values()).unwrap();
let next_values: &CpuColumnsView<P> = next_values.borrow();

bootstrap_kernel::eval_bootstrap_kernel_packed(local_values, next_values, yield_constr);
contextops::eval_packed(local_values, next_values, yield_constr);
control_flow::eval_packed_generic(local_values, next_values, yield_constr);
decode::eval_packed_generic(local_values, yield_constr);
Expand All @@ -262,12 +273,24 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for CpuStark<F, D
fn eval_ext_circuit(
&self,
builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder<F, D>,
vars: StarkEvaluationTargets<D, { Self::COLUMNS }>,
vars: &Self::EvaluationFrameTarget,
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
) {
let local_values = vars.local_values.borrow();
let next_values = vars.next_values.borrow();
bootstrap_kernel::eval_bootstrap_kernel_circuit(builder, vars, yield_constr);
let local_values =
TryInto::<[ExtensionTarget<D>; NUM_CPU_COLUMNS]>::try_into(vars.get_local_values())
.unwrap();
let local_values: &CpuColumnsView<ExtensionTarget<D>> = local_values.borrow();
let next_values =
TryInto::<[ExtensionTarget<D>; NUM_CPU_COLUMNS]>::try_into(vars.get_next_values())
.unwrap();
let next_values: &CpuColumnsView<ExtensionTarget<D>> = next_values.borrow();

bootstrap_kernel::eval_bootstrap_kernel_ext_circuit(
builder,
local_values,
next_values,
yield_constr,
);
contextops::eval_ext_circuit(builder, local_values, next_values, yield_constr);
control_flow::eval_ext_circuit(builder, local_values, next_values, yield_constr);
decode::eval_ext_circuit(builder, local_values, yield_constr);
Expand Down
20 changes: 13 additions & 7 deletions evm/src/cross_table_lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ use plonky2::plonk::config::GenericConfig;
use crate::all_stark::{Table, NUM_TABLES};
use crate::config::StarkConfig;
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
use crate::evaluation_frame::StarkEvaluationFrame;
use crate::permutation::{GrandProductChallenge, GrandProductChallengeSet};
use crate::proof::{StarkProofTarget, StarkProofWithMetadata};
use crate::stark::Stark;
use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars};

/// Represent a linear combination of columns.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -473,7 +473,7 @@ impl<'a, F: RichField + Extendable<D>, const D: usize>
/// Z(w) = Z(gw) * combine(w) where combine is called on the local row
/// and not the next. This enables CTLs across two rows.
pub(crate) fn eval_cross_table_lookup_checks<F, FE, P, S, const D: usize, const D2: usize>(
vars: StarkEvaluationVars<FE, P, { S::COLUMNS }>,
vars: &S::EvaluationFrame<FE, P, D2>,
ctl_vars: &[CtlCheckVars<F, FE, P, D2>],
consumer: &mut ConstraintConsumer<P>,
) where
Expand All @@ -482,6 +482,9 @@ pub(crate) fn eval_cross_table_lookup_checks<F, FE, P, S, const D: usize, const
P: PackedField<Scalar = FE>,
S: Stark<F, D>,
{
let local_values = vars.get_local_values();
let next_values = vars.get_next_values();

for lookup_vars in ctl_vars {
let CtlCheckVars {
local_z,
Expand All @@ -493,11 +496,11 @@ pub(crate) fn eval_cross_table_lookup_checks<F, FE, P, S, const D: usize, const

let evals = columns
.iter()
.map(|c| c.eval_with_next(vars.local_values, vars.next_values))
.map(|c| c.eval_with_next(local_values, next_values))
.collect::<Vec<_>>();
let combined = challenges.combine(evals.iter());
let local_filter = if let Some(column) = filter_column {
column.eval_with_next(vars.local_values, vars.next_values)
column.eval_with_next(local_values, next_values)
} else {
P::ONES
};
Expand Down Expand Up @@ -580,10 +583,13 @@ pub(crate) fn eval_cross_table_lookup_checks_circuit<
const D: usize,
>(
builder: &mut CircuitBuilder<F, D>,
vars: StarkEvaluationTargets<D, { S::COLUMNS }>,
vars: &S::EvaluationFrameTarget,
ctl_vars: &[CtlCheckVarsTarget<F, D>],
consumer: &mut RecursiveConstraintConsumer<F, D>,
) {
let local_values = vars.get_local_values();
let next_values = vars.get_next_values();

for lookup_vars in ctl_vars {
let CtlCheckVarsTarget {
local_z,
Expand All @@ -595,7 +601,7 @@ pub(crate) fn eval_cross_table_lookup_checks_circuit<

let one = builder.one_extension();
let local_filter = if let Some(column) = filter_column {
column.eval_circuit(builder, vars.local_values)
column.eval_circuit(builder, local_values)
} else {
one
};
Expand All @@ -611,7 +617,7 @@ pub(crate) fn eval_cross_table_lookup_checks_circuit<

let evals = columns
.iter()
.map(|c| c.eval_with_next_circuit(builder, vars.local_values, vars.next_values))
.map(|c| c.eval_with_next_circuit(builder, local_values, next_values))
.collect::<Vec<_>>();

let combined = challenges.combine_circuit(builder, &evals);
Expand Down
47 changes: 47 additions & 0 deletions evm/src/evaluation_frame.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/// A trait for viewing an evaluation frame of a STARK table.
///
/// It allows to access the current and next rows at a given step
/// and can be used to implement constraint evaluation both natively
/// and recursively.
pub trait StarkEvaluationFrame<T: Copy + Clone + Default>: Sized {
/// The number of columns for the STARK table this evaluation frame views.
const COLUMNS: usize;

/// Returns the local values (i.e. current row) for this evaluation frame.
fn get_local_values(&self) -> &[T];
/// Returns the next values (i.e. next row) for this evaluation frame.
fn get_next_values(&self) -> &[T];

/// Outputs a new evaluation frame from the provided local and next values.
///
/// **NOTE**: Concrete implementations of this method SHOULD ensure that
/// the provided slices lengths match the `Self::COLUMNS` value.
fn from_values(lv: &[T], nv: &[T]) -> Self;
}

pub struct StarkFrame<T: Copy + Clone + Default, const N: usize> {
local_values: [T; N],
next_values: [T; N],
}

impl<T: Copy + Clone + Default, const N: usize> StarkEvaluationFrame<T> for StarkFrame<T, N> {
const COLUMNS: usize = N;

fn get_local_values(&self) -> &[T] {
&self.local_values
}

fn get_next_values(&self) -> &[T] {
&self.next_values
}

fn from_values(lv: &[T], nv: &[T]) -> Self {
assert_eq!(lv.len(), Self::COLUMNS);
assert_eq!(nv.len(), Self::COLUMNS);

Self {
local_values: lv.try_into().unwrap(),
next_values: nv.try_into().unwrap(),
}
}
}
24 changes: 2 additions & 22 deletions evm/src/fixed_recursive_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,10 @@ use plonky2::util::timing::TimingTree;
use plonky2_util::log2_ceil;

use crate::all_stark::{all_cross_table_lookups, AllStark, Table, NUM_TABLES};
use crate::arithmetic::arithmetic_stark::ArithmeticStark;
use crate::byte_packing::byte_packing_stark::BytePackingStark;
use crate::config::StarkConfig;
use crate::cpu::cpu_stark::CpuStark;
use crate::cross_table_lookup::{verify_cross_table_lookups_circuit, CrossTableLookup};
use crate::generation::GenerationInputs;
use crate::get_challenges::observe_public_values_target;
use crate::keccak::keccak_stark::KeccakStark;
use crate::keccak_sponge::keccak_sponge_stark::KeccakSpongeStark;
use crate::logic::LogicStark;
use crate::memory::memory_stark::MemoryStark;
use crate::permutation::{get_grand_product_challenge_set_target, GrandProductChallengeSet};
use crate::proof::{
BlockHashesTarget, BlockMetadataTarget, ExtraBlockDataTarget, PublicValues, PublicValuesTarget,
Expand Down Expand Up @@ -297,13 +290,6 @@ where
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F> + 'static,
C::Hasher: AlgebraicHasher<F>,
[(); ArithmeticStark::<F, D>::COLUMNS]:,
[(); BytePackingStark::<F, D>::COLUMNS]:,
[(); CpuStark::<F, D>::COLUMNS]:,
[(); KeccakStark::<F, D>::COLUMNS]:,
[(); KeccakSpongeStark::<F, D>::COLUMNS]:,
[(); LogicStark::<F, D>::COLUMNS]:,
[(); MemoryStark::<F, D>::COLUMNS]:,
{
pub fn to_bytes(
&self,
Expand Down Expand Up @@ -1083,10 +1069,7 @@ where
degree_bits_range: Range<usize>,
all_ctls: &[CrossTableLookup<F>],
stark_config: &StarkConfig,
) -> Self
where
[(); S::COLUMNS]:,
{
) -> Self {
let by_stark_size = degree_bits_range
.map(|degree_bits| {
(
Expand Down Expand Up @@ -1207,10 +1190,7 @@ where
degree_bits: usize,
all_ctls: &[CrossTableLookup<F>],
stark_config: &StarkConfig,
) -> Self
where
[(); S::COLUMNS]:,
{
) -> Self {
let initial_wrapper = recursive_stark_circuit(
table,
stark,
Expand Down
Loading

0 comments on commit d6be2b9

Please sign in to comment.