reth_testing_utils/
genesis_allocator.rs1use alloy_genesis::GenesisAccount;
5use alloy_primitives::{
6 map::{AddressMap, Entry},
7 Address, Bytes, B256, U256,
8};
9use secp256k1::{
10 rand::{rng, RngCore},
11 Keypair,
12};
13use std::{collections::BTreeMap, fmt};
14
15pub struct GenesisAllocator<'a> {
44 alloc: AddressMap<GenesisAccount>,
46 rng: Box<dyn RngCore + 'a>,
48}
49
50impl<'a> GenesisAllocator<'a> {
51 pub fn new_with_rng<R>(rng: &'a mut R) -> Self
53 where
54 R: RngCore,
55 {
56 Self { alloc: AddressMap::default(), rng: Box::new(rng) }
57 }
58
59 pub fn with_rng<R>(mut self, rng: &'a mut R) -> Self
61 where
62 R: RngCore + std::fmt::Debug,
63 {
64 self.rng = Box::new(rng);
65 self
66 }
67
68 pub fn new_funded_account(&mut self, balance: U256) -> (Keypair, Address) {
72 let pair = Keypair::new(&mut self.rng);
73 let address =
74 Address::from_raw_public_key(&pair.public_key().serialize_uncompressed()[1..]);
75
76 self.alloc.insert(address, GenesisAccount::default().with_balance(balance));
77
78 (pair, address)
79 }
80
81 pub fn new_funded_account_with_code(
85 &mut self,
86 balance: U256,
87 code: Bytes,
88 ) -> (Keypair, Address) {
89 let pair = Keypair::new(&mut self.rng);
90 let address =
91 Address::from_raw_public_key(&pair.public_key().serialize_uncompressed()[1..]);
92
93 self.alloc
94 .insert(address, GenesisAccount::default().with_balance(balance).with_code(Some(code)));
95
96 (pair, address)
97 }
98
99 pub fn new_funded_account_with_storage(
103 &mut self,
104 balance: U256,
105 storage: BTreeMap<B256, B256>,
106 ) -> (Keypair, Address) {
107 let pair = Keypair::new(&mut self.rng);
108 let address =
109 Address::from_raw_public_key(&pair.public_key().serialize_uncompressed()[1..]);
110
111 self.alloc.insert(
112 address,
113 GenesisAccount::default().with_balance(balance).with_storage(Some(storage)),
114 );
115
116 (pair, address)
117 }
118
119 pub fn new_account_with_code_and_storage(
123 &mut self,
124 code: Bytes,
125 storage: BTreeMap<B256, B256>,
126 ) -> (Keypair, Address) {
127 let pair = Keypair::new(&mut self.rng);
128 let address =
129 Address::from_raw_public_key(&pair.public_key().serialize_uncompressed()[1..]);
130
131 self.alloc.insert(
132 address,
133 GenesisAccount::default().with_code(Some(code)).with_storage(Some(storage)),
134 );
135
136 (pair, address)
137 }
138
139 pub fn new_account_with_code(&mut self, code: Bytes) -> (Keypair, Address) {
143 let pair = Keypair::new(&mut self.rng);
144 let address =
145 Address::from_raw_public_key(&pair.public_key().serialize_uncompressed()[1..]);
146
147 self.alloc.insert(address, GenesisAccount::default().with_code(Some(code)));
148
149 (pair, address)
150 }
151
152 pub fn add_funded_account_with_address(&mut self, address: Address, balance: U256) {
157 self.alloc.insert(address, GenesisAccount::default().with_balance(balance));
158 }
159
160 pub fn add_account(&mut self, account: GenesisAccount) -> Address {
164 let pair = Keypair::new(&mut self.rng);
165 let address =
166 Address::from_raw_public_key(&pair.public_key().serialize_uncompressed()[1..]);
167
168 self.alloc.insert(address, account);
169
170 address
171 }
172
173 pub fn get_account(&self, address: &Address) -> Option<&GenesisAccount> {
177 self.alloc.get(address)
178 }
179
180 pub fn get_account_mut(&mut self, address: &Address) -> Option<&mut GenesisAccount> {
182 self.alloc.get_mut(address)
183 }
184
185 pub fn account_entry(&mut self, address: Address) -> Entry<'_, Address, GenesisAccount> {
187 self.alloc.entry(address)
188 }
189
190 pub fn build(self) -> AddressMap<GenesisAccount> {
192 self.alloc
193 }
194}
195
196impl Default for GenesisAllocator<'_> {
197 fn default() -> Self {
198 Self { alloc: AddressMap::default(), rng: Box::new(rng()) }
199 }
200}
201
202impl fmt::Debug for GenesisAllocator<'_> {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 f.debug_struct("GenesisAllocator").field("alloc", &self.alloc).finish_non_exhaustive()
205 }
206}