lambdaworks_crypto/hash/poseidon/
parameters.rs

1use alloc::vec::Vec;
2use lambdaworks_math::field::{element::FieldElement as FE, traits::IsPrimeField};
3
4/// Parameters for Poseidon
5/// MDS constants and rounds constants are stored as references to slices
6/// representing matrices of `N_MDS_MATRIX_ROWS * N_MDS_MATRIX_COLS` and
7/// `N_ROUND_CONSTANTS_ROWS * N_ROUND_CONSTANTS_COLS` respectively.
8/// We use this representation rather than an array because we can't use the
9/// associated constants for dimension, requiring many generic parameters
10/// otherwise.
11pub trait PermutationParameters {
12    type F: IsPrimeField + 'static;
13
14    const RATE: usize;
15    const CAPACITY: usize;
16    const ALPHA: u32;
17    const N_FULL_ROUNDS: usize;
18    const N_PARTIAL_ROUNDS: usize;
19    const STATE_SIZE: usize = Self::RATE + Self::CAPACITY;
20
21    const MDS_MATRIX: &'static [FE<Self::F>];
22    const N_MDS_MATRIX_ROWS: usize;
23    const N_MDS_MATRIX_COLS: usize;
24
25    const ROUND_CONSTANTS: &'static [FE<Self::F>];
26    const N_ROUND_CONSTANTS_ROWS: usize;
27    const N_ROUND_CONSTANTS_COLS: usize;
28
29    /// This is the mix function that operates with the MDS matrix
30    /// Round Constants are sometimes picked to simplify this function,
31    /// so it can be redefined by each set of permutation parameters if a simplification can be made to make it faster. Notice in that case, MDS constants may not be used.
32    fn mix(state: &mut [FE<Self::F>]) {
33        let mut new_state: Vec<FE<Self::F>> = Vec::with_capacity(Self::STATE_SIZE);
34        for i in 0..Self::STATE_SIZE {
35            let mut new_e = FE::zero();
36            for (j, current_state) in state.iter().enumerate() {
37                let mut mij = Self::MDS_MATRIX[i * Self::N_MDS_MATRIX_COLS + j].clone();
38                mij *= current_state;
39                new_e += mij;
40            }
41            new_state.push(new_e);
42        }
43        state.clone_from_slice(&new_state[0..Self::STATE_SIZE]);
44    }
45}