mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(revm): Integrate State (#3512)
Co-authored-by: Roman Krasiuk <rokrassyuk@gmail.com> Co-authored-by: Alexey Shekhirin <a.shekhirin@gmail.com> Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com> Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>
This commit is contained in:
@ -31,8 +31,14 @@ use reth_primitives::{
|
||||
Header, ReceiptWithBloom, SealedBlock, SealedHeader, TransactionSigned, EMPTY_OMMER_ROOT, H256,
|
||||
U256,
|
||||
};
|
||||
use reth_provider::{BlockReaderIdExt, CanonStateNotificationSender, PostState, StateProvider};
|
||||
use reth_revm::executor::Executor;
|
||||
use reth_provider::{
|
||||
BlockExecutor, BlockReaderIdExt, BundleStateWithReceipts, CanonStateNotificationSender,
|
||||
StateProviderFactory,
|
||||
};
|
||||
use reth_revm::{
|
||||
database::StateProviderDatabase, db::states::bundle_state::BundleRetention,
|
||||
processor::EVMProcessor, State,
|
||||
};
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@ -289,41 +295,51 @@ impl StorageInner {
|
||||
header
|
||||
}
|
||||
|
||||
/// Executes the block with the given block and senders, on the provided [Executor].
|
||||
/// Executes the block with the given block and senders, on the provided [EVMProcessor].
|
||||
///
|
||||
/// This returns the poststate from execution and post-block changes, as well as the gas used.
|
||||
pub(crate) fn execute<DB: StateProvider>(
|
||||
pub(crate) fn execute(
|
||||
&mut self,
|
||||
block: &Block,
|
||||
executor: &mut Executor<DB>,
|
||||
executor: &mut EVMProcessor<'_>,
|
||||
senders: Vec<Address>,
|
||||
) -> Result<(PostState, u64), BlockExecutionError> {
|
||||
) -> Result<(BundleStateWithReceipts, u64), BlockExecutionError> {
|
||||
trace!(target: "consensus::auto", transactions=?&block.body, "executing transactions");
|
||||
|
||||
let (post_state, gas_used) =
|
||||
let (receipts, gas_used) =
|
||||
executor.execute_transactions(block, U256::ZERO, Some(senders))?;
|
||||
|
||||
// apply post block changes
|
||||
let post_state = executor.apply_post_block_changes(block, U256::ZERO, post_state)?;
|
||||
// Save receipts.
|
||||
executor.save_receipts(receipts)?;
|
||||
|
||||
Ok((post_state, gas_used))
|
||||
// add post execution state change
|
||||
// Withdrawals, rewards etc.
|
||||
executor.apply_post_execution_state_change(block, U256::ZERO)?;
|
||||
|
||||
// merge transitions
|
||||
executor.db_mut().merge_transitions(BundleRetention::Reverts);
|
||||
|
||||
// apply post block changes
|
||||
Ok((executor.take_output_state(), gas_used))
|
||||
}
|
||||
|
||||
/// Fills in the post-execution header fields based on the given PostState and gas used.
|
||||
/// Fills in the post-execution header fields based on the given BundleState and gas used.
|
||||
/// In doing this, the state root is calculated and the final header is returned.
|
||||
pub(crate) fn complete_header<DB: StateProvider>(
|
||||
pub(crate) fn complete_header<S: StateProviderFactory>(
|
||||
&self,
|
||||
mut header: Header,
|
||||
post_state: &PostState,
|
||||
executor: &mut Executor<DB>,
|
||||
bundle_state: &BundleStateWithReceipts,
|
||||
client: &S,
|
||||
gas_used: u64,
|
||||
) -> Header {
|
||||
let receipts = post_state.receipts(header.number);
|
||||
) -> Result<Header, BlockExecutionError> {
|
||||
let receipts = bundle_state.receipts_by_block(header.number);
|
||||
header.receipts_root = if receipts.is_empty() {
|
||||
EMPTY_RECEIPTS
|
||||
} else {
|
||||
let receipts_with_bloom =
|
||||
receipts.iter().map(|r| r.clone().into()).collect::<Vec<ReceiptWithBloom>>();
|
||||
let receipts_with_bloom = receipts
|
||||
.iter()
|
||||
.map(|r| (*r).clone().expect("receipts have not been pruned").into())
|
||||
.collect::<Vec<ReceiptWithBloom>>();
|
||||
header.logs_bloom =
|
||||
receipts_with_bloom.iter().fold(Bloom::zero(), |bloom, r| bloom | r.bloom);
|
||||
proofs::calculate_receipt_root(&receipts_with_bloom)
|
||||
@ -332,21 +348,25 @@ impl StorageInner {
|
||||
header.gas_used = gas_used;
|
||||
|
||||
// calculate the state root
|
||||
let state_root = executor.db().db.0.state_root(post_state.clone()).unwrap();
|
||||
let state_root = client
|
||||
.latest()
|
||||
.map_err(|_| BlockExecutionError::ProviderError)?
|
||||
.state_root(bundle_state.clone())
|
||||
.unwrap();
|
||||
header.state_root = state_root;
|
||||
header
|
||||
Ok(header)
|
||||
}
|
||||
|
||||
/// Builds and executes a new block with the given transactions, on the provided [Executor].
|
||||
/// Builds and executes a new block with the given transactions, on the provided [EVMProcessor].
|
||||
///
|
||||
/// This returns the header of the executed block, as well as the poststate from execution.
|
||||
pub(crate) fn build_and_execute<DB: StateProvider>(
|
||||
pub(crate) fn build_and_execute(
|
||||
&mut self,
|
||||
transactions: Vec<TransactionSigned>,
|
||||
executor: &mut Executor<DB>,
|
||||
client: &impl StateProviderFactory,
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
) -> Result<(SealedHeader, PostState), BlockExecutionError> {
|
||||
let header = self.build_header_template(&transactions, chain_spec);
|
||||
) -> Result<(SealedHeader, BundleStateWithReceipts), BlockExecutionError> {
|
||||
let header = self.build_header_template(&transactions, chain_spec.clone());
|
||||
|
||||
let block = Block { header, body: transactions, ommers: vec![], withdrawals: None };
|
||||
|
||||
@ -356,15 +376,21 @@ impl StorageInner {
|
||||
trace!(target: "consensus::auto", transactions=?&block.body, "executing transactions");
|
||||
|
||||
// now execute the block
|
||||
let (post_state, gas_used) = self.execute(&block, executor, senders)?;
|
||||
let db = State::builder()
|
||||
.with_database_boxed(Box::new(StateProviderDatabase::new(client.latest().unwrap())))
|
||||
.with_bundle_update()
|
||||
.build();
|
||||
let mut executor = EVMProcessor::new_with_state(chain_spec, db);
|
||||
|
||||
let (bundle_state, gas_used) = self.execute(&block, &mut executor, senders)?;
|
||||
|
||||
let Block { header, body, .. } = block;
|
||||
let body = BlockBody { transactions: body, ommers: vec![], withdrawals: None };
|
||||
|
||||
trace!(target: "consensus::auto", ?post_state, ?header, ?body, "executed block, calculating state root and completing header");
|
||||
trace!(target: "consensus::auto", ?bundle_state, ?header, ?body, "executed block, calculating state root and completing header");
|
||||
|
||||
// fill in the rest of the fields
|
||||
let header = self.complete_header(header, &post_state, executor, gas_used);
|
||||
let header = self.complete_header(header, &bundle_state, client, gas_used)?;
|
||||
|
||||
trace!(target: "consensus::auto", root=?header.state_root, ?body, "calculated root");
|
||||
|
||||
@ -374,6 +400,6 @@ impl StorageInner {
|
||||
// set new header with hash that should have been updated by insert_new_block
|
||||
let new_header = header.seal(self.best_hash);
|
||||
|
||||
Ok((new_header, post_state))
|
||||
Ok((new_header, bundle_state))
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,10 +4,6 @@ use reth_beacon_consensus::{BeaconEngineMessage, ForkchoiceStatus};
|
||||
use reth_interfaces::consensus::ForkchoiceState;
|
||||
use reth_primitives::{Block, ChainSpec, IntoRecoveredTransaction, SealedBlockWithSenders};
|
||||
use reth_provider::{CanonChainTracker, CanonStateNotificationSender, Chain, StateProviderFactory};
|
||||
use reth_revm::{
|
||||
database::{State, SubState},
|
||||
executor::Executor,
|
||||
};
|
||||
use reth_stages::PipelineEvent;
|
||||
use reth_transaction_pool::{TransactionPool, ValidPoolTransaction};
|
||||
use std::{
|
||||
@ -127,13 +123,8 @@ where
|
||||
})
|
||||
.unzip();
|
||||
|
||||
// execute the new block
|
||||
let substate = SubState::new(State::new(client.latest().unwrap()));
|
||||
let mut executor = Executor::new(Arc::clone(&chain_spec), substate);
|
||||
|
||||
match storage.build_and_execute(transactions.clone(), &mut executor, chain_spec)
|
||||
{
|
||||
Ok((new_header, post_state)) => {
|
||||
match storage.build_and_execute(transactions.clone(), &client, chain_spec) {
|
||||
Ok((new_header, bundle_state)) => {
|
||||
// clear all transactions from pool
|
||||
pool.remove_transactions(
|
||||
transactions.iter().map(|tx| tx.hash()).collect(),
|
||||
@ -202,7 +193,7 @@ where
|
||||
debug!(target: "consensus::auto", header=?sealed_block_with_senders.hash(), "sending block notification");
|
||||
|
||||
let chain =
|
||||
Arc::new(Chain::new(vec![(sealed_block_with_senders, post_state)]));
|
||||
Arc::new(Chain::new(vec![sealed_block_with_senders], bundle_state));
|
||||
|
||||
// send block notification
|
||||
let _ = canon_state_notification
|
||||
|
||||
Reference in New Issue
Block a user