1pub mod prf;
2pub mod prg;
3pub mod rng;
4
5use std::sync::Arc;
6
7pub use rand_chacha::rand_core::CryptoRngCore;
8#[cfg(any(test, feature = "dev"))]
9pub use rng::test_rng;
10pub use rng::{BaseRng, Seed, SeedableRng};
11use subtle::Choice;
12use typenum::Unsigned;
13
14use crate::{
15 algebra::field::FieldExtension,
16 constants::Lambda,
17 errors::PrimitiveError,
18 types::{HeapArray, Positive},
19 utils::IntoExactSizeIterator,
20};
21
22pub trait Random: Sized {
25 fn random(rng: impl CryptoRngCore) -> Self;
27
28 fn random_n<Container: FromIterator<Self>>(
30 mut rng: impl CryptoRngCore,
31 size: usize,
32 ) -> Container {
33 (0..size).map(|_| Self::random(&mut rng)).collect()
34 }
35
36 fn random_array<M: Positive>(rng: impl CryptoRngCore) -> HeapArray<Self, M> {
38 HeapArray::random(rng)
39 }
40}
41
42impl Random for Seed {
43 #[inline]
44 fn random(mut rng: impl CryptoRngCore) -> Self {
45 let mut seed = [0u8; 32];
46 rng.fill_bytes(&mut seed);
47 seed
48 }
49}
50
51impl<T: Random> Random for Arc<T> {
52 #[inline]
53 fn random(mut source: impl CryptoRngCore) -> Self {
54 Arc::new(T::random(&mut source))
55 }
56}
57
58impl<T1: Random, T2: Random> Random for (T1, T2) {
59 #[inline]
60 fn random(mut source: impl CryptoRngCore) -> Self {
61 (T1::random(&mut source), T2::random(&mut source))
62 }
63}
64
65impl<T: Random> RandomWith<usize> for Vec<T> {
66 #[inline]
67 fn random_with(mut source: impl CryptoRngCore, n_elements: usize) -> Self {
68 (0..n_elements).map(|_| T::random(&mut source)).collect()
69 }
70}
71
72pub trait RandomWith<D: Clone>: Sized {
74 fn random_with(rng: impl CryptoRngCore, data: D) -> Self;
76
77 fn random_n_with<Container: FromIterator<Self>>(
79 mut rng: impl CryptoRngCore,
80 size: usize,
81 data: D,
82 ) -> Container {
83 (0..size)
84 .map(|_| Self::random_with(&mut rng, data.clone()))
85 .collect()
86 }
87
88 fn random_n_with_each<Container: FromIterator<Self>>(
90 mut rng: impl CryptoRngCore,
91 all_data: impl IntoExactSizeIterator<Item = D>,
92 ) -> Container {
93 all_data
94 .into_iter()
95 .map(|data| Self::random_with(&mut rng, data))
96 .collect()
97 }
98}
99
100impl<D: Clone, T: RandomWith<D>> RandomWith<Vec<D>> for Vec<T> {
101 #[inline]
104 fn random_with(mut source: impl CryptoRngCore, data: Vec<D>) -> Self {
105 T::random_n_with_each(&mut source, data)
106 }
107
108 #[inline]
111 fn random_n_with<Container: FromIterator<Self>>(
112 mut rng: impl CryptoRngCore,
113 size: usize,
114 data: Vec<D>,
115 ) -> Container {
116 let mut res = (0..data.len())
117 .map(|_| Vec::<T>::with_capacity(size))
118 .collect::<Vec<_>>();
119 for _ in 0..size {
120 let row: Vec<_> = T::random_n_with_each(&mut rng, data.clone());
121 for (res_row, item) in res.iter_mut().zip(row) {
122 res_row.push(item);
123 }
124 }
125 res.into_iter().collect()
126 }
127}
128
129pub trait RandomNonZero: Sized {
131 fn random_non_zero(rng: impl CryptoRngCore) -> Result<Self, PrimitiveError>;
133
134 fn random_n_non_zero<Container: FromIterator<Self>>(
136 mut rng: impl CryptoRngCore,
137 size: usize,
138 ) -> Result<Container, PrimitiveError> {
139 (0..size).map(|_| Self::random_non_zero(&mut rng)).collect()
140 }
141}
142
143impl<T: FieldExtension> RandomNonZero for T {
144 #[inline]
159 fn random_non_zero(mut rng: impl CryptoRngCore) -> Result<Self, PrimitiveError> {
160 let n_tries = (Lambda::USIZE).div_ceil(std::mem::size_of::<Self>()) + 1;
161 for _ in 0..n_tries {
162 let value = <Self as ff::Field>::random(&mut rng);
163 if !<Choice as Into<bool>>::into(value.is_zero()) {
164 return Ok(value);
165 }
166 }
167 Err(PrimitiveError::ZeroValueSampled(
168 std::any::type_name::<Self>().into(),
169 ))
170 }
171}
172
173impl Random for u8 {
174 #[inline]
175 fn random(mut rng: impl CryptoRngCore) -> Self {
176 let mut buf = [0u8; 1];
177 rng.fill_bytes(&mut buf);
178 buf[0]
179 }
180
181 fn random_n<Container: FromIterator<Self>>(
182 mut rng: impl CryptoRngCore,
183 size: usize,
184 ) -> Container {
185 let mut buf = vec![0u8; size];
186 rng.fill_bytes(&mut buf);
187 buf.into_iter().collect()
188 }
189}
190
191impl Random for usize {
192 #[inline]
193 fn random(mut rng: impl CryptoRngCore) -> Self {
194 let mut buf = [0u8; std::mem::size_of::<usize>()];
195 rng.fill_bytes(&mut buf);
196 usize::from_le_bytes(buf)
197 }
198
199 fn random_n<Container: FromIterator<Self>>(
200 mut rng: impl CryptoRngCore,
201 size: usize,
202 ) -> Container {
203 let mut buf = vec![0u8; size * std::mem::size_of::<usize>()];
204 rng.fill_bytes(&mut buf);
205 buf.chunks_exact(std::mem::size_of::<usize>())
206 .map(|chunk| usize::from_le_bytes(chunk.try_into().unwrap()))
207 .collect()
208 }
209}