bc_rand/
seeded_random.rs

1use rand::{CryptoRng, RngCore};
2use rand_xoshiro::{Xoshiro256StarStar, rand_core::SeedableRng};
3
4use crate::RandomNumberGenerator;
5
6/// A random number generator that can be used as a source of deterministic
7/// pseudo-randomness for testing purposes.
8#[derive(Debug, Clone)]
9pub struct SeededRandomNumberGenerator {
10    rng: Xoshiro256StarStar,
11}
12
13impl SeededRandomNumberGenerator {
14    /// Creates a new seeded random number generator.
15    ///
16    /// The seed should be a 256-bit value, represented as an array of 4 64-bit
17    /// integers. For the output distribution to look random, the seed
18    /// should not have any obvious patterns, like all zeroes or all ones.
19    ///
20    /// This is not cryptographically secure, and should only be used for
21    /// testing purposes.
22    pub fn new(seed: [u64; 4]) -> Self {
23        let mut seed_bytes = [0u8; 32];
24        for i in 0..4 {
25            seed_bytes[i * 8..(i + 1) * 8]
26                .copy_from_slice(&seed[i].to_le_bytes());
27        }
28        Self { rng: Xoshiro256StarStar::from_seed(seed_bytes) }
29    }
30
31    pub fn next_u64(&mut self) -> u64 { self.rng.next_u64() }
32}
33
34impl RngCore for SeededRandomNumberGenerator {
35    fn next_u32(&mut self) -> u32 { self.next_u64() as u32 }
36
37    fn next_u64(&mut self) -> u64 { self.rng.next_u64() }
38
39    fn fill_bytes(&mut self, dest: &mut [u8]) { self.rng.fill_bytes(dest); }
40}
41
42// Note that we implement `CryptoRng` for `SeededRandomNumberGenerator` because
43// it is required by the some third-party crates, but this is NOT a
44// cryptographically secure random number generator.
45// `SeededRandomNumberGenerator` should only be used for testing purposes.
46impl CryptoRng for SeededRandomNumberGenerator {}
47
48impl RandomNumberGenerator for SeededRandomNumberGenerator {
49    fn random_data(&mut self, size: usize) -> Vec<u8> {
50        // This might not be the most efficient implementation,
51        // but it works the same as the Swift version.
52        (0..size).map(|_| self.next_u64() as u8).collect()
53    }
54
55    fn fill_random_data(&mut self, data: &mut [u8]) {
56        data.iter_mut().for_each(|x| *x = self.next_u64() as u8);
57    }
58}
59
60/// Creates a seeded random number generator with a fixed seed.
61pub fn make_fake_random_number_generator() -> SeededRandomNumberGenerator {
62    SeededRandomNumberGenerator::new([
63        17295166580085024720,
64        422929670265678780,
65        5577237070365765850,
66        7953171132032326923,
67    ])
68}
69
70/// Creates a vector of random data with a fixed seed.
71pub fn fake_random_data(size: usize) -> Vec<u8> {
72    make_fake_random_number_generator().random_data(size)
73}
74
75#[cfg(test)]
76mod tests {
77    use crate::{
78        RandomNumberGenerator, SeededRandomNumberGenerator, fake_random_data,
79        rng_next_in_range, rng_next_with_upper_bound,
80    };
81
82    const TEST_SEED: [u64; 4] = [
83        17295166580085024720,
84        422929670265678780,
85        5577237070365765850,
86        7953171132032326923,
87    ];
88
89    #[test]
90    fn test_next_u64() {
91        let mut rng = SeededRandomNumberGenerator::new(TEST_SEED);
92        assert_eq!(rng.next_u64(), 1104683000648959614);
93    }
94
95    #[test]
96    fn test_next_50() {
97        let mut rng = SeededRandomNumberGenerator::new(TEST_SEED);
98        let expected_values: Vec<u64> = vec![
99            1104683000648959614,
100            9817345228149227957,
101            546276821344993881,
102            15870950426333349563,
103            830653509032165567,
104            14772257893953840492,
105            3512633850838187726,
106            6358411077290857510,
107            7897285047238174514,
108            18314839336815726031,
109            4978716052961022367,
110            17373022694051233817,
111            663115362299242570,
112            9811238046242345451,
113            8113787839071393872,
114            16155047452816275860,
115            673245095821315645,
116            1610087492396736743,
117            1749670338128618977,
118            3927771759340679115,
119            9610589375631783853,
120            5311608497352460372,
121            11014490817524419548,
122            6320099928172676090,
123            12513554919020212402,
124            6823504187935853178,
125            1215405011954300226,
126            8109228150255944821,
127            4122548551796094879,
128            16544885818373129566,
129            5597102191057004591,
130            11690994260783567085,
131            9374498734039011409,
132            18246806104446739078,
133            2337407889179712900,
134            12608919248151905477,
135            7641631838640172886,
136            8421574250687361351,
137            8697189342072434208,
138            8766286633078002696,
139            14800090277885439654,
140            17865860059234099833,
141            4673315107448681522,
142            14288183874156623863,
143            7587575203648284614,
144            9109213819045273474,
145            11817665411945280786,
146            1745089530919138651,
147            5730370365819793488,
148            5496865518262805451,
149        ];
150        assert!(expected_values.into_iter().all(|x| x == rng.next_u64()));
151    }
152
153    #[test]
154    fn test_fake_random_data() {
155        assert_eq!(
156            fake_random_data(100),
157            hex_literal::hex!(
158                "7eb559bbbf6cce2632cf9f194aeb50943de7e1cbad54dcfab27a42759f5e2fed518684c556472008a67932f7c682125b50cb72e8216f6906358fdaf28d3545532daee0c5bb5023f50cd8e71ec14901ac746c576c481b893be6656b80622b3a564e59b4e2"
159            )
160        );
161    }
162
163    #[test]
164    fn test_next_with_upper_bound() {
165        let mut rng = SeededRandomNumberGenerator::new(TEST_SEED);
166        assert_eq!(rng_next_with_upper_bound(&mut rng, 10000u32), 745);
167    }
168
169    #[test]
170    fn test_in_range() {
171        let mut rng = SeededRandomNumberGenerator::new(TEST_SEED);
172        let v = (0..100)
173            .map(|_| rng_next_in_range(&mut rng, &(0..100)))
174            .collect::<Vec<_>>();
175        let expected_values: Vec<i32> = vec![
176            7, 44, 92, 16, 16, 67, 41, 74, 66, 20, 18, 6, 62, 34, 4, 69, 99,
177            19, 0, 85, 22, 27, 56, 23, 19, 5, 23, 76, 80, 27, 74, 69, 17, 92,
178            31, 32, 55, 36, 49, 23, 53, 2, 46, 6, 43, 66, 34, 71, 64, 69, 25,
179            14, 17, 23, 32, 6, 23, 65, 35, 11, 21, 37, 58, 92, 98, 8, 38, 49,
180            7, 24, 24, 71, 37, 63, 91, 21, 11, 66, 52, 54, 55, 19, 76, 46, 89,
181            38, 91, 95, 33, 25, 4, 30, 66, 51, 5, 91, 62, 27, 92, 39,
182        ];
183        assert_eq!(v, expected_values);
184    }
185
186    #[test]
187    fn test_fill_random_data() {
188        let mut rng = SeededRandomNumberGenerator::new(TEST_SEED);
189        let v1 = rng.random_data(100);
190        let mut rng = SeededRandomNumberGenerator::new(TEST_SEED);
191        let mut v2 = [0u8; 100];
192        rng.fill_random_data(&mut v2);
193        assert_eq!(v1, v2);
194    }
195}