1use crate::externals::TreeNodeTypes;
4
5use super::BlockchainTree;
6use alloy_eips::BlockNumHash;
7use alloy_primitives::{BlockHash, BlockNumber};
8use parking_lot::RwLock;
9use reth_blockchain_tree_api::{
10 error::{CanonicalError, InsertBlockError},
11 BlockValidationKind, BlockchainTreeEngine, BlockchainTreeViewer, CanonicalOutcome,
12 InsertPayloadOk,
13};
14use reth_evm::execute::BlockExecutorProvider;
15use reth_node_types::NodeTypesWithDB;
16use reth_primitives::{Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader};
17use reth_provider::{
18 providers::ProviderNodeTypes, BlockchainTreePendingStateProvider, CanonStateNotifications,
19 CanonStateSubscriptions, FullExecutionDataProvider, NodePrimitivesProvider, ProviderError,
20};
21use reth_storage_errors::provider::ProviderResult;
22use std::{collections::BTreeMap, sync::Arc};
23use tracing::trace;
24
25#[derive(Clone, Debug)]
27pub struct ShareableBlockchainTree<N: NodeTypesWithDB, E> {
28 pub tree: Arc<RwLock<BlockchainTree<N, E>>>,
30}
31
32impl<N: NodeTypesWithDB, E> ShareableBlockchainTree<N, E> {
33 pub fn new(tree: BlockchainTree<N, E>) -> Self {
35 Self { tree: Arc::new(RwLock::new(tree)) }
36 }
37}
38
39impl<N, E> BlockchainTreeEngine for ShareableBlockchainTree<N, E>
40where
41 N: TreeNodeTypes,
42 E: BlockExecutorProvider<Primitives = N::Primitives>,
43{
44 fn buffer_block(&self, block: SealedBlockWithSenders) -> Result<(), InsertBlockError> {
45 let mut tree = self.tree.write();
46 tree.buffer_block(block)
49 }
50
51 fn insert_block(
52 &self,
53 block: SealedBlockWithSenders,
54 validation_kind: BlockValidationKind,
55 ) -> Result<InsertPayloadOk, InsertBlockError> {
56 trace!(target: "blockchain_tree", hash = %block.hash(), number = block.number, parent_hash = %block.parent_hash, "Inserting block");
57 let mut tree = self.tree.write();
58 let res = tree.insert_block(block, validation_kind);
59 tree.update_chains_metrics();
60 res
61 }
62
63 fn finalize_block(&self, finalized_block: BlockNumber) -> ProviderResult<()> {
64 trace!(target: "blockchain_tree", finalized_block, "Finalizing block");
65 let mut tree = self.tree.write();
66 tree.finalize_block(finalized_block)?;
67 tree.update_chains_metrics();
68
69 Ok(())
70 }
71
72 fn connect_buffered_blocks_to_canonical_hashes_and_finalize(
73 &self,
74 last_finalized_block: BlockNumber,
75 ) -> Result<(), CanonicalError> {
76 trace!(target: "blockchain_tree", last_finalized_block, "Connecting buffered blocks to canonical hashes and finalizing the tree");
77 let mut tree = self.tree.write();
78 let res =
79 tree.connect_buffered_blocks_to_canonical_hashes_and_finalize(last_finalized_block);
80 tree.update_chains_metrics();
81 Ok(res?)
82 }
83
84 fn update_block_hashes_and_clear_buffered(
85 &self,
86 ) -> Result<BTreeMap<BlockNumber, BlockHash>, CanonicalError> {
87 let mut tree = self.tree.write();
88 let res = tree.update_block_hashes_and_clear_buffered();
89 tree.update_chains_metrics();
90 Ok(res?)
91 }
92
93 fn connect_buffered_blocks_to_canonical_hashes(&self) -> Result<(), CanonicalError> {
94 trace!(target: "blockchain_tree", "Connecting buffered blocks to canonical hashes");
95 let mut tree = self.tree.write();
96 let res = tree.connect_buffered_blocks_to_canonical_hashes();
97 tree.update_chains_metrics();
98 Ok(res?)
99 }
100
101 fn make_canonical(&self, block_hash: BlockHash) -> Result<CanonicalOutcome, CanonicalError> {
102 trace!(target: "blockchain_tree", %block_hash, "Making block canonical");
103 let mut tree = self.tree.write();
104 let res = tree.make_canonical(block_hash);
105 tree.update_chains_metrics();
106 res
107 }
108}
109
110impl<N, E> BlockchainTreeViewer for ShareableBlockchainTree<N, E>
111where
112 N: TreeNodeTypes,
113 E: BlockExecutorProvider<Primitives = N::Primitives>,
114{
115 fn header_by_hash(&self, hash: BlockHash) -> Option<SealedHeader> {
116 trace!(target: "blockchain_tree", ?hash, "Returning header by hash");
117 self.tree.read().sidechain_block_by_hash(hash).map(|b| b.header.clone())
118 }
119
120 fn block_by_hash(&self, block_hash: BlockHash) -> Option<SealedBlock> {
121 trace!(target: "blockchain_tree", ?block_hash, "Returning block by hash");
122 self.tree.read().sidechain_block_by_hash(block_hash).cloned()
123 }
124
125 fn block_with_senders_by_hash(&self, block_hash: BlockHash) -> Option<SealedBlockWithSenders> {
126 trace!(target: "blockchain_tree", ?block_hash, "Returning block by hash");
127 self.tree.read().block_with_senders_by_hash(block_hash).cloned()
128 }
129
130 fn buffered_header_by_hash(&self, block_hash: BlockHash) -> Option<SealedHeader> {
131 self.tree.read().get_buffered_block(&block_hash).map(|b| b.header.clone())
132 }
133
134 fn is_canonical(&self, hash: BlockHash) -> Result<bool, ProviderError> {
135 trace!(target: "blockchain_tree", ?hash, "Checking if block is canonical");
136 self.tree.read().is_block_hash_canonical(&hash)
137 }
138
139 fn lowest_buffered_ancestor(&self, hash: BlockHash) -> Option<SealedBlockWithSenders> {
140 trace!(target: "blockchain_tree", ?hash, "Returning lowest buffered ancestor");
141 self.tree.read().lowest_buffered_ancestor(&hash).cloned()
142 }
143
144 fn canonical_tip(&self) -> BlockNumHash {
145 trace!(target: "blockchain_tree", "Returning canonical tip");
146 self.tree.read().block_indices().canonical_tip()
147 }
148
149 fn pending_block_num_hash(&self) -> Option<BlockNumHash> {
150 trace!(target: "blockchain_tree", "Returning first pending block");
151 self.tree.read().block_indices().pending_block_num_hash()
152 }
153
154 fn pending_block(&self) -> Option<SealedBlock> {
155 trace!(target: "blockchain_tree", "Returning first pending block");
156 self.tree.read().pending_block().cloned()
157 }
158
159 fn pending_block_and_receipts(&self) -> Option<(SealedBlock, Vec<Receipt>)> {
160 let tree = self.tree.read();
161 let pending_block = tree.pending_block()?.clone();
162 let receipts =
163 tree.receipts_by_block_hash(pending_block.hash())?.into_iter().cloned().collect();
164 Some((pending_block, receipts))
165 }
166
167 fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<Vec<Receipt>> {
168 let tree = self.tree.read();
169 Some(tree.receipts_by_block_hash(block_hash)?.into_iter().cloned().collect())
170 }
171}
172
173impl<N, E> BlockchainTreePendingStateProvider for ShareableBlockchainTree<N, E>
174where
175 N: TreeNodeTypes,
176 E: BlockExecutorProvider<Primitives = N::Primitives>,
177{
178 fn find_pending_state_provider(
179 &self,
180 block_hash: BlockHash,
181 ) -> Option<Box<dyn FullExecutionDataProvider>> {
182 trace!(target: "blockchain_tree", ?block_hash, "Finding pending state provider");
183 let provider = self.tree.read().post_state_data(block_hash)?;
184 Some(Box::new(provider))
185 }
186}
187
188impl<N, E> NodePrimitivesProvider for ShareableBlockchainTree<N, E>
189where
190 N: ProviderNodeTypes,
191 E: Send + Sync,
192{
193 type Primitives = N::Primitives;
194}
195
196impl<N, E> CanonStateSubscriptions for ShareableBlockchainTree<N, E>
197where
198 N: TreeNodeTypes,
199 E: Send + Sync,
200{
201 fn subscribe_to_canonical_state(&self) -> CanonStateNotifications {
202 trace!(target: "blockchain_tree", "Registered subscriber for canonical state");
203 self.tree.read().subscribe_canon_state()
204 }
205}