1use crate::{
4 CanonStateNotification, CanonStateNotificationSender, CanonStateNotifications, ChainInfoTracker,
5};
6use alloy_consensus::{transaction::TransactionMeta, BlockHeader};
7use alloy_eips::{BlockHashOrNumber, BlockNumHash};
8use alloy_primitives::{map::B256Map, BlockNumber, TxHash, B256};
9use parking_lot::RwLock;
10use reth_chainspec::ChainInfo;
11use reth_ethereum_primitives::EthPrimitives;
12use reth_execution_types::{
13 BlockExecutionOutput, BlockExecutionResult, Chain, DecodedRevmBal, ExecutionOutcome,
14 RecoveredBlockAndExecutionOutput,
15};
16use reth_metrics::{metrics::Gauge, Metrics};
17use reth_primitives_traits::{
18 BlockBody as _, IndexedTx, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader,
19 SignedTransaction,
20};
21use reth_trie::{updates::TrieUpdatesSorted, HashedPostStateSorted, LazyTrieData, SortedTrieData};
22use std::{collections::BTreeMap, sync::Arc, time::Instant};
23use tokio::sync::{broadcast, watch};
24
25const CANON_STATE_NOTIFICATION_CHANNEL_SIZE: usize = 256;
27
28#[derive(Metrics)]
30#[metrics(scope = "blockchain_tree.in_mem_state")]
31pub(crate) struct InMemoryStateMetrics {
32 pub(crate) earliest_block: Gauge,
34 pub(crate) latest_block: Gauge,
36 pub(crate) num_blocks: Gauge,
38}
39
40#[derive(Debug, Default)]
56pub(crate) struct InMemoryState<N: NodePrimitives = EthPrimitives> {
57 blocks: RwLock<B256Map<Arc<BlockState<N>>>>,
59 numbers: RwLock<BTreeMap<u64, B256>>,
61 pending: watch::Sender<Option<BlockState<N>>>,
63 metrics: InMemoryStateMetrics,
65}
66
67impl<N: NodePrimitives> InMemoryState<N> {
68 pub(crate) fn new(
69 blocks: B256Map<Arc<BlockState<N>>>,
70 numbers: BTreeMap<u64, B256>,
71 pending: Option<BlockState<N>>,
72 ) -> Self {
73 let (pending, _) = watch::channel(pending);
74 let this = Self {
75 blocks: RwLock::new(blocks),
76 numbers: RwLock::new(numbers),
77 pending,
78 metrics: Default::default(),
79 };
80 this.update_metrics();
81 this
82 }
83
84 pub(crate) fn update_metrics(&self) {
90 let (count, earliest, latest) = {
91 let numbers = self.numbers.read();
92 let count = numbers.len();
93 let earliest = numbers.first_key_value().map(|(number, _)| *number);
94 let latest = numbers.last_key_value().map(|(number, _)| *number);
95 (count, earliest, latest)
96 };
97 if let Some(earliest_block_number) = earliest {
98 self.metrics.earliest_block.set(earliest_block_number as f64);
99 }
100 if let Some(latest_block_number) = latest {
101 self.metrics.latest_block.set(latest_block_number as f64);
102 }
103 self.metrics.num_blocks.set(count as f64);
104 }
105
106 pub(crate) fn state_by_hash(&self, hash: B256) -> Option<Arc<BlockState<N>>> {
108 self.blocks.read().get(&hash).cloned()
109 }
110
111 pub(crate) fn state_by_number(&self, number: u64) -> Option<Arc<BlockState<N>>> {
113 let hash = self.hash_by_number(number)?;
114 self.state_by_hash(hash)
115 }
116
117 pub(crate) fn hash_by_number(&self, number: u64) -> Option<B256> {
119 self.numbers.read().get(&number).copied()
120 }
121
122 pub(crate) fn head_state(&self) -> Option<Arc<BlockState<N>>> {
124 let hash = *self.numbers.read().last_key_value()?.1;
125 self.state_by_hash(hash)
126 }
127
128 pub(crate) fn pending_state(&self) -> Option<BlockState<N>> {
131 self.pending.borrow().clone()
132 }
133
134 #[cfg(test)]
135 fn block_count(&self) -> usize {
136 self.blocks.read().len()
137 }
138}
139
140#[derive(Debug)]
143pub(crate) struct CanonicalInMemoryStateInner<N: NodePrimitives> {
144 pub(crate) chain_info_tracker: ChainInfoTracker<N>,
147 pub(crate) in_memory_state: InMemoryState<N>,
149 pub(crate) canon_state_notification_sender: CanonStateNotificationSender<N>,
151}
152
153impl<N: NodePrimitives> CanonicalInMemoryStateInner<N> {
154 fn clear(&self) {
156 {
157 let mut numbers = self.in_memory_state.numbers.write();
159 let mut blocks = self.in_memory_state.blocks.write();
160 numbers.clear();
161 blocks.clear();
162 self.in_memory_state.pending.send_modify(|p| {
163 p.take();
164 });
165 }
166 self.in_memory_state.update_metrics();
167 }
168}
169
170#[derive(Debug, Clone)]
174pub struct CanonicalInMemoryState<N: NodePrimitives = EthPrimitives> {
175 pub(crate) inner: Arc<CanonicalInMemoryStateInner<N>>,
176}
177
178impl<N: NodePrimitives> CanonicalInMemoryState<N> {
179 pub fn new(
182 blocks: B256Map<Arc<BlockState<N>>>,
183 numbers: BTreeMap<u64, B256>,
184 pending: Option<BlockState<N>>,
185 finalized: Option<SealedHeader<N::BlockHeader>>,
186 safe: Option<SealedHeader<N::BlockHeader>>,
187 ) -> Self {
188 let in_memory_state = InMemoryState::new(blocks, numbers, pending);
189 let header = in_memory_state.head_state().map_or_else(SealedHeader::default, |state| {
190 state.block_ref().recovered_block().clone_sealed_header()
191 });
192 let chain_info_tracker = ChainInfoTracker::new(header, finalized, safe);
193 let (canon_state_notification_sender, _) =
194 broadcast::channel(CANON_STATE_NOTIFICATION_CHANNEL_SIZE);
195
196 Self {
197 inner: Arc::new(CanonicalInMemoryStateInner {
198 chain_info_tracker,
199 in_memory_state,
200 canon_state_notification_sender,
201 }),
202 }
203 }
204
205 pub fn empty() -> Self {
207 Self::new(B256Map::default(), BTreeMap::new(), None, None, None)
208 }
209
210 pub fn with_head(
213 head: SealedHeader<N::BlockHeader>,
214 finalized: Option<SealedHeader<N::BlockHeader>>,
215 safe: Option<SealedHeader<N::BlockHeader>>,
216 ) -> Self {
217 let chain_info_tracker = ChainInfoTracker::new(head, finalized, safe);
218 let in_memory_state = InMemoryState::default();
219 let (canon_state_notification_sender, _) =
220 broadcast::channel(CANON_STATE_NOTIFICATION_CHANNEL_SIZE);
221 let inner = CanonicalInMemoryStateInner {
222 chain_info_tracker,
223 in_memory_state,
224 canon_state_notification_sender,
225 };
226
227 Self { inner: Arc::new(inner) }
228 }
229
230 pub fn hash_by_number(&self, number: u64) -> Option<B256> {
232 self.inner.in_memory_state.hash_by_number(number)
233 }
234
235 pub fn header_by_hash(&self, hash: B256) -> Option<SealedHeader<N::BlockHeader>> {
237 self.state_by_hash(hash)
238 .map(|block| block.block_ref().recovered_block().clone_sealed_header())
239 }
240
241 pub fn clear_state(&self) {
243 self.inner.clear()
244 }
245
246 pub fn set_pending_block(&self, pending: ExecutedBlock<N>) {
250 let parent = self.state_by_hash(pending.recovered_block().parent_hash());
252 let pending = BlockState::with_parent(pending, parent);
253 self.inner.in_memory_state.pending.send_modify(|p| {
254 p.replace(pending);
255 });
256 self.inner.in_memory_state.update_metrics();
257 }
258
259 fn update_blocks<I, R>(&self, new_blocks: I, reorged: R)
264 where
265 I: IntoIterator<Item = ExecutedBlock<N>>,
266 R: IntoIterator<Item = ExecutedBlock<N>>,
267 {
268 {
269 let mut numbers = self.inner.in_memory_state.numbers.write();
271 let mut blocks = self.inner.in_memory_state.blocks.write();
272
273 for block in reorged {
275 let hash = block.recovered_block().hash();
276 let number = block.recovered_block().number();
277 blocks.remove(&hash);
278 numbers.remove(&number);
279 }
280
281 for block in new_blocks {
283 let parent = blocks.get(&block.recovered_block().parent_hash()).cloned();
284 let block_state = BlockState::with_parent(block, parent);
285 let hash = block_state.hash();
286 let number = block_state.number();
287
288 blocks.insert(hash, Arc::new(block_state));
290 numbers.insert(number, hash);
291 }
292
293 self.inner.in_memory_state.pending.send_modify(|p| {
295 p.take();
296 });
297 }
298 self.inner.in_memory_state.update_metrics();
299 }
300
301 pub fn update_chain(&self, new_chain: NewCanonicalChain<N>) {
303 match new_chain {
304 NewCanonicalChain::Commit { new } => {
305 self.update_blocks(new, vec![]);
306 }
307 NewCanonicalChain::Reorg { new, old } => {
308 self.update_blocks(new, old);
309 }
310 }
311 }
312
313 pub fn remove_persisted_blocks(&self, persisted_num_hash: BlockNumHash) {
318 self.remove_persisted_blocks_until(persisted_num_hash, persisted_num_hash.number);
319 }
320
321 pub fn remove_persisted_blocks_until(
324 &self,
325 persisted_num_hash: BlockNumHash,
326 remove_until: BlockNumber,
327 ) {
328 self.set_persisted(persisted_num_hash);
329 {
334 if self.inner.in_memory_state.blocks.read().get(&persisted_num_hash.hash).is_none() {
335 return
337 }
338 }
339
340 {
341 let mut numbers = self.inner.in_memory_state.numbers.write();
343 let mut blocks = self.inner.in_memory_state.blocks.write();
344
345 let remove_until = remove_until.min(persisted_num_hash.number);
346
347 numbers.clear();
349
350 let mut old_blocks = blocks
352 .drain()
353 .filter(|(_, b)| b.block_ref().recovered_block().number() > remove_until)
354 .map(|(_, b)| b.block.clone())
355 .collect::<Vec<_>>();
356
357 old_blocks.sort_unstable_by_key(|block| block.recovered_block().number());
359
360 for block in old_blocks {
362 let parent = blocks.get(&block.recovered_block().parent_hash()).cloned();
363 let block_state = BlockState::with_parent(block, parent);
364 let hash = block_state.hash();
365 let number = block_state.number();
366
367 blocks.insert(hash, Arc::new(block_state));
369 numbers.insert(number, hash);
370 }
371
372 self.inner.in_memory_state.pending.send_modify(|p| {
374 if let Some(p) = p.as_mut() {
375 p.parent = blocks.get(&p.block_ref().recovered_block().parent_hash()).cloned();
376 }
377 });
378 }
379 self.inner.in_memory_state.update_metrics();
380 }
381
382 pub fn state_by_hash(&self, hash: B256) -> Option<Arc<BlockState<N>>> {
384 self.inner.in_memory_state.state_by_hash(hash)
385 }
386
387 pub fn state_by_number(&self, number: u64) -> Option<Arc<BlockState<N>>> {
389 self.inner.in_memory_state.state_by_number(number)
390 }
391
392 pub fn head_state(&self) -> Option<Arc<BlockState<N>>> {
394 self.inner.in_memory_state.head_state()
395 }
396
397 pub fn pending_state(&self) -> Option<BlockState<N>> {
399 self.inner.in_memory_state.pending_state()
400 }
401
402 pub fn pending_block_num_hash(&self) -> Option<BlockNumHash> {
404 self.inner
405 .in_memory_state
406 .pending_state()
407 .map(|state| BlockNumHash { number: state.number(), hash: state.hash() })
408 }
409
410 pub fn chain_info(&self) -> ChainInfo {
412 self.inner.chain_info_tracker.chain_info()
413 }
414
415 pub fn get_canonical_block_number(&self) -> u64 {
417 self.inner.chain_info_tracker.get_canonical_block_number()
418 }
419
420 pub fn get_safe_num_hash(&self) -> Option<BlockNumHash> {
422 self.inner.chain_info_tracker.get_safe_num_hash()
423 }
424
425 pub fn get_finalized_num_hash(&self) -> Option<BlockNumHash> {
427 self.inner.chain_info_tracker.get_finalized_num_hash()
428 }
429
430 pub fn on_forkchoice_update_received(&self) {
432 self.inner.chain_info_tracker.on_forkchoice_update_received();
433 }
434
435 pub fn last_received_update_timestamp(&self) -> Option<Instant> {
437 self.inner.chain_info_tracker.last_forkchoice_update_received_at()
438 }
439
440 pub fn set_canonical_head(&self, header: SealedHeader<N::BlockHeader>) {
442 self.inner.chain_info_tracker.set_canonical_head(header);
443 }
444
445 pub fn set_safe(&self, header: SealedHeader<N::BlockHeader>) {
447 self.inner.chain_info_tracker.set_safe(header);
448 }
449
450 pub fn set_finalized(&self, header: SealedHeader<N::BlockHeader>) {
452 self.inner.chain_info_tracker.set_finalized(header);
453 }
454
455 pub fn set_persisted(&self, num_hash: BlockNumHash) {
457 self.inner.chain_info_tracker.set_persisted(num_hash);
458 }
459
460 pub fn get_canonical_head(&self) -> SealedHeader<N::BlockHeader> {
462 self.inner.chain_info_tracker.get_canonical_head()
463 }
464
465 pub fn get_finalized_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
467 self.inner.chain_info_tracker.get_finalized_header()
468 }
469
470 pub fn get_safe_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
472 self.inner.chain_info_tracker.get_safe_header()
473 }
474
475 pub fn get_persisted_num_hash(&self) -> Option<BlockNumHash> {
477 self.inner.chain_info_tracker.get_persisted_num_hash()
478 }
479
480 pub fn pending_sealed_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
482 self.pending_state().map(|h| h.block_ref().recovered_block().clone_sealed_header())
483 }
484
485 pub fn pending_header(&self) -> Option<N::BlockHeader> {
487 self.pending_sealed_header().map(|sealed_header| sealed_header.unseal())
488 }
489
490 pub fn pending_block(&self) -> Option<SealedBlock<N::Block>> {
492 self.pending_state()
493 .map(|block_state| block_state.block_ref().recovered_block().sealed_block().clone())
494 }
495
496 pub fn pending_recovered_block(&self) -> Option<Arc<RecoveredBlock<N::Block>>> {
498 self.pending_state().map(|block_state| Arc::clone(&block_state.block_ref().recovered_block))
499 }
500
501 pub fn pending_block_and_receipts(
503 &self,
504 ) -> Option<RecoveredBlockAndExecutionOutput<N::Block, N::Receipt>> {
505 self.pending_state().map(|block_state| {
506 RecoveredBlockAndExecutionOutput::new(
507 Arc::clone(&block_state.block_ref().recovered_block),
508 Arc::clone(&block_state.block_ref().execution_output),
509 )
510 })
511 }
512
513 pub fn subscribe_canon_state(&self) -> CanonStateNotifications<N> {
515 self.inner.canon_state_notification_sender.subscribe()
516 }
517
518 pub fn subscribe_safe_block(&self) -> watch::Receiver<Option<SealedHeader<N::BlockHeader>>> {
520 self.inner.chain_info_tracker.subscribe_safe_block()
521 }
522
523 pub fn subscribe_finalized_block(
525 &self,
526 ) -> watch::Receiver<Option<SealedHeader<N::BlockHeader>>> {
527 self.inner.chain_info_tracker.subscribe_finalized_block()
528 }
529
530 pub fn subscribe_persisted_block(&self) -> watch::Receiver<Option<BlockNumHash>> {
532 self.inner.chain_info_tracker.subscribe_persisted_block()
533 }
534
535 pub fn notify_canon_state(&self, event: CanonStateNotification<N>) {
537 self.inner.canon_state_notification_sender.send(event).ok();
538 }
539
540 pub fn canonical_chain(&self) -> impl Iterator<Item = Arc<BlockState<N>>> {
545 self.inner.in_memory_state.head_state().into_iter().flat_map(|head| head.iter())
546 }
547
548 pub fn transaction_by_hash(&self, hash: TxHash) -> Option<N::SignedTx> {
550 for block_state in self.canonical_chain() {
551 if let Some(tx) =
552 block_state.block_ref().recovered_block().body().transaction_by_hash(&hash)
553 {
554 return Some(tx.clone())
555 }
556 }
557 None
558 }
559
560 pub fn transaction_by_hash_with_meta(
563 &self,
564 tx_hash: TxHash,
565 ) -> Option<(N::SignedTx, TransactionMeta)> {
566 for block_state in self.canonical_chain() {
567 if let Some(indexed) = block_state.find_indexed(tx_hash) {
568 return Some((indexed.tx().clone(), indexed.meta()));
569 }
570 }
571 None
572 }
573}
574
575#[derive(Debug, Clone)]
578pub struct BlockState<N: NodePrimitives = EthPrimitives> {
579 block: ExecutedBlock<N>,
581 parent: Option<Arc<Self>>,
583}
584
585impl<N: NodePrimitives> PartialEq for BlockState<N> {
586 fn eq(&self, other: &Self) -> bool {
587 self.block == other.block && self.parent == other.parent
588 }
589}
590
591impl<N: NodePrimitives> BlockState<N> {
592 pub const fn new(block: ExecutedBlock<N>) -> Self {
594 Self { block, parent: None }
595 }
596
597 pub const fn with_parent(block: ExecutedBlock<N>, parent: Option<Arc<Self>>) -> Self {
599 Self { block, parent }
600 }
601
602 pub fn anchor(&self) -> BlockNumHash {
604 let mut current = self;
605 while let Some(parent) = ¤t.parent {
606 current = parent;
607 }
608 current.block.recovered_block().parent_num_hash()
609 }
610
611 pub fn block(&self) -> ExecutedBlock<N> {
613 self.block.clone()
614 }
615
616 pub const fn block_ref(&self) -> &ExecutedBlock<N> {
618 &self.block
619 }
620
621 pub fn hash(&self) -> B256 {
623 self.block.recovered_block().hash()
624 }
625
626 pub fn number(&self) -> u64 {
628 self.block.recovered_block().number()
629 }
630
631 pub fn state_root(&self) -> B256 {
634 self.block.recovered_block().state_root()
635 }
636
637 pub fn receipts(&self) -> &Vec<N::Receipt> {
639 &self.block.execution_outcome().receipts
640 }
641
642 pub fn executed_block_receipts(&self) -> Vec<N::Receipt> {
649 self.receipts().clone()
650 }
651
652 pub fn executed_block_receipts_ref(&self) -> &[N::Receipt] {
657 self.receipts()
658 }
659
660 pub fn parent_state_chain(&self) -> impl Iterator<Item = &Self> + '_ {
667 std::iter::successors(self.parent.as_deref(), |state| state.parent.as_deref())
668 }
669
670 pub fn chain(&self) -> impl Iterator<Item = &Self> {
674 std::iter::successors(Some(self), |state| state.parent.as_deref())
675 }
676
677 pub fn append_parent_chain<'a>(&'a self, chain: &mut Vec<&'a Self>) {
684 chain.extend(self.parent_state_chain());
685 }
686
687 pub fn iter(self: Arc<Self>) -> impl Iterator<Item = Arc<Self>> {
691 std::iter::successors(Some(self), |state| state.parent.clone())
692 }
693
694 pub fn block_on_chain(&self, hash_or_num: BlockHashOrNumber) -> Option<&Self> {
696 self.chain().find(|block| match hash_or_num {
697 BlockHashOrNumber::Hash(hash) => block.hash() == hash,
698 BlockHashOrNumber::Number(number) => block.number() == number,
699 })
700 }
701
702 pub fn transaction_on_chain(&self, hash: TxHash) -> Option<N::SignedTx> {
704 self.chain().find_map(|block_state| {
705 block_state.block_ref().recovered_block().body().transaction_by_hash(&hash).cloned()
706 })
707 }
708
709 pub fn transaction_meta_on_chain(
711 &self,
712 tx_hash: TxHash,
713 ) -> Option<(N::SignedTx, TransactionMeta)> {
714 self.chain().find_map(|block_state| {
715 block_state.find_indexed(tx_hash).map(|indexed| (indexed.tx().clone(), indexed.meta()))
716 })
717 }
718
719 pub fn find_indexed(&self, tx_hash: TxHash) -> Option<IndexedTx<'_, N::Block>> {
721 self.block_ref().recovered_block().find_indexed(tx_hash)
722 }
723}
724
725impl<N: NodePrimitives> Drop for BlockState<N> {
728 fn drop(&mut self) {
729 let mut parent = self.parent.take();
730 while let Some(state) = parent {
731 let Some(mut state) = Arc::into_inner(state) else { break };
734 parent = state.parent.take();
736 }
737 }
738}
739
740#[derive(Clone, Debug)]
742pub struct ExecutedBlock<N: NodePrimitives = EthPrimitives> {
743 pub recovered_block: Arc<RecoveredBlock<N::Block>>,
745 pub execution_output: Arc<BlockExecutionOutput<N::Receipt>>,
747 pub trie_data: LazyTrieData,
752 pub bal: Option<Arc<DecodedRevmBal>>,
764}
765
766impl<N: NodePrimitives> Default for ExecutedBlock<N> {
767 fn default() -> Self {
768 Self {
769 recovered_block: Default::default(),
770 execution_output: Arc::new(BlockExecutionOutput {
771 result: BlockExecutionResult {
772 receipts: Default::default(),
773 requests: Default::default(),
774 gas_used: 0,
775 blob_gas_used: 0,
776 },
777 state: Default::default(),
778 }),
779 trie_data: LazyTrieData::ready(SortedTrieData::default()),
780 bal: None,
781 }
782 }
783}
784
785impl<N: NodePrimitives> PartialEq for ExecutedBlock<N> {
786 fn eq(&self, other: &Self) -> bool {
787 self.recovered_block == other.recovered_block &&
790 self.execution_output == other.execution_output
791 }
792}
793
794impl<N: NodePrimitives> ExecutedBlock<N> {
795 pub fn new(
800 recovered_block: Arc<RecoveredBlock<N::Block>>,
801 execution_output: Arc<BlockExecutionOutput<N::Receipt>>,
802 trie_data: SortedTrieData,
803 ) -> Self {
804 Self {
805 recovered_block,
806 execution_output,
807 trie_data: LazyTrieData::ready(trie_data),
808 bal: None,
809 }
810 }
811
812 pub const fn with_deferred_trie_data(
826 recovered_block: Arc<RecoveredBlock<N::Block>>,
827 execution_output: Arc<BlockExecutionOutput<N::Receipt>>,
828 trie_data: LazyTrieData,
829 ) -> Self {
830 Self { recovered_block, execution_output, trie_data, bal: None }
831 }
832
833 pub fn with_bal(mut self, bal: Option<Arc<DecodedRevmBal>>) -> Self {
835 self.bal = bal;
836 self
837 }
838
839 #[inline]
843 pub const fn bal(&self) -> Option<&Arc<DecodedRevmBal>> {
844 self.bal.as_ref()
845 }
846
847 #[inline]
849 pub fn sealed_block(&self) -> &SealedBlock<N::Block> {
850 self.recovered_block.sealed_block()
851 }
852
853 #[inline]
855 pub fn recovered_block(&self) -> &RecoveredBlock<N::Block> {
856 &self.recovered_block
857 }
858
859 #[inline]
861 pub fn execution_outcome(&self) -> &BlockExecutionOutput<N::Receipt> {
862 &self.execution_output
863 }
864
865 #[inline]
871 #[tracing::instrument(level = "debug", target = "engine::tree", name = "trie_data", skip_all)]
872 pub fn trie_data(&self) -> SortedTrieData {
873 self.trie_data.get().clone()
874 }
875
876 #[inline]
881 pub fn trie_data_handle(&self) -> LazyTrieData {
882 self.trie_data.clone()
883 }
884
885 #[inline]
889 pub fn hashed_state(&self) -> Arc<HashedPostStateSorted> {
890 self.trie_data().hashed_state
891 }
892
893 #[inline]
897 pub fn hashed_state_ref(&self) -> &HashedPostStateSorted {
898 &self.trie_data.get().hashed_state
899 }
900
901 pub fn hashed_state_refs(blocks: &[Self]) -> Vec<&HashedPostStateSorted> {
905 blocks.iter().map(Self::hashed_state_ref).collect()
906 }
907
908 #[inline]
912 pub fn trie_updates(&self) -> Arc<TrieUpdatesSorted> {
913 self.trie_data().trie_updates
914 }
915
916 #[inline]
920 pub fn trie_updates_ref(&self) -> &TrieUpdatesSorted {
921 &self.trie_data.get().trie_updates
922 }
923
924 pub fn trie_updates_refs(blocks: &[Self]) -> Vec<&TrieUpdatesSorted> {
928 blocks.iter().map(Self::trie_updates_ref).collect()
929 }
930
931 #[inline]
933 pub fn block_number(&self) -> BlockNumber {
934 self.recovered_block.header().number()
935 }
936}
937
938#[derive(Debug)]
940pub enum NewCanonicalChain<N: NodePrimitives = EthPrimitives> {
941 Commit {
943 new: Vec<ExecutedBlock<N>>,
945 },
946 Reorg {
949 new: Vec<ExecutedBlock<N>>,
951 old: Vec<ExecutedBlock<N>>,
953 },
954}
955
956impl<N: NodePrimitives<SignedTx: SignedTransaction>> NewCanonicalChain<N> {
957 pub const fn new_block_count(&self) -> usize {
959 match self {
960 Self::Commit { new } | Self::Reorg { new, .. } => new.len(),
961 }
962 }
963
964 pub const fn reorged_block_count(&self) -> usize {
966 match self {
967 Self::Commit { .. } => 0,
968 Self::Reorg { old, .. } => old.len(),
969 }
970 }
971
972 pub fn to_chain_notification(&self) -> CanonStateNotification<N> {
974 match self {
975 Self::Commit { new } => {
976 CanonStateNotification::Commit { new: Arc::new(Self::blocks_to_chain(new)) }
977 }
978 Self::Reorg { new, old } => CanonStateNotification::Reorg {
979 new: Arc::new(Self::blocks_to_chain(new)),
980 old: Arc::new(Self::blocks_to_chain(old)),
981 },
982 }
983 }
984
985 fn blocks_to_chain(blocks: &[ExecutedBlock<N>]) -> Chain<N> {
987 let mut chain = match blocks {
988 [] => Chain::default(),
989 [first, rest @ ..] => {
990 let mut chain = Chain::from_block(
991 Arc::clone(&first.recovered_block),
992 ExecutionOutcome::from((
993 first.execution_outcome().clone(),
994 first.block_number(),
995 )),
996 first.trie_data_handle(),
997 );
998 for exec in rest {
999 chain.append_block(
1000 Arc::clone(&exec.recovered_block),
1001 ExecutionOutcome::from((
1002 exec.execution_outcome().clone(),
1003 exec.block_number(),
1004 )),
1005 exec.trie_data_handle(),
1006 );
1007 }
1008 chain
1009 }
1010 };
1011 for exec in blocks {
1012 if let Some(bal) = exec.bal() {
1013 chain.insert_bal(exec.block_number(), Arc::clone(bal));
1014 }
1015 }
1016 chain
1017 }
1018
1019 pub fn tip(&self) -> &RecoveredBlock<N::Block> {
1024 self.new_blocks().last().expect("non empty blocks").recovered_block()
1025 }
1026
1027 pub fn new_blocks(&self) -> &[ExecutedBlock<N>] {
1029 match self {
1030 Self::Commit { new } | Self::Reorg { new, .. } => new,
1031 }
1032 }
1033
1034 pub fn contains(&self, hash: B256) -> bool {
1038 self.new_blocks().iter().any(|block| block.recovered_block().hash() == hash)
1039 }
1040}
1041
1042#[cfg(test)]
1043mod tests {
1044 use super::*;
1045 use crate::test_utils::TestBlockBuilder;
1046 use alloy_eips::eip7685::Requests;
1047 use alloy_primitives::Bytes;
1048 use rand::Rng;
1049 use reth_ethereum_primitives::{EthPrimitives, Receipt};
1050
1051 fn create_mock_state(
1052 test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
1053 block_number: u64,
1054 parent_hash: B256,
1055 ) -> BlockState {
1056 BlockState::new(
1057 test_block_builder.get_executed_block_with_number(block_number, parent_hash),
1058 )
1059 }
1060
1061 fn create_mock_state_chain(
1062 test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
1063 num_blocks: u64,
1064 ) -> Vec<BlockState> {
1065 let mut chain = Vec::with_capacity(num_blocks as usize);
1066 let mut parent_hash = B256::random();
1067 let mut parent_state: Option<BlockState> = None;
1068
1069 for i in 1..=num_blocks {
1070 let mut state = create_mock_state(test_block_builder, i, parent_hash);
1071 if let Some(parent) = parent_state {
1072 state.parent = Some(Arc::new(parent));
1073 }
1074 parent_hash = state.hash();
1075 parent_state = Some(state.clone());
1076 chain.push(state);
1077 }
1078
1079 chain
1080 }
1081
1082 #[test]
1083 fn test_in_memory_state_impl_state_by_hash() {
1084 let mut state_by_hash = B256Map::default();
1085 let number = rand::rng().random::<u64>();
1086 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1087 let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1088 state_by_hash.insert(state.hash(), state.clone());
1089
1090 let in_memory_state = InMemoryState::new(state_by_hash, BTreeMap::new(), None);
1091
1092 assert_eq!(in_memory_state.state_by_hash(state.hash()), Some(state));
1093 assert_eq!(in_memory_state.state_by_hash(B256::random()), None);
1094 }
1095
1096 #[test]
1097 fn test_in_memory_state_impl_state_by_number() {
1098 let mut state_by_hash = B256Map::default();
1099 let mut hash_by_number = BTreeMap::new();
1100
1101 let number = rand::rng().random::<u64>();
1102 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1103 let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1104 let hash = state.hash();
1105
1106 state_by_hash.insert(hash, state.clone());
1107 hash_by_number.insert(number, hash);
1108
1109 let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1110
1111 assert_eq!(in_memory_state.state_by_number(number), Some(state));
1112 assert_eq!(in_memory_state.state_by_number(number + 1), None);
1113 }
1114
1115 #[test]
1116 fn test_in_memory_state_impl_head_state() {
1117 let mut state_by_hash = B256Map::default();
1118 let mut hash_by_number = BTreeMap::new();
1119 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1120 let state1 = Arc::new(create_mock_state(&mut test_block_builder, 1, B256::random()));
1121 let hash1 = state1.hash();
1122 let state2 = Arc::new(create_mock_state(&mut test_block_builder, 2, hash1));
1123 let hash2 = state2.hash();
1124 hash_by_number.insert(1, hash1);
1125 hash_by_number.insert(2, hash2);
1126 state_by_hash.insert(hash1, state1);
1127 state_by_hash.insert(hash2, state2);
1128
1129 let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1130 let head_state = in_memory_state.head_state().unwrap();
1131
1132 assert_eq!(head_state.hash(), hash2);
1133 assert_eq!(head_state.number(), 2);
1134 }
1135
1136 #[test]
1137 fn test_in_memory_state_impl_pending_state() {
1138 let pending_number = rand::rng().random::<u64>();
1139 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1140 let pending_state =
1141 create_mock_state(&mut test_block_builder, pending_number, B256::random());
1142 let pending_hash = pending_state.hash();
1143
1144 let in_memory_state =
1145 InMemoryState::new(B256Map::default(), BTreeMap::new(), Some(pending_state));
1146
1147 let result = in_memory_state.pending_state();
1148 assert!(result.is_some());
1149 let actual_pending_state = result.unwrap();
1150 assert_eq!(actual_pending_state.block.recovered_block().hash(), pending_hash);
1151 assert_eq!(actual_pending_state.block.recovered_block().number, pending_number);
1152 }
1153
1154 #[test]
1155 fn test_in_memory_state_impl_no_pending_state() {
1156 let in_memory_state: InMemoryState =
1157 InMemoryState::new(B256Map::default(), BTreeMap::new(), None);
1158
1159 assert_eq!(in_memory_state.pending_state(), None);
1160 }
1161
1162 #[test]
1163 fn test_state() {
1164 let number = rand::rng().random::<u64>();
1165 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1166 let block = test_block_builder.get_executed_block_with_number(number, B256::random());
1167
1168 let state = BlockState::new(block.clone());
1169
1170 assert_eq!(state.block(), block);
1171 assert_eq!(state.hash(), block.recovered_block().hash());
1172 assert_eq!(state.number(), number);
1173 assert_eq!(state.state_root(), block.recovered_block().state_root);
1174 }
1175
1176 #[test]
1177 fn test_state_receipts() {
1178 let receipts = vec![vec![Receipt::default()]];
1179 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1180 let block =
1181 test_block_builder.get_executed_block_with_receipts(receipts.clone(), B256::random());
1182
1183 let state = BlockState::new(block);
1184
1185 assert_eq!(state.receipts(), receipts.first().unwrap());
1186 }
1187
1188 #[test]
1189 fn test_in_memory_state_chain_update() {
1190 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1191 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1192 let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1193 let block2 = test_block_builder.get_executed_block_with_number(0, B256::random());
1194 let chain = NewCanonicalChain::Commit { new: vec![block1.clone()] };
1195 state.update_chain(chain);
1196 assert_eq!(
1197 state.head_state().unwrap().block_ref().recovered_block().hash(),
1198 block1.recovered_block().hash()
1199 );
1200 assert_eq!(
1201 state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1202 block1.recovered_block().hash()
1203 );
1204
1205 let chain = NewCanonicalChain::Reorg { new: vec![block2.clone()], old: vec![block1] };
1206 state.update_chain(chain);
1207 assert_eq!(
1208 state.head_state().unwrap().block_ref().recovered_block().hash(),
1209 block2.recovered_block().hash()
1210 );
1211 assert_eq!(
1212 state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1213 block2.recovered_block().hash()
1214 );
1215
1216 assert_eq!(state.inner.in_memory_state.block_count(), 1);
1217 }
1218
1219 #[test]
1220 fn test_in_memory_state_set_pending_block() {
1221 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1222 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1223
1224 let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1226
1227 let block2 =
1229 test_block_builder.get_executed_block_with_number(1, block1.recovered_block().hash());
1230
1231 let chain = NewCanonicalChain::Commit { new: vec![block1.clone(), block2.clone()] };
1233 state.update_chain(chain);
1234
1235 assert!(state.pending_state().is_none());
1237
1238 state.set_pending_block(block2.clone());
1240
1241 assert_eq!(
1243 state.pending_state().unwrap(),
1244 BlockState::with_parent(block2.clone(), Some(Arc::new(BlockState::new(block1))))
1245 );
1246
1247 assert_eq!(state.pending_block().unwrap(), block2.recovered_block().sealed_block().clone());
1249
1250 assert_eq!(
1252 state.pending_block_num_hash().unwrap(),
1253 BlockNumHash { number: 1, hash: block2.recovered_block().hash() }
1254 );
1255
1256 assert_eq!(state.pending_header().unwrap(), block2.recovered_block().header().clone());
1258
1259 assert_eq!(
1261 state.pending_sealed_header().unwrap(),
1262 block2.recovered_block().clone_sealed_header()
1263 );
1264
1265 let pending_block = state.pending_recovered_block().unwrap();
1267 assert!(Arc::ptr_eq(&pending_block, &block2.recovered_block));
1268
1269 let pending = state.pending_block_and_receipts().unwrap();
1271 assert!(Arc::ptr_eq(pending.block(), &block2.recovered_block));
1272 assert!(Arc::ptr_eq(pending.execution_output(), &block2.execution_output));
1273 }
1274
1275 #[test]
1276 fn test_canonical_in_memory_state_canonical_chain_empty() {
1277 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1278 assert!(state.canonical_chain().next().is_none());
1279 }
1280
1281 #[test]
1282 fn test_canonical_in_memory_state_canonical_chain_single_block() {
1283 let block = TestBlockBuilder::eth().get_executed_block_with_number(1, B256::random());
1284 let hash = block.recovered_block().hash();
1285 let mut blocks = B256Map::default();
1286 blocks.insert(hash, Arc::new(BlockState::new(block)));
1287 let mut numbers = BTreeMap::new();
1288 numbers.insert(1, hash);
1289
1290 let state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1291 let chain: Vec<_> = state.canonical_chain().collect();
1292
1293 assert_eq!(chain.len(), 1);
1294 assert_eq!(chain[0].number(), 1);
1295 assert_eq!(chain[0].hash(), hash);
1296 }
1297
1298 #[test]
1299 fn test_canonical_in_memory_state_canonical_chain_multiple_blocks() {
1300 let mut parent_hash = B256::random();
1301 let mut block_builder = TestBlockBuilder::eth();
1302 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1303
1304 for i in 1..=3 {
1305 let block = block_builder.get_executed_block_with_number(i, parent_hash);
1306 let hash = block.recovered_block().hash();
1307 state.update_blocks(Some(block), None);
1308 parent_hash = hash;
1309 }
1310
1311 let chain: Vec<_> = state.canonical_chain().collect();
1312
1313 assert_eq!(chain.len(), 3);
1314 assert_eq!(chain[0].number(), 3);
1315 assert_eq!(chain[1].number(), 2);
1316 assert_eq!(chain[2].number(), 1);
1317 }
1318
1319 #[test]
1321 fn test_canonical_in_memory_state_canonical_chain_with_pending_block() {
1322 let mut parent_hash = B256::random();
1323 let mut block_builder = TestBlockBuilder::<EthPrimitives>::eth();
1324 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1325
1326 for i in 1..=2 {
1327 let block = block_builder.get_executed_block_with_number(i, parent_hash);
1328 let hash = block.recovered_block().hash();
1329 state.update_blocks(Some(block), None);
1330 parent_hash = hash;
1331 }
1332
1333 let pending_block = block_builder.get_executed_block_with_number(3, parent_hash);
1334 state.set_pending_block(pending_block);
1335 let chain: Vec<_> = state.canonical_chain().collect();
1336
1337 assert_eq!(chain.len(), 2);
1338 assert_eq!(chain[0].number(), 2);
1339 assert_eq!(chain[1].number(), 1);
1340 }
1341
1342 #[test]
1343 fn test_block_state_parent_blocks() {
1344 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1345 let chain = create_mock_state_chain(&mut test_block_builder, 4);
1346
1347 let parents: Vec<_> = chain[3].parent_state_chain().collect();
1348 assert_eq!(parents.len(), 3);
1349 assert_eq!(parents[0].block().recovered_block().number, 3);
1350 assert_eq!(parents[1].block().recovered_block().number, 2);
1351 assert_eq!(parents[2].block().recovered_block().number, 1);
1352
1353 let parents: Vec<_> = chain[2].parent_state_chain().collect();
1354 assert_eq!(parents.len(), 2);
1355 assert_eq!(parents[0].block().recovered_block().number, 2);
1356 assert_eq!(parents[1].block().recovered_block().number, 1);
1357
1358 assert_eq!(chain[0].parent_state_chain().count(), 0);
1359 }
1360
1361 #[test]
1362 fn test_block_state_single_block_state_chain() {
1363 let single_block_number = 1;
1364 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1365 let single_block =
1366 create_mock_state(&mut test_block_builder, single_block_number, B256::random());
1367 let single_block_hash = single_block.block().recovered_block().hash();
1368
1369 assert_eq!(single_block.parent_state_chain().count(), 0);
1370
1371 let block_state_chain = single_block.chain().collect::<Vec<_>>();
1372 assert_eq!(block_state_chain.len(), 1);
1373 assert_eq!(block_state_chain[0].block().recovered_block().number, single_block_number);
1374 assert_eq!(block_state_chain[0].block().recovered_block().hash(), single_block_hash);
1375 }
1376
1377 #[test]
1378 fn test_block_state_chain() {
1379 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1380 let chain = create_mock_state_chain(&mut test_block_builder, 3);
1381
1382 let block_state_chain = chain[2].chain().collect::<Vec<_>>();
1383 assert_eq!(block_state_chain.len(), 3);
1384 assert_eq!(block_state_chain[0].block().recovered_block().number, 3);
1385 assert_eq!(block_state_chain[1].block().recovered_block().number, 2);
1386 assert_eq!(block_state_chain[2].block().recovered_block().number, 1);
1387
1388 let block_state_chain = chain[1].chain().collect::<Vec<_>>();
1389 assert_eq!(block_state_chain.len(), 2);
1390 assert_eq!(block_state_chain[0].block().recovered_block().number, 2);
1391 assert_eq!(block_state_chain[1].block().recovered_block().number, 1);
1392
1393 let block_state_chain = chain[0].chain().collect::<Vec<_>>();
1394 assert_eq!(block_state_chain.len(), 1);
1395 assert_eq!(block_state_chain[0].block().recovered_block().number, 1);
1396 }
1397
1398 #[test]
1399 fn test_to_chain_notification() {
1400 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1402 let block0 = test_block_builder.get_executed_block_with_number(0, B256::random());
1403 let block1 =
1404 test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1405 let block1a =
1406 test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1407 let block2 =
1408 test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1409 let block2a =
1410 test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1411
1412 let chain_commit = NewCanonicalChain::Commit { new: vec![block0.clone(), block1.clone()] };
1414
1415 let mut expected_trie_data = BTreeMap::new();
1417 expected_trie_data.insert(0, LazyTrieData::ready(block0.trie_data()));
1418 expected_trie_data.insert(1, LazyTrieData::ready(block1.trie_data()));
1419
1420 let commit_execution_outcome = ExecutionOutcome {
1422 receipts: vec![vec![], vec![]],
1423 requests: vec![Requests::default(), Requests::default()],
1424 first_block: 0,
1425 ..Default::default()
1426 };
1427
1428 assert_eq!(
1429 chain_commit.to_chain_notification(),
1430 CanonStateNotification::Commit {
1431 new: Arc::new(Chain::new(
1432 vec![block0.recovered_block().clone(), block1.recovered_block().clone()],
1433 commit_execution_outcome,
1434 expected_trie_data,
1435 ))
1436 }
1437 );
1438
1439 let chain_reorg = NewCanonicalChain::Reorg {
1441 new: vec![block1a.clone(), block2a.clone()],
1442 old: vec![block1.clone(), block2.clone()],
1443 };
1444
1445 let mut old_trie_data = BTreeMap::new();
1447 old_trie_data.insert(1, LazyTrieData::ready(block1.trie_data()));
1448 old_trie_data.insert(2, LazyTrieData::ready(block2.trie_data()));
1449
1450 let mut new_trie_data = BTreeMap::new();
1452 new_trie_data.insert(1, LazyTrieData::ready(block1a.trie_data()));
1453 new_trie_data.insert(2, LazyTrieData::ready(block2a.trie_data()));
1454
1455 let reorg_execution_outcome = ExecutionOutcome {
1458 receipts: vec![vec![], vec![]],
1459 requests: vec![Requests::default(), Requests::default()],
1460 first_block: 1,
1461 ..Default::default()
1462 };
1463
1464 assert_eq!(
1465 chain_reorg.to_chain_notification(),
1466 CanonStateNotification::Reorg {
1467 old: Arc::new(Chain::new(
1468 vec![block1.recovered_block().clone(), block2.recovered_block().clone()],
1469 reorg_execution_outcome.clone(),
1470 old_trie_data,
1471 )),
1472 new: Arc::new(Chain::new(
1473 vec![block1a.recovered_block().clone(), block2a.recovered_block().clone()],
1474 reorg_execution_outcome,
1475 new_trie_data,
1476 ))
1477 }
1478 );
1479 }
1480
1481 #[test]
1482 fn test_to_chain_notification_carries_prepared_bal() {
1483 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1484 let block0 = test_block_builder.get_executed_block_with_number(0, B256::random());
1485 let block1 = test_block_builder
1486 .get_executed_block_with_number(1, block0.recovered_block.hash())
1487 .with_bal(Some(Arc::new(DecodedRevmBal::new(
1488 Arc::new(revm::state::bal::Bal::default()),
1489 Bytes::from_static(&[0xc0]),
1490 ))));
1491
1492 let chain = NewCanonicalChain::Commit { new: vec![block0, block1.clone()] };
1493 let CanonStateNotification::Commit { new } = chain.to_chain_notification() else {
1494 panic!("expected a commit notification")
1495 };
1496
1497 assert_eq!(new.bals().len(), 1);
1499 assert_eq!(new.bal_at(1), block1.bal());
1500
1501 let mut blocks_and_bals = new.blocks_and_bals();
1502 let (block, bal) = blocks_and_bals.next().expect("block with BAL");
1503 assert_eq!(block.hash(), block1.recovered_block.hash());
1504 assert_eq!(Some(bal), block1.bal());
1505 assert!(blocks_and_bals.next().is_none());
1506 }
1507
1508 fn block_state_chain(depth: usize, mut parent: Option<Arc<BlockState>>) -> Arc<BlockState> {
1509 let block = ExecutedBlock::default();
1510 for _ in 0..depth {
1511 parent = Some(Arc::new(BlockState::with_parent(block.clone(), parent)));
1512 }
1513 parent.expect("nonempty chain")
1514 }
1515
1516 #[test]
1517 fn deep_chain_drop_preserves_shared_tail() {
1518 const DEPTH: usize = 100_000;
1519
1520 std::thread::Builder::new()
1522 .stack_size(64 * 1024)
1523 .spawn(|| {
1524 let tail = block_state_chain(DEPTH, None);
1525 let tail_payload = Arc::downgrade(&tail.block_ref().execution_output);
1526 let head = block_state_chain(DEPTH, Some(tail.clone()));
1527 let head_payload = Arc::downgrade(&head.block_ref().execution_output);
1528
1529 drop(head);
1530 assert_eq!(head_payload.strong_count(), 0);
1531 assert_eq!(Arc::strong_count(&tail), 1);
1532 assert_eq!(tail_payload.strong_count(), DEPTH);
1533
1534 drop(tail);
1535 assert_eq!(tail_payload.strong_count(), 0);
1536 })
1537 .unwrap()
1538 .join()
1539 .unwrap();
1540 }
1541}