1use {
4 rand::{Rng, SeedableRng},
5 rand_chacha::ChaChaRng,
6 rayon::prelude::*,
7 solana_keypair::{keypair_from_seed, Keypair},
8};
9
10pub struct GenKeys {
11 generator: ChaChaRng,
12}
13
14impl GenKeys {
15 pub fn new(seed: [u8; 32]) -> GenKeys {
16 let generator = ChaChaRng::from_seed(seed);
17 GenKeys { generator }
18 }
19
20 fn gen_seed(&mut self) -> [u8; 32] {
21 let mut seed = [0u8; 32];
22 self.generator.fill(&mut seed);
23 seed
24 }
25
26 fn gen_n_seeds(&mut self, n: u64) -> Vec<[u8; 32]> {
27 (0..n).map(|_| self.gen_seed()).collect()
28 }
29
30 pub fn gen_keypair(&mut self) -> Keypair {
31 let mut seed = [0u8; Keypair::SECRET_KEY_LENGTH];
32 self.generator.fill(&mut seed[..]);
33 keypair_from_seed(&seed).unwrap()
34 }
35
36 pub fn gen_n_keypairs(&mut self, n: u64) -> Vec<Keypair> {
37 self.gen_n_seeds(n)
38 .into_par_iter()
39 .map(|seed| {
40 let mut keypair_seed = [0u8; Keypair::SECRET_KEY_LENGTH];
41 ChaChaRng::from_seed(seed).fill(&mut keypair_seed[..]);
42 keypair_from_seed(&keypair_seed).unwrap()
43 })
44 .collect()
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 pub use solana_pubkey::Pubkey;
51 use {super::*, solana_signer::Signer, std::collections::HashSet};
52
53 #[test]
54 fn test_new_key_is_deterministic() {
55 let seed = [0u8; 32];
56 let mut gen0 = GenKeys::new(seed);
57 let mut gen1 = GenKeys::new(seed);
58
59 for _ in 0..100 {
60 assert_eq!(gen0.gen_seed().to_vec(), gen1.gen_seed().to_vec());
61 }
62 }
63
64 #[test]
65 fn test_gen_keypair_is_deterministic() {
66 let seed = [0u8; 32];
67 let mut gen0 = GenKeys::new(seed);
68 let mut gen1 = GenKeys::new(seed);
69 assert_eq!(
70 gen0.gen_keypair().to_bytes().to_vec(),
71 gen1.gen_keypair().to_bytes().to_vec()
72 );
73 }
74
75 fn gen_n_pubkeys(seed: [u8; 32], n: u64) -> HashSet<Pubkey> {
76 GenKeys::new(seed)
77 .gen_n_keypairs(n)
78 .into_iter()
79 .map(|x| x.pubkey())
80 .collect()
81 }
82
83 #[test]
84 fn test_gen_n_pubkeys_deterministic() {
85 let seed = [0u8; 32];
86 assert_eq!(gen_n_pubkeys(seed, 50), gen_n_pubkeys(seed, 50));
87 }
88}