ivc/poseidon_55_0_7_3_7/columns.rs
1//! The column layout will be as follow, supposing a state size of 3 elements:
2//! ```text
3//! | C1 | C2 | C3 | C4 | C5 | C6 | ... | C_(k) | C_(k + 1) | C_(k + 2) |
4//! |--- |----|----|-----|-----|-----|-----|-------|-----------|-----------|
5//! | x | y | z | x' | y' | z' | ... | x'' | y'' | z'' |
6//! | MDS \circ SBOX | | MDS \circ SBOX |
7//! |-----------------| |-------------------------------|
8//! ```
9//!
10//! where (x', y', z') = MDS(x^7, y^7, z^7), i.e. the result of the linear layer
11//!
12//! We will have, for N full rounds:
13//! - `3` input columns
14//! - `N * 3` round columns, indexed by the round number and the index in the state,
15//! the number of rounds.
16//!
17//! The round constants are added as fixed selectors.
18
19use kimchi_msm::columns::{Column, ColumnIndexer};
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
22pub enum PoseidonColumn<const STATE_SIZE: usize, const NB_FULL_ROUND: usize> {
23 Input(usize),
24 Round(usize, usize),
25 RoundConstant(usize, usize),
26}
27
28impl<const STATE_SIZE: usize, const NB_FULL_ROUND: usize> ColumnIndexer<usize>
29 for PoseidonColumn<STATE_SIZE, NB_FULL_ROUND>
30{
31 const N_COL: usize = STATE_SIZE + NB_FULL_ROUND * STATE_SIZE;
32
33 fn to_column(self) -> Column<usize> {
34 match self {
35 PoseidonColumn::Input(i) => {
36 assert!(i < STATE_SIZE);
37 Column::Relation(i)
38 }
39 PoseidonColumn::Round(round, state_index) => {
40 assert!(state_index < STATE_SIZE);
41 // We start round 0
42 assert!(round < NB_FULL_ROUND);
43 let idx = STATE_SIZE + (round * STATE_SIZE + state_index);
44 Column::Relation(idx)
45 }
46 PoseidonColumn::RoundConstant(round, state_index) => {
47 assert!(state_index < STATE_SIZE);
48 // We start round 0
49 assert!(round < NB_FULL_ROUND);
50 let idx = round * STATE_SIZE + state_index;
51 Column::FixedSelector(idx)
52 }
53 }
54 }
55}