2022-06-27 07:18:21 -07:00
|
|
|
use plonky2::field::extension::Extendable;
|
2022-06-27 12:24:09 -07:00
|
|
|
use plonky2::field::types::Field;
|
2022-05-06 17:22:30 +02:00
|
|
|
use plonky2::hash::hash_types::RichField;
|
|
|
|
|
|
2022-05-13 10:48:56 +02:00
|
|
|
use crate::config::StarkConfig;
|
2022-06-27 10:40:16 -07:00
|
|
|
use crate::cpu::cpu_stark;
|
2022-05-18 09:22:58 +02:00
|
|
|
use crate::cpu::cpu_stark::CpuStark;
|
2022-06-27 10:40:16 -07:00
|
|
|
use crate::cross_table_lookup::{CrossTableLookup, TableWithColumns};
|
|
|
|
|
use crate::keccak::keccak_stark;
|
2022-05-18 09:22:58 +02:00
|
|
|
use crate::keccak::keccak_stark::KeccakStark;
|
2022-06-27 10:40:16 -07:00
|
|
|
use crate::logic;
|
2022-06-17 11:57:14 -07:00
|
|
|
use crate::logic::LogicStark;
|
2022-06-23 13:59:57 -07:00
|
|
|
use crate::memory::memory_stark::MemoryStark;
|
2022-06-27 16:03:56 -07:00
|
|
|
use crate::memory::{memory_stark, NUM_CHANNELS};
|
2022-05-06 17:22:30 +02:00
|
|
|
use crate::stark::Stark;
|
|
|
|
|
|
2022-05-12 20:38:11 +02:00
|
|
|
#[derive(Clone)]
|
2022-05-06 17:35:25 +02:00
|
|
|
pub struct AllStark<F: RichField + Extendable<D>, const D: usize> {
|
2022-05-11 14:35:33 +02:00
|
|
|
pub cpu_stark: CpuStark<F, D>,
|
|
|
|
|
pub keccak_stark: KeccakStark<F, D>,
|
2022-06-17 11:57:14 -07:00
|
|
|
pub logic_stark: LogicStark<F, D>,
|
2022-06-23 13:59:57 -07:00
|
|
|
pub memory_stark: MemoryStark<F, D>,
|
2022-05-17 09:24:22 +02:00
|
|
|
pub cross_table_lookups: Vec<CrossTableLookup<F>>,
|
2022-05-06 17:22:30 +02:00
|
|
|
}
|
|
|
|
|
|
2022-07-04 18:10:03 -07:00
|
|
|
impl<F: RichField + Extendable<D>, const D: usize> Default for AllStark<F, D> {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
cpu_stark: CpuStark::default(),
|
|
|
|
|
keccak_stark: KeccakStark::default(),
|
|
|
|
|
logic_stark: LogicStark::default(),
|
|
|
|
|
memory_stark: MemoryStark::default(),
|
|
|
|
|
cross_table_lookups: all_cross_table_lookups(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-13 10:48:56 +02:00
|
|
|
impl<F: RichField + Extendable<D>, const D: usize> AllStark<F, D> {
|
|
|
|
|
pub(crate) fn nums_permutation_zs(&self, config: &StarkConfig) -> Vec<usize> {
|
2022-05-19 09:41:15 +02:00
|
|
|
let ans = vec![
|
2022-05-13 10:48:56 +02:00
|
|
|
self.cpu_stark.num_permutation_batches(config),
|
|
|
|
|
self.keccak_stark.num_permutation_batches(config),
|
2022-06-17 11:57:14 -07:00
|
|
|
self.logic_stark.num_permutation_batches(config),
|
2022-06-17 16:38:31 -07:00
|
|
|
self.memory_stark.num_permutation_batches(config),
|
2022-05-19 09:41:15 +02:00
|
|
|
];
|
|
|
|
|
debug_assert_eq!(ans.len(), Table::num_tables());
|
|
|
|
|
ans
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn permutation_batch_sizes(&self) -> Vec<usize> {
|
|
|
|
|
let ans = vec![
|
|
|
|
|
self.cpu_stark.permutation_batch_size(),
|
|
|
|
|
self.keccak_stark.permutation_batch_size(),
|
2022-06-17 11:57:14 -07:00
|
|
|
self.logic_stark.permutation_batch_size(),
|
2022-06-17 16:38:31 -07:00
|
|
|
self.memory_stark.permutation_batch_size(),
|
2022-05-19 09:41:15 +02:00
|
|
|
];
|
|
|
|
|
debug_assert_eq!(ans.len(), Table::num_tables());
|
|
|
|
|
ans
|
2022-05-13 10:48:56 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-11 11:07:16 +02:00
|
|
|
#[derive(Debug, Copy, Clone)]
|
2022-05-06 17:22:30 +02:00
|
|
|
pub enum Table {
|
|
|
|
|
Cpu = 0,
|
|
|
|
|
Keccak = 1,
|
2022-06-17 11:57:14 -07:00
|
|
|
Logic = 2,
|
2022-06-23 13:59:57 -07:00
|
|
|
Memory = 3,
|
2022-05-06 17:22:30 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-19 09:41:15 +02:00
|
|
|
impl Table {
|
|
|
|
|
pub(crate) fn num_tables() -> usize {
|
2022-06-23 13:59:57 -07:00
|
|
|
Table::Memory as usize + 1
|
2022-05-19 09:41:15 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-27 10:40:16 -07:00
|
|
|
#[allow(unused)] // TODO: Should be used soon.
|
|
|
|
|
pub(crate) fn all_cross_table_lookups<F: Field>() -> Vec<CrossTableLookup<F>> {
|
2022-08-23 17:24:35 -07:00
|
|
|
vec![ctl_keccak(), ctl_logic(), ctl_memory()]
|
2022-06-27 10:40:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn ctl_keccak<F: Field>() -> CrossTableLookup<F> {
|
|
|
|
|
CrossTableLookup::new(
|
|
|
|
|
vec![TableWithColumns::new(
|
|
|
|
|
Table::Cpu,
|
|
|
|
|
cpu_stark::ctl_data_keccak(),
|
|
|
|
|
Some(cpu_stark::ctl_filter_keccak()),
|
|
|
|
|
)],
|
|
|
|
|
TableWithColumns::new(
|
|
|
|
|
Table::Keccak,
|
|
|
|
|
keccak_stark::ctl_data(),
|
|
|
|
|
Some(keccak_stark::ctl_filter()),
|
|
|
|
|
),
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn ctl_logic<F: Field>() -> CrossTableLookup<F> {
|
|
|
|
|
CrossTableLookup::new(
|
|
|
|
|
vec![TableWithColumns::new(
|
|
|
|
|
Table::Cpu,
|
|
|
|
|
cpu_stark::ctl_data_logic(),
|
|
|
|
|
Some(cpu_stark::ctl_filter_logic()),
|
|
|
|
|
)],
|
|
|
|
|
TableWithColumns::new(Table::Logic, logic::ctl_data(), Some(logic::ctl_filter())),
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-23 17:24:35 -07:00
|
|
|
fn ctl_memory<F: Field>() -> CrossTableLookup<F> {
|
2022-06-27 10:40:16 -07:00
|
|
|
CrossTableLookup::new(
|
2022-08-23 17:24:35 -07:00
|
|
|
(0..NUM_CHANNELS)
|
|
|
|
|
.map(|channel| {
|
|
|
|
|
TableWithColumns::new(
|
|
|
|
|
Table::Cpu,
|
|
|
|
|
cpu_stark::ctl_data_memory(channel),
|
|
|
|
|
Some(cpu_stark::ctl_filter_memory(channel)),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
2022-06-27 10:40:16 -07:00
|
|
|
TableWithColumns::new(
|
|
|
|
|
Table::Memory,
|
|
|
|
|
memory_stark::ctl_data(),
|
2022-08-23 17:24:35 -07:00
|
|
|
Some(memory_stark::ctl_filter()),
|
2022-06-27 10:40:16 -07:00
|
|
|
),
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-12 20:38:11 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
2022-06-29 16:23:44 -07:00
|
|
|
use std::borrow::BorrowMut;
|
|
|
|
|
|
2022-05-12 20:38:11 +02:00
|
|
|
use anyhow::Result;
|
2022-06-15 09:33:52 -07:00
|
|
|
use ethereum_types::U256;
|
2022-07-18 11:50:58 -07:00
|
|
|
use itertools::Itertools;
|
2022-06-17 11:57:14 -07:00
|
|
|
use plonky2::field::polynomial::PolynomialValues;
|
2022-07-07 09:27:50 -07:00
|
|
|
use plonky2::field::types::{Field, PrimeField64};
|
2022-05-24 17:50:28 +02:00
|
|
|
use plonky2::iop::witness::PartialWitness;
|
|
|
|
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
|
|
|
|
use plonky2::plonk::circuit_data::CircuitConfig;
|
2022-05-12 20:38:11 +02:00
|
|
|
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
|
|
|
|
use plonky2::util::timing::TimingTree;
|
2022-06-10 21:02:56 +02:00
|
|
|
use rand::{thread_rng, Rng};
|
2022-05-12 20:38:11 +02:00
|
|
|
|
2022-07-04 18:10:03 -07:00
|
|
|
use crate::all_stark::AllStark;
|
2022-05-12 20:38:11 +02:00
|
|
|
use crate::config::StarkConfig;
|
2022-06-27 10:40:16 -07:00
|
|
|
use crate::cpu::cpu_stark::CpuStark;
|
2022-07-28 04:36:33 +10:00
|
|
|
use crate::cpu::kernel::aggregator::KERNEL;
|
2022-07-11 11:07:16 +02:00
|
|
|
use crate::cross_table_lookup::testutils::check_ctls;
|
2022-06-27 10:40:16 -07:00
|
|
|
use crate::keccak::keccak_stark::{KeccakStark, NUM_INPUTS, NUM_ROUNDS};
|
2022-06-15 09:33:52 -07:00
|
|
|
use crate::logic::{self, LogicStark, Operation};
|
2022-07-16 09:59:23 -07:00
|
|
|
use crate::memory::memory_stark::tests::generate_random_memory_ops;
|
|
|
|
|
use crate::memory::memory_stark::MemoryStark;
|
2022-06-27 16:03:56 -07:00
|
|
|
use crate::memory::NUM_CHANNELS;
|
2022-05-24 17:50:28 +02:00
|
|
|
use crate::proof::AllProof;
|
2022-05-12 20:38:11 +02:00
|
|
|
use crate::prover::prove;
|
2022-05-24 17:50:28 +02:00
|
|
|
use crate::recursive_verifier::{
|
|
|
|
|
add_virtual_all_proof, set_all_proof_target, verify_proof_circuit,
|
|
|
|
|
};
|
2022-06-03 19:24:47 -07:00
|
|
|
use crate::stark::Stark;
|
2022-06-25 13:34:04 -07:00
|
|
|
use crate::util::{limb_from_bits_le, trace_rows_to_poly_values};
|
2022-05-12 20:38:11 +02:00
|
|
|
use crate::verifier::verify_proof;
|
2022-06-17 16:51:32 -07:00
|
|
|
use crate::{cpu, keccak, memory};
|
2022-05-12 20:38:11 +02:00
|
|
|
|
2022-05-24 17:50:28 +02:00
|
|
|
const D: usize = 2;
|
|
|
|
|
type C = PoseidonGoldilocksConfig;
|
|
|
|
|
type F = <C as GenericConfig<D>>::F;
|
2022-05-12 20:38:11 +02:00
|
|
|
|
2022-06-17 11:57:14 -07:00
|
|
|
fn make_keccak_trace<R: Rng>(
|
|
|
|
|
num_keccak_perms: usize,
|
|
|
|
|
keccak_stark: &KeccakStark<F, D>,
|
|
|
|
|
rng: &mut R,
|
|
|
|
|
) -> Vec<PolynomialValues<F>> {
|
2022-06-13 18:54:12 +02:00
|
|
|
let keccak_inputs = (0..num_keccak_perms)
|
2022-06-10 19:30:51 +02:00
|
|
|
.map(|_| [0u64; NUM_INPUTS].map(|_| rng.gen()))
|
2022-06-06 10:31:42 -07:00
|
|
|
.collect_vec();
|
2022-06-17 11:57:14 -07:00
|
|
|
keccak_stark.generate_trace(keccak_inputs)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_logic_trace<R: Rng>(
|
|
|
|
|
num_rows: usize,
|
|
|
|
|
logic_stark: &LogicStark<F, D>,
|
|
|
|
|
rng: &mut R,
|
|
|
|
|
) -> Vec<PolynomialValues<F>> {
|
2022-07-12 14:33:10 -07:00
|
|
|
let all_ops = [logic::Op::And, logic::Op::Or, logic::Op::Xor];
|
2022-06-15 09:33:52 -07:00
|
|
|
let ops = (0..num_rows)
|
|
|
|
|
.map(|_| {
|
2022-07-12 14:33:10 -07:00
|
|
|
let op = all_ops[rng.gen_range(0..all_ops.len())];
|
2022-06-15 09:33:52 -07:00
|
|
|
let input0 = U256(rng.gen());
|
|
|
|
|
let input1 = U256(rng.gen());
|
2022-07-12 14:33:10 -07:00
|
|
|
Operation::new(op, input0, input1)
|
2022-06-15 09:33:52 -07:00
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
logic_stark.generate_trace(ops)
|
2022-06-17 11:57:14 -07:00
|
|
|
}
|
2022-06-17 17:06:32 -07:00
|
|
|
|
2022-06-17 17:06:19 -07:00
|
|
|
fn make_memory_trace<R: Rng>(
|
|
|
|
|
num_memory_ops: usize,
|
|
|
|
|
memory_stark: &MemoryStark<F, D>,
|
|
|
|
|
rng: &mut R,
|
2022-07-07 09:28:34 -07:00
|
|
|
) -> (Vec<PolynomialValues<F>>, usize) {
|
2022-06-17 17:06:19 -07:00
|
|
|
let memory_ops = generate_random_memory_ops(num_memory_ops, rng);
|
2022-07-08 12:19:11 -07:00
|
|
|
let trace = memory_stark.generate_trace(memory_ops);
|
|
|
|
|
let num_ops = trace[0].values.len();
|
|
|
|
|
(trace, num_ops)
|
2022-06-17 17:06:19 -07:00
|
|
|
}
|
2022-06-17 11:57:14 -07:00
|
|
|
|
|
|
|
|
fn make_cpu_trace(
|
|
|
|
|
num_keccak_perms: usize,
|
|
|
|
|
num_logic_rows: usize,
|
2022-06-17 17:06:19 -07:00
|
|
|
num_memory_ops: usize,
|
2022-06-17 11:57:14 -07:00
|
|
|
cpu_stark: &CpuStark<F, D>,
|
|
|
|
|
keccak_trace: &[PolynomialValues<F>],
|
|
|
|
|
logic_trace: &[PolynomialValues<F>],
|
2022-06-17 17:06:19 -07:00
|
|
|
memory_trace: &mut [PolynomialValues<F>],
|
2022-06-17 11:57:14 -07:00
|
|
|
) -> Vec<PolynomialValues<F>> {
|
2022-06-13 18:54:12 +02:00
|
|
|
let keccak_input_limbs: Vec<[F; 2 * NUM_INPUTS]> = (0..num_keccak_perms)
|
2022-06-10 21:02:56 +02:00
|
|
|
.map(|i| {
|
|
|
|
|
(0..2 * NUM_INPUTS)
|
|
|
|
|
.map(|j| {
|
2022-08-23 12:22:54 -07:00
|
|
|
keccak::columns::reg_input_limb(j)
|
|
|
|
|
.eval_table(keccak_trace, (i + 1) * NUM_ROUNDS - 1)
|
2022-06-10 21:02:56 +02:00
|
|
|
})
|
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
|
.try_into()
|
|
|
|
|
.unwrap()
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
2022-06-13 18:54:12 +02:00
|
|
|
let keccak_output_limbs: Vec<[F; 2 * NUM_INPUTS]> = (0..num_keccak_perms)
|
2022-06-10 21:02:56 +02:00
|
|
|
.map(|i| {
|
|
|
|
|
(0..2 * NUM_INPUTS)
|
|
|
|
|
.map(|j| {
|
2022-08-23 12:22:54 -07:00
|
|
|
keccak_trace[keccak::columns::reg_output_limb(j)].values
|
|
|
|
|
[(i + 1) * NUM_ROUNDS - 1]
|
2022-06-10 21:02:56 +02:00
|
|
|
})
|
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
|
.try_into()
|
|
|
|
|
.unwrap()
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
2022-06-06 10:31:42 -07:00
|
|
|
|
2022-06-29 16:23:44 -07:00
|
|
|
let mut cpu_trace_rows: Vec<[F; CpuStark::<F, D>::COLUMNS]> = vec![];
|
2022-06-29 17:34:38 -07:00
|
|
|
let mut bootstrap_row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
bootstrap_row.is_bootstrap_kernel = F::ONE;
|
|
|
|
|
cpu_trace_rows.push(bootstrap_row.into());
|
|
|
|
|
|
2022-06-13 18:54:12 +02:00
|
|
|
for i in 0..num_keccak_perms {
|
2022-06-29 16:23:44 -07:00
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
row.is_keccak = F::ONE;
|
2022-07-18 11:50:58 -07:00
|
|
|
let keccak = row.general.keccak_mut();
|
|
|
|
|
for j in 0..2 * NUM_INPUTS {
|
|
|
|
|
keccak.input_limbs[j] = keccak_input_limbs[i][j];
|
|
|
|
|
keccak.output_limbs[j] = keccak_output_limbs[i][j];
|
2022-06-17 11:57:14 -07:00
|
|
|
}
|
2022-06-29 16:23:44 -07:00
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
2022-06-17 11:57:14 -07:00
|
|
|
}
|
2022-06-29 16:23:44 -07:00
|
|
|
|
2022-06-17 11:57:14 -07:00
|
|
|
for i in 0..num_logic_rows {
|
2022-06-29 16:23:44 -07:00
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
row.is_cpu_cycle = F::ONE;
|
2022-08-16 09:46:10 -07:00
|
|
|
row.is_kernel_mode = F::ONE;
|
2022-08-17 12:20:23 -07:00
|
|
|
// Since these are the first cycle rows, we must start with PC=route_txn then increment.
|
|
|
|
|
row.program_counter = F::from_canonical_usize(KERNEL.global_labels["route_txn"] + i);
|
2022-06-29 16:23:44 -07:00
|
|
|
row.opcode = [
|
2022-06-29 10:02:03 +02:00
|
|
|
(logic::columns::IS_AND, 0x16),
|
|
|
|
|
(logic::columns::IS_OR, 0x17),
|
|
|
|
|
(logic::columns::IS_XOR, 0x18),
|
2022-06-17 11:57:14 -07:00
|
|
|
]
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|(col, opcode)| logic_trace[col].values[i] * F::from_canonical_u64(opcode))
|
|
|
|
|
.sum();
|
2022-07-18 11:50:58 -07:00
|
|
|
let logic = row.general.logic_mut();
|
|
|
|
|
|
|
|
|
|
let input0_bit_cols = logic::columns::limb_bit_cols_for_input(logic::columns::INPUT0);
|
|
|
|
|
for (col_cpu, limb_cols_logic) in logic.input0.iter_mut().zip(input0_bit_cols) {
|
|
|
|
|
*col_cpu = limb_from_bits_le(limb_cols_logic.map(|col| logic_trace[col].values[i]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input1_bit_cols = logic::columns::limb_bit_cols_for_input(logic::columns::INPUT1);
|
|
|
|
|
for (col_cpu, limb_cols_logic) in logic.input1.iter_mut().zip(input1_bit_cols) {
|
|
|
|
|
*col_cpu = limb_from_bits_le(limb_cols_logic.map(|col| logic_trace[col].values[i]));
|
2022-06-10 21:02:56 +02:00
|
|
|
}
|
2022-07-18 11:50:58 -07:00
|
|
|
|
|
|
|
|
for (col_cpu, col_logic) in logic.output.iter_mut().zip(logic::columns::RESULT) {
|
2022-06-29 16:23:44 -07:00
|
|
|
*col_cpu = logic_trace[col_logic].values[i];
|
2022-06-25 13:34:04 -07:00
|
|
|
}
|
2022-07-18 11:50:58 -07:00
|
|
|
|
2022-06-29 16:23:44 -07:00
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
2022-06-10 21:02:56 +02:00
|
|
|
}
|
2022-06-23 13:59:57 -07:00
|
|
|
for i in 0..num_memory_ops {
|
2022-07-07 09:52:38 -07:00
|
|
|
let mem_timestamp: usize = memory_trace[memory::columns::TIMESTAMP].values[i]
|
|
|
|
|
.to_canonical_u64()
|
|
|
|
|
.try_into()
|
|
|
|
|
.unwrap();
|
2022-07-07 09:28:07 -07:00
|
|
|
let clock = mem_timestamp / NUM_CHANNELS;
|
|
|
|
|
let channel = mem_timestamp % NUM_CHANNELS;
|
2022-06-23 13:59:57 -07:00
|
|
|
|
2022-08-23 17:24:35 -07:00
|
|
|
let filter = memory_trace[memory::columns::FILTER].values[i];
|
|
|
|
|
assert!(filter.is_one() || filter.is_zero());
|
|
|
|
|
let is_actual_op = filter.is_one();
|
2022-07-07 09:27:50 -07:00
|
|
|
|
2022-08-23 17:24:35 -07:00
|
|
|
if is_actual_op {
|
2022-07-07 16:27:11 -07:00
|
|
|
let row: &mut cpu::columns::CpuColumnsView<F> = cpu_trace_rows[clock].borrow_mut();
|
|
|
|
|
|
|
|
|
|
row.mem_channel_used[channel] = F::ONE;
|
|
|
|
|
row.clock = F::from_canonical_usize(clock);
|
|
|
|
|
row.mem_is_read[channel] = memory_trace[memory::columns::IS_READ].values[i];
|
|
|
|
|
row.mem_addr_context[channel] =
|
|
|
|
|
memory_trace[memory::columns::ADDR_CONTEXT].values[i];
|
|
|
|
|
row.mem_addr_segment[channel] =
|
|
|
|
|
memory_trace[memory::columns::ADDR_SEGMENT].values[i];
|
|
|
|
|
row.mem_addr_virtual[channel] =
|
|
|
|
|
memory_trace[memory::columns::ADDR_VIRTUAL].values[i];
|
|
|
|
|
for j in 0..8 {
|
|
|
|
|
row.mem_value[channel][j] =
|
|
|
|
|
memory_trace[memory::columns::value_limb(j)].values[i];
|
|
|
|
|
}
|
2022-06-23 13:59:57 -07:00
|
|
|
}
|
|
|
|
|
}
|
2022-06-29 17:34:38 -07:00
|
|
|
|
2022-08-16 09:46:10 -07:00
|
|
|
// Trap to kernel
|
|
|
|
|
{
|
|
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
let last_row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
cpu_trace_rows[cpu_trace_rows.len() - 1].into();
|
|
|
|
|
row.is_cpu_cycle = F::ONE;
|
|
|
|
|
row.opcode = F::from_canonical_u8(0x0a); // `EXP` is implemented in software
|
|
|
|
|
row.is_kernel_mode = F::ONE;
|
|
|
|
|
row.program_counter = last_row.program_counter + F::ONE;
|
|
|
|
|
row.general.syscalls_mut().output = [
|
|
|
|
|
row.program_counter,
|
|
|
|
|
F::ONE,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `EXIT_KERNEL` (to kernel)
|
|
|
|
|
{
|
|
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
row.is_cpu_cycle = F::ONE;
|
|
|
|
|
row.opcode = F::from_canonical_u8(0xf9);
|
|
|
|
|
row.is_kernel_mode = F::ONE;
|
|
|
|
|
row.program_counter = F::from_canonical_usize(KERNEL.global_labels["sys_exp"]);
|
|
|
|
|
row.general.jumps_mut().input0 = [
|
|
|
|
|
F::from_canonical_u16(15682),
|
|
|
|
|
F::ONE,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `JUMP` (in kernel mode)
|
|
|
|
|
{
|
|
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
row.is_cpu_cycle = F::ONE;
|
|
|
|
|
row.opcode = F::from_canonical_u8(0x56);
|
|
|
|
|
row.is_kernel_mode = F::ONE;
|
|
|
|
|
row.program_counter = F::from_canonical_u16(15682);
|
|
|
|
|
row.general.jumps_mut().input0 = [
|
|
|
|
|
F::from_canonical_u16(15106),
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
row.general.jumps_mut().input1 = [
|
|
|
|
|
F::ONE,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
row.general.jumps_mut().input0_upper_zero = F::ONE;
|
|
|
|
|
row.general.jumps_mut().dst_valid_or_kernel = F::ONE;
|
|
|
|
|
row.general.jumps_mut().input0_jumpable = F::ONE;
|
|
|
|
|
row.general.jumps_mut().input1_sum_inv = F::ONE;
|
|
|
|
|
row.general.jumps_mut().should_jump = F::ONE;
|
|
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `EXIT_KERNEL` (to userspace)
|
|
|
|
|
{
|
|
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
row.is_cpu_cycle = F::ONE;
|
|
|
|
|
row.opcode = F::from_canonical_u8(0xf9);
|
|
|
|
|
row.is_kernel_mode = F::ONE;
|
|
|
|
|
row.program_counter = F::from_canonical_u16(15106);
|
|
|
|
|
row.general.jumps_mut().input0 = [
|
|
|
|
|
F::from_canonical_u16(63064),
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `JUMP` (taken)
|
|
|
|
|
{
|
|
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
row.is_cpu_cycle = F::ONE;
|
|
|
|
|
row.opcode = F::from_canonical_u8(0x56);
|
|
|
|
|
row.is_kernel_mode = F::ZERO;
|
|
|
|
|
row.program_counter = F::from_canonical_u16(63064);
|
|
|
|
|
row.general.jumps_mut().input0 = [
|
|
|
|
|
F::from_canonical_u16(3754),
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
row.general.jumps_mut().input1 = [
|
|
|
|
|
F::ONE,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
row.general.jumps_mut().input0_upper_zero = F::ONE;
|
|
|
|
|
row.general.jumps_mut().dst_valid = F::ONE;
|
|
|
|
|
row.general.jumps_mut().dst_valid_or_kernel = F::ONE;
|
|
|
|
|
row.general.jumps_mut().input0_jumpable = F::ONE;
|
|
|
|
|
row.general.jumps_mut().input1_sum_inv = F::ONE;
|
|
|
|
|
row.general.jumps_mut().should_jump = F::ONE;
|
|
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `JUMPI` (taken)
|
|
|
|
|
{
|
|
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
row.is_cpu_cycle = F::ONE;
|
|
|
|
|
row.opcode = F::from_canonical_u8(0x57);
|
|
|
|
|
row.is_kernel_mode = F::ZERO;
|
|
|
|
|
row.program_counter = F::from_canonical_u16(3754);
|
|
|
|
|
row.general.jumps_mut().input0 = [
|
|
|
|
|
F::from_canonical_u16(37543),
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
row.general.jumps_mut().input1 = [
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ONE,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
row.general.jumps_mut().input0_upper_zero = F::ONE;
|
|
|
|
|
row.general.jumps_mut().dst_valid = F::ONE;
|
|
|
|
|
row.general.jumps_mut().dst_valid_or_kernel = F::ONE;
|
|
|
|
|
row.general.jumps_mut().input0_jumpable = F::ONE;
|
|
|
|
|
row.general.jumps_mut().input1_sum_inv = F::ONE;
|
|
|
|
|
row.general.jumps_mut().should_jump = F::ONE;
|
|
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `JUMPI` (not taken)
|
|
|
|
|
{
|
|
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
row.is_cpu_cycle = F::ONE;
|
|
|
|
|
row.opcode = F::from_canonical_u8(0x57);
|
|
|
|
|
row.is_kernel_mode = F::ZERO;
|
|
|
|
|
row.program_counter = F::from_canonical_u16(37543);
|
|
|
|
|
row.general.jumps_mut().input0 = [
|
|
|
|
|
F::from_canonical_u16(37543),
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ONE,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
row.general.jumps_mut().input0_upper_sum_inv = F::ONE;
|
|
|
|
|
row.general.jumps_mut().dst_valid = F::ONE;
|
|
|
|
|
row.general.jumps_mut().dst_valid_or_kernel = F::ONE;
|
|
|
|
|
row.general.jumps_mut().input0_jumpable = F::ZERO;
|
|
|
|
|
row.general.jumps_mut().should_continue = F::ONE;
|
|
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `JUMP` (trapping)
|
|
|
|
|
{
|
|
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
|
|
|
|
let last_row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
cpu_trace_rows[cpu_trace_rows.len() - 1].into();
|
|
|
|
|
row.is_cpu_cycle = F::ONE;
|
|
|
|
|
row.opcode = F::from_canonical_u8(0x56);
|
|
|
|
|
row.is_kernel_mode = F::ZERO;
|
|
|
|
|
row.program_counter = last_row.program_counter + F::ONE;
|
|
|
|
|
row.general.jumps_mut().input0 = [
|
|
|
|
|
F::from_canonical_u16(37543),
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ONE,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
row.general.jumps_mut().input1 = [
|
|
|
|
|
F::ONE,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
F::ZERO,
|
|
|
|
|
];
|
|
|
|
|
row.general.jumps_mut().input0_upper_sum_inv = F::ONE;
|
|
|
|
|
row.general.jumps_mut().dst_valid = F::ONE;
|
|
|
|
|
row.general.jumps_mut().dst_valid_or_kernel = F::ONE;
|
|
|
|
|
row.general.jumps_mut().input0_jumpable = F::ZERO;
|
|
|
|
|
row.general.jumps_mut().input1_sum_inv = F::ONE;
|
|
|
|
|
row.general.jumps_mut().should_trap = F::ONE;
|
|
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-29 17:34:38 -07:00
|
|
|
// Pad to a power of two.
|
2022-07-28 17:30:20 -07:00
|
|
|
for i in 0..cpu_trace_rows.len().next_power_of_two() - cpu_trace_rows.len() {
|
2022-07-28 04:36:33 +10:00
|
|
|
let mut row: cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
[F::ZERO; CpuStark::<F, D>::COLUMNS].into();
|
2022-08-16 09:46:10 -07:00
|
|
|
row.opcode = F::from_canonical_u8(0xff);
|
2022-07-28 04:36:33 +10:00
|
|
|
row.is_cpu_cycle = F::ONE;
|
2022-08-16 09:46:10 -07:00
|
|
|
row.is_kernel_mode = F::ONE;
|
|
|
|
|
row.program_counter =
|
|
|
|
|
F::from_canonical_usize(KERNEL.global_labels["fault_exception"] + i);
|
2022-07-28 04:36:33 +10:00
|
|
|
cpu_stark.generate(row.borrow_mut());
|
|
|
|
|
cpu_trace_rows.push(row.into());
|
2022-06-29 17:34:38 -07:00
|
|
|
}
|
2022-07-28 04:36:33 +10:00
|
|
|
|
|
|
|
|
// Ensure we finish in a halted state.
|
|
|
|
|
{
|
|
|
|
|
let num_rows = cpu_trace_rows.len();
|
|
|
|
|
let halt_label = F::from_canonical_usize(KERNEL.global_labels["halt_pc0"]);
|
|
|
|
|
|
|
|
|
|
let last_row: &mut cpu::columns::CpuColumnsView<F> =
|
|
|
|
|
cpu_trace_rows[num_rows - 1].borrow_mut();
|
|
|
|
|
last_row.program_counter = halt_label;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 11:57:14 -07:00
|
|
|
trace_rows_to_poly_values(cpu_trace_rows)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_proof(config: &StarkConfig) -> Result<(AllStark<F, D>, AllProof<F, C, D>)> {
|
2022-07-04 18:10:03 -07:00
|
|
|
let all_stark = AllStark::default();
|
2022-06-17 11:57:14 -07:00
|
|
|
|
|
|
|
|
let num_logic_rows = 62;
|
2022-06-23 13:59:57 -07:00
|
|
|
let num_memory_ops = 1 << 5;
|
|
|
|
|
|
2022-06-17 11:57:14 -07:00
|
|
|
let mut rng = thread_rng();
|
|
|
|
|
let num_keccak_perms = 2;
|
|
|
|
|
|
2022-07-04 18:10:03 -07:00
|
|
|
let keccak_trace = make_keccak_trace(num_keccak_perms, &all_stark.keccak_stark, &mut rng);
|
|
|
|
|
let logic_trace = make_logic_trace(num_logic_rows, &all_stark.logic_stark, &mut rng);
|
2022-07-11 17:37:17 -07:00
|
|
|
let mem_trace = make_memory_trace(num_memory_ops, &all_stark.memory_stark, &mut rng);
|
2022-07-07 09:28:34 -07:00
|
|
|
let mut memory_trace = mem_trace.0;
|
|
|
|
|
let num_memory_ops = mem_trace.1;
|
2022-06-17 11:57:14 -07:00
|
|
|
let cpu_trace = make_cpu_trace(
|
|
|
|
|
num_keccak_perms,
|
|
|
|
|
num_logic_rows,
|
2022-06-23 13:59:57 -07:00
|
|
|
num_memory_ops,
|
2022-07-04 18:10:03 -07:00
|
|
|
&all_stark.cpu_stark,
|
2022-06-17 11:57:14 -07:00
|
|
|
&keccak_trace,
|
|
|
|
|
&logic_trace,
|
2022-06-17 17:06:19 -07:00
|
|
|
&mut memory_trace,
|
2022-06-17 11:57:14 -07:00
|
|
|
);
|
2022-06-06 10:31:42 -07:00
|
|
|
|
2022-07-11 11:07:16 +02:00
|
|
|
let traces = vec![cpu_trace, keccak_trace, logic_trace, memory_trace];
|
|
|
|
|
check_ctls(&traces, &all_stark.cross_table_lookups);
|
|
|
|
|
|
2022-05-12 20:38:11 +02:00
|
|
|
let proof = prove::<F, C, D>(
|
|
|
|
|
&all_stark,
|
2022-05-26 20:44:59 +02:00
|
|
|
config,
|
2022-07-11 11:07:16 +02:00
|
|
|
traces,
|
2022-06-17 17:06:19 -07:00
|
|
|
vec![vec![]; 4],
|
2022-05-12 20:38:11 +02:00
|
|
|
&mut TimingTree::default(),
|
|
|
|
|
)?;
|
|
|
|
|
|
2022-05-24 17:50:28 +02:00
|
|
|
Ok((all_stark, proof))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_all_stark() -> Result<()> {
|
|
|
|
|
let config = StarkConfig::standard_fast_config();
|
|
|
|
|
let (all_stark, proof) = get_proof(&config)?;
|
2022-05-12 20:38:11 +02:00
|
|
|
verify_proof(all_stark, proof, &config)
|
2022-05-06 17:22:30 +02:00
|
|
|
}
|
2022-05-24 17:50:28 +02:00
|
|
|
|
|
|
|
|
#[test]
|
2022-05-26 16:27:15 +02:00
|
|
|
fn test_all_stark_recursive_verifier() -> Result<()> {
|
2022-05-24 17:50:28 +02:00
|
|
|
init_logger();
|
|
|
|
|
|
|
|
|
|
let config = StarkConfig::standard_fast_config();
|
|
|
|
|
let (all_stark, proof) = get_proof(&config)?;
|
|
|
|
|
verify_proof(all_stark.clone(), proof.clone(), &config)?;
|
|
|
|
|
|
|
|
|
|
recursive_proof(all_stark, proof, &config, true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn recursive_proof(
|
|
|
|
|
inner_all_stark: AllStark<F, D>,
|
|
|
|
|
inner_proof: AllProof<F, C, D>,
|
|
|
|
|
inner_config: &StarkConfig,
|
|
|
|
|
print_gate_counts: bool,
|
|
|
|
|
) -> Result<()> {
|
|
|
|
|
let circuit_config = CircuitConfig::standard_recursion_config();
|
|
|
|
|
let mut builder = CircuitBuilder::<F, D>::new(circuit_config);
|
|
|
|
|
let mut pw = PartialWitness::new();
|
2022-05-26 16:27:15 +02:00
|
|
|
let degree_bits = inner_proof.degree_bits(inner_config);
|
|
|
|
|
let nums_ctl_zs = inner_proof.nums_ctl_zs();
|
|
|
|
|
let pt = add_virtual_all_proof(
|
|
|
|
|
&mut builder,
|
|
|
|
|
&inner_all_stark,
|
|
|
|
|
inner_config,
|
|
|
|
|
°ree_bits,
|
|
|
|
|
&nums_ctl_zs,
|
|
|
|
|
);
|
2022-05-24 17:50:28 +02:00
|
|
|
set_all_proof_target(&mut pw, &pt, &inner_proof, builder.zero());
|
|
|
|
|
|
|
|
|
|
verify_proof_circuit::<F, C, D>(&mut builder, inner_all_stark, pt, inner_config);
|
|
|
|
|
|
|
|
|
|
if print_gate_counts {
|
|
|
|
|
builder.print_gate_counts(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let data = builder.build::<C>();
|
|
|
|
|
let proof = data.prove(pw)?;
|
|
|
|
|
data.verify(proof)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn init_logger() {
|
|
|
|
|
let _ = env_logger::builder().format_timestamp(None).try_init();
|
|
|
|
|
}
|
2022-05-06 17:22:30 +02:00
|
|
|
}
|