1use crate::{AppendableChain, BlockBuffer, BlockIndices};
4use alloy_primitives::{BlockHash, BlockNumber};
5use reth_primitives::{Receipt, SealedBlock, SealedBlockWithSenders};
6use std::collections::{BTreeMap, HashMap};
7
8#[derive(Debug)]
10pub(crate) struct TreeState {
11 block_chain_id_generator: u64,
13 pub(crate) chains: HashMap<SidechainId, AppendableChain>,
15 pub(crate) block_indices: BlockIndices,
20 pub(crate) buffered_blocks: BlockBuffer,
22}
23
24impl TreeState {
25 pub(crate) fn new(
28 last_finalized_block_number: BlockNumber,
29 last_canonical_hashes: impl IntoIterator<Item = (BlockNumber, BlockHash)>,
30 buffer_limit: u32,
31 ) -> Self {
32 Self {
33 block_chain_id_generator: 0,
34 chains: Default::default(),
35 block_indices: BlockIndices::new(
36 last_finalized_block_number,
37 BTreeMap::from_iter(last_canonical_hashes),
38 ),
39 buffered_blocks: BlockBuffer::new(buffer_limit),
40 }
41 }
42
43 #[inline]
45 fn next_id(&mut self) -> SidechainId {
46 let id = self.block_chain_id_generator;
47 self.block_chain_id_generator += 1;
48 SidechainId(id)
49 }
50
51 #[inline]
53 pub(crate) const fn block_indices(&self) -> &BlockIndices {
54 &self.block_indices
55 }
56
57 #[inline]
61 pub(crate) fn block_by_hash(&self, block_hash: BlockHash) -> Option<&SealedBlock> {
62 self.block_with_senders_by_hash(block_hash).map(|block| &block.block)
63 }
64
65 #[inline]
69 pub(crate) fn block_with_senders_by_hash(
70 &self,
71 block_hash: BlockHash,
72 ) -> Option<&SealedBlockWithSenders> {
73 let id = self.block_indices.get_side_chain_id(&block_hash)?;
74 let chain = self.chains.get(&id)?;
75 chain.block_with_senders(block_hash)
76 }
77
78 pub(crate) fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<Vec<&Receipt>> {
82 let id = self.block_indices.get_side_chain_id(&block_hash)?;
83 let chain = self.chains.get(&id)?;
84 chain.receipts_by_block_hash(block_hash)
85 }
86
87 pub(crate) fn insert_chain(&mut self, chain: AppendableChain) -> Option<SidechainId> {
91 if chain.is_empty() {
92 return None
93 }
94 let chain_id = self.next_id();
95
96 self.block_indices.insert_chain(chain_id, &chain);
97 self.chains.insert(chain_id, chain);
99 Some(chain_id)
100 }
101
102 pub(crate) fn get_buffered_block(&self, hash: &BlockHash) -> Option<&SealedBlockWithSenders> {
104 self.buffered_blocks.block(hash)
105 }
106
107 pub(crate) fn lowest_buffered_ancestor(
109 &self,
110 hash: &BlockHash,
111 ) -> Option<&SealedBlockWithSenders> {
112 self.buffered_blocks.lowest_ancestor(hash)
113 }
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
118pub(crate) struct SidechainId(u64);
119
120impl From<SidechainId> for u64 {
121 fn from(value: SidechainId) -> Self {
122 value.0
123 }
124}
125
126#[cfg(test)]
127impl From<u64> for SidechainId {
128 fn from(value: u64) -> Self {
129 Self(value)
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use crate::canonical_chain::CanonicalChain;
137 use alloy_primitives::B256;
138 use reth_execution_types::Chain;
139 use reth_provider::ExecutionOutcome;
140
141 #[test]
142 fn test_tree_state_initialization() {
143 let last_finalized_block_number = 10u64;
145 let last_canonical_hashes = vec![(9u64, B256::random()), (10u64, B256::random())];
146 let buffer_limit = 5;
147
148 let tree_state = TreeState::new(
150 last_finalized_block_number,
151 last_canonical_hashes.clone(),
152 buffer_limit,
153 );
154
155 assert_eq!(tree_state.block_chain_id_generator, 0);
157 assert_eq!(tree_state.block_indices().last_finalized_block(), last_finalized_block_number);
158 assert_eq!(
159 *tree_state.block_indices.canonical_chain().inner(),
160 *CanonicalChain::new(last_canonical_hashes.into_iter().collect()).inner()
161 );
162 assert!(tree_state.chains.is_empty());
163 assert!(tree_state.buffered_blocks.lru.is_empty());
164 }
165
166 #[test]
167 fn test_tree_state_next_id() {
168 let mut tree_state = TreeState::new(0, vec![], 5);
170
171 let first_id = tree_state.next_id();
173 let second_id = tree_state.next_id();
174
175 assert_eq!(first_id, SidechainId(0));
177 assert_eq!(second_id, SidechainId(1));
178 assert_eq!(tree_state.block_chain_id_generator, 2);
179 }
180
181 #[test]
182 fn test_tree_state_insert_chain() {
183 let mut tree_state = TreeState::new(0, vec![], 5);
185
186 let block: SealedBlockWithSenders = Default::default();
188 let block1_hash = B256::random();
189 let block2_hash = B256::random();
190
191 let mut block1 = block.clone();
192 let mut block2 = block;
193
194 block1.block.header.set_hash(block1_hash);
195 block1.block.header.set_block_number(9);
196 block2.block.header.set_hash(block2_hash);
197 block2.block.header.set_block_number(10);
198
199 let chain = AppendableChain::new(Chain::new(
200 [block1, block2],
201 Default::default(),
202 Default::default(),
203 ));
204
205 let chain_id = tree_state.insert_chain(chain).unwrap();
207
208 assert_eq!(chain_id, SidechainId(0));
210 assert!(tree_state.chains.contains_key(&chain_id));
211
212 assert_eq!(
214 tree_state.block_indices.get_side_chain_id(&block1_hash).unwrap(),
215 SidechainId(0)
216 );
217 assert_eq!(
218 tree_state.block_indices.get_side_chain_id(&block2_hash).unwrap(),
219 SidechainId(0)
220 );
221
222 assert_eq!(tree_state.block_chain_id_generator, 1);
224
225 let chain_empty = AppendableChain::new(Chain::default());
227
228 let chain_id = tree_state.insert_chain(chain_empty);
230
231 assert!(chain_id.is_none());
233
234 assert!(tree_state.chains.contains_key(&SidechainId(0)));
236 assert!(!tree_state.chains.contains_key(&SidechainId(1)));
237 assert_eq!(
238 tree_state.block_indices.get_side_chain_id(&block1_hash).unwrap(),
239 SidechainId(0)
240 );
241 assert_eq!(
242 tree_state.block_indices.get_side_chain_id(&block2_hash).unwrap(),
243 SidechainId(0)
244 );
245 assert_eq!(tree_state.block_chain_id_generator, 1);
246 }
247
248 #[test]
249 fn test_block_by_hash_side_chain() {
250 let mut tree_state = TreeState::new(0, vec![], 5);
252
253 let block1_hash = B256::random();
255 let block2_hash = B256::random();
256
257 let mut block1: SealedBlockWithSenders = Default::default();
258 let mut block2: SealedBlockWithSenders = Default::default();
259
260 block1.block.header.set_hash(block1_hash);
261 block1.block.header.set_block_number(9);
262 block2.block.header.set_hash(block2_hash);
263 block2.block.header.set_block_number(10);
264
265 let chain = AppendableChain::new(Chain::new(
267 vec![block1.clone(), block2.clone()],
268 Default::default(),
269 Default::default(),
270 ));
271
272 tree_state.insert_chain(chain).unwrap();
274
275 let retrieved_block1 = tree_state.block_by_hash(block1_hash);
277 assert_eq!(*retrieved_block1.unwrap(), block1.block);
278
279 let retrieved_block2 = tree_state.block_by_hash(block2_hash);
280 assert_eq!(*retrieved_block2.unwrap(), block2.block);
281
282 let non_existent_hash = B256::random();
284 let result = tree_state.block_by_hash(non_existent_hash);
285
286 assert!(result.is_none());
288 }
289
290 #[test]
291 fn test_block_with_senders_by_hash() {
292 let mut tree_state = TreeState::new(0, vec![], 5);
294
295 let block1_hash = B256::random();
297 let block2_hash = B256::random();
298
299 let mut block1: SealedBlockWithSenders = Default::default();
300 let mut block2: SealedBlockWithSenders = Default::default();
301
302 block1.block.header.set_hash(block1_hash);
303 block1.block.header.set_block_number(9);
304 block2.block.header.set_hash(block2_hash);
305 block2.block.header.set_block_number(10);
306
307 let chain = AppendableChain::new(Chain::new(
309 vec![block1.clone(), block2.clone()],
310 Default::default(),
311 Default::default(),
312 ));
313
314 tree_state.insert_chain(chain).unwrap();
316
317 let retrieved_block1 = tree_state.block_with_senders_by_hash(block1_hash);
319 assert_eq!(*retrieved_block1.unwrap(), block1);
320
321 let retrieved_block2 = tree_state.block_with_senders_by_hash(block2_hash);
322 assert_eq!(*retrieved_block2.unwrap(), block2);
323
324 let non_existent_hash = B256::random();
326 let result = tree_state.block_with_senders_by_hash(non_existent_hash);
327
328 assert!(result.is_none());
330 }
331
332 #[test]
333 fn test_get_buffered_block() {
334 let mut tree_state = TreeState::new(0, vec![], 5);
336
337 let block_hash = B256::random();
339 let mut block: SealedBlockWithSenders = Default::default();
340 block.block.header.set_hash(block_hash);
341
342 tree_state.buffered_blocks.insert_block(block.clone());
344
345 let retrieved_block = tree_state.get_buffered_block(&block_hash);
347 assert_eq!(*retrieved_block.unwrap(), block);
348
349 let non_existent_hash = B256::random();
351 let result = tree_state.get_buffered_block(&non_existent_hash);
352
353 assert!(result.is_none());
355 }
356
357 #[test]
358 fn test_lowest_buffered_ancestor() {
359 let mut tree_state = TreeState::new(0, vec![], 5);
361
362 let ancestor_hash = B256::random();
364 let descendant_hash = B256::random();
365
366 let mut ancestor_block: SealedBlockWithSenders = Default::default();
367 let mut descendant_block: SealedBlockWithSenders = Default::default();
368
369 ancestor_block.block.header.set_hash(ancestor_hash);
370 descendant_block.block.header.set_hash(descendant_hash);
371 descendant_block.block.header.set_parent_hash(ancestor_hash);
372
373 tree_state.buffered_blocks.insert_block(ancestor_block.clone());
375 tree_state.buffered_blocks.insert_block(descendant_block.clone());
376
377 let lowest_ancestor = tree_state.lowest_buffered_ancestor(&descendant_hash);
379 assert!(lowest_ancestor.is_some());
380 assert_eq!(lowest_ancestor.unwrap().block.header.hash(), ancestor_hash);
381
382 let non_existent_hash = B256::random();
384 let result = tree_state.lowest_buffered_ancestor(&non_existent_hash);
385
386 assert!(result.is_none());
388 }
389
390 #[test]
391 fn test_receipts_by_block_hash() {
392 let mut tree_state = TreeState::new(0, vec![], 5);
394
395 let block_hash = B256::random();
397 let receipt1 = Receipt::default();
398 let receipt2 = Receipt::default();
399
400 let mut block: SealedBlockWithSenders = Default::default();
401 block.block.header.set_hash(block_hash);
402
403 let receipts = vec![receipt1, receipt2];
404
405 let chain = AppendableChain::new(Chain::new(
407 vec![block.clone()],
408 ExecutionOutcome { receipts: receipts.clone().into(), ..Default::default() },
409 Default::default(),
410 ));
411
412 tree_state.insert_chain(chain).unwrap();
414
415 let retrieved_receipts = tree_state.receipts_by_block_hash(block_hash);
417 assert!(retrieved_receipts.is_some());
418
419 let receipts_ref: Vec<&Receipt> = receipts.iter().collect();
421 assert_eq!(retrieved_receipts.unwrap(), receipts_ref);
422
423 let non_existent_hash = B256::random();
425 let result = tree_state.receipts_by_block_hash(non_existent_hash);
426
427 assert!(result.is_none());
429 }
430}