plonky2/evm/src/cpu/columns.rs
wborgeaud 54629a0ef9 Merge branch 'main' into sha3_interpreter_ecrecover
# Conflicts:
#	evm/src/cpu/kernel/interpreter.rs
#	evm/src/cpu/kernel/tests/ecrecover.rs
2022-07-19 15:24:28 +02:00

246 lines
6.9 KiB
Rust

// TODO: remove when possible.
#![allow(dead_code)]
use std::borrow::{Borrow, BorrowMut};
use std::mem::{size_of, transmute, transmute_copy, ManuallyDrop};
use std::ops::{Index, IndexMut};
use crate::memory;
#[repr(C)]
#[derive(Eq, PartialEq, Debug)]
pub struct CpuColumnsView<T> {
/// Filter. 1 if the row is part of bootstrapping the kernel code, 0 otherwise.
pub is_bootstrap_kernel: T,
/// Filter. 1 if the row is part of bootstrapping a contract's code, 0 otherwise.
pub is_bootstrap_contract: T,
/// Filter. 1 if the row corresponds to a cycle of execution and 0 otherwise.
/// Lets us re-use decode columns in non-cycle rows.
pub is_cpu_cycle: T,
/// If CPU cycle: The opcode being decoded, in {0, ..., 255}.
pub opcode: T,
// If CPU cycle: flags for EVM instructions. PUSHn, DUPn, and SWAPn only get one flag each.
// Invalid opcodes are split between a number of flags for practical reasons. Exactly one of
// these flags must be 1.
pub is_stop: T,
pub is_add: T,
pub is_mul: T,
pub is_sub: T,
pub is_div: T,
pub is_sdiv: T,
pub is_mod: T,
pub is_smod: T,
pub is_addmod: T,
pub is_mulmod: T,
pub is_exp: T,
pub is_signextend: T,
pub is_lt: T,
pub is_gt: T,
pub is_slt: T,
pub is_sgt: T,
pub is_eq: T, // Note: This column must be 0 when is_cpu_cycle = 0.
pub is_iszero: T, // Note: This column must be 0 when is_cpu_cycle = 0.
pub is_and: T,
pub is_or: T,
pub is_xor: T,
pub is_not: T,
pub is_byte: T,
pub is_shl: T,
pub is_shr: T,
pub is_sar: T,
pub is_keccak256: T,
pub is_address: T,
pub is_balance: T,
pub is_origin: T,
pub is_caller: T,
pub is_callvalue: T,
pub is_calldataload: T,
pub is_calldatasize: T,
pub is_calldatacopy: T,
pub is_codesize: T,
pub is_codecopy: T,
pub is_gasprice: T,
pub is_extcodesize: T,
pub is_extcodecopy: T,
pub is_returndatasize: T,
pub is_returndatacopy: T,
pub is_extcodehash: T,
pub is_blockhash: T,
pub is_coinbase: T,
pub is_timestamp: T,
pub is_number: T,
pub is_difficulty: T,
pub is_gaslimit: T,
pub is_chainid: T,
pub is_selfbalance: T,
pub is_basefee: T,
pub is_pop: T,
pub is_mload: T,
pub is_mstore: T,
pub is_mstore8: T,
pub is_sload: T,
pub is_sstore: T,
pub is_jump: T,
pub is_jumpi: T,
pub is_pc: T,
pub is_msize: T,
pub is_gas: T,
pub is_jumpdest: T,
pub is_get_state_root: T,
pub is_set_state_root: T,
pub is_get_receipt_root: T,
pub is_set_receipt_root: T,
pub is_push: T,
pub is_dup: T,
pub is_swap: T,
pub is_log0: T,
pub is_log1: T,
pub is_log2: T,
pub is_log3: T,
pub is_log4: T,
pub is_panic: T,
pub is_create: T,
pub is_call: T,
pub is_callcode: T,
pub is_return: T,
pub is_delegatecall: T,
pub is_create2: T,
pub is_get_context: T,
pub is_set_context: T,
pub is_consume_gas: T,
pub is_exit_kernel: T,
pub is_staticcall: T,
pub is_mload_general: T,
pub is_mstore_general: T,
pub is_revert: T,
pub is_selfdestruct: T,
// An instruction is invalid if _any_ of the below flags is 1.
pub is_invalid_0: T,
pub is_invalid_1: T,
pub is_invalid_2: T,
pub is_invalid_3: T,
pub is_invalid_4: T,
pub is_invalid_5: T,
pub is_invalid_6: T,
pub is_invalid_7: T,
pub is_invalid_8: T,
pub is_invalid_9: T,
pub is_invalid_10: T,
pub is_invalid_11: T,
pub is_invalid_12: T,
pub is_invalid_13: T,
pub is_invalid_14: T,
/// If CPU cycle: the opcode, broken up into bits in **big-endian** order.
pub opcode_bits: [T; 8],
/// Filter. 1 iff a Keccak permutation is computed on this row.
pub is_keccak: T,
pub keccak_input_limbs: [T; 50],
pub keccak_output_limbs: [T; 50],
// Assuming a limb size of 16 bits. This can be changed, but it must be <= 28 bits.
// TODO: These input/output columns can be shared between the logic operations and others.
pub logic_input0: [T; 16],
pub logic_input1: [T; 16],
pub logic_output: [T; 16],
pub simple_logic_diff: T,
pub simple_logic_diff_inv: T,
pub(crate) clock: T,
/// 1 if this row includes a memory operation in the `i`th channel of the memory bus, otherwise
/// 0.
pub mem_channel_used: [T; memory::NUM_CHANNELS],
pub mem_is_read: [T; memory::NUM_CHANNELS],
pub mem_addr_context: [T; memory::NUM_CHANNELS],
pub mem_addr_segment: [T; memory::NUM_CHANNELS],
pub mem_addr_virtual: [T; memory::NUM_CHANNELS],
pub mem_value: [[T; memory::VALUE_LIMBS]; memory::NUM_CHANNELS],
}
// `u8` is guaranteed to have a `size_of` of 1.
pub const NUM_CPU_COLUMNS: usize = size_of::<CpuColumnsView<u8>>();
unsafe fn transmute_no_compile_time_size_checks<T, U>(value: T) -> U {
debug_assert_eq!(size_of::<T>(), size_of::<U>());
// Need ManuallyDrop so that `value` is not dropped by this function.
let value = ManuallyDrop::new(value);
// Copy the bit pattern. The original value is no longer safe to use.
transmute_copy(&value)
}
impl<T> From<[T; NUM_CPU_COLUMNS]> for CpuColumnsView<T> {
fn from(value: [T; NUM_CPU_COLUMNS]) -> Self {
unsafe { transmute_no_compile_time_size_checks(value) }
}
}
impl<T> From<CpuColumnsView<T>> for [T; NUM_CPU_COLUMNS] {
fn from(value: CpuColumnsView<T>) -> Self {
unsafe { transmute_no_compile_time_size_checks(value) }
}
}
impl<T> Borrow<CpuColumnsView<T>> for [T; NUM_CPU_COLUMNS] {
fn borrow(&self) -> &CpuColumnsView<T> {
unsafe { transmute(self) }
}
}
impl<T> BorrowMut<CpuColumnsView<T>> for [T; NUM_CPU_COLUMNS] {
fn borrow_mut(&mut self) -> &mut CpuColumnsView<T> {
unsafe { transmute(self) }
}
}
impl<T> Borrow<[T; NUM_CPU_COLUMNS]> for CpuColumnsView<T> {
fn borrow(&self) -> &[T; NUM_CPU_COLUMNS] {
unsafe { transmute(self) }
}
}
impl<T> BorrowMut<[T; NUM_CPU_COLUMNS]> for CpuColumnsView<T> {
fn borrow_mut(&mut self) -> &mut [T; NUM_CPU_COLUMNS] {
unsafe { transmute(self) }
}
}
impl<T, I> Index<I> for CpuColumnsView<T>
where
[T]: Index<I>,
{
type Output = <[T] as Index<I>>::Output;
fn index(&self, index: I) -> &Self::Output {
let arr: &[T; NUM_CPU_COLUMNS] = self.borrow();
<[T] as Index<I>>::index(arr, index)
}
}
impl<T, I> IndexMut<I> for CpuColumnsView<T>
where
[T]: IndexMut<I>,
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
let arr: &mut [T; NUM_CPU_COLUMNS] = self.borrow_mut();
<[T] as IndexMut<I>>::index_mut(arr, index)
}
}
const fn make_col_map() -> CpuColumnsView<usize> {
let mut indices_arr = [0; NUM_CPU_COLUMNS];
let mut i = 0;
while i < NUM_CPU_COLUMNS {
indices_arr[i] = i;
i += 1;
}
unsafe { transmute::<[usize; NUM_CPU_COLUMNS], CpuColumnsView<usize>>(indices_arr) }
}
pub const COL_MAP: CpuColumnsView<usize> = make_col_map();