mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 23:03:08 +00:00
generate_keccak_general, generate_byte
This commit is contained in:
parent
25205f319a
commit
d3aa33975a
@ -62,6 +62,18 @@ impl Kernel {
|
||||
padded_code.resize(padded_len, 0);
|
||||
padded_code
|
||||
}
|
||||
|
||||
/// Get a string representation of the current offset for debugging purposes.
|
||||
pub(crate) fn offset_name(&self, offset: usize) -> String {
|
||||
self.offset_label(offset)
|
||||
.unwrap_or_else(|| offset.to_string())
|
||||
}
|
||||
|
||||
pub(crate) fn offset_label(&self, offset: usize) -> Option<String> {
|
||||
self.global_labels
|
||||
.iter()
|
||||
.find_map(|(k, v)| (*v == offset).then(|| k.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
|
||||
|
||||
@ -355,18 +355,12 @@ impl<'a> Interpreter<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get a string representation of the current offset for debugging purposes.
|
||||
fn offset_name(&self) -> String {
|
||||
self.offset_label()
|
||||
.unwrap_or_else(|| self.offset.to_string())
|
||||
KERNEL.offset_name(self.offset)
|
||||
}
|
||||
|
||||
fn offset_label(&self) -> Option<String> {
|
||||
// TODO: Not sure we should use KERNEL? Interpreter is more general in other places.
|
||||
KERNEL
|
||||
.global_labels
|
||||
.iter()
|
||||
.find_map(|(k, v)| (*v == self.offset).then(|| k.clone()))
|
||||
KERNEL.offset_label(self.offset)
|
||||
}
|
||||
|
||||
fn run_stop(&mut self) {
|
||||
|
||||
@ -12,10 +12,10 @@ use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer
|
||||
use crate::cross_table_lookup::Column;
|
||||
use crate::keccak::keccak_stark::NUM_INPUTS;
|
||||
use crate::keccak_memory::columns::*;
|
||||
use crate::memory::segments::Segment;
|
||||
use crate::stark::Stark;
|
||||
use crate::util::trace_rows_to_poly_values;
|
||||
use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars};
|
||||
use crate::witness::memory::MemoryAddress;
|
||||
|
||||
pub(crate) fn ctl_looked_data<F: Field>() -> Vec<Column<F>> {
|
||||
Column::singles([COL_CONTEXT, COL_SEGMENT, COL_VIRTUAL, COL_READ_TIMESTAMP]).collect()
|
||||
@ -67,10 +67,8 @@ pub(crate) fn ctl_filter<F: Field>() -> Column<F> {
|
||||
/// Information about a Keccak memory operation needed for witness generation.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct KeccakMemoryOp {
|
||||
// The address at which we will read inputs and write outputs.
|
||||
pub(crate) context: usize,
|
||||
pub(crate) segment: Segment,
|
||||
pub(crate) virt: usize,
|
||||
/// The base address at which we will read inputs and write outputs.
|
||||
pub(crate) address: MemoryAddress,
|
||||
|
||||
/// The timestamp at which inputs should be read from memory.
|
||||
/// Outputs will be written at the following timestamp.
|
||||
@ -131,9 +129,9 @@ impl<F: RichField + Extendable<D>, const D: usize> KeccakMemoryStark<F, D> {
|
||||
fn generate_row_for_op(&self, op: KeccakMemoryOp) -> [F; NUM_COLUMNS] {
|
||||
let mut row = [F::ZERO; NUM_COLUMNS];
|
||||
row[COL_IS_REAL] = F::ONE;
|
||||
row[COL_CONTEXT] = F::from_canonical_usize(op.context);
|
||||
row[COL_SEGMENT] = F::from_canonical_usize(op.segment as usize);
|
||||
row[COL_VIRTUAL] = F::from_canonical_usize(op.virt);
|
||||
row[COL_CONTEXT] = F::from_canonical_usize(op.address.context);
|
||||
row[COL_SEGMENT] = F::from_canonical_usize(op.address.segment as usize);
|
||||
row[COL_VIRTUAL] = F::from_canonical_usize(op.address.virt);
|
||||
row[COL_READ_TIMESTAMP] = F::from_canonical_usize(op.read_timestamp);
|
||||
for i in 0..25 {
|
||||
let input_u64 = op.input[i];
|
||||
|
||||
@ -21,7 +21,7 @@ pub(crate) struct KeccakSpongeColumnsView<T: Copy> {
|
||||
/// in the block will be padding bytes; 0 otherwise.
|
||||
pub is_final_block: T,
|
||||
|
||||
// The address at which we will read the input block.
|
||||
// The base address at which we will read the input block.
|
||||
pub context: T,
|
||||
pub segment: T,
|
||||
pub virt: T,
|
||||
|
||||
@ -18,10 +18,10 @@ use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer
|
||||
use crate::cpu::kernel::keccak_util::keccakf_u32s;
|
||||
use crate::cross_table_lookup::Column;
|
||||
use crate::keccak_sponge::columns::*;
|
||||
use crate::memory::segments::Segment;
|
||||
use crate::stark::Stark;
|
||||
use crate::util::trace_rows_to_poly_values;
|
||||
use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars};
|
||||
use crate::witness::memory::MemoryAddress;
|
||||
|
||||
#[allow(unused)] // TODO: Should be used soon.
|
||||
pub(crate) fn ctl_looked_data<F: Field>() -> Vec<Column<F>> {
|
||||
@ -144,10 +144,8 @@ pub(crate) fn ctl_looking_memory_filter<F: Field>(i: usize) -> Column<F> {
|
||||
/// Information about a Keccak sponge operation needed for witness generation.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct KeccakSpongeOp {
|
||||
// The address at which inputs are read.
|
||||
pub(crate) context: usize,
|
||||
pub(crate) segment: Segment,
|
||||
pub(crate) virt: usize,
|
||||
/// The base address at which inputs are read.
|
||||
pub(crate) base_address: MemoryAddress,
|
||||
|
||||
/// The timestamp at which inputs are read.
|
||||
pub(crate) timestamp: usize,
|
||||
@ -295,9 +293,9 @@ impl<F: RichField + Extendable<D>, const D: usize> KeccakSpongeStark<F, D> {
|
||||
already_absorbed_bytes: usize,
|
||||
mut sponge_state: [u32; KECCAK_WIDTH_U32S],
|
||||
) {
|
||||
row.context = F::from_canonical_usize(op.context);
|
||||
row.segment = F::from_canonical_usize(op.segment as usize);
|
||||
row.virt = F::from_canonical_usize(op.virt);
|
||||
row.context = F::from_canonical_usize(op.base_address.context);
|
||||
row.segment = F::from_canonical_usize(op.base_address.segment as usize);
|
||||
row.virt = F::from_canonical_usize(op.base_address.virt);
|
||||
row.timestamp = F::from_canonical_usize(op.timestamp);
|
||||
row.len = F::from_canonical_usize(op.len);
|
||||
row.already_absorbed_bytes = F::from_canonical_usize(already_absorbed_bytes);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum ProgramError {
|
||||
OutOfGas,
|
||||
InvalidOpcode,
|
||||
|
||||
@ -13,6 +13,7 @@ pub enum MemoryChannel {
|
||||
use MemoryChannel::{Code, GeneralPurpose};
|
||||
|
||||
use crate::memory::segments::Segment;
|
||||
use crate::util::u256_saturating_cast_usize;
|
||||
|
||||
impl MemoryChannel {
|
||||
pub fn index(&self) -> usize {
|
||||
@ -41,6 +42,14 @@ impl MemoryAddress {
|
||||
virt,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new_u256s(context: U256, segment: U256, virt: U256) -> Self {
|
||||
Self {
|
||||
context: u256_saturating_cast_usize(context),
|
||||
segment: u256_saturating_cast_usize(segment),
|
||||
virt: u256_saturating_cast_usize(virt),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
|
||||
@ -7,6 +7,7 @@ use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::membus::NUM_GP_CHANNELS;
|
||||
use crate::cpu::simple_logic::eq_iszero::generate_pinv_diff;
|
||||
use crate::generation::state::GenerationState;
|
||||
use crate::keccak_sponge::keccak_sponge_stark::KeccakSpongeOp;
|
||||
use crate::memory::segments::Segment;
|
||||
use crate::util::u256_saturating_cast_usize;
|
||||
use crate::witness::errors::ProgramError;
|
||||
@ -100,6 +101,40 @@ pub(crate) fn generate_ternary_arithmetic_op<F: Field>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn generate_keccak_general<F: Field>(
|
||||
state: &mut GenerationState<F>,
|
||||
mut row: CpuColumnsView<F>,
|
||||
) -> Result<(), ProgramError> {
|
||||
let [(context, log_in0), (segment, log_in1), (base_virt, log_in2), (len, log_in3)] =
|
||||
stack_pop_with_log_and_fill::<4, _>(state, &mut row)?;
|
||||
let len = len.as_usize();
|
||||
|
||||
let mut base_address = MemoryAddress::new_u256s(context, segment, base_virt);
|
||||
let input = (0..len)
|
||||
.map(|i| {
|
||||
let address = MemoryAddress {
|
||||
virt: base_address.virt.saturating_add(i),
|
||||
..base_address
|
||||
};
|
||||
let val = state.memory.get(address);
|
||||
val.as_u32() as u8
|
||||
})
|
||||
.collect();
|
||||
|
||||
state.traces.push_keccak_sponge(KeccakSpongeOp {
|
||||
base_address,
|
||||
timestamp: state.traces.clock(),
|
||||
len,
|
||||
input,
|
||||
});
|
||||
state.traces.push_memory(log_in0);
|
||||
state.traces.push_memory(log_in1);
|
||||
state.traces.push_memory(log_in2);
|
||||
state.traces.push_memory(log_in3);
|
||||
state.traces.push_cpu(row);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn generate_prover_input<F: Field>(
|
||||
state: &mut GenerationState<F>,
|
||||
mut row: CpuColumnsView<F>,
|
||||
@ -285,6 +320,26 @@ pub(crate) fn generate_not<F: Field>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn generate_byte<F: Field>(
|
||||
state: &mut GenerationState<F>,
|
||||
mut row: CpuColumnsView<F>,
|
||||
) -> Result<(), ProgramError> {
|
||||
let [(i, log_in0), (x, log_in1)] = stack_pop_with_log_and_fill::<2, _>(state, &mut row)?;
|
||||
|
||||
let byte = if i < 32.into() {
|
||||
x.byte(i.as_usize())
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let log_out = stack_push_log_and_fill(state, &mut row, byte.into())?;
|
||||
|
||||
state.traces.push_memory(log_in0);
|
||||
state.traces.push_memory(log_in1);
|
||||
state.traces.push_memory(log_out);
|
||||
state.traces.push_cpu(row);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn generate_iszero<F: Field>(
|
||||
state: &mut GenerationState<F>,
|
||||
mut row: CpuColumnsView<F>,
|
||||
@ -395,17 +450,9 @@ pub(crate) fn generate_mload_general<F: Field>(
|
||||
let [(context, log_in0), (segment, log_in1), (virt, log_in2)] =
|
||||
stack_pop_with_log_and_fill::<3, _>(state, &mut row)?;
|
||||
|
||||
// If virt won't fit in a usize, don't try to convert it, just return 0.
|
||||
let val = if virt > usize::MAX.into() {
|
||||
U256::zero()
|
||||
} else {
|
||||
state.memory.get(MemoryAddress {
|
||||
context: context.as_usize(),
|
||||
segment: segment.as_usize(),
|
||||
virt: virt.as_usize(),
|
||||
})
|
||||
};
|
||||
|
||||
let val = state
|
||||
.memory
|
||||
.get(MemoryAddress::new_u256s(context, segment, virt));
|
||||
let log_out = stack_push_log_and_fill(state, &mut row, val)?;
|
||||
|
||||
state.traces.push_memory(log_in0);
|
||||
|
||||
@ -78,8 +78,12 @@ impl<T: Copy> Traces<T> {
|
||||
self.arithmetic.push(op);
|
||||
}
|
||||
|
||||
pub fn push_memory(&mut self, val: MemoryOp) {
|
||||
self.memory_ops.push(val);
|
||||
pub fn push_memory(&mut self, op: MemoryOp) {
|
||||
self.memory_ops.push(op);
|
||||
}
|
||||
|
||||
pub fn push_keccak_sponge(&mut self, op: KeccakSpongeOp) {
|
||||
self.keccak_sponge_ops.push(op);
|
||||
}
|
||||
|
||||
pub fn clock(&self) -> usize {
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
use itertools::Itertools;
|
||||
use plonky2::field::types::Field;
|
||||
|
||||
use crate::cpu::columns::CpuColumnsView;
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::generation::state::GenerationState;
|
||||
use crate::memory::segments::Segment;
|
||||
use crate::witness::errors::ProgramError;
|
||||
use crate::witness::memory::MemoryAddress;
|
||||
use crate::witness::operation::*;
|
||||
use crate::witness::state::RegistersState;
|
||||
use crate::witness::util::mem_read_code_with_log_and_fill;
|
||||
use crate::witness::util::{mem_read_code_with_log_and_fill, stack_peek};
|
||||
use crate::{arithmetic, logic};
|
||||
|
||||
fn read_code_memory<F: Field>(state: &mut GenerationState<F>, row: &mut CpuColumnsView<F>) -> u8 {
|
||||
@ -186,7 +188,7 @@ fn perform_op<F: Field>(
|
||||
Operation::Swap(n) => generate_swap(n, state, row)?,
|
||||
Operation::Iszero => generate_iszero(state, row)?,
|
||||
Operation::Not => generate_not(state, row)?,
|
||||
Operation::Byte => todo!(),
|
||||
Operation::Byte => generate_byte(state, row)?,
|
||||
Operation::Syscall(opcode) => generate_syscall(opcode, state, row)?,
|
||||
Operation::Eq => generate_eq(state, row)?,
|
||||
Operation::BinaryLogic(binary_logic_op) => {
|
||||
@ -194,7 +196,7 @@ fn perform_op<F: Field>(
|
||||
}
|
||||
Operation::BinaryArithmetic(op) => generate_binary_arithmetic_op(op, state, row)?,
|
||||
Operation::TernaryArithmetic(op) => generate_ternary_arithmetic_op(op, state, row)?,
|
||||
Operation::KeccakGeneral => todo!(),
|
||||
Operation::KeccakGeneral => generate_keccak_general(state, row)?,
|
||||
Operation::ProverInput => generate_prover_input(state, row)?,
|
||||
Operation::Pop => generate_pop(state, row)?,
|
||||
Operation::Jump => generate_jump(state, row)?,
|
||||
@ -226,7 +228,15 @@ fn try_perform_instruction<F: Field>(state: &mut GenerationState<F>) -> Result<(
|
||||
|
||||
let opcode = read_code_memory(state, &mut row);
|
||||
let op = decode(state.registers, opcode)?;
|
||||
log::trace!("Executing {:?} at {}", op, state.registers.program_counter);
|
||||
let pc = state.registers.program_counter;
|
||||
|
||||
log::trace!("Executing {:?} at {}", op, KERNEL.offset_name(pc));
|
||||
log::trace!(
|
||||
"Stack: {:?}",
|
||||
(0..state.registers.stack_len)
|
||||
.map(|i| stack_peek(state, i).unwrap())
|
||||
.collect_vec()
|
||||
);
|
||||
fill_op_flag(op, &mut row);
|
||||
|
||||
perform_op(state, op, row)
|
||||
@ -246,11 +256,11 @@ pub(crate) fn transition<F: Field>(state: &mut GenerationState<F>) {
|
||||
.memory
|
||||
.apply_ops(state.traces.mem_ops_since(checkpoint.traces));
|
||||
}
|
||||
Err(_) => {
|
||||
state.rollback(checkpoint);
|
||||
Err(e) => {
|
||||
if state.registers.is_kernel {
|
||||
panic!("exception in kernel mode");
|
||||
panic!("exception in kernel mode: {:?}", e);
|
||||
}
|
||||
state.rollback(checkpoint);
|
||||
handle_error(state)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user