From af1c9b76146553b11d45cf6d98095ddac9fa2ac9 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Tue, 24 Dec 2024 03:06:47 +0400 Subject: [PATCH] refactor: integrate BuiltPayload::Primitives (#13484) Co-authored-by: Matthias Seitz --- Cargo.lock | 3 +- bin/reth-bench/src/bench/new_payload_fcu.rs | 2 +- bin/reth-bench/src/bench/new_payload_only.rs | 2 +- crates/e2e-test-utils/src/node.rs | 2 +- crates/e2e-test-utils/src/payload.rs | 3 +- crates/engine/local/Cargo.toml | 1 - crates/engine/local/src/miner.rs | 31 ++++---------- crates/engine/primitives/src/lib.rs | 9 +++- crates/engine/util/src/reorg.rs | 2 +- crates/ethereum/engine-primitives/src/lib.rs | 19 +++++++-- .../ethereum/engine-primitives/src/payload.rs | 25 ++++------- crates/node/types/src/lib.rs | 6 +-- crates/optimism/node/Cargo.toml | 1 + crates/optimism/node/src/engine.rs | 15 ++++++- crates/optimism/payload/Cargo.toml | 6 ++- crates/optimism/payload/src/payload.rs | 5 +++ crates/payload/basic/src/stack.rs | 11 +++-- crates/payload/builder/Cargo.toml | 1 + crates/payload/builder/src/service.rs | 5 ++- crates/payload/primitives/src/traits.rs | 13 +++--- crates/primitives/src/block.rs | 1 + crates/rpc/rpc-engine-api/tests/it/payload.rs | 1 + .../rpc-types-compat/src/engine/payload.rs | 41 +++++++++++++++---- examples/custom-engine-types/src/main.rs | 9 ++++ 24 files changed, 136 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 91e25d037..ccf19e52d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7328,7 +7328,6 @@ dependencies = [ "reth-payload-primitives", "reth-provider", "reth-prune", - "reth-rpc-types-compat", "reth-stages-api", "reth-transaction-pool", "tokio", @@ -8540,6 +8539,7 @@ dependencies = [ "reth-provider", "reth-revm", "reth-rpc-server-types", + "reth-rpc-types-compat", "reth-tasks", "reth-tracing", "reth-transaction-pool", @@ -8571,6 +8571,7 @@ dependencies = [ "reth-optimism-consensus", "reth-optimism-evm", "reth-optimism-forks", + "reth-optimism-primitives", "reth-payload-builder", "reth-payload-builder-primitives", "reth-payload-primitives", diff --git a/bin/reth-bench/src/bench/new_payload_fcu.rs b/bin/reth-bench/src/bench/new_payload_fcu.rs index 141620209..c08cb3b2a 100644 --- a/bin/reth-bench/src/bench/new_payload_fcu.rs +++ b/bin/reth-bench/src/bench/new_payload_fcu.rs @@ -81,7 +81,7 @@ impl Command { let versioned_hashes: Vec = block.body.blob_versioned_hashes_iter().copied().collect(); let parent_beacon_block_root = block.parent_beacon_block_root; - let payload = block_to_payload(block); + let payload = block_to_payload(block).0; debug!(?block_number, "Sending payload",); diff --git a/bin/reth-bench/src/bench/new_payload_only.rs b/bin/reth-bench/src/bench/new_payload_only.rs index c76870568..339ba0f63 100644 --- a/bin/reth-bench/src/bench/new_payload_only.rs +++ b/bin/reth-bench/src/bench/new_payload_only.rs @@ -65,7 +65,7 @@ impl Command { let versioned_hashes: Vec = block.body.blob_versioned_hashes_iter().copied().collect(); let parent_beacon_block_root = block.parent_beacon_block_root; - let payload = block_to_payload(block); + let payload = block_to_payload(block).0; let block_number = payload.block_number(); diff --git a/crates/e2e-test-utils/src/node.rs b/crates/e2e-test-utils/src/node.rs index b5dd44841..e64892c0e 100644 --- a/crates/e2e-test-utils/src/node.rs +++ b/crates/e2e-test-utils/src/node.rs @@ -107,7 +107,7 @@ where let tx_hash = self.rpc.inject_tx(raw_tx).await?; let (payload, eth_attr) = self.advance_block().await?; let block_hash = payload.block().hash(); - let block_number = payload.block().number; + let block_number = payload.block().number(); self.assert_new_block(tx_hash, block_hash, block_number).await?; chain.push((payload, eth_attr)); } diff --git a/crates/e2e-test-utils/src/payload.rs b/crates/e2e-test-utils/src/payload.rs index 45889a171..1f2df9e07 100644 --- a/crates/e2e-test-utils/src/payload.rs +++ b/crates/e2e-test-utils/src/payload.rs @@ -1,4 +1,5 @@ use futures_util::StreamExt; +use reth_node_api::BlockBody; use reth_payload_builder::{PayloadBuilderHandle, PayloadId}; use reth_payload_builder_primitives::{Events, PayloadBuilder}; use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes, PayloadTypes}; @@ -57,7 +58,7 @@ impl PayloadTestContext { pub async fn wait_for_built_payload(&self, payload_id: PayloadId) { loop { let payload = self.payload_builder.best_payload(payload_id).await.unwrap().unwrap(); - if payload.block().body.transactions.is_empty() { + if payload.block().body.transactions().is_empty() { tokio::time::sleep(std::time::Duration::from_millis(20)).await; continue } diff --git a/crates/engine/local/Cargo.toml b/crates/engine/local/Cargo.toml index 7e29dbf9a..10837b174 100644 --- a/crates/engine/local/Cargo.toml +++ b/crates/engine/local/Cargo.toml @@ -24,7 +24,6 @@ reth-payload-builder-primitives.workspace = true reth-payload-primitives.workspace = true reth-provider.workspace = true reth-prune.workspace = true -reth-rpc-types-compat.workspace = true reth-transaction-pool.workspace = true reth-stages-api.workspace = true diff --git a/crates/engine/local/src/miner.rs b/crates/engine/local/src/miner.rs index d66c188d6..447e89a00 100644 --- a/crates/engine/local/src/miner.rs +++ b/crates/engine/local/src/miner.rs @@ -2,16 +2,14 @@ use alloy_consensus::BlockHeader; use alloy_primitives::{TxHash, B256}; -use alloy_rpc_types_engine::{CancunPayloadFields, ExecutionPayloadSidecar, ForkchoiceState}; +use alloy_rpc_types_engine::ForkchoiceState; use eyre::OptionExt; use futures_util::{stream::Fuse, StreamExt}; -use reth_chainspec::EthereumHardforks; use reth_engine_primitives::{BeaconEngineMessage, EngineApiMessageVersion, EngineTypes}; use reth_payload_builder::PayloadBuilderHandle; use reth_payload_builder_primitives::PayloadBuilder; use reth_payload_primitives::{BuiltPayload, PayloadAttributesBuilder, PayloadKind, PayloadTypes}; -use reth_provider::{BlockReader, ChainSpecProvider}; -use reth_rpc_types_compat::engine::payload::block_to_payload; +use reth_provider::BlockReader; use reth_transaction_pool::TransactionPool; use std::{ future::Future, @@ -75,9 +73,7 @@ impl Future for MiningMode { /// Local miner advancing the chain/ #[derive(Debug)] -pub struct LocalMiner { - /// Provider to read the current tip of the chain. - provider: Provider, +pub struct LocalMiner { /// The payload attribute builder for the engine payload_attributes_builder: B, /// Sender for events to engine. @@ -92,15 +88,14 @@ pub struct LocalMiner { last_block_hashes: Vec, } -impl LocalMiner +impl LocalMiner where EngineT: EngineTypes, - Provider: BlockReader + ChainSpecProvider + 'static, B: PayloadAttributesBuilder<::PayloadAttributes>, { /// Spawns a new [`LocalMiner`] with the given parameters. pub fn spawn_new( - provider: Provider, + provider: impl BlockReader, payload_attributes_builder: B, to_engine: UnboundedSender>, mode: MiningMode, @@ -110,7 +105,6 @@ where provider.sealed_header(provider.best_block_number().unwrap()).unwrap().unwrap(); let miner = Self { - provider, payload_attributes_builder, to_engine, mode, @@ -211,21 +205,12 @@ where let block = payload.block(); - let cancun_fields = - self.provider.chain_spec().is_cancun_active_at_timestamp(block.timestamp).then(|| { - CancunPayloadFields { - parent_beacon_block_root: block.parent_beacon_block_root.unwrap(), - versioned_hashes: block.body.blob_versioned_hashes_iter().copied().collect(), - } - }); - let (tx, rx) = oneshot::channel(); + let (payload, sidecar) = EngineT::block_to_payload(payload.block().clone()); self.to_engine.send(BeaconEngineMessage::NewPayload { - payload: block_to_payload(payload.block().clone()), + payload, // todo: prague support - sidecar: cancun_fields - .map(ExecutionPayloadSidecar::v3) - .unwrap_or_else(ExecutionPayloadSidecar::none), + sidecar, tx, })?; diff --git a/crates/engine/primitives/src/lib.rs b/crates/engine/primitives/src/lib.rs index 2bd642cfa..9921023c4 100644 --- a/crates/engine/primitives/src/lib.rs +++ b/crates/engine/primitives/src/lib.rs @@ -30,7 +30,7 @@ pub use reth_payload_primitives::{ PayloadTypes, }; use reth_payload_primitives::{InvalidPayloadAttributesError, PayloadAttributes}; -use reth_primitives::SealedBlockFor; +use reth_primitives::{NodePrimitives, SealedBlockFor}; use reth_primitives_traits::Block; use serde::{de::DeserializeOwned, ser::Serialize}; @@ -80,6 +80,13 @@ pub trait EngineTypes: + Send + Sync + 'static; + + /// Converts a [`BuiltPayload`] into an [`ExecutionPayload`] and [`ExecutionPayloadSidecar`]. + fn block_to_payload( + block: SealedBlockFor< + <::Primitives as NodePrimitives>::Block, + >, + ) -> (ExecutionPayload, ExecutionPayloadSidecar); } /// Type that validates an [`ExecutionPayload`]. diff --git a/crates/engine/util/src/reorg.rs b/crates/engine/util/src/reorg.rs index b9b93329a..e61b86346 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -437,7 +437,7 @@ where .seal_slow(); Ok(( - block_to_payload(reorg_block), + block_to_payload(reorg_block).0, // todo(onbjerg): how do we support execution requests? reorg_target .header diff --git a/crates/ethereum/engine-primitives/src/lib.rs b/crates/ethereum/engine-primitives/src/lib.rs index 59c870f4d..d1301882c 100644 --- a/crates/ethereum/engine-primitives/src/lib.rs +++ b/crates/ethereum/engine-primitives/src/lib.rs @@ -18,13 +18,14 @@ pub use alloy_rpc_types_engine::{ }; pub use payload::{EthBuiltPayload, EthPayloadBuilderAttributes}; use reth_chainspec::ChainSpec; -use reth_engine_primitives::{EngineTypes, EngineValidator, PayloadValidator}; +use reth_engine_primitives::{BuiltPayload, EngineTypes, EngineValidator, PayloadValidator}; use reth_payload_primitives::{ validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError, PayloadOrAttributes, PayloadTypes, }; use reth_payload_validator::ExecutionPayloadValidator; -use reth_primitives::{Block, SealedBlock}; +use reth_primitives::{Block, NodePrimitives, SealedBlock, SealedBlockFor}; +use reth_rpc_types_compat::engine::payload::block_to_payload; /// The types used in the default mainnet ethereum beacon consensus engine. #[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)] @@ -39,9 +40,11 @@ impl PayloadTypes for EthEngineTypes { type PayloadBuilderAttributes = T::PayloadBuilderAttributes; } -impl EngineTypes for EthEngineTypes +impl EngineTypes for EthEngineTypes where - T::BuiltPayload: TryInto + T: PayloadTypes, + T::BuiltPayload: BuiltPayload> + + TryInto + TryInto + TryInto + TryInto, @@ -50,6 +53,14 @@ where type ExecutionPayloadEnvelopeV2 = ExecutionPayloadEnvelopeV2; type ExecutionPayloadEnvelopeV3 = ExecutionPayloadEnvelopeV3; type ExecutionPayloadEnvelopeV4 = ExecutionPayloadEnvelopeV4; + + fn block_to_payload( + block: SealedBlockFor< + <::Primitives as NodePrimitives>::Block, + >, + ) -> (ExecutionPayload, ExecutionPayloadSidecar) { + block_to_payload(block) + } } /// A default payload type for [`EthEngineTypes`] diff --git a/crates/ethereum/engine-primitives/src/payload.rs b/crates/ethereum/engine-primitives/src/payload.rs index 61e74c7b8..98baa11eb 100644 --- a/crates/ethereum/engine-primitives/src/payload.rs +++ b/crates/ethereum/engine-primitives/src/payload.rs @@ -9,7 +9,7 @@ use alloy_rpc_types_engine::{ }; use reth_chain_state::ExecutedBlock; use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes}; -use reth_primitives::SealedBlock; +use reth_primitives::{EthPrimitives, SealedBlock}; use reth_rpc_types_compat::engine::payload::{ block_to_payload_v1, block_to_payload_v3, convert_block_to_payload_field_v2, }; @@ -89,6 +89,8 @@ impl EthBuiltPayload { } impl BuiltPayload for EthBuiltPayload { + type Primitives = EthPrimitives; + fn block(&self) -> &SealedBlock { &self.block } @@ -107,6 +109,8 @@ impl BuiltPayload for EthBuiltPayload { } impl BuiltPayload for &EthBuiltPayload { + type Primitives = EthPrimitives; + fn block(&self) -> &SealedBlock { (**self).block() } @@ -166,24 +170,9 @@ impl From for ExecutionPayloadEnvelopeV3 { impl From for ExecutionPayloadEnvelopeV4 { fn from(value: EthBuiltPayload) -> Self { - let EthBuiltPayload { block, fees, sidecars, requests, .. } = value; - Self { - envelope_inner: ExecutionPayloadEnvelopeV3 { - execution_payload: block_to_payload_v3(Arc::unwrap_or_clone(block)), - block_value: fees, - // From the engine API spec: - // - // > Client software **MAY** use any heuristics to decide whether to set - // `shouldOverrideBuilder` flag or not. If client software does not implement any - // heuristic this flag **SHOULD** be set to `false`. - // - // Spec: - // - should_override_builder: false, - blobs_bundle: sidecars.into_iter().map(Into::into).collect::>().into(), - }, - execution_requests: requests.unwrap_or_default(), + execution_requests: value.requests.clone().unwrap_or_default(), + envelope_inner: value.into(), } } } diff --git a/crates/node/types/src/lib.rs b/crates/node/types/src/lib.rs index 6e1eb81a0..8cdf9015f 100644 --- a/crates/node/types/src/lib.rs +++ b/crates/node/types/src/lib.rs @@ -19,7 +19,7 @@ use reth_db_api::{ database_metrics::{DatabaseMetadata, DatabaseMetrics}, Database, }; -use reth_engine_primitives::EngineTypes; +use reth_engine_primitives::{BuiltPayload, EngineTypes}; use reth_trie_db::StateCommitment; /// The type that configures the essential types of an Ethereum-like node. @@ -41,7 +41,7 @@ pub trait NodeTypes: Send + Sync + Unpin + 'static { /// The type that configures an Ethereum-like node with an engine for consensus. pub trait NodeTypesWithEngine: NodeTypes { /// The node's engine types, defining the interaction with the consensus engine. - type Engine: EngineTypes; + type Engine: EngineTypes>; } /// A helper trait that is downstream of the [`NodeTypesWithEngine`] trait and adds database to the @@ -225,7 +225,7 @@ where impl NodeTypesWithEngine for AnyNodeTypesWithEngine where P: NodePrimitives + Send + Sync + Unpin + 'static, - E: EngineTypes + Send + Sync + Unpin, + E: EngineTypes> + Send + Sync + Unpin, C: EthChainSpec
+ 'static, SC: StateCommitment, S: Default + Send + Sync + Unpin + Debug + 'static, diff --git a/crates/optimism/node/Cargo.toml b/crates/optimism/node/Cargo.toml index ee6c969fd..ef8697efb 100644 --- a/crates/optimism/node/Cargo.toml +++ b/crates/optimism/node/Cargo.toml @@ -33,6 +33,7 @@ reth-revm = { workspace = true, features = ["std"] } reth-beacon-consensus.workspace = true reth-trie-db.workspace = true reth-rpc-server-types.workspace = true +reth-rpc-types-compat.workspace = true reth-tasks = { workspace = true, optional = true } # op-reth diff --git a/crates/optimism/node/src/engine.rs b/crates/optimism/node/src/engine.rs index f85219279..c8fcad324 100644 --- a/crates/optimism/node/src/engine.rs +++ b/crates/optimism/node/src/engine.rs @@ -12,13 +12,15 @@ use reth_node_api::{ EngineObjectValidationError, MessageValidationKind, PayloadOrAttributes, PayloadTypes, VersionSpecificValidationError, }, - validate_version_specific_fields, EngineTypes, EngineValidator, PayloadValidator, + validate_version_specific_fields, BuiltPayload, EngineTypes, EngineValidator, NodePrimitives, + PayloadValidator, }; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_forks::{OpHardfork, OpHardforks}; use reth_optimism_payload_builder::{OpBuiltPayload, OpPayloadBuilderAttributes}; use reth_payload_validator::ExecutionPayloadValidator; use reth_primitives::{Block, SealedBlockFor}; +use reth_rpc_types_compat::engine::payload::block_to_payload; use std::sync::Arc; /// The types used in the optimism beacon consensus engine. @@ -36,7 +38,8 @@ impl PayloadTypes for OpEngineTypes { impl EngineTypes for OpEngineTypes where - T::BuiltPayload: TryInto + T::BuiltPayload: BuiltPayload> + + TryInto + TryInto + TryInto + TryInto, @@ -45,6 +48,14 @@ where type ExecutionPayloadEnvelopeV2 = ExecutionPayloadEnvelopeV2; type ExecutionPayloadEnvelopeV3 = OpExecutionPayloadEnvelopeV3; type ExecutionPayloadEnvelopeV4 = OpExecutionPayloadEnvelopeV4; + + fn block_to_payload( + block: SealedBlockFor< + <::Primitives as NodePrimitives>::Block, + >, + ) -> (ExecutionPayload, ExecutionPayloadSidecar) { + block_to_payload(block) + } } /// A default payload type for [`OpEngineTypes`] diff --git a/crates/optimism/payload/Cargo.toml b/crates/optimism/payload/Cargo.toml index ba74dbe70..61d48a1fc 100644 --- a/crates/optimism/payload/Cargo.toml +++ b/crates/optimism/payload/Cargo.toml @@ -33,6 +33,7 @@ reth-optimism-chainspec.workspace = true reth-optimism-consensus.workspace = true reth-optimism-evm.workspace = true reth-optimism-forks.workspace = true +reth-optimism-primitives.workspace = true # ethereum revm.workspace = true @@ -57,5 +58,6 @@ optimism = [ "reth-optimism-evm/optimism", "revm/optimism", "reth-execution-types/optimism", - "reth-optimism-consensus/optimism" -] \ No newline at end of file + "reth-optimism-consensus/optimism", + "reth-optimism-primitives/optimism" +] diff --git a/crates/optimism/payload/src/payload.rs b/crates/optimism/payload/src/payload.rs index 1a8655bd7..9577bbbec 100644 --- a/crates/optimism/payload/src/payload.rs +++ b/crates/optimism/payload/src/payload.rs @@ -14,6 +14,7 @@ use op_alloy_rpc_types_engine::{OpExecutionPayloadEnvelopeV3, OpExecutionPayload use reth_chain_state::ExecutedBlock; use reth_chainspec::EthereumHardforks; use reth_optimism_chainspec::OpChainSpec; +use reth_optimism_primitives::OpPrimitives; use reth_payload_builder::EthPayloadBuilderAttributes; use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes}; use reth_primitives::{transaction::WithEncoded, SealedBlock, TransactionSigned}; @@ -186,6 +187,8 @@ impl OpBuiltPayload { } impl BuiltPayload for OpBuiltPayload { + type Primitives = OpPrimitives; + fn block(&self) -> &SealedBlock { &self.block } @@ -204,6 +207,8 @@ impl BuiltPayload for OpBuiltPayload { } impl BuiltPayload for &OpBuiltPayload { + type Primitives = OpPrimitives; + fn block(&self) -> &SealedBlock { (**self).block() } diff --git a/crates/payload/basic/src/stack.rs b/crates/payload/basic/src/stack.rs index 77314d443..d7cf9d131 100644 --- a/crates/payload/basic/src/stack.rs +++ b/crates/payload/basic/src/stack.rs @@ -7,7 +7,7 @@ use alloy_eips::eip4895::Withdrawals; use alloy_primitives::{Address, B256, U256}; use reth_payload_builder::PayloadId; use reth_payload_primitives::BuiltPayload; -use reth_primitives::SealedBlock; +use reth_primitives::{NodePrimitives, SealedBlockFor}; use alloy_eips::eip7685::Requests; use std::{error::Error, fmt}; @@ -151,9 +151,11 @@ where impl BuiltPayload for Either where L: BuiltPayload, - R: BuiltPayload, + R: BuiltPayload, { - fn block(&self) -> &SealedBlock { + type Primitives = L::Primitives; + + fn block(&self) -> &SealedBlockFor<::Block> { match self { Self::Left(l) => l.block(), Self::Right(r) => r.block(), @@ -184,7 +186,8 @@ where L::Attributes: Unpin + Clone, R::Attributes: Unpin + Clone, L::BuiltPayload: Unpin + Clone, - R::BuiltPayload: Unpin + Clone, + R::BuiltPayload: + BuiltPayload::Primitives> + Unpin + Clone, <>::Attributes as PayloadBuilderAttributes>::Error: 'static, <>::Attributes as PayloadBuilderAttributes>::Error: 'static, { diff --git a/crates/payload/builder/Cargo.toml b/crates/payload/builder/Cargo.toml index d709c1208..9dddbc7e4 100644 --- a/crates/payload/builder/Cargo.toml +++ b/crates/payload/builder/Cargo.toml @@ -21,6 +21,7 @@ reth-payload-primitives.workspace = true reth-ethereum-engine-primitives.workspace = true # alloy +alloy-consensus.workspace = true alloy-primitives = { workspace = true, optional = true } alloy-rpc-types = { workspace = true, features = ["engine"] } diff --git a/crates/payload/builder/src/service.rs b/crates/payload/builder/src/service.rs index aaff23dda..de51a791c 100644 --- a/crates/payload/builder/src/service.rs +++ b/crates/payload/builder/src/service.rs @@ -7,6 +7,7 @@ use crate::{ metrics::PayloadBuilderServiceMetrics, traits::PayloadJobGenerator, KeepPayloadJobAlive, PayloadJob, }; +use alloy_consensus::BlockHeader; use alloy_rpc_types::engine::PayloadId; use futures_util::{future::FutureExt, Stream, StreamExt}; use reth_chain_state::CanonStateNotification; @@ -284,7 +285,7 @@ where .find(|(_, job_id)| *job_id == id) .map(|(j, _)| j.best_payload().map(|p| p.into())); if let Some(Ok(ref best)) = res { - self.metrics.set_best_revenue(best.block().number, f64::from(best.fees())); + self.metrics.set_best_revenue(best.block().number(), f64::from(best.fees())); } res @@ -318,7 +319,7 @@ where payload_events.send(Events::BuiltPayload(payload.clone().into())).ok(); resolved_metrics - .set_resolved_revenue(payload.block().number, f64::from(payload.fees())); + .set_resolved_revenue(payload.block().number(), f64::from(payload.fees())); } res.map(|p| p.into()) }; diff --git a/crates/payload/primitives/src/traits.rs b/crates/payload/primitives/src/traits.rs index d3afbef50..a02e00d99 100644 --- a/crates/payload/primitives/src/traits.rs +++ b/crates/payload/primitives/src/traits.rs @@ -5,19 +5,22 @@ use alloy_eips::{ use alloy_primitives::{Address, B256, U256}; use alloy_rpc_types_engine::{PayloadAttributes as EthPayloadAttributes, PayloadId}; use reth_chain_state::ExecutedBlock; -use reth_primitives::{EthPrimitives, NodePrimitives, SealedBlock}; +use reth_primitives::{NodePrimitives, SealedBlockFor}; -/// Represents a built payload type that contains a built [`SealedBlock`] and can be converted into +/// Represents a built payload type that contains a built `SealedBlock` and can be converted into /// engine API execution payloads. -pub trait BuiltPayload: Send + Sync + std::fmt::Debug { +pub trait BuiltPayload: Send + Sync + std::fmt::Debug { + /// The node's primitive types + type Primitives: NodePrimitives; + /// Returns the built block (sealed) - fn block(&self) -> &SealedBlock; + fn block(&self) -> &SealedBlockFor<::Block>; /// Returns the fees collected for the built block fn fees(&self) -> U256; /// Returns the entire execution data for the built block, if available. - fn executed_block(&self) -> Option> { + fn executed_block(&self) -> Option> { None } diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index 36d1b382a..dbfe1365d 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -467,6 +467,7 @@ pub type SealedBlockFor = SealedBlock< ::Header, ::Body, >; + /// Sealed block with senders recovered from transactions. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Deref, DerefMut)] pub struct SealedBlockWithSenders { diff --git a/crates/rpc/rpc-engine-api/tests/it/payload.rs b/crates/rpc/rpc-engine-api/tests/it/payload.rs index 094946c21..61199773e 100644 --- a/crates/rpc/rpc-engine-api/tests/it/payload.rs +++ b/crates/rpc/rpc-engine-api/tests/it/payload.rs @@ -28,6 +28,7 @@ fn transform_block Block>(src: SealedBlock, f: F) -> Executi header: SealedHeader::seal(transformed.header), body: transformed.body, }) + .0 } #[test] diff --git a/crates/rpc/rpc-types-compat/src/engine/payload.rs b/crates/rpc/rpc-types-compat/src/engine/payload.rs index a56441ec2..61f24fbd7 100644 --- a/crates/rpc/rpc-types-compat/src/engine/payload.rs +++ b/crates/rpc/rpc-types-compat/src/engine/payload.rs @@ -5,19 +5,20 @@ use alloy_consensus::{constants::MAXIMUM_EXTRA_DATA_SIZE, Header, EMPTY_OMMER_RO use alloy_eips::{ eip2718::{Decodable2718, Encodable2718}, eip4895::Withdrawals, + eip7685::RequestsOrHash, }; use alloy_primitives::{B256, U256}; use alloy_rlp::BufMut; use alloy_rpc_types_engine::{ payload::{ExecutionPayloadBodyV1, ExecutionPayloadFieldV2, ExecutionPayloadInputV2}, - ExecutionPayload, ExecutionPayloadSidecar, ExecutionPayloadV1, ExecutionPayloadV2, - ExecutionPayloadV3, PayloadError, + CancunPayloadFields, ExecutionPayload, ExecutionPayloadSidecar, ExecutionPayloadV1, + ExecutionPayloadV2, ExecutionPayloadV3, PayloadError, PraguePayloadFields, }; use reth_primitives::{ proofs::{self}, Block, BlockBody, BlockExt, SealedBlock, }; -use reth_primitives_traits::BlockBody as _; +use reth_primitives_traits::{BlockBody as _, SignedTransaction}; /// Converts [`ExecutionPayloadV1`] to [`Block`] pub fn try_payload_v1_to_block( @@ -119,10 +120,34 @@ pub fn try_payload_v3_to_block( } /// Converts [`SealedBlock`] to [`ExecutionPayload`] -pub fn block_to_payload( +pub fn block_to_payload( value: SealedBlock>, -) -> ExecutionPayload { - if value.header.parent_beacon_block_root.is_some() { +) -> (ExecutionPayload, ExecutionPayloadSidecar) { + let cancun = if let Some(parent_beacon_block_root) = value.parent_beacon_block_root { + Some(CancunPayloadFields { + parent_beacon_block_root, + versioned_hashes: value.body.blob_versioned_hashes_iter().copied().collect(), + }) + } else { + None + }; + + let prague = if let Some(requests_hash) = value.requests_hash { + Some(PraguePayloadFields { + requests: RequestsOrHash::Hash(requests_hash), + target_blobs_per_block: value.target_blobs_per_block.unwrap_or_default(), + }) + } else { + None + }; + + let sidecar = match (cancun, prague) { + (Some(cancun), Some(prague)) => ExecutionPayloadSidecar::v4(cancun, prague), + (Some(cancun), None) => ExecutionPayloadSidecar::v3(cancun), + _ => ExecutionPayloadSidecar::none(), + }; + + let execution_payload = if value.header.parent_beacon_block_root.is_some() { // block with parent beacon block root: V3 ExecutionPayload::V3(block_to_payload_v3(value)) } else if value.body.withdrawals.is_some() { @@ -131,7 +156,9 @@ pub fn block_to_payload( } else { // otherwise V1 ExecutionPayload::V1(block_to_payload_v1(value)) - } + }; + + (execution_payload, sidecar) } /// Converts [`SealedBlock`] to [`ExecutionPayloadV1`] diff --git a/examples/custom-engine-types/src/main.rs b/examples/custom-engine-types/src/main.rs index 8a5b9f9be..c64cd0495 100644 --- a/examples/custom-engine-types/src/main.rs +++ b/examples/custom-engine-types/src/main.rs @@ -41,6 +41,7 @@ use reth::{ primitives::{Block, EthPrimitives, SealedBlockFor, TransactionSigned}, providers::{CanonStateSubscriptions, EthStorage, StateProviderFactory}, rpc::{ + compat::engine::payload::block_to_payload, eth::EthApi, types::engine::{ExecutionPayload, ExecutionPayloadSidecar, PayloadError}, }, @@ -170,6 +171,14 @@ impl EngineTypes for CustomEngineTypes { type ExecutionPayloadEnvelopeV2 = ExecutionPayloadEnvelopeV2; type ExecutionPayloadEnvelopeV3 = ExecutionPayloadEnvelopeV3; type ExecutionPayloadEnvelopeV4 = ExecutionPayloadEnvelopeV4; + + fn block_to_payload( + block: SealedBlockFor< + <::Primitives as reth_node_api::NodePrimitives>::Block, + >, + ) -> (ExecutionPayload, ExecutionPayloadSidecar) { + block_to_payload(block) + } } /// Custom engine validator