1use crate::Vec;
2use ark_ff::{FromBytes, ToBytes};
3use ark_std::marker::PhantomData;
4use ark_std::rand::{RngCore, SeedableRng};
5use digest::{generic_array::GenericArray, Digest};
6use rand_chacha::ChaChaRng;
7
8pub struct FiatShamirRng<D: Digest> {
12 r: ChaChaRng,
13 seed: GenericArray<u8, D::OutputSize>,
14 #[doc(hidden)]
15 digest: PhantomData<D>,
16}
17
18impl<D: Digest> RngCore for FiatShamirRng<D> {
19 #[inline]
20 fn next_u32(&mut self) -> u32 {
21 self.r.next_u32()
22 }
23
24 #[inline]
25 fn next_u64(&mut self) -> u64 {
26 self.r.next_u64()
27 }
28
29 #[inline]
30 fn fill_bytes(&mut self, dest: &mut [u8]) {
31 self.r.fill_bytes(dest);
32 }
33
34 #[inline]
35 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), ark_std::rand::Error> {
36 Ok(self.r.fill_bytes(dest))
37 }
38}
39
40impl<D: Digest> FiatShamirRng<D> {
41 #[inline]
44 pub fn from_seed<'a, T: 'a + ToBytes>(seed: &'a T) -> Self {
45 let mut bytes = Vec::new();
46 seed.write(&mut bytes).expect("failed to convert to bytes");
47 let seed = D::digest(&bytes);
48 let r_seed: [u8; 32] = FromBytes::read(seed.as_ref()).expect("failed to get [u32; 8]");
49 let r = ChaChaRng::from_seed(r_seed);
50 Self {
51 r,
52 seed,
53 digest: PhantomData,
54 }
55 }
56
57 #[inline]
60 pub fn absorb<'a, T: 'a + ToBytes>(&mut self, seed: &'a T) {
61 let mut bytes = Vec::new();
62 seed.write(&mut bytes).expect("failed to convert to bytes");
63 bytes.extend_from_slice(&self.seed);
64 self.seed = D::digest(&bytes);
65 let seed: [u8; 32] = FromBytes::read(self.seed.as_ref()).expect("failed to get [u32; 8]");
66 self.r = ChaChaRng::from_seed(seed);
67 }
68}