1use core::{array, iter};
2
3use itertools::Itertools;
4use std_shims::Vec;
5
6use super::Channel;
7use crate::core::fields::m31::{BaseField, P};
8use crate::core::fields::qm31::{SecureField, SECURE_EXTENSION_DEGREE};
9use crate::core::vcs::blake2_hash::{Blake2sHash, Blake2sHasherGeneric};
10
11pub const BLAKE_BYTES_PER_HASH: usize = 32;
12pub const FELTS_PER_HASH: usize = 8;
13
14pub type Blake2sChannel = Blake2sChannelGeneric<false>;
15pub type Blake2sM31Channel = Blake2sChannelGeneric<true>;
17
18#[derive(Default, Clone, Debug)]
20pub struct Blake2sChannelGeneric<const IS_M31_OUTPUT: bool> {
21 digest: Blake2sHash,
22 n_draws: u32,
23}
24
25impl<const IS_M31_OUTPUT: bool> Blake2sChannelGeneric<IS_M31_OUTPUT> {
26 pub const POW_PREFIX: u32 = 0x12345678;
27
28 pub const fn digest(&self) -> Blake2sHash {
29 self.digest
30 }
31 pub const fn update_digest(&mut self, new_digest: Blake2sHash) {
32 self.digest = new_digest;
33 self.n_draws = 0;
34 }
35 fn draw_base_felts(&mut self) -> [BaseField; FELTS_PER_HASH] {
37 loop {
40 let u32s: [u32; FELTS_PER_HASH] = self.draw_u32s().try_into().unwrap();
41
42 if u32s.iter().all(|x| *x < 2 * P) {
44 return u32s
45 .into_iter()
46 .map(|x| BaseField::reduce(x as u64))
47 .collect::<Vec<_>>()
48 .try_into()
49 .unwrap();
50 }
51 }
52 }
53}
54
55impl<const IS_M31_OUTPUT: bool> Channel for Blake2sChannelGeneric<IS_M31_OUTPUT> {
56 const BYTES_PER_HASH: usize = BLAKE_BYTES_PER_HASH;
57
58 fn mix_felts(&mut self, felts: &[SecureField]) {
59 let felts_bytes = felts
60 .iter()
61 .flat_map(|qm31| qm31.to_m31_array())
62 .flat_map(|m31| m31.0.to_le_bytes())
63 .collect_vec();
64 let mut hasher = Blake2sHasherGeneric::<IS_M31_OUTPUT>::new();
65 hasher.update(self.digest.as_ref());
66 hasher.update(&felts_bytes);
67
68 self.update_digest(hasher.finalize());
69 }
70
71 fn mix_u32s(&mut self, data: &[u32]) {
72 let mut hasher = Blake2sHasherGeneric::<IS_M31_OUTPUT>::new();
73 hasher.update(self.digest.as_ref());
74 for word in data {
75 hasher.update(&word.to_le_bytes());
76 }
77
78 self.update_digest(hasher.finalize());
79 }
80
81 fn mix_u64(&mut self, value: u64) {
82 self.mix_u32s(&[value as u32, (value >> 32) as u32])
83 }
84
85 fn draw_secure_felt(&mut self) -> SecureField {
86 let felts: [BaseField; FELTS_PER_HASH] = self.draw_base_felts();
87 SecureField::from_m31_array(felts[..SECURE_EXTENSION_DEGREE].try_into().unwrap())
88 }
89
90 fn draw_secure_felts(&mut self, n_felts: usize) -> Vec<SecureField> {
91 let mut felts = iter::from_fn(|| Some(self.draw_base_felts())).flatten();
92 let secure_felts = iter::from_fn(|| {
93 Some(SecureField::from_m31_array([
94 felts.next()?,
95 felts.next()?,
96 felts.next()?,
97 felts.next()?,
98 ]))
99 });
100 secure_felts.take(n_felts).collect()
101 }
102
103 fn draw_u32s(&mut self) -> Vec<u32> {
104 let mut hash_input = self.digest.as_ref().to_vec();
105
106 let counter_bytes = self.n_draws.to_le_bytes();
108 hash_input.extend_from_slice(&counter_bytes);
109
110 hash_input.push(0_u8);
113
114 self.n_draws += 1;
115 Blake2sHasherGeneric::<IS_M31_OUTPUT>::hash(&hash_input)
116 .0
117 .chunks_exact(4)
118 .map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap()))
119 .collect()
120 }
121
122 fn verify_pow_nonce(&self, n_bits: u32, nonce: u64) -> bool {
125 let digest = self.digest();
126 let mut hasher = Blake2sHasherGeneric::<IS_M31_OUTPUT>::default();
128 hasher.update(&Self::POW_PREFIX.to_le_bytes());
129 hasher.update(&[0_u8; 12]);
130 hasher.update(&digest.0[..]);
131 hasher.update(&n_bits.to_le_bytes());
132 let prefixed_digest = hasher.finalize();
133 let mut hasher = Blake2sHasherGeneric::<IS_M31_OUTPUT>::default();
135 hasher.update(prefixed_digest.as_ref());
136 hasher.update(&nonce.to_le_bytes());
137 let res = hasher.finalize();
138 let n_zeros = u128::from_le_bytes(array::from_fn(|i| res.0[i])).trailing_zeros();
139 n_zeros >= n_bits
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use itertools::Itertools;
146 use std_shims::BTreeSet;
147
148 use crate::core::channel::blake2s::Blake2sChannel;
149 use crate::core::channel::Channel;
150 use crate::core::fields::qm31::SecureField;
151 use crate::m31;
152
153 #[test]
154 fn test_channel_draws() {
155 let mut channel = Blake2sChannel::default();
156
157 assert_eq!(channel.n_draws, 0);
158
159 channel.draw_u32s();
160 assert_eq!(channel.n_draws, 1);
161
162 channel.draw_secure_felts(9);
163 assert_eq!(channel.n_draws, 6);
164 }
165
166 #[test]
167 fn test_draw_u32s() {
168 let mut channel = Blake2sChannel::default();
169
170 let first_random_words = channel.draw_u32s();
171
172 assert_ne!(first_random_words, channel.draw_u32s());
174 }
175
176 #[test]
177 pub fn test_draw_secure_felt() {
178 let mut channel = Blake2sChannel::default();
179
180 let first_random_felt = channel.draw_secure_felt();
181
182 assert_ne!(first_random_felt, channel.draw_secure_felt());
184 }
185
186 #[test]
187 pub fn test_draw_secure_felts() {
188 let mut channel = Blake2sChannel::default();
189
190 let mut random_felts = channel.draw_secure_felts(5);
191 random_felts.extend(channel.draw_secure_felts(4));
192
193 assert_eq!(
195 random_felts.len(),
196 random_felts.iter().collect::<BTreeSet<_>>().len()
197 );
198 }
199
200 #[test]
201 pub fn test_mix_felts() {
202 let mut channel = Blake2sChannel::default();
203 let initial_digest = channel.digest;
204 let felts = (0..2)
205 .map(|i| SecureField::from(m31!(i + 1923782)))
206 .collect_vec();
207
208 channel.mix_felts(felts.as_slice());
209
210 assert_ne!(initial_digest, channel.digest);
211 }
212
213 #[test]
214 pub fn test_mix_u64() {
215 let mut channel = Blake2sChannel::default();
216 channel.mix_u64(0x1111222233334444);
217 let digest_64 = channel.digest;
218
219 let mut channel = Blake2sChannel::default();
220 channel.mix_u32s(&[0x33334444, 0x11112222]);
221
222 assert_eq!(digest_64, channel.digest);
223 let digest_bytes: [u8; 32] = digest_64.into();
224 assert_eq!(
225 digest_bytes,
226 [
227 0xbc, 0x9e, 0x3f, 0xc1, 0xd2, 0x4e, 0x88, 0x97, 0x95, 0x6d, 0x33, 0x59, 0x32, 0x73,
228 0x97, 0x24, 0x9d, 0x6b, 0xca, 0xcd, 0x22, 0x4d, 0x92, 0x74, 0x4, 0xe7, 0xba, 0x4a,
229 0x77, 0xdc, 0x6e, 0xce
230 ]
231 )
232 }
233
234 #[test]
235 pub fn test_mix_u32s() {
236 let mut channel = Blake2sChannel::default();
237 channel.mix_u32s(&[1, 2, 3, 4, 5, 6, 7, 8, 9]);
238 let digest: [u8; 32] = channel.digest.into();
239 assert_eq!(
240 digest,
241 [
242 0x70, 0x91, 0x76, 0x83, 0x57, 0xbb, 0x1b, 0xb3, 0x34, 0x6f, 0xda, 0xb6, 0xb3, 0x57,
243 0xd7, 0xfa, 0x46, 0xb8, 0xfb, 0xe3, 0x2c, 0x2e, 0x43, 0x24, 0xa0, 0xff, 0xc2, 0x94,
244 0xcb, 0xf9, 0xa1, 0xc7
245 ]
246 );
247 }
248}