Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/node/builder/src/launch/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,8 @@ impl EngineNodeLauncher {
tokio::select! {
payload = built_payloads.select_next_some() => {
if let Some(executed_block) = payload.executed_block() {
debug!(target: "reth::cli", block=?executed_block.recovered_block().num_hash(), "inserting built payload");
engine_service.orchestrator_mut().handler_mut().handler_mut().on_event(EngineApiRequest::InsertExecutedBlock(executed_block).into());
debug!(target: "reth::cli", block=?executed_block.recovered_block.num_hash(), "inserting built payload");
engine_service.orchestrator_mut().handler_mut().handler_mut().on_event(EngineApiRequest::InsertExecutedBlock(executed_block.into_executed_payload()).into());
}
}
event = engine_service.next() => {
Expand Down
2 changes: 1 addition & 1 deletion crates/optimism/payload/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ reth-payload-builder-primitives.workspace = true
reth-payload-util.workspace = true
reth-payload-primitives = { workspace = true, features = ["op"] }
reth-basic-payload-builder.workspace = true
reth-chain-state.workspace = true
reth-payload-validator.workspace = true

# op-reth
Expand All @@ -52,3 +51,4 @@ tracing.workspace = true
thiserror.workspace = true
sha2.workspace = true
serde.workspace = true
either.workspace = true
9 changes: 4 additions & 5 deletions crates/optimism/payload/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use alloy_primitives::{B256, U256};
use alloy_rpc_types_debug::ExecutionWitness;
use alloy_rpc_types_engine::PayloadId;
use reth_basic_payload_builder::*;
use reth_chain_state::ExecutedBlock;
use reth_chainspec::{ChainSpecProvider, EthChainSpec};
use reth_evm::{
block::BlockExecutorFor,
Expand All @@ -30,7 +29,7 @@ use reth_optimism_txpool::{
OpPooledTx,
};
use reth_payload_builder_primitives::PayloadBuilderError;
use reth_payload_primitives::{BuildNextEnv, PayloadBuilderAttributes};
use reth_payload_primitives::{BuildNextEnv, BuiltPayloadExecutedBlock, PayloadBuilderAttributes};
use reth_payload_util::{BestPayloadTransactions, NoopPayloadTransactions, PayloadTransactions};
use reth_primitives_traits::{
HeaderTy, NodePrimitives, SealedHeader, SealedHeaderFor, SignedTransaction, TxTy,
Expand Down Expand Up @@ -386,11 +385,11 @@ impl<Txs> OpBuilder<'_, Txs> {
);

// create the executed block data
let executed: ExecutedBlock<N> = ExecutedBlock {
let executed: BuiltPayloadExecutedBlock<N> = BuiltPayloadExecutedBlock {
recovered_block: Arc::new(block),
execution_output: Arc::new(execution_outcome),
hashed_state: Arc::new(hashed_state),
trie_updates: Arc::new(trie_updates),
hashed_state: either::Either::Left(Arc::new(hashed_state)),
trie_updates: either::Either::Left(Arc::new(trie_updates)),
};

let no_tx_pool = ctx.attributes().no_tx_pool();
Expand Down
11 changes: 6 additions & 5 deletions crates/optimism/payload/src/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ use op_alloy_consensus::{encode_holocene_extra_data, encode_jovian_extra_data, E
use op_alloy_rpc_types_engine::{
OpExecutionPayloadEnvelopeV3, OpExecutionPayloadEnvelopeV4, OpExecutionPayloadV4,
};
use reth_chain_state::ExecutedBlock;
use reth_chainspec::EthChainSpec;
use reth_optimism_evm::OpNextBlockEnvAttributes;
use reth_optimism_forks::OpHardforks;
use reth_payload_builder::{EthPayloadBuilderAttributes, PayloadBuilderError};
use reth_payload_primitives::{BuildNextEnv, BuiltPayload, PayloadBuilderAttributes};
use reth_payload_primitives::{
BuildNextEnv, BuiltPayload, BuiltPayloadExecutedBlock, PayloadBuilderAttributes,
};
use reth_primitives_traits::{
NodePrimitives, SealedBlock, SealedHeader, SignedTransaction, WithEncoded,
};
Expand Down Expand Up @@ -176,7 +177,7 @@ pub struct OpBuiltPayload<N: NodePrimitives = OpPrimitives> {
/// Sealed block
pub(crate) block: Arc<SealedBlock<N::Block>>,
/// Block execution data for the payload, if any.
pub(crate) executed_block: Option<ExecutedBlock<N>>,
pub(crate) executed_block: Option<BuiltPayloadExecutedBlock<N>>,
/// The fees of the block
pub(crate) fees: U256,
}
Expand All @@ -189,7 +190,7 @@ impl<N: NodePrimitives> OpBuiltPayload<N> {
id: PayloadId,
block: Arc<SealedBlock<N::Block>>,
fees: U256,
executed_block: Option<ExecutedBlock<N>>,
executed_block: Option<BuiltPayloadExecutedBlock<N>>,
) -> Self {
Self { id, block, fees, executed_block }
}
Expand Down Expand Up @@ -226,7 +227,7 @@ impl<N: NodePrimitives> BuiltPayload for OpBuiltPayload<N> {
self.fees
}

fn executed_block(&self) -> Option<ExecutedBlock<N>> {
fn executed_block(&self) -> Option<BuiltPayloadExecutedBlock<N>> {
self.executed_block.clone()
}

Expand Down
4 changes: 4 additions & 0 deletions crates/payload/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ reth-primitives-traits.workspace = true
reth-chainspec.workspace = true
reth-errors.workspace = true
reth-chain-state.workspace = true
reth-execution-types.workspace = true
reth-trie-common.workspace = true

# alloy
alloy-eips.workspace = true
Expand All @@ -38,6 +40,8 @@ assert_matches.workspace = true
default = ["std"]
std = [
"reth-chainspec/std",
"reth-execution-types/std",
"reth-trie-common/std",
"alloy-eips/std",
"alloy-primitives/std",
"alloy-rpc-types-engine/std",
Expand Down
4 changes: 2 additions & 2 deletions crates/payload/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ pub use error::{

mod traits;
pub use traits::{
BuildNextEnv, BuiltPayload, PayloadAttributes, PayloadAttributesBuilder,
PayloadBuilderAttributes,
BuildNextEnv, BuiltPayload, BuiltPayloadExecutedBlock, PayloadAttributes,
PayloadAttributesBuilder, PayloadBuilderAttributes,
};

mod payload;
Expand Down
62 changes: 57 additions & 5 deletions crates/payload/primitives/src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,68 @@
//! Core traits for working with execution payloads.

use crate::PayloadBuilderError;
use alloc::{boxed::Box, vec::Vec};
use alloc::{boxed::Box, sync::Arc, vec::Vec};
use alloy_eips::{
eip4895::{Withdrawal, Withdrawals},
eip7685::Requests,
};
use alloy_primitives::{Address, B256, U256};
use alloy_rpc_types_engine::{PayloadAttributes as EthPayloadAttributes, PayloadId};
use core::fmt;
use reth_chain_state::ExecutedBlock;
use reth_primitives_traits::{NodePrimitives, SealedBlock, SealedHeader};
use either::Either;
use reth_execution_types::ExecutionOutcome;
use reth_primitives_traits::{NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader};
use reth_trie_common::{
updates::{TrieUpdates, TrieUpdatesSorted},
HashedPostState, HashedPostStateSorted,
};

/// Represents an executed block for payload building purposes.
///
/// This type captures the complete execution state of a built block,
/// including the recovered block, execution outcome, hashed state, and trie updates.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BuiltPayloadExecutedBlock<N: NodePrimitives> {
/// Recovered Block
pub recovered_block: Arc<RecoveredBlock<N::Block>>,
/// Block's execution outcome.
pub execution_output: Arc<ExecutionOutcome<N::Receipt>>,
/// Block's hashed state.
///
/// Supports both unsorted and sorted variants so payload builders can avoid cloning in order
/// to convert from one to the other when it's not necessary.
pub hashed_state: Either<Arc<HashedPostState>, Arc<HashedPostStateSorted>>,
/// Trie updates that result from calculating the state root for the block.
///
/// Supports both unsorted and sorted variants so payload builders can avoid cloning in order
/// to convert from one to the other when it's not necessary.
pub trie_updates: Either<Arc<TrieUpdates>, Arc<TrieUpdatesSorted>>,
}

impl<N: NodePrimitives> BuiltPayloadExecutedBlock<N> {
/// Converts this into an [`reth_chain_state::ExecutedBlock`].
///
/// If the hashed state or trie updates are in sorted form, they will be converted
/// back to their unsorted representations.
pub fn into_executed_payload(self) -> reth_chain_state::ExecutedBlock<N> {
let hashed_state = match self.hashed_state {
Either::Left(unsorted) => unsorted,
Either::Right(sorted) => Arc::new(Arc::unwrap_or_clone(sorted).into()),
};

let trie_updates = match self.trie_updates {
Either::Left(unsorted) => unsorted,
Either::Right(sorted) => Arc::new(Arc::unwrap_or_clone(sorted).into()),
};

reth_chain_state::ExecutedBlock {
recovered_block: self.recovered_block,
execution_output: self.execution_output,
hashed_state,
trie_updates,
}
}
}

/// Represents a successfully built execution payload (block).
///
Expand All @@ -30,7 +82,7 @@ pub trait BuiltPayload: Send + Sync + fmt::Debug {
/// Returns the complete execution result including state updates.
///
/// Returns `None` if execution data is not available or not tracked.
fn executed_block(&self) -> Option<ExecutedBlock<Self::Primitives>> {
fn executed_block(&self) -> Option<BuiltPayloadExecutedBlock<Self::Primitives>> {
None
}

Expand Down Expand Up @@ -155,7 +207,7 @@ where
}
}

impl<Attributes, L, R> PayloadAttributesBuilder<Attributes> for either::Either<L, R>
impl<Attributes, L, R> PayloadAttributesBuilder<Attributes> for Either<L, R>
where
L: PayloadAttributesBuilder<Attributes>,
R: PayloadAttributesBuilder<Attributes>,
Expand Down
43 changes: 43 additions & 0 deletions crates/trie/common/src/hashed_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,49 @@ impl HashedStorageSorted {
}
}

impl From<HashedStorageSorted> for HashedStorage {
fn from(sorted: HashedStorageSorted) -> Self {
let mut storage = B256Map::default();

// Add all non-zero valued slots
for (slot, value) in sorted.non_zero_valued_slots {
storage.insert(slot, value);
}

// Add all zero valued slots
for slot in sorted.zero_valued_slots {
storage.insert(slot, U256::ZERO);
}

Self { wiped: sorted.wiped, storage }
}
}

impl From<HashedPostStateSorted> for HashedPostState {
fn from(sorted: HashedPostStateSorted) -> Self {
let mut accounts = B256Map::default();

// Add all updated accounts
for (address, account) in sorted.accounts.accounts {
accounts.insert(address, Some(account));
}

// Add all destroyed accounts
for address in sorted.accounts.destroyed_accounts {
accounts.insert(address, None);
}

// Convert storages
let storages = sorted
.storages
.into_iter()
.map(|(address, storage)| (address, storage.into()))
.collect();

Self { accounts, storages }
}
}

/// An iterator that yields chunks of the state updates of at most `size` account and storage
/// targets.
///
Expand Down
1 change: 0 additions & 1 deletion examples/custom-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ license.workspace = true

[dependencies]
# reth
reth-chain-state.workspace = true
reth-codecs.workspace = true
reth-network-peers.workspace = true
reth-node-builder.workspace = true
Expand Down
11 changes: 5 additions & 6 deletions examples/custom-node/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ use crate::{
};
use alloy_eips::eip2718::WithEncoded;
use op_alloy_rpc_types_engine::{OpExecutionData, OpExecutionPayload};
use reth_chain_state::ExecutedBlock;
use reth_engine_primitives::EngineApiValidator;
use reth_ethereum::{
node::api::{
validate_version_specific_fields, AddOnsContext, BuiltPayload, EngineApiMessageVersion,
EngineObjectValidationError, ExecutionPayload, FullNodeComponents, NewPayloadError,
NodePrimitives, PayloadAttributes, PayloadBuilderAttributes, PayloadOrAttributes,
PayloadTypes, PayloadValidator,
validate_version_specific_fields, AddOnsContext, BuiltPayload, BuiltPayloadExecutedBlock,
EngineApiMessageVersion, EngineObjectValidationError, ExecutionPayload, FullNodeComponents,
NewPayloadError, NodePrimitives, PayloadAttributes, PayloadBuilderAttributes,
PayloadOrAttributes, PayloadTypes, PayloadValidator,
},
primitives::{RecoveredBlock, SealedBlock},
storage::StateProviderFactory,
Expand Down Expand Up @@ -167,7 +166,7 @@ impl BuiltPayload for CustomBuiltPayload {
self.0.fees()
}

fn executed_block(&self) -> Option<ExecutedBlock<Self::Primitives>> {
fn executed_block(&self) -> Option<BuiltPayloadExecutedBlock<Self::Primitives>> {
self.0.executed_block()
}

Expand Down
Loading