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, // statesize
8    pub(crate) d: usize, // sbox degree
9    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>>, // external matrix
16    pub(crate) mu: Vec<S>,       // diagonal of internal matrix
17    pub(crate) abc: [S; 3],      // alpha, beta, gamma
18    #[allow(dead_code)]
19    pub(crate) a_: [S; 3], // alpha^2, 3*alpha, 4*alpha
20}
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 mut shake = Self::init_shake();
34        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        // precomputations for more efficient neptune implementation
40        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 init_shake() -> XofReaderCoreWrapper<Shake128ReaderCore> {
63    //     let mut shake = Shake128::default();
64    //     shake.update(Self::INIT_SHAKE.as_bytes());
65    //     for i in S::char().as_ref() {
66    //         shake.update(&u64::to_le_bytes(*i));
67    //     }
68    //     shake.finalize_xof()
69    // }
70
71    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        // TODO adapt for real instantiation :)
89        (0..t)
90            .map(|_| {
91                let mut tmp = utils::random_scalar_without_0::<S>();
92                tmp.sub_assign(&S::one()); // For faster impl
93                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>>; // M' matrix
103        let m__: Vec<Vec<S>>; // M'' matrix
104
105        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            // TODO adapt for real instantiation :)
123            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        // M' matrix
140        for row in 0..t_ {
141            for col in 0..t_ {
142                mat[2 * row][2 * col] = m_[row][col];
143            }
144        }
145
146        // M'' matrix
147        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}