openvm_keccak256_circuit/
columns.rs1use core::mem::size_of;
2
3use openvm_circuit::system::memory::offline_checker::{MemoryReadAuxCols, MemoryWriteAuxCols};
4use openvm_circuit_primitives::utils::assert_array_eq;
5use openvm_circuit_primitives_derive::AlignedBorrow;
6use openvm_instructions::riscv::RV32_REGISTER_NUM_LIMBS;
7use openvm_stark_backend::p3_air::AirBuilder;
8use p3_keccak_air::KeccakCols as KeccakPermCols;
9
10use super::{
11 KECCAK_ABSORB_READS, KECCAK_DIGEST_WRITES, KECCAK_RATE_BYTES, KECCAK_RATE_U16S,
12 KECCAK_REGISTER_READS, KECCAK_WORD_SIZE,
13};
14
15#[repr(C)]
16#[derive(Debug, AlignedBorrow)]
17pub struct KeccakVmCols<T> {
18 pub inner: KeccakPermCols<T>,
20 pub sponge: KeccakSpongeCols<T>,
22 pub instruction: KeccakInstructionCols<T>,
24 pub mem_oc: KeccakMemoryCols<T>,
26}
27
28#[allow(clippy::too_many_arguments)]
31#[repr(C)]
32#[derive(Copy, Clone, Debug, Default, AlignedBorrow, derive_new::new)]
33pub struct KeccakInstructionCols<T> {
34 pub pc: T,
36 pub is_enabled: T,
39 pub is_enabled_first_round: T,
42 pub start_timestamp: T,
45 pub dst_ptr: T,
47 pub src_ptr: T,
49 pub len_ptr: T,
51 pub dst: [T; RV32_REGISTER_NUM_LIMBS],
54 pub src_limbs: [T; RV32_REGISTER_NUM_LIMBS - 1],
59 pub src: T,
60 pub len_limbs: [T; RV32_REGISTER_NUM_LIMBS - 1],
65 pub remaining_len: T,
68}
69
70#[repr(C)]
71#[derive(Clone, Copy, Debug, AlignedBorrow)]
72pub struct KeccakSpongeCols<T> {
73 pub is_new_start: T,
77
78 pub is_padding_byte: [T; KECCAK_RATE_BYTES],
82
83 pub block_bytes: [T; KECCAK_RATE_BYTES],
86
87 pub state_hi: [T; KECCAK_RATE_U16S],
92}
93
94#[repr(C)]
95#[derive(Clone, Debug, AlignedBorrow)]
96pub struct KeccakMemoryCols<T> {
97 pub register_aux: [MemoryReadAuxCols<T>; KECCAK_REGISTER_READS],
98 pub absorb_reads: [MemoryReadAuxCols<T>; KECCAK_ABSORB_READS],
99 pub digest_writes: [MemoryWriteAuxCols<T, KECCAK_WORD_SIZE>; KECCAK_DIGEST_WRITES],
100 pub partial_block: [T; KECCAK_WORD_SIZE - 1],
107}
108
109impl<T: Copy> KeccakVmCols<T> {
110 pub const fn remaining_len(&self) -> T {
111 self.instruction.remaining_len
112 }
113
114 pub const fn is_new_start(&self) -> T {
115 self.sponge.is_new_start
116 }
117
118 pub fn postimage(&self, y: usize, x: usize, limb: usize) -> T {
119 self.inner.a_prime_prime_prime(y, x, limb)
120 }
121
122 pub fn is_first_round(&self) -> T {
123 *self.inner.step_flags.first().unwrap()
124 }
125
126 pub fn is_last_round(&self) -> T {
127 *self.inner.step_flags.last().unwrap()
128 }
129}
130
131impl<T: Copy> KeccakInstructionCols<T> {
132 pub fn assert_eq<AB: AirBuilder>(&self, builder: &mut AB, other: Self)
133 where
134 T: Into<AB::Expr>,
135 {
136 builder.assert_eq(self.pc, other.pc);
137 builder.assert_eq(self.is_enabled, other.is_enabled);
138 builder.assert_eq(self.start_timestamp, other.start_timestamp);
139 builder.assert_eq(self.dst_ptr, other.dst_ptr);
140 builder.assert_eq(self.src_ptr, other.src_ptr);
141 builder.assert_eq(self.len_ptr, other.len_ptr);
142 assert_array_eq(builder, self.dst, other.dst);
143 assert_array_eq(builder, self.src_limbs, other.src_limbs);
144 builder.assert_eq(self.src, other.src);
145 assert_array_eq(builder, self.len_limbs, other.len_limbs);
146 builder.assert_eq(self.remaining_len, other.remaining_len);
147 }
148}
149
150pub const NUM_KECCAK_VM_COLS: usize = size_of::<KeccakVmCols<u8>>();
151pub const NUM_KECCAK_INSTRUCTION_COLS: usize = size_of::<KeccakInstructionCols<u8>>();
152pub const NUM_KECCAK_SPONGE_COLS: usize = size_of::<KeccakSpongeCols<u8>>();
153pub const NUM_KECCAK_MEMORY_COLS: usize = size_of::<KeccakMemoryCols<u8>>();