zkhash/poseidon2/
poseidon2_params.rs

1use ark_ff::PrimeField;
2
3use crate::utils;
4
5#[derive(Clone, Debug)]
6pub struct Poseidon2Params<F: PrimeField> {
7    pub(crate) t: usize,              // statesize
8    pub(crate) d: usize,              // sbox degree
9    pub(crate) rounds_f_div_2: usize, // Full rounds divided by 2
10    pub(crate) rounds_p: usize,
11    pub(crate) rounds: usize,
12    pub(crate) mat_internal_diag_m_1: Vec<F>,
13    pub(crate) _mat_internal: Vec<Vec<F>>,
14    pub(crate) round_constants: Vec<Vec<F>>,
15}
16
17impl<F: PrimeField> Poseidon2Params<F> {
18    #[allow(clippy::too_many_arguments)]
19    pub const INIT_SHAKE: &'static str = "Poseidon2";
20
21    pub fn new(
22        t: usize,
23        d: usize,
24        rounds_f: usize,
25        rounds_p: usize,
26        mat_internal_diag_m_1: &[F],
27        mat_internal: &[Vec<F>],
28        round_constants: &[Vec<F>],
29    ) -> Self {
30        assert!(d == 3 || d == 5 || d == 7 || d == 11);
31        assert_eq!(rounds_f % 2, 0);
32        let r = rounds_f / 2;
33        let rounds = rounds_f + rounds_p;
34
35        Poseidon2Params {
36            t,
37            d,
38            rounds_f_div_2: r,
39            rounds_p,
40            rounds,
41            mat_internal_diag_m_1: mat_internal_diag_m_1.to_owned(),
42            _mat_internal: mat_internal.to_owned(),
43            round_constants: round_constants.to_owned(),
44        }
45    }
46
47    // Unused
48    pub fn equivalent_round_constants(
49        round_constants: &[Vec<F>],
50        mat_internal: &[Vec<F>],
51        rounds_f_beginning: usize,
52        rounds_p: usize,
53    ) -> Vec<Vec<F>> {
54        let mut opt = vec![Vec::new(); rounds_p + 1];
55        let mat_internal_inv = utils::mat_inverse(mat_internal);
56
57        let p_end = rounds_f_beginning + rounds_p - 1;
58        let mut tmp = round_constants[p_end].clone();
59        for i in (0..rounds_p - 1).rev() {
60            let inv_cip = Self::mat_vec_mul(&mat_internal_inv, &tmp);
61            opt[i + 1] = vec![inv_cip[0]];
62            tmp = round_constants[rounds_f_beginning + i].clone();
63            for i in 1..inv_cip.len() {
64                tmp[i].add_assign(&inv_cip[i]);
65            }
66        }
67        opt[0] = tmp;
68        opt[rounds_p] = vec![F::zero(); opt[0].len()]; // opt[0].len() = t
69
70        opt
71    }
72
73    pub fn mat_vec_mul(mat: &[Vec<F>], input: &[F]) -> Vec<F> {
74        let t = mat.len();
75        debug_assert!(t == input.len());
76        let mut out = vec![F::zero(); t];
77        for row in 0..t {
78            for (col, inp) in input.iter().enumerate() {
79                let mut tmp = mat[row][col];
80                tmp.mul_assign(inp);
81                out[row].add_assign(&tmp);
82            }
83        }
84        out
85    }
86}