From e7defb23345491297f35865b135ed03b29abfb5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Anda=20Estensen?= Date: Sat, 7 Sep 2024 11:27:38 +0200 Subject: [PATCH] feat: return executed block in eth payload builder (#10717) --- Cargo.lock | 2 + crates/ethereum/engine-primitives/Cargo.toml | 1 + .../ethereum/engine-primitives/src/payload.rs | 14 ++++++- crates/ethereum/payload/Cargo.toml | 1 + crates/ethereum/payload/src/lib.rs | 40 +++++++++++++++---- crates/payload/builder/src/lib.rs | 2 +- crates/payload/builder/src/test_utils.rs | 1 + 7 files changed, 52 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e696b72ac..cff9db821 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7092,6 +7092,7 @@ name = "reth-ethereum-engine-primitives" version = "1.0.6" dependencies = [ "alloy-rlp", + "reth-chain-state", "reth-chainspec", "reth-engine-primitives", "reth-evm-ethereum", @@ -7129,6 +7130,7 @@ name = "reth-ethereum-payload-builder" version = "1.0.6" dependencies = [ "reth-basic-payload-builder", + "reth-chain-state", "reth-errors", "reth-evm", "reth-evm-ethereum", diff --git a/crates/ethereum/engine-primitives/Cargo.toml b/crates/ethereum/engine-primitives/Cargo.toml index 8a1f25808..07ece0083 100644 --- a/crates/ethereum/engine-primitives/Cargo.toml +++ b/crates/ethereum/engine-primitives/Cargo.toml @@ -21,6 +21,7 @@ reth-rpc-types.workspace = true reth-rpc-types-compat.workspace = true revm-primitives.workspace = true alloy-rlp.workspace = true +reth-chain-state.workspace = true # misc serde.workspace = true diff --git a/crates/ethereum/engine-primitives/src/payload.rs b/crates/ethereum/engine-primitives/src/payload.rs index 7de120530..724e11b90 100644 --- a/crates/ethereum/engine-primitives/src/payload.rs +++ b/crates/ethereum/engine-primitives/src/payload.rs @@ -1,6 +1,7 @@ //! Contains types required for building a payload. use alloy_rlp::Encodable; +use reth_chain_state::ExecutedBlock; use reth_chainspec::ChainSpec; use reth_evm_ethereum::revm_spec_by_timestamp_after_merge; use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes}; @@ -30,6 +31,8 @@ pub struct EthBuiltPayload { pub(crate) id: PayloadId, /// The built block pub(crate) block: SealedBlock, + /// Block execution data for the payload, if any. + pub(crate) executed_block: Option, /// The fees of the block pub(crate) fees: U256, /// The blobs, proofs, and commitments in the block. If the block is pre-cancun, this will be @@ -48,8 +51,9 @@ impl EthBuiltPayload { block: SealedBlock, fees: U256, receipts: Vec, + executed_block: Option, ) -> Self { - Self { id, block, fees, sidecars: Vec::new(), receipts } + Self { id, block, executed_block, fees, sidecars: Vec::new(), receipts } } /// Returns the identifier of the payload. @@ -87,6 +91,10 @@ impl BuiltPayload for EthBuiltPayload { self.fees } + fn executed_block(&self) -> Option { + self.executed_block.clone() + } + fn receipts(&self) -> &[Receipt] { &self.receipts } @@ -101,6 +109,10 @@ impl<'a> BuiltPayload for &'a EthBuiltPayload { (**self).fees() } + fn executed_block(&self) -> Option { + self.executed_block.clone() + } + fn receipts(&self) -> &[Receipt] { &self.receipts } diff --git a/crates/ethereum/payload/Cargo.toml b/crates/ethereum/payload/Cargo.toml index 4037ca588..9689f6162 100644 --- a/crates/ethereum/payload/Cargo.toml +++ b/crates/ethereum/payload/Cargo.toml @@ -24,6 +24,7 @@ reth-evm.workspace = true reth-evm-ethereum.workspace = true reth-errors.workspace = true reth-trie.workspace = true +reth-chain-state.workspace = true # ethereum revm.workspace = true diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 5707d97dd..87e071509 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -13,6 +13,7 @@ use reth_basic_payload_builder::{ commit_withdrawals, is_better_payload, BuildArguments, BuildOutcome, PayloadBuilder, PayloadConfig, WithdrawalsOutcome, }; +use reth_chain_state::ExecutedBlock; use reth_errors::RethError; use reth_evm::{ system_calls::{ @@ -45,6 +46,7 @@ use revm::{ primitives::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState}, DatabaseCommit, State, }; +use std::sync::Arc; use tracing::{debug, trace, warn}; /// Ethereum payload builder @@ -255,7 +257,13 @@ where let block = Block { header, body: vec![], ommers: vec![], withdrawals, requests }; let sealed_block = block.seal_slow(); - Ok(EthBuiltPayload::new(attributes.payload_id(), sealed_block, U256::ZERO, Vec::new())) + Ok(EthBuiltPayload::new( + attributes.payload_id(), + sealed_block, + U256::ZERO, + Vec::new(), + None, + )) } } @@ -298,6 +306,7 @@ where let base_fee = initialized_block_env.basefee.to::(); let mut executed_txs = Vec::new(); + let mut executed_senders = Vec::new(); let mut best_txs = pool.best_transactions_with_attributes(BestTransactionsAttributes::new( base_fee, @@ -444,7 +453,8 @@ where .expect("fee is always valid; execution succeeded"); total_fees += U256::from(miner_fee) * U256::from(gas_used); - // append transaction to the list of executed transactions + // append sender and transaction to the respective lists + executed_senders.push(tx.signer()); executed_txs.push(tx.into_signed()); } @@ -500,11 +510,16 @@ where let logs_bloom = execution_outcome.block_logs_bloom(block_number).expect("Number is in range"); // calculate the state root - let state_root = { + let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); + let (state_root, trie_output) = { let state_provider = db.database.0.inner.borrow_mut(); - state_provider - .db - .state_root(HashedPostState::from_bundle_state(&execution_outcome.state().state))? + state_provider.db.state_root_with_updates(hashed_state.clone()).inspect_err(|err| { + warn!(target: "payload_builder", + parent_hash=%parent_block.hash(), + %err, + "failed to calculate state root for empty payload" + ); + })? }; // create the block header @@ -566,7 +581,18 @@ where debug!(target: "payload_builder", ?sealed_block, "sealed built block"); let receipts_pay: Vec = receipts.into_iter().flatten().collect(); - let mut payload = EthBuiltPayload::new(attributes.id, sealed_block, total_fees, receipts_pay); + + // create the executed block data + let executed = ExecutedBlock { + block: Arc::new(sealed_block.clone()), + senders: Arc::new(executed_senders), + execution_output: Arc::new(execution_outcome), + hashed_state: Arc::new(hashed_state), + trie: Arc::new(trie_output), + }; + + let mut payload = + EthBuiltPayload::new(attributes.id, sealed_block, total_fees, receipts_pay, Some(executed)); // extend the payload with the blob sidecars from the executed txs payload.extend_sidecars(blob_sidecars); diff --git a/crates/payload/builder/src/lib.rs b/crates/payload/builder/src/lib.rs index fc74c21a1..56c9d1ab4 100644 --- a/crates/payload/builder/src/lib.rs +++ b/crates/payload/builder/src/lib.rs @@ -65,7 +65,7 @@ //! }, //! ..Default::default() //! }; -//! let payload = EthBuiltPayload::new(self.attributes.id, payload.seal_slow(), U256::ZERO, Vec::new()); +//! let payload = EthBuiltPayload::new(self.attributes.id, payload.seal_slow(), U256::ZERO, Vec::new(), None); //! Ok(payload) //! } //! diff --git a/crates/payload/builder/src/test_utils.rs b/crates/payload/builder/src/test_utils.rs index c94ca2cc0..23e484344 100644 --- a/crates/payload/builder/src/test_utils.rs +++ b/crates/payload/builder/src/test_utils.rs @@ -87,6 +87,7 @@ impl PayloadJob for TestPayloadJob { Block::default().seal_slow(), U256::ZERO, Vec::new(), + None, )) }