reth_testing_utils/
genesis_allocator.rs1use alloy_primitives::{Address, Bytes, B256, U256};
5use reth_primitives_traits::crypto::secp256k1::public_key_to_address;
6use secp256k1::{
7 rand::{thread_rng, RngCore},
8 Keypair, Secp256k1,
9};
10use seismic_alloy_genesis::GenesisAccount;
11use std::{
12 collections::{hash_map::Entry, BTreeMap, HashMap},
13 fmt,
14};
15
16pub struct GenesisAllocator<'a> {
45 alloc: HashMap<Address, GenesisAccount>,
47 rng: Box<dyn RngCore + 'a>,
49}
50
51impl<'a> GenesisAllocator<'a> {
52 pub fn new_with_rng<R>(rng: &'a mut R) -> Self
54 where
55 R: RngCore,
56 {
57 Self { alloc: HashMap::default(), rng: Box::new(rng) }
58 }
59
60 pub fn with_rng<R>(mut self, rng: &'a mut R) -> Self
62 where
63 R: RngCore + std::fmt::Debug,
64 {
65 self.rng = Box::new(rng);
66 self
67 }
68
69 pub fn new_funded_account(&mut self, balance: U256) -> (Keypair, Address) {
73 let secp = Secp256k1::new();
74 let pair = Keypair::new(&secp, &mut self.rng);
75 let address = public_key_to_address(pair.public_key());
76
77 self.alloc.insert(address, GenesisAccount::default().with_balance(balance));
78
79 (pair, address)
80 }
81
82 pub fn new_funded_account_with_code(
86 &mut self,
87 balance: U256,
88 code: Bytes,
89 ) -> (Keypair, Address) {
90 let secp = Secp256k1::new();
91 let pair = Keypair::new(&secp, &mut self.rng);
92 let address = public_key_to_address(pair.public_key());
93
94 self.alloc
95 .insert(address, GenesisAccount::default().with_balance(balance).with_code(Some(code)));
96
97 (pair, address)
98 }
99
100 pub fn new_funded_account_with_storage(
104 &mut self,
105 balance: U256,
106 storage: BTreeMap<B256, B256>,
107 ) -> (Keypair, Address) {
108 let secp = Secp256k1::new();
109 let pair = Keypair::new(&secp, &mut self.rng);
110 let address = public_key_to_address(pair.public_key());
111
112 let storage = seismic_alloy_genesis::convert_fixedbytes_map_to_flagged_storage(storage);
113
114 self.alloc.insert(
115 address,
116 GenesisAccount::default().with_balance(balance).with_storage(Some(storage)),
117 );
118
119 (pair, address)
120 }
121
122 pub fn new_account_with_code_and_storage(
126 &mut self,
127 code: Bytes,
128 storage: BTreeMap<B256, B256>,
129 ) -> (Keypair, Address) {
130 let secp = Secp256k1::new();
131 let pair = Keypair::new(&secp, &mut self.rng);
132 let address = public_key_to_address(pair.public_key());
133
134 let storage = seismic_alloy_genesis::convert_fixedbytes_map_to_flagged_storage(storage);
135
136 self.alloc.insert(
137 address,
138 GenesisAccount::default().with_code(Some(code)).with_storage(Some(storage)),
139 );
140
141 (pair, address)
142 }
143
144 pub fn new_account_with_code(&mut self, code: Bytes) -> (Keypair, Address) {
148 let secp = Secp256k1::new();
149 let pair = Keypair::new(&secp, &mut self.rng);
150 let address = public_key_to_address(pair.public_key());
151
152 self.alloc.insert(address, GenesisAccount::default().with_code(Some(code)));
153
154 (pair, address)
155 }
156
157 pub fn add_funded_account_with_address(&mut self, address: Address, balance: U256) {
162 self.alloc.insert(address, GenesisAccount::default().with_balance(balance));
163 }
164
165 pub fn add_account(&mut self, account: GenesisAccount) -> Address {
169 let secp = Secp256k1::new();
170 let pair = Keypair::new(&secp, &mut self.rng);
171 let address = public_key_to_address(pair.public_key());
172
173 self.alloc.insert(address, account);
174
175 address
176 }
177
178 pub fn get_account(&self, address: &Address) -> Option<&GenesisAccount> {
182 self.alloc.get(address)
183 }
184
185 pub fn get_account_mut(&mut self, address: &Address) -> Option<&mut GenesisAccount> {
187 self.alloc.get_mut(address)
188 }
189
190 pub fn account_entry(&mut self, address: Address) -> Entry<'_, Address, GenesisAccount> {
192 self.alloc.entry(address)
193 }
194
195 pub fn build(self) -> HashMap<Address, GenesisAccount> {
197 self.alloc
198 }
199}
200
201impl Default for GenesisAllocator<'_> {
202 fn default() -> Self {
203 Self { alloc: HashMap::default(), rng: Box::new(thread_rng()) }
204 }
205}
206
207impl fmt::Debug for GenesisAllocator<'_> {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 f.debug_struct("GenesisAllocator").field("alloc", &self.alloc).finish_non_exhaustive()
210 }
211}