1//! The Grain LFSR in self-shrinking mode, as used by Poseidon.
23use std::marker::PhantomData;
45use bitvec::prelude::*;
6use ff::{FromUniformBytes, PrimeField};
78const STATE: usize = 80;
910#[derive(Debug, Clone, Copy)]
11pub(super) enum FieldType {
12/// GF(2^n)
13#[allow(dead_code)]
14Binary,
15/// GF(p)
16PrimeOrder,
17}
1819impl FieldType {
20fn tag(&self) -> u8 {
21match self {
22 FieldType::Binary => 0,
23 FieldType::PrimeOrder => 1,
24 }
25 }
26}
2728#[derive(Debug, Clone, Copy)]
29pub(super) enum SboxType {
30/// x^alpha
31Pow,
32/// x^(-1)
33#[allow(dead_code)]
34Inv,
35}
3637impl SboxType {
38fn tag(&self) -> u8 {
39match self {
40 SboxType::Pow => 0,
41 SboxType::Inv => 1,
42 }
43 }
44}
4546pub(super) struct Grain<F> {
47 state: BitArr!(for 80, in u8, Msb0),
48 next_bit: usize,
49 _field: PhantomData<F>,
50}
5152impl<F: PrimeField> Grain<F> {
53pub(super) fn new(sbox: SboxType, t: u16, r_f: u16, r_p: u16) -> Self {
54// Initialize the LFSR state.
55let mut state = bitarr![u8, Msb0; 1; STATE];
56let mut set_bits = |offset: usize, len, value| {
57// Poseidon reference impl sets initial state bits in MSB order.
58for i in 0..len {
59*state.get_mut(offset + len - 1 - i).unwrap() = (value >> i) & 1 != 0;
60 }
61 };
62 set_bits(0, 2, FieldType::PrimeOrder.tag() as u16);
63 set_bits(2, 4, sbox.tag() as u16);
64 set_bits(6, 12, F::NUM_BITS as u16);
65 set_bits(18, 12, t);
66 set_bits(30, 10, r_f);
67 set_bits(40, 10, r_p);
6869let mut grain = Grain {
70 state,
71 next_bit: STATE,
72 _field: PhantomData,
73 };
7475// Discard the first 160 bits.
76for _ in 0..20 {
77 grain.load_next_8_bits();
78 grain.next_bit = STATE;
79 }
8081 grain
82 }
8384fn load_next_8_bits(&mut self) {
85let mut new_bits = 0u8;
86for i in 0..8 {
87 new_bits |= ((self.state[i + 62]
88 ^ self.state[i + 51]
89 ^ self.state[i + 38]
90 ^ self.state[i + 23]
91 ^ self.state[i + 13]
92 ^ self.state[i]) as u8)
93 << i;
94 }
95self.state.rotate_left(8);
96self.next_bit -= 8;
97for i in 0..8 {
98*self.state.get_mut(self.next_bit + i).unwrap() = (new_bits >> i) & 1 != 0;
99 }
100 }
101102fn get_next_bit(&mut self) -> bool {
103if self.next_bit == STATE {
104self.load_next_8_bits();
105 }
106let ret = self.state[self.next_bit];
107self.next_bit += 1;
108 ret
109 }
110111/// Returns the next field element from this Grain instantiation.
112pub(super) fn next_field_element(&mut self) -> F {
113// Loop until we get an element in the field.
114loop {
115let mut bytes = F::Repr::default();
116117// Poseidon reference impl interprets the bits as a repr in MSB order, because
118 // it's easy to do that in Python. Meanwhile, our field elements all use LSB
119 // order. There's little motivation to diverge from the reference impl; these
120 // are all constants, so we aren't introducing big-endianness into the rest of
121 // the circuit (assuming unkeyed Poseidon, but we probably wouldn't want to
122 // implement Grain inside a circuit, so we'd use a different round constant
123 // derivation function there).
124let view = bytes.as_mut();
125for (i, bit) in self.take(F::NUM_BITS as usize).enumerate() {
126// If we diverged from the reference impl and interpreted the bits in LSB
127 // order, we would remove this line.
128let i = F::NUM_BITS as usize - 1 - i;
129130 view[i / 8] |= if bit { 1 << (i % 8) } else { 0 };
131 }
132133if let Some(f) = F::from_repr_vartime(bytes) {
134break f;
135 }
136 }
137 }
138139/// Returns the next field element from this Grain instantiation, without using
140 /// rejection sampling.
141pub(super) fn next_field_element_without_rejection(&mut self) -> F
142where
143F: FromUniformBytes<64>,
144 {
145let mut bytes = [0u8; 64];
146147// Poseidon reference impl interprets the bits as a repr in MSB order, because
148 // it's easy to do that in Python. Additionally, it does not use rejection
149 // sampling in cases where the constants don't specifically need to be uniformly
150 // random for security. We do not provide APIs that take a field-element-sized
151 // array and reduce it modulo the field order, because those are unsafe APIs to
152 // offer generally (accidentally using them can lead to divergence in consensus
153 // systems due to not rejecting canonical forms).
154 //
155 // Given that we don't want to diverge from the reference implementation, we hack
156 // around this restriction by serializing the bits into a 64-byte array and then
157 // calling F::from_bytes_wide. PLEASE DO NOT COPY THIS INTO YOUR OWN CODE!
158let view = bytes.as_mut();
159for (i, bit) in self.take(F::NUM_BITS as usize).enumerate() {
160// If we diverged from the reference impl and interpreted the bits in LSB
161 // order, we would remove this line.
162let i = F::NUM_BITS as usize - 1 - i;
163164 view[i / 8] |= if bit { 1 << (i % 8) } else { 0 };
165 }
166167 F::from_uniform_bytes(&bytes)
168 }
169}
170171impl<F: PrimeField> Iterator for Grain<F> {
172type Item = bool;
173174fn next(&mut self) -> Option<Self::Item> {
175// Evaluate bits in pairs:
176 // - If the first bit is a 1, output the second bit.
177 // - If the first bit is a 0, discard the second bit.
178while !self.get_next_bit() {
179self.get_next_bit();
180 }
181Some(self.get_next_bit())
182 }
183}
184185#[cfg(test)]
186mod tests {
187use super::super::pasta::Fp;
188use super::{Grain, SboxType};
189190#[test]
191fn grain() {
192let mut grain = Grain::<Fp>::new(SboxType::Pow, 3, 8, 56);
193let _f = grain.next_field_element();
194 }
195}