zkhash/poseidon2/
poseidon2_params.rs1use ark_ff::PrimeField;
2
3use crate::utils;
4
5#[derive(Clone, Debug)]
6pub struct Poseidon2Params<F: PrimeField> {
7 pub(crate) t: usize, pub(crate) d: usize, pub(crate) rounds_f_div_2: usize, 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 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
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}