zkhash/neptune/
neptune_params.rs
1use ark_ff::PrimeField;
2
3use crate::fields::utils;
4
5#[derive(Clone, Debug)]
6pub struct NeptuneParams<S: PrimeField> {
7 pub(crate) t: usize, pub(crate) d: usize, pub(crate) rounds_f_beginning: usize,
10 pub(crate) rounds_p: usize,
11 #[allow(dead_code)]
12 pub(crate) rounds_f_end: usize,
13 pub(crate) rounds: usize,
14 pub(crate) round_constants: Vec<Vec<S>>,
15 pub(crate) m_e: Vec<Vec<S>>, pub(crate) mu: Vec<S>, pub(crate) abc: [S; 3], #[allow(dead_code)]
19 pub(crate) a_: [S; 3], }
21
22impl<S: PrimeField> NeptuneParams<S> {
23 pub const INIT_SHAKE: &'static str = "Neptune";
24
25 pub fn new(t: usize, d: usize, rounds_f: usize, rounds_p: usize) -> Self {
26 assert!(d == 3 || d == 5 || d == 7);
27 assert_eq!(rounds_f % 2, 0);
28 assert_eq!(t % 2, 0);
29
30 let r = rounds_f / 2;
31 let rounds = rounds_f + rounds_p;
32
33 let round_constants = Self::instantiate_rc(t, rounds);
35 let m_e = Self::instantiate_external_matrix(t);
36 let mu = Self::instantiate_mu(t);
37 let abc = Self::instantiate_abc();
38
39 let mut a_ = [abc[0]; 3];
41 a_[0].square_in_place();
42 a_[1].double_in_place();
43 a_[2] = a_[1];
44 a_[1].add_assign(&abc[0]);
45 a_[2].double_in_place();
46
47 NeptuneParams {
48 t,
49 d,
50 rounds_f_beginning: r,
51 rounds_p,
52 rounds_f_end: r,
53 rounds,
54 round_constants,
55 m_e,
56 mu,
57 abc,
58 a_,
59 }
60 }
61
62 fn instantiate_rc(t: usize, rounds: usize) -> Vec<Vec<S>> {
72 (0..rounds)
73 .map(|_| {
74 (0..t)
75 .map(|_| utils::random_scalar())
76 .collect()
77 })
78 .collect()
79 }
80
81 fn instantiate_abc() -> [S; 3] {
82 let mut abc = [S::one(); 3];
83 abc[2] = utils::random_scalar();
84 abc
85 }
86
87 fn instantiate_mu(t: usize) -> Vec<S> {
88 (0..t)
90 .map(|_| {
91 let mut tmp = utils::random_scalar_without_0::<S>();
92 tmp.sub_assign(&S::one()); tmp
94 })
95 .collect()
96 }
97
98 fn instantiate_external_matrix(t: usize) -> Vec<Vec<S>> {
99 let t_ = t >> 1;
100 let mut mat = vec![vec![S::zero(); t]; t];
101
102 let m_: Vec<Vec<S>>; let m__: Vec<Vec<S>>; if t == 4 {
106 m_ = Self::circ_mat(&[S::from(2 as u64), S::one()]);
107 m__ = Self::circ_mat(&[S::one(), S::from(2 as u64)]);
108 } else if t == 8 {
109 m_ = Self::circ_mat(&[
110 S::from(3 as u64),
111 S::from(2 as u64),
112 S::from(1 as u64),
113 S::from(1 as u64),
114 ]);
115 m__ = Self::circ_mat(&[
116 S::from(1 as u64),
117 S::from(1 as u64),
118 S::from(2 as u64),
119 S::from(3 as u64),
120 ]);
121 } else {
122 m_ = (0..t_)
124 .map(|_| {
125 (0..t_)
126 .map(|_| utils::random_scalar())
127 .collect()
128 })
129 .collect();
130 m__ = (0..t_)
131 .map(|_| {
132 (0..t_)
133 .map(|_| utils::random_scalar())
134 .collect()
135 })
136 .collect();
137 }
138
139 for row in 0..t_ {
141 for col in 0..t_ {
142 mat[2 * row][2 * col] = m_[row][col];
143 }
144 }
145
146 for row in 0..t_ {
148 for col in 0..t_ {
149 mat[2 * row + 1][2 * col + 1] = m__[row][col];
150 }
151 }
152 mat
153 }
154
155 fn circ_mat(row: &[S]) -> Vec<Vec<S>> {
156 let t = row.len();
157 let mut mat: Vec<Vec<S>> = Vec::with_capacity(t);
158 let mut rot = row.to_owned();
159 mat.push(rot.clone());
160 for _ in 1..t {
161 rot.rotate_right(1);
162 mat.push(rot.clone());
163 }
164 mat
165 }
166}