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