reth_testing_utils/
genesis_allocator.rs1use alloy_genesis::GenesisAccount;
5use alloy_primitives::{Address, Bytes, B256, U256};
6use reth_primitives::public_key_to_address;
7use secp256k1::{
8 rand::{thread_rng, RngCore},
9 Keypair, Secp256k1,
10};
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 self.alloc.insert(
113 address,
114 GenesisAccount::default().with_balance(balance).with_storage(Some(storage)),
115 );
116
117 (pair, address)
118 }
119
120 pub fn new_account_with_code_and_storage(
124 &mut self,
125 code: Bytes,
126 storage: BTreeMap<B256, B256>,
127 ) -> (Keypair, Address) {
128 let secp = Secp256k1::new();
129 let pair = Keypair::new(&secp, &mut self.rng);
130 let address = public_key_to_address(pair.public_key());
131
132 self.alloc.insert(
133 address,
134 GenesisAccount::default().with_code(Some(code)).with_storage(Some(storage)),
135 );
136
137 (pair, address)
138 }
139
140 pub fn new_account_with_code(&mut self, code: Bytes) -> (Keypair, Address) {
144 let secp = Secp256k1::new();
145 let pair = Keypair::new(&secp, &mut self.rng);
146 let address = public_key_to_address(pair.public_key());
147
148 self.alloc.insert(address, GenesisAccount::default().with_code(Some(code)));
149
150 (pair, address)
151 }
152
153 pub fn add_funded_account_with_address(&mut self, address: Address, balance: U256) {
158 self.alloc.insert(address, GenesisAccount::default().with_balance(balance));
159 }
160
161 pub fn add_account(&mut self, account: GenesisAccount) -> Address {
165 let secp = Secp256k1::new();
166 let pair = Keypair::new(&secp, &mut self.rng);
167 let address = public_key_to_address(pair.public_key());
168
169 self.alloc.insert(address, account);
170
171 address
172 }
173
174 pub fn get_account(&self, address: &Address) -> Option<&GenesisAccount> {
178 self.alloc.get(address)
179 }
180
181 pub fn get_account_mut(&mut self, address: &Address) -> Option<&mut GenesisAccount> {
183 self.alloc.get_mut(address)
184 }
185
186 pub fn account_entry(&mut self, address: Address) -> Entry<'_, Address, GenesisAccount> {
188 self.alloc.entry(address)
189 }
190
191 pub fn build(self) -> HashMap<Address, GenesisAccount> {
193 self.alloc
194 }
195}
196
197impl Default for GenesisAllocator<'_> {
198 fn default() -> Self {
199 Self { alloc: HashMap::default(), rng: Box::new(thread_rng()) }
200 }
201}
202
203impl fmt::Debug for GenesisAllocator<'_> {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 f.debug_struct("GenesisAllocator").field("alloc", &self.alloc).finish_non_exhaustive()
206 }
207}