1use super::externals::TreeExternals;
7use crate::BundleStateDataRef;
8use alloy_eips::ForkBlock;
9use alloy_primitives::{BlockHash, BlockNumber, U256};
10use reth_blockchain_tree_api::{
11 error::{BlockchainTreeError, InsertBlockErrorKind},
12 BlockAttachment, BlockValidationKind,
13};
14use reth_consensus::{ConsensusError, PostExecutionInput};
15use reth_evm::execute::{BlockExecutorProvider, Executor};
16use reth_execution_errors::BlockExecutionError;
17use reth_execution_types::{Chain, ExecutionOutcome};
18use reth_primitives::{GotExpected, SealedBlockWithSenders, SealedHeader};
19use reth_provider::{
20 providers::{BundleStateProvider, ConsistentDbView, TreeNodeTypes},
21 DBProvider, FullExecutionDataProvider, HashedPostStateProvider, ProviderError,
22 StateRootProvider, TryIntoHistoricalStateProvider,
23};
24use reth_revm::database::StateProviderDatabase;
25use reth_trie::{updates::TrieUpdates, TrieInput};
26use reth_trie_parallel::root::ParallelStateRoot;
27use std::{
28 collections::BTreeMap,
29 ops::{Deref, DerefMut},
30 time::Instant,
31};
32
33#[derive(Clone, Debug, Default, PartialEq, Eq)]
36pub struct AppendableChain {
37 chain: Chain,
38}
39
40impl Deref for AppendableChain {
41 type Target = Chain;
42
43 fn deref(&self) -> &Self::Target {
44 &self.chain
45 }
46}
47
48impl DerefMut for AppendableChain {
49 fn deref_mut(&mut self) -> &mut Self::Target {
50 &mut self.chain
51 }
52}
53
54impl AppendableChain {
55 pub const fn new(chain: Chain) -> Self {
57 Self { chain }
58 }
59
60 pub fn into_inner(self) -> Chain {
62 self.chain
63 }
64
65 pub fn new_canonical_fork<N, E>(
70 block: SealedBlockWithSenders,
71 parent_header: &SealedHeader,
72 canonical_block_hashes: &BTreeMap<BlockNumber, BlockHash>,
73 canonical_fork: ForkBlock,
74 externals: &TreeExternals<N, E>,
75 block_attachment: BlockAttachment,
76 block_validation_kind: BlockValidationKind,
77 ) -> Result<Self, InsertBlockErrorKind>
78 where
79 N: TreeNodeTypes,
80 E: BlockExecutorProvider<Primitives = N::Primitives>,
81 {
82 let execution_outcome = ExecutionOutcome::default();
83 let empty = BTreeMap::new();
84
85 let state_provider = BundleStateDataRef {
86 execution_outcome: &execution_outcome,
87 sidechain_block_hashes: &empty,
88 canonical_block_hashes,
89 canonical_fork,
90 };
91
92 let (bundle_state, trie_updates) = Self::validate_and_execute(
93 block.clone(),
94 parent_header,
95 state_provider,
96 externals,
97 block_attachment,
98 block_validation_kind,
99 )?;
100
101 Ok(Self::new(Chain::new(vec![block], bundle_state, trie_updates)))
102 }
103
104 pub(crate) fn new_chain_fork<N, E>(
108 &self,
109 block: SealedBlockWithSenders,
110 side_chain_block_hashes: BTreeMap<BlockNumber, BlockHash>,
111 canonical_block_hashes: &BTreeMap<BlockNumber, BlockHash>,
112 canonical_fork: ForkBlock,
113 externals: &TreeExternals<N, E>,
114 block_validation_kind: BlockValidationKind,
115 ) -> Result<Self, InsertBlockErrorKind>
116 where
117 N: TreeNodeTypes,
118 E: BlockExecutorProvider<Primitives = N::Primitives>,
119 {
120 let parent_number =
121 block.number.checked_sub(1).ok_or(BlockchainTreeError::GenesisBlockHasNoParent)?;
122 let parent = self.blocks().get(&parent_number).ok_or(
123 BlockchainTreeError::BlockNumberNotFoundInChain { block_number: parent_number },
124 )?;
125
126 let mut execution_outcome = self.execution_outcome().clone();
127
128 execution_outcome.revert_to(parent.number);
130
131 let bundle_state_data = BundleStateDataRef {
133 execution_outcome: &execution_outcome,
134 sidechain_block_hashes: &side_chain_block_hashes,
135 canonical_block_hashes,
136 canonical_fork,
137 };
138 let (block_state, _) = Self::validate_and_execute(
139 block.clone(),
140 parent,
141 bundle_state_data,
142 externals,
143 BlockAttachment::HistoricalFork,
144 block_validation_kind,
145 )?;
146 execution_outcome.extend(block_state);
149
150 let size = execution_outcome.receipts().len();
153 execution_outcome.receipts_mut().drain(0..size - 1);
154 execution_outcome.state_mut().take_n_reverts(size - 1);
155 execution_outcome.set_first_block(block.number);
156
157 Ok(Self::new(Chain::from_block(block, execution_outcome, None)))
159 }
160
161 fn validate_and_execute<EDP, N, E>(
171 block: SealedBlockWithSenders,
172 parent_block: &SealedHeader,
173 bundle_state_data_provider: EDP,
174 externals: &TreeExternals<N, E>,
175 block_attachment: BlockAttachment,
176 block_validation_kind: BlockValidationKind,
177 ) -> Result<(ExecutionOutcome, Option<TrieUpdates>), BlockExecutionError>
178 where
179 EDP: FullExecutionDataProvider,
180 N: TreeNodeTypes,
181 E: BlockExecutorProvider<Primitives = N::Primitives>,
182 {
183 externals.consensus.validate_header_against_parent(&block, parent_block)?;
185
186 let canonical_fork = bundle_state_data_provider.canonical_fork();
188
189 let consistent_view =
197 ConsistentDbView::new_with_latest_tip(externals.provider_factory.clone())?;
198 let state_provider = consistent_view
199 .provider_ro()?
200 .disable_long_read_transaction_safety()
203 .try_into_history_at_block(canonical_fork.number)?;
204
205 let provider = BundleStateProvider::new(state_provider, bundle_state_data_provider);
206
207 let db = StateProviderDatabase::new(&provider);
208 let executor = externals.executor_factory.executor(db);
209 let block_hash = block.hash();
210 let block = block.unseal();
211
212 let state = executor.execute((&block, U256::MAX).into())?;
213 externals.consensus.validate_block_post_execution(
214 &block,
215 PostExecutionInput::new(&state.receipts, &state.requests),
216 )?;
217
218 let initial_execution_outcome = ExecutionOutcome::from((state, block.number));
219
220 if block_validation_kind.is_exhaustive() {
223 let start = Instant::now();
225 let (state_root, trie_updates) = if block_attachment.is_canonical() {
226 let mut execution_outcome =
227 provider.block_execution_data_provider.execution_outcome().clone();
228 execution_outcome.extend(initial_execution_outcome.clone());
229 ParallelStateRoot::new(
230 consistent_view,
231 TrieInput::from_state(provider.hashed_post_state(execution_outcome.state())),
232 )
233 .incremental_root_with_updates()
234 .map(|(root, updates)| (root, Some(updates)))
235 .map_err(ProviderError::from)?
236 } else {
237 let hashed_state = provider.hashed_post_state(initial_execution_outcome.state());
238 let state_root = provider.state_root(hashed_state)?;
239 (state_root, None)
240 };
241 if block.state_root != state_root {
242 return Err(ConsensusError::BodyStateRootDiff(
243 GotExpected { got: state_root, expected: block.state_root }.into(),
244 )
245 .into())
246 }
247
248 tracing::debug!(
249 target: "blockchain_tree::chain",
250 number = block.number,
251 hash = %block_hash,
252 elapsed = ?start.elapsed(),
253 "Validated state root"
254 );
255
256 Ok((initial_execution_outcome, trie_updates))
257 } else {
258 Ok((initial_execution_outcome, None))
259 }
260 }
261
262 #[track_caller]
274 #[allow(clippy::too_many_arguments)]
275 pub(crate) fn append_block<N, E>(
276 &mut self,
277 block: SealedBlockWithSenders,
278 side_chain_block_hashes: BTreeMap<BlockNumber, BlockHash>,
279 canonical_block_hashes: &BTreeMap<BlockNumber, BlockHash>,
280 externals: &TreeExternals<N, E>,
281 canonical_fork: ForkBlock,
282 block_attachment: BlockAttachment,
283 block_validation_kind: BlockValidationKind,
284 ) -> Result<(), InsertBlockErrorKind>
285 where
286 N: TreeNodeTypes,
287 E: BlockExecutorProvider<Primitives = N::Primitives>,
288 {
289 let parent_block = self.chain.tip();
290
291 let bundle_state_data = BundleStateDataRef {
292 execution_outcome: self.execution_outcome(),
293 sidechain_block_hashes: &side_chain_block_hashes,
294 canonical_block_hashes,
295 canonical_fork,
296 };
297
298 let (block_state, _) = Self::validate_and_execute(
299 block.clone(),
300 parent_block,
301 bundle_state_data,
302 externals,
303 block_attachment,
304 block_validation_kind,
305 )?;
306 self.chain.append_block(block, block_state);
308
309 Ok(())
310 }
311}