11//! Keccak-f[1600] permutation chip.
22//!
3- //! A single wide table (2,638 columns) that proves Keccak-f[1600] permutations.
3+ //! A single wide table (3,139 columns) that proves Keccak-f[1600] permutations.
44//! Each permutation uses 24 rows (one per round). All intermediate values are
55//! stored as columns and verified via purely polynomial constraints — no lookups.
66//!
@@ -961,11 +961,17 @@ pub fn create_constraints(
961961/// - `EcallKeccak` receiver on the first row of each real permutation.
962962/// - 25 `Memw` reads on `first`, binding the preimage to memory at `timestamp`.
963963/// - 25 `Memw` writes on `export`, binding the final state to memory at `timestamp + 1`.
964+ /// - `IsByte` range checks on preimage bytes (on `first`) and output bytes (on `export`).
964965pub fn bus_interactions ( ) -> Vec < BusInteraction > {
965- let mut interactions = Vec :: with_capacity ( 51 ) ;
966+ // 1 EcallKeccak + 25 Memw reads + 25 Memw writes + 200 IsByte preimage + 200 IsByte output
967+ let mut interactions = Vec :: with_capacity ( 451 ) ;
966968 let syscall_lo = KECCAK_SYSCALL_NUMBER & 0xFFFF_FFFF ;
967969 let syscall_hi = KECCAK_SYSCALL_NUMBER >> 32 ;
968970
971+ // EcallKeccak receiver: binds (timestamp, syscall_number, state_addr) from the CPU.
972+ // Including state_addr provides a direct binding between the CPU's ECALL and the
973+ // keccak permutation's memory region, rather than relying solely on transitive
974+ // enforcement through the MEMW bus.
969975 interactions. push ( BusInteraction :: receiver (
970976 BusId :: EcallKeccak ,
971977 Multiplicity :: Column ( cols:: FIRST ) ,
@@ -980,9 +986,49 @@ pub fn bus_interactions() -> Vec<BusInteraction> {
980986 } ,
981987 BusValue :: constant( syscall_lo) ,
982988 BusValue :: constant( syscall_hi) ,
989+ BusValue :: Packed {
990+ start_column: cols:: STATE_ADDR_0 ,
991+ packing: Packing :: Direct ,
992+ } ,
993+ BusValue :: Packed {
994+ start_column: cols:: STATE_ADDR_1 ,
995+ packing: Packing :: Direct ,
996+ } ,
983997 ] ,
984998 ) ) ;
985999
1000+ // -------------------------------------------------------------------------
1001+ // IsByte range checks — defense in depth
1002+ // -------------------------------------------------------------------------
1003+ // Byte columns are already transitively range-checked through the MEMW bus
1004+ // (MEMW table enforces IsByte on its VALUE columns). These explicit checks
1005+ // ensure keccak byte columns remain sound even if MEMW range checks are
1006+ // refactored in the future.
1007+
1008+ // Preimage bytes: range-checked on `first` (where they enter the MEMW bus)
1009+ for i in 0 ..200 {
1010+ interactions. push ( BusInteraction :: sender (
1011+ BusId :: IsByte ,
1012+ Multiplicity :: Column ( cols:: FIRST ) ,
1013+ vec ! [ BusValue :: Packed {
1014+ start_column: cols:: PREIMAGE_BYTES + i,
1015+ packing: Packing :: Direct ,
1016+ } ] ,
1017+ ) ) ;
1018+ }
1019+
1020+ // Output bytes: range-checked on `export` (where they enter the MEMW bus)
1021+ for i in 0 ..200 {
1022+ interactions. push ( BusInteraction :: sender (
1023+ BusId :: IsByte ,
1024+ Multiplicity :: Column ( cols:: EXPORT ) ,
1025+ vec ! [ BusValue :: Packed {
1026+ start_column: cols:: OUTPUT_BYTES + i,
1027+ packing: Packing :: Direct ,
1028+ } ] ,
1029+ ) ) ;
1030+ }
1031+
9861032 for lane_idx in 0 ..25 {
9871033 let x = lane_idx % 5 ;
9881034 let y = lane_idx / 5 ;
0 commit comments