2023-10-09 09:07:01 -04:00
|
|
|
use std::borrow::Borrow;
|
2022-09-22 18:09:23 -07:00
|
|
|
use std::iter::repeat;
|
2022-05-18 09:22:58 +02:00
|
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
2022-06-23 14:36:14 -07:00
|
|
|
use itertools::Itertools;
|
2022-06-27 07:18:21 -07:00
|
|
|
use plonky2::field::extension::{Extendable, FieldExtension};
|
2022-06-27 15:07:52 -07:00
|
|
|
use plonky2::field::packed::PackedField;
|
2022-06-27 12:24:09 -07:00
|
|
|
use plonky2::field::types::Field;
|
2022-05-18 09:22:58 +02:00
|
|
|
use plonky2::hash::hash_types::RichField;
|
2023-09-22 09:19:13 -04:00
|
|
|
use plonky2::iop::ext_target::ExtensionTarget;
|
2022-05-18 09:22:58 +02:00
|
|
|
|
2023-10-09 09:07:01 -04:00
|
|
|
use super::columns::CpuColumnsView;
|
2023-09-15 17:46:58 -04:00
|
|
|
use super::halt;
|
2023-11-13 11:03:50 -05:00
|
|
|
use super::membus::NUM_GP_CHANNELS;
|
Cross-table lookup for arithmetic stark (#905)
* First draft of linking arithmetic Stark into the CTL mechanism.
* Handle {ADD,SUB,MUL}FP254 operations explicitly in `modular.rs`.
* Adjust argument order; add tests.
* Add CTLs for ADD, MUL, SUB, LT and GT.
* Add CTLs for {ADD,MUL,SUB}MOD, DIV and MOD.
* Add CTLs for {ADD,MUL,SUB}FP254 operations.
* Refactor the CPU/arithmetic CTL mapping; add some documentation.
* Minor comment fixes.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Merge `*FP254` CTL into main CTL; rename some registers.
* Connect extra argument from CPU in binary ops to facilitate combining with ternary ops.
* Merge modular ops CTL into main CTL.
* Refactor DIV and MOD code into its own module.
* Merge DIV and MOD into arithmetic CTL.
* Clippy.
* Fixes related to merge.
* Simplify register naming.
* Generate u16 BN254 modulus limbs at compile time.
* Clippy.
* Add degree bits ranges for Arithmetic table.
2023-05-11 03:29:06 +10:00
|
|
|
use crate::all_stark::Table;
|
2022-05-18 09:22:58 +02:00
|
|
|
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
2023-10-09 09:07:01 -04:00
|
|
|
use crate::cpu::columns::{COL_MAP, NUM_CPU_COLUMNS};
|
2022-09-10 13:20:30 -07:00
|
|
|
use crate::cpu::{
|
2023-11-30 10:04:08 -05:00
|
|
|
byte_unpacking, clock, contextops, control_flow, decode, dup_swap, gas, jumps, membus, memio,
|
|
|
|
|
modfp254, pc, push0, shift, simple_logic, stack, syscalls_exceptions,
|
2022-09-10 13:20:30 -07:00
|
|
|
};
|
2023-12-05 17:02:37 -05:00
|
|
|
use crate::cross_table_lookup::{Column, Filter, TableWithColumns};
|
2023-09-22 09:19:13 -04:00
|
|
|
use crate::evaluation_frame::{StarkEvaluationFrame, StarkFrame};
|
2024-01-08 11:46:26 +01:00
|
|
|
use crate::memory::segments::{Segment, SEGMENT_SCALING_FACTOR};
|
2022-09-22 18:09:23 -07:00
|
|
|
use crate::memory::{NUM_CHANNELS, VALUE_LIMBS};
|
2022-05-18 09:22:58 +02:00
|
|
|
use crate::stark::Stark;
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Creates the vector of `Columns` corresponding to the General Purpose channels when calling the Keccak sponge:
|
|
|
|
|
/// the CPU reads the output of the sponge directly from the `KeccakSpongeStark` table.
|
2023-11-13 09:26:56 -05:00
|
|
|
pub(crate) fn ctl_data_keccak_sponge<F: Field>() -> Vec<Column<F>> {
|
2022-09-22 18:09:23 -07:00
|
|
|
// When executing KECCAK_GENERAL, the GP memory channels are used as follows:
|
2024-01-08 11:46:26 +01:00
|
|
|
// GP channel 0: stack[-1] = addr (context, segment, virt)
|
|
|
|
|
// GP channel 1: stack[-2] = len
|
2023-11-13 11:03:50 -05:00
|
|
|
// Next GP channel 0: pushed = outputs
|
2024-01-08 11:46:26 +01:00
|
|
|
let (context, segment, virt) = get_addr(&COL_MAP, 0);
|
|
|
|
|
let context = Column::single(context);
|
|
|
|
|
let segment = Column::single(segment);
|
|
|
|
|
let virt = Column::single(virt);
|
|
|
|
|
let len = Column::single(COL_MAP.mem_channels[1].value[0]);
|
2022-08-14 16:36:07 -07:00
|
|
|
|
|
|
|
|
let num_channels = F::from_canonical_usize(NUM_CHANNELS);
|
2022-12-03 11:21:31 -08:00
|
|
|
let timestamp = Column::linear_combination([(COL_MAP.clock, num_channels)]);
|
2022-08-14 16:36:07 -07:00
|
|
|
|
2022-12-03 11:21:31 -08:00
|
|
|
let mut cols = vec![context, segment, virt, len, timestamp];
|
2023-10-26 17:52:54 -04:00
|
|
|
cols.extend(Column::singles_next_row(COL_MAP.mem_channels[0].value));
|
2022-12-03 11:21:31 -08:00
|
|
|
cols
|
2022-06-21 10:28:44 -07:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// CTL filter for a call to the Keccak sponge.
|
2023-12-07 13:07:06 -05:00
|
|
|
// KECCAK_GENERAL is differentiated from JUMPDEST by its second bit set to 0.
|
2023-12-05 17:02:37 -05:00
|
|
|
pub(crate) fn ctl_filter_keccak_sponge<F: Field>() -> Filter<F> {
|
2023-12-07 13:07:06 -05:00
|
|
|
Filter::new(
|
|
|
|
|
vec![(
|
|
|
|
|
Column::single(COL_MAP.op.jumpdest_keccak_general),
|
|
|
|
|
Column::linear_combination_with_constant([(COL_MAP.opcode_bits[1], -F::ONE)], F::ONE),
|
|
|
|
|
)],
|
|
|
|
|
vec![],
|
|
|
|
|
)
|
2022-08-14 16:36:07 -07:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Creates the vector of `Columns` corresponding to the two inputs and
|
Cross-table lookup for arithmetic stark (#905)
* First draft of linking arithmetic Stark into the CTL mechanism.
* Handle {ADD,SUB,MUL}FP254 operations explicitly in `modular.rs`.
* Adjust argument order; add tests.
* Add CTLs for ADD, MUL, SUB, LT and GT.
* Add CTLs for {ADD,MUL,SUB}MOD, DIV and MOD.
* Add CTLs for {ADD,MUL,SUB}FP254 operations.
* Refactor the CPU/arithmetic CTL mapping; add some documentation.
* Minor comment fixes.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Merge `*FP254` CTL into main CTL; rename some registers.
* Connect extra argument from CPU in binary ops to facilitate combining with ternary ops.
* Merge modular ops CTL into main CTL.
* Refactor DIV and MOD code into its own module.
* Merge DIV and MOD into arithmetic CTL.
* Clippy.
* Fixes related to merge.
* Simplify register naming.
* Generate u16 BN254 modulus limbs at compile time.
* Clippy.
* Add degree bits ranges for Arithmetic table.
2023-05-11 03:29:06 +10:00
|
|
|
/// one output of a binary operation.
|
2023-09-14 10:36:48 -04:00
|
|
|
fn ctl_data_binops<F: Field>() -> Vec<Column<F>> {
|
|
|
|
|
let mut res = Column::singles(COL_MAP.mem_channels[0].value).collect_vec();
|
Cross-table lookup for arithmetic stark (#905)
* First draft of linking arithmetic Stark into the CTL mechanism.
* Handle {ADD,SUB,MUL}FP254 operations explicitly in `modular.rs`.
* Adjust argument order; add tests.
* Add CTLs for ADD, MUL, SUB, LT and GT.
* Add CTLs for {ADD,MUL,SUB}MOD, DIV and MOD.
* Add CTLs for {ADD,MUL,SUB}FP254 operations.
* Refactor the CPU/arithmetic CTL mapping; add some documentation.
* Minor comment fixes.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Merge `*FP254` CTL into main CTL; rename some registers.
* Connect extra argument from CPU in binary ops to facilitate combining with ternary ops.
* Merge modular ops CTL into main CTL.
* Refactor DIV and MOD code into its own module.
* Merge DIV and MOD into arithmetic CTL.
* Clippy.
* Fixes related to merge.
* Simplify register naming.
* Generate u16 BN254 modulus limbs at compile time.
* Clippy.
* Add degree bits ranges for Arithmetic table.
2023-05-11 03:29:06 +10:00
|
|
|
res.extend(Column::singles(COL_MAP.mem_channels[1].value));
|
2023-10-26 17:52:54 -04:00
|
|
|
res.extend(Column::singles_next_row(COL_MAP.mem_channels[0].value));
|
Cross-table lookup for arithmetic stark (#905)
* First draft of linking arithmetic Stark into the CTL mechanism.
* Handle {ADD,SUB,MUL}FP254 operations explicitly in `modular.rs`.
* Adjust argument order; add tests.
* Add CTLs for ADD, MUL, SUB, LT and GT.
* Add CTLs for {ADD,MUL,SUB}MOD, DIV and MOD.
* Add CTLs for {ADD,MUL,SUB}FP254 operations.
* Refactor the CPU/arithmetic CTL mapping; add some documentation.
* Minor comment fixes.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Merge `*FP254` CTL into main CTL; rename some registers.
* Connect extra argument from CPU in binary ops to facilitate combining with ternary ops.
* Merge modular ops CTL into main CTL.
* Refactor DIV and MOD code into its own module.
* Merge DIV and MOD into arithmetic CTL.
* Clippy.
* Fixes related to merge.
* Simplify register naming.
* Generate u16 BN254 modulus limbs at compile time.
* Clippy.
* Add degree bits ranges for Arithmetic table.
2023-05-11 03:29:06 +10:00
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Creates the vector of `Columns` corresponding to the three inputs and
|
2023-08-09 09:17:06 -04:00
|
|
|
/// one output of a ternary operation. By default, ternary operations use
|
2023-11-07 15:52:00 -05:00
|
|
|
/// the first three memory channels, and the next top of the stack for the
|
|
|
|
|
/// result (binary operations do not use the third inputs).
|
2023-10-05 09:56:56 -04:00
|
|
|
fn ctl_data_ternops<F: Field>() -> Vec<Column<F>> {
|
|
|
|
|
let mut res = Column::singles(COL_MAP.mem_channels[0].value).collect_vec();
|
|
|
|
|
res.extend(Column::singles(COL_MAP.mem_channels[1].value));
|
|
|
|
|
res.extend(Column::singles(COL_MAP.mem_channels[2].value));
|
2023-10-26 17:52:54 -04:00
|
|
|
res.extend(Column::singles_next_row(COL_MAP.mem_channels[0].value));
|
2022-06-21 10:28:44 -07:00
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Creates the vector of columns corresponding to the opcode, the two inputs and the output of the logic operation.
|
2023-11-13 09:26:56 -05:00
|
|
|
pub(crate) fn ctl_data_logic<F: Field>() -> Vec<Column<F>> {
|
2023-08-11 10:21:11 -04:00
|
|
|
// Instead of taking single columns, we reconstruct the entire opcode value directly.
|
2023-08-11 09:23:58 -04:00
|
|
|
let mut res = vec![Column::le_bits(COL_MAP.opcode_bits)];
|
2023-09-14 10:36:48 -04:00
|
|
|
res.extend(ctl_data_binops());
|
2023-08-11 09:23:58 -04:00
|
|
|
res
|
Cross-table lookup for arithmetic stark (#905)
* First draft of linking arithmetic Stark into the CTL mechanism.
* Handle {ADD,SUB,MUL}FP254 operations explicitly in `modular.rs`.
* Adjust argument order; add tests.
* Add CTLs for ADD, MUL, SUB, LT and GT.
* Add CTLs for {ADD,MUL,SUB}MOD, DIV and MOD.
* Add CTLs for {ADD,MUL,SUB}FP254 operations.
* Refactor the CPU/arithmetic CTL mapping; add some documentation.
* Minor comment fixes.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Merge `*FP254` CTL into main CTL; rename some registers.
* Connect extra argument from CPU in binary ops to facilitate combining with ternary ops.
* Merge modular ops CTL into main CTL.
* Refactor DIV and MOD code into its own module.
* Merge DIV and MOD into arithmetic CTL.
* Clippy.
* Fixes related to merge.
* Simplify register naming.
* Generate u16 BN254 modulus limbs at compile time.
* Clippy.
* Add degree bits ranges for Arithmetic table.
2023-05-11 03:29:06 +10:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// CTL filter for logic operations.
|
2023-12-05 17:02:37 -05:00
|
|
|
pub(crate) fn ctl_filter_logic<F: Field>() -> Filter<F> {
|
|
|
|
|
Filter::new_simple(Column::single(COL_MAP.op.logic_op))
|
2022-06-21 10:28:44 -07:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Returns the `TableWithColumns` for the CPU rows calling arithmetic operations.
|
2023-11-13 09:26:56 -05:00
|
|
|
pub(crate) fn ctl_arithmetic_base_rows<F: Field>() -> TableWithColumns<F> {
|
2023-09-14 10:36:48 -04:00
|
|
|
// Instead of taking single columns, we reconstruct the entire opcode value directly.
|
|
|
|
|
let mut columns = vec![Column::le_bits(COL_MAP.opcode_bits)];
|
2023-10-05 09:56:56 -04:00
|
|
|
columns.extend(ctl_data_ternops());
|
Cross-table lookup for arithmetic stark (#905)
* First draft of linking arithmetic Stark into the CTL mechanism.
* Handle {ADD,SUB,MUL}FP254 operations explicitly in `modular.rs`.
* Adjust argument order; add tests.
* Add CTLs for ADD, MUL, SUB, LT and GT.
* Add CTLs for {ADD,MUL,SUB}MOD, DIV and MOD.
* Add CTLs for {ADD,MUL,SUB}FP254 operations.
* Refactor the CPU/arithmetic CTL mapping; add some documentation.
* Minor comment fixes.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Combine addcy CTLs at the expense of repeated constraint evaluation.
* Merge `*FP254` CTL into main CTL; rename some registers.
* Connect extra argument from CPU in binary ops to facilitate combining with ternary ops.
* Merge modular ops CTL into main CTL.
* Refactor DIV and MOD code into its own module.
* Merge DIV and MOD into arithmetic CTL.
* Clippy.
* Fixes related to merge.
* Simplify register naming.
* Generate u16 BN254 modulus limbs at compile time.
* Clippy.
* Add degree bits ranges for Arithmetic table.
2023-05-11 03:29:06 +10:00
|
|
|
// Create the CPU Table whose columns are those with the three
|
|
|
|
|
// inputs and one output of the ternary operations listed in `ops`
|
|
|
|
|
// (also `ops` is used as the operation filter). The list of
|
|
|
|
|
// operations includes binary operations which will simply ignore
|
|
|
|
|
// the third input.
|
2023-12-13 16:21:24 +01:00
|
|
|
let col_bit = Column::linear_combination_with_constant(
|
|
|
|
|
vec![(COL_MAP.opcode_bits[5], F::NEG_ONE)],
|
|
|
|
|
F::ONE,
|
|
|
|
|
);
|
2023-08-09 09:17:06 -04:00
|
|
|
TableWithColumns::new(
|
|
|
|
|
Table::Cpu,
|
2023-09-14 10:36:48 -04:00
|
|
|
columns,
|
2023-12-13 16:21:24 +01:00
|
|
|
Some(Filter::new(
|
|
|
|
|
vec![(Column::single(COL_MAP.op.push_prover_input), col_bit)],
|
|
|
|
|
vec![Column::sum([
|
|
|
|
|
COL_MAP.op.binary_op,
|
|
|
|
|
COL_MAP.op.fp254_op,
|
|
|
|
|
COL_MAP.op.ternary_op,
|
|
|
|
|
COL_MAP.op.shift,
|
|
|
|
|
COL_MAP.op.syscall,
|
|
|
|
|
COL_MAP.op.exception,
|
|
|
|
|
])],
|
|
|
|
|
)),
|
2023-08-09 09:17:06 -04:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Creates the vector of `Columns` corresponding to the contents of General Purpose channels when calling byte packing.
|
|
|
|
|
/// We use `ctl_data_keccak_sponge` because the `Columns` are the same as the ones computed for `KeccakSpongeStark`.
|
2023-11-13 09:26:56 -05:00
|
|
|
pub(crate) fn ctl_data_byte_packing<F: Field>() -> Vec<Column<F>> {
|
2023-12-15 19:44:59 -05:00
|
|
|
let mut res = vec![Column::constant(F::ONE)]; // is_read
|
|
|
|
|
res.extend(ctl_data_keccak_sponge());
|
|
|
|
|
res
|
2023-09-12 14:45:37 -04:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// CTL filter for the `MLOAD_32BYTES` operation.
|
2023-12-08 17:57:45 -05:00
|
|
|
/// MLOAD_32 BYTES is differentiated from MSTORE_32BYTES by its fifth bit set to 1.
|
2023-12-05 17:02:37 -05:00
|
|
|
pub(crate) fn ctl_filter_byte_packing<F: Field>() -> Filter<F> {
|
2023-12-08 17:57:45 -05:00
|
|
|
Filter::new(
|
|
|
|
|
vec![(
|
|
|
|
|
Column::single(COL_MAP.op.m_op_32bytes),
|
|
|
|
|
Column::single(COL_MAP.opcode_bits[5]),
|
|
|
|
|
)],
|
|
|
|
|
vec![],
|
|
|
|
|
)
|
2023-09-12 14:45:37 -04:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Creates the vector of `Columns` corresponding to the contents of General Purpose channels when calling byte unpacking.
|
2023-11-13 09:26:56 -05:00
|
|
|
pub(crate) fn ctl_data_byte_unpacking<F: Field>() -> Vec<Column<F>> {
|
2023-12-15 19:44:59 -05:00
|
|
|
let is_read = Column::constant(F::ZERO);
|
|
|
|
|
|
2023-09-12 14:45:37 -04:00
|
|
|
// When executing MSTORE_32BYTES, the GP memory channels are used as follows:
|
2024-01-08 11:46:26 +01:00
|
|
|
// GP channel 0: stack[-1] = addr (context, segment, virt)
|
|
|
|
|
// GP channel 1: stack[-2] = val
|
2023-11-13 11:03:50 -05:00
|
|
|
// Next GP channel 0: pushed = new_offset (virt + len)
|
2024-01-08 11:46:26 +01:00
|
|
|
let (context, segment, virt) = get_addr(&COL_MAP, 0);
|
|
|
|
|
let mut res = vec![
|
|
|
|
|
is_read,
|
|
|
|
|
Column::single(context),
|
|
|
|
|
Column::single(segment),
|
|
|
|
|
Column::single(virt),
|
|
|
|
|
];
|
2023-11-13 11:03:50 -05:00
|
|
|
|
|
|
|
|
// len can be reconstructed as new_offset - virt.
|
|
|
|
|
let len = Column::linear_combination_and_next_row_with_constant(
|
2024-01-08 11:46:26 +01:00
|
|
|
[(COL_MAP.mem_channels[0].value[0], -F::ONE)],
|
2023-11-13 11:03:50 -05:00
|
|
|
[(COL_MAP.mem_channels[0].value[0], F::ONE)],
|
|
|
|
|
F::ZERO,
|
|
|
|
|
);
|
2024-01-08 11:46:26 +01:00
|
|
|
res.push(len);
|
2023-09-12 14:45:37 -04:00
|
|
|
|
|
|
|
|
let num_channels = F::from_canonical_usize(NUM_CHANNELS);
|
|
|
|
|
let timestamp = Column::linear_combination([(COL_MAP.clock, num_channels)]);
|
2024-01-08 11:46:26 +01:00
|
|
|
res.push(timestamp);
|
2023-09-12 14:45:37 -04:00
|
|
|
|
2024-01-08 11:46:26 +01:00
|
|
|
let val = Column::singles(COL_MAP.mem_channels[1].value);
|
2023-09-12 14:45:37 -04:00
|
|
|
res.extend(val);
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// CTL filter for the `MSTORE_32BYTES` operation.
|
2023-12-08 17:57:45 -05:00
|
|
|
/// MSTORE_32BYTES is differentiated from MLOAD_32BYTES by its fifth bit set to 0.
|
2023-12-05 17:02:37 -05:00
|
|
|
pub(crate) fn ctl_filter_byte_unpacking<F: Field>() -> Filter<F> {
|
2023-12-08 17:57:45 -05:00
|
|
|
Filter::new(
|
|
|
|
|
vec![(
|
|
|
|
|
Column::single(COL_MAP.op.m_op_32bytes),
|
|
|
|
|
Column::linear_combination_with_constant([(COL_MAP.opcode_bits[5], -F::ONE)], F::ONE),
|
|
|
|
|
)],
|
|
|
|
|
vec![],
|
|
|
|
|
)
|
2023-09-12 14:45:37 -04:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 11:15:14 -05:00
|
|
|
/// Creates the vector of `Columns` corresponding to the contents of the CPU registers when performing a `PUSH`.
|
|
|
|
|
/// `PUSH` internal reads are done by calling `BytePackingStark`.
|
|
|
|
|
pub(crate) fn ctl_data_byte_packing_push<F: Field>() -> Vec<Column<F>> {
|
2023-12-15 19:44:59 -05:00
|
|
|
let is_read = Column::constant(F::ONE);
|
2023-11-15 11:15:14 -05:00
|
|
|
let context = Column::single(COL_MAP.code_context);
|
|
|
|
|
let segment = Column::constant(F::from_canonical_usize(Segment::Code as usize));
|
|
|
|
|
// The initial offset if `pc + 1`.
|
|
|
|
|
let virt =
|
|
|
|
|
Column::linear_combination_with_constant([(COL_MAP.program_counter, F::ONE)], F::ONE);
|
|
|
|
|
let val = Column::singles_next_row(COL_MAP.mem_channels[0].value);
|
|
|
|
|
|
|
|
|
|
// We fetch the length from the `PUSH` opcode lower bits, that indicate `len - 1`.
|
|
|
|
|
let len = Column::le_bits_with_constant(&COL_MAP.opcode_bits[0..5], F::ONE);
|
|
|
|
|
|
|
|
|
|
let num_channels = F::from_canonical_usize(NUM_CHANNELS);
|
|
|
|
|
let timestamp = Column::linear_combination([(COL_MAP.clock, num_channels)]);
|
|
|
|
|
|
2023-12-15 19:44:59 -05:00
|
|
|
let mut res = vec![is_read, context, segment, virt, len, timestamp];
|
2023-11-15 11:15:14 -05:00
|
|
|
res.extend(val);
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// CTL filter for the `PUSH` operation.
|
2023-12-05 17:02:37 -05:00
|
|
|
pub(crate) fn ctl_filter_byte_packing_push<F: Field>() -> Filter<F> {
|
2023-12-13 16:21:24 +01:00
|
|
|
let bit_col = Column::single(COL_MAP.opcode_bits[5]);
|
|
|
|
|
Filter::new(
|
|
|
|
|
vec![(Column::single(COL_MAP.op.push_prover_input), bit_col)],
|
|
|
|
|
vec![],
|
|
|
|
|
)
|
2023-11-15 11:15:14 -05:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Index of the memory channel storing code.
|
2023-11-17 15:45:38 -05:00
|
|
|
pub(crate) const MEM_CODE_CHANNEL_IDX: usize = 0;
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Index of the first general purpose memory channel.
|
2023-11-17 15:45:38 -05:00
|
|
|
pub(crate) const MEM_GP_CHANNELS_IDX_START: usize = MEM_CODE_CHANNEL_IDX + 1;
|
2022-09-22 18:09:23 -07:00
|
|
|
|
2024-01-08 11:46:26 +01:00
|
|
|
/// Recover the three components of an address, given a CPU row and
|
|
|
|
|
/// a provided memory channel index.
|
|
|
|
|
/// The components are recovered as follows:
|
|
|
|
|
///
|
|
|
|
|
/// - `context`, shifted by 2^64 (i.e. at index 2)
|
|
|
|
|
/// - `segment`, shifted by 2^32 (i.e. at index 1)
|
|
|
|
|
/// - `virtual`, not shifted (i.e. at index 0)
|
|
|
|
|
pub(crate) const fn get_addr<T: Copy>(lv: &CpuColumnsView<T>, mem_channel: usize) -> (T, T, T) {
|
|
|
|
|
let addr_context = lv.mem_channels[mem_channel].value[2];
|
|
|
|
|
let addr_segment = lv.mem_channels[mem_channel].value[1];
|
|
|
|
|
let addr_virtual = lv.mem_channels[mem_channel].value[0];
|
|
|
|
|
(addr_context, addr_segment, addr_virtual)
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-22 18:09:23 -07:00
|
|
|
/// Make the time/channel column for memory lookups.
|
|
|
|
|
fn mem_time_and_channel<F: Field>(channel: usize) -> Column<F> {
|
|
|
|
|
let scalar = F::from_canonical_usize(NUM_CHANNELS);
|
|
|
|
|
let addend = F::from_canonical_usize(channel);
|
|
|
|
|
Column::linear_combination_with_constant([(COL_MAP.clock, scalar)], addend)
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Creates the vector of `Columns` corresponding to the contents of the code channel when reading code values.
|
2023-11-13 09:26:56 -05:00
|
|
|
pub(crate) fn ctl_data_code_memory<F: Field>() -> Vec<Column<F>> {
|
2022-09-22 18:09:23 -07:00
|
|
|
let mut cols = vec![
|
2024-01-08 11:46:26 +01:00
|
|
|
Column::constant(F::ONE), // is_read
|
|
|
|
|
Column::single(COL_MAP.code_context), // addr_context
|
|
|
|
|
Column::constant(F::from_canonical_usize(Segment::Code.unscale())), // addr_segment
|
|
|
|
|
Column::single(COL_MAP.program_counter), // addr_virtual
|
2022-09-22 18:09:23 -07:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Low limb of the value matches the opcode bits
|
|
|
|
|
cols.push(Column::le_bits(COL_MAP.opcode_bits));
|
|
|
|
|
|
|
|
|
|
// High limbs of the value are all zero.
|
|
|
|
|
cols.extend(repeat(Column::constant(F::ZERO)).take(VALUE_LIMBS - 1));
|
|
|
|
|
|
|
|
|
|
cols.push(mem_time_and_channel(MEM_CODE_CHANNEL_IDX));
|
|
|
|
|
|
|
|
|
|
cols
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Creates the vector of `Columns` corresponding to the contents of General Purpose channels.
|
2023-11-13 09:26:56 -05:00
|
|
|
pub(crate) fn ctl_data_gp_memory<F: Field>(channel: usize) -> Vec<Column<F>> {
|
2022-08-26 22:05:16 -07:00
|
|
|
let channel_map = COL_MAP.mem_channels[channel];
|
2022-09-22 18:09:23 -07:00
|
|
|
let mut cols: Vec<_> = Column::singles([
|
2022-08-26 22:05:16 -07:00
|
|
|
channel_map.is_read,
|
|
|
|
|
channel_map.addr_context,
|
|
|
|
|
channel_map.addr_segment,
|
|
|
|
|
channel_map.addr_virtual,
|
2022-06-23 14:36:14 -07:00
|
|
|
])
|
2022-09-22 18:09:23 -07:00
|
|
|
.collect();
|
|
|
|
|
|
2022-08-26 22:05:16 -07:00
|
|
|
cols.extend(Column::singles(channel_map.value));
|
2022-07-07 09:27:50 -07:00
|
|
|
|
2022-09-22 18:09:23 -07:00
|
|
|
cols.push(mem_time_and_channel(MEM_GP_CHANNELS_IDX_START + channel));
|
2022-07-07 09:52:38 -07:00
|
|
|
|
2022-06-23 14:36:14 -07:00
|
|
|
cols
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-13 11:03:50 -05:00
|
|
|
pub(crate) fn ctl_data_partial_memory<F: Field>() -> Vec<Column<F>> {
|
|
|
|
|
let channel_map = COL_MAP.partial_channel;
|
|
|
|
|
let values = COL_MAP.mem_channels[0].value;
|
|
|
|
|
let mut cols: Vec<_> = Column::singles([
|
|
|
|
|
channel_map.is_read,
|
|
|
|
|
channel_map.addr_context,
|
|
|
|
|
channel_map.addr_segment,
|
|
|
|
|
channel_map.addr_virtual,
|
|
|
|
|
])
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
cols.extend(Column::singles(values));
|
|
|
|
|
|
|
|
|
|
cols.push(mem_time_and_channel(
|
|
|
|
|
MEM_GP_CHANNELS_IDX_START + NUM_GP_CHANNELS,
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
cols
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// CTL filter for code read and write operations.
|
2023-12-05 17:02:37 -05:00
|
|
|
pub(crate) fn ctl_filter_code_memory<F: Field>() -> Filter<F> {
|
|
|
|
|
Filter::new_simple(Column::sum(COL_MAP.op.iter()))
|
2022-09-22 18:09:23 -07:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// CTL filter for General Purpose memory read and write operations.
|
2023-12-05 17:02:37 -05:00
|
|
|
pub(crate) fn ctl_filter_gp_memory<F: Field>(channel: usize) -> Filter<F> {
|
|
|
|
|
Filter::new_simple(Column::single(COL_MAP.mem_channels[channel].used))
|
2022-06-23 14:36:14 -07:00
|
|
|
}
|
|
|
|
|
|
2023-12-05 17:02:37 -05:00
|
|
|
pub(crate) fn ctl_filter_partial_memory<F: Field>() -> Filter<F> {
|
|
|
|
|
Filter::new_simple(Column::single(COL_MAP.partial_channel.used))
|
2023-11-13 11:03:50 -05:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Structure representing the CPU Stark.
|
2022-07-04 18:10:03 -07:00
|
|
|
#[derive(Copy, Clone, Default)]
|
2023-11-13 09:26:56 -05:00
|
|
|
pub(crate) struct CpuStark<F, const D: usize> {
|
2022-05-18 09:22:58 +02:00
|
|
|
pub f: PhantomData<F>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for CpuStark<F, D> {
|
2023-09-22 09:19:13 -04:00
|
|
|
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>;
|
2022-05-18 09:22:58 +02:00
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Evaluates all CPU constraints.
|
2022-05-18 09:22:58 +02:00
|
|
|
fn eval_packed_generic<FE, P, const D2: usize>(
|
|
|
|
|
&self,
|
2023-09-22 09:19:13 -04:00
|
|
|
vars: &Self::EvaluationFrame<FE, P, D2>,
|
2022-12-02 22:47:07 -08:00
|
|
|
yield_constr: &mut ConstraintConsumer<P>,
|
2022-05-18 09:22:58 +02:00
|
|
|
) where
|
|
|
|
|
FE: FieldExtension<D2, BaseField = F>,
|
|
|
|
|
P: PackedField<Scalar = FE>,
|
|
|
|
|
{
|
2023-09-22 10:14:47 -04:00
|
|
|
let local_values: &[P; NUM_CPU_COLUMNS] = vars.get_local_values().try_into().unwrap();
|
2023-09-22 09:19:13 -04:00
|
|
|
let local_values: &CpuColumnsView<P> = local_values.borrow();
|
2023-09-22 10:14:47 -04:00
|
|
|
let next_values: &[P; NUM_CPU_COLUMNS] = vars.get_next_values().try_into().unwrap();
|
2023-09-22 09:19:13 -04:00
|
|
|
let next_values: &CpuColumnsView<P> = next_values.borrow();
|
|
|
|
|
|
2023-11-13 11:03:50 -05:00
|
|
|
byte_unpacking::eval_packed(local_values, next_values, yield_constr);
|
2023-11-09 16:42:18 -05:00
|
|
|
clock::eval_packed(local_values, next_values, yield_constr);
|
2022-12-11 10:59:14 -08:00
|
|
|
contextops::eval_packed(local_values, next_values, yield_constr);
|
2022-12-02 22:47:07 -08:00
|
|
|
control_flow::eval_packed_generic(local_values, next_values, yield_constr);
|
2023-04-07 17:06:57 -04:00
|
|
|
decode::eval_packed_generic(local_values, yield_constr);
|
2023-10-11 22:28:49 +02:00
|
|
|
dup_swap::eval_packed(local_values, next_values, yield_constr);
|
2023-02-14 22:30:19 -08:00
|
|
|
gas::eval_packed(local_values, next_values, yield_constr);
|
2023-09-15 17:46:58 -04:00
|
|
|
halt::eval_packed(local_values, next_values, yield_constr);
|
2022-12-11 11:08:33 -08:00
|
|
|
jumps::eval_packed(local_values, next_values, yield_constr);
|
2022-12-02 22:47:07 -08:00
|
|
|
membus::eval_packed(local_values, yield_constr);
|
2023-09-15 00:51:02 +01:00
|
|
|
memio::eval_packed(local_values, next_values, yield_constr);
|
2022-12-02 22:47:07 -08:00
|
|
|
modfp254::eval_packed(local_values, yield_constr);
|
2023-10-11 22:28:49 +02:00
|
|
|
pc::eval_packed(local_values, next_values, yield_constr);
|
|
|
|
|
push0::eval_packed(local_values, next_values, yield_constr);
|
2022-12-02 22:47:07 -08:00
|
|
|
shift::eval_packed(local_values, yield_constr);
|
2023-08-28 16:32:04 -04:00
|
|
|
simple_logic::eval_packed(local_values, next_values, yield_constr);
|
|
|
|
|
stack::eval_packed(local_values, next_values, yield_constr);
|
2023-07-21 10:55:09 +01:00
|
|
|
syscalls_exceptions::eval_packed(local_values, next_values, yield_constr);
|
2022-05-18 09:22:58 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-30 14:28:24 -04:00
|
|
|
/// Circuit version of `eval_packed_generic`.
|
|
|
|
|
/// Evaluates all CPU constraints.
|
2022-05-18 09:22:58 +02:00
|
|
|
fn eval_ext_circuit(
|
|
|
|
|
&self,
|
2022-06-03 19:24:47 -07:00
|
|
|
builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder<F, D>,
|
2023-09-22 09:19:13 -04:00
|
|
|
vars: &Self::EvaluationFrameTarget,
|
2022-12-02 22:47:07 -08:00
|
|
|
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
|
2022-05-18 09:22:58 +02:00
|
|
|
) {
|
2023-09-22 10:14:47 -04:00
|
|
|
let local_values: &[ExtensionTarget<D>; NUM_CPU_COLUMNS] =
|
|
|
|
|
vars.get_local_values().try_into().unwrap();
|
2023-09-22 09:19:13 -04:00
|
|
|
let local_values: &CpuColumnsView<ExtensionTarget<D>> = local_values.borrow();
|
2023-09-22 10:14:47 -04:00
|
|
|
let next_values: &[ExtensionTarget<D>; NUM_CPU_COLUMNS] =
|
|
|
|
|
vars.get_next_values().try_into().unwrap();
|
2023-09-22 09:19:13 -04:00
|
|
|
let next_values: &CpuColumnsView<ExtensionTarget<D>> = next_values.borrow();
|
|
|
|
|
|
2023-11-13 11:03:50 -05:00
|
|
|
byte_unpacking::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2023-11-09 16:42:18 -05:00
|
|
|
clock::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2022-12-11 10:59:14 -08:00
|
|
|
contextops::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2022-12-02 22:47:07 -08:00
|
|
|
control_flow::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2023-04-07 17:06:57 -04:00
|
|
|
decode::eval_ext_circuit(builder, local_values, yield_constr);
|
2023-10-11 22:28:49 +02:00
|
|
|
dup_swap::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2023-02-14 22:30:19 -08:00
|
|
|
gas::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2023-09-15 17:46:58 -04:00
|
|
|
halt::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2022-12-11 11:08:33 -08:00
|
|
|
jumps::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2022-12-02 22:47:07 -08:00
|
|
|
membus::eval_ext_circuit(builder, local_values, yield_constr);
|
2023-09-15 00:51:02 +01:00
|
|
|
memio::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2022-12-02 22:47:07 -08:00
|
|
|
modfp254::eval_ext_circuit(builder, local_values, yield_constr);
|
2023-10-11 22:28:49 +02:00
|
|
|
pc::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
|
|
|
|
push0::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2022-12-02 22:47:07 -08:00
|
|
|
shift::eval_ext_circuit(builder, local_values, yield_constr);
|
2023-08-28 16:32:04 -04:00
|
|
|
simple_logic::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
|
|
|
|
stack::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2023-07-21 10:55:09 +01:00
|
|
|
syscalls_exceptions::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
2022-05-18 09:22:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn constraint_degree(&self) -> usize {
|
|
|
|
|
3
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-19 11:10:10 +02:00
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use anyhow::Result;
|
|
|
|
|
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
|
|
|
|
|
|
|
|
|
use crate::cpu::cpu_stark::CpuStark;
|
|
|
|
|
use crate::stark_testing::{test_stark_circuit_constraints, test_stark_low_degree};
|
|
|
|
|
|
|
|
|
|
#[test]
|
2022-05-20 08:34:25 +02:00
|
|
|
fn test_stark_degree() -> Result<()> {
|
2022-05-19 11:10:10 +02:00
|
|
|
const D: usize = 2;
|
|
|
|
|
type C = PoseidonGoldilocksConfig;
|
|
|
|
|
type F = <C as GenericConfig<D>>::F;
|
|
|
|
|
type S = CpuStark<F, D>;
|
|
|
|
|
|
|
|
|
|
let stark = S {
|
|
|
|
|
f: Default::default(),
|
|
|
|
|
};
|
2022-05-20 08:34:25 +02:00
|
|
|
test_stark_low_degree(stark)
|
2022-05-19 11:10:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_stark_circuit() -> Result<()> {
|
|
|
|
|
const D: usize = 2;
|
|
|
|
|
type C = PoseidonGoldilocksConfig;
|
|
|
|
|
type F = <C as GenericConfig<D>>::F;
|
|
|
|
|
type S = CpuStark<F, D>;
|
|
|
|
|
|
|
|
|
|
let stark = S {
|
|
|
|
|
f: Default::default(),
|
|
|
|
|
};
|
|
|
|
|
test_stark_circuit_constraints::<F, C, S, D>(stark)
|
|
|
|
|
}
|
|
|
|
|
}
|