mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
feat(examples): add custom engine API to custom-node example (#15436)
This commit is contained in:
@@ -1,25 +1,18 @@
|
||||
use crate::primitives::CustomNodePrimitives;
|
||||
use alloy_rpc_types_engine::{
|
||||
BlobsBundleV1, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3,
|
||||
};
|
||||
use op_alloy_rpc_types_engine::{
|
||||
OpExecutionData, OpExecutionPayload, OpExecutionPayloadEnvelopeV3,
|
||||
OpExecutionPayloadEnvelopeV4, OpExecutionPayloadV4,
|
||||
};
|
||||
use op_alloy_rpc_types_engine::{OpExecutionData, OpExecutionPayload};
|
||||
use reth_chain_state::ExecutedBlockWithTrieUpdates;
|
||||
use reth_node_api::{
|
||||
BuiltPayload, EngineTypes, ExecutionPayload, NodePrimitives, PayloadAttributes,
|
||||
PayloadBuilderAttributes, PayloadTypes,
|
||||
BuiltPayload, ExecutionPayload, NodePrimitives, PayloadAttributes, PayloadBuilderAttributes,
|
||||
PayloadTypes,
|
||||
};
|
||||
use reth_optimism_node::{OpBuiltPayload, OpPayloadAttributes, OpPayloadBuilderAttributes};
|
||||
use reth_optimism_primitives::OpTransactionSigned;
|
||||
use reth_primitives_traits::SealedBlock;
|
||||
use revm_primitives::U256;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub struct CustomEngineTypes;
|
||||
pub struct CustomPayloadTypes;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CustomExecutionData {
|
||||
@@ -164,79 +157,7 @@ impl From<CustomBuiltPayload>
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CustomBuiltPayload> for ExecutionPayloadV1 {
|
||||
fn from(value: CustomBuiltPayload) -> Self {
|
||||
Self::from_block_unchecked(value.block().hash(), &value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CustomBuiltPayload> for ExecutionPayloadV2 {
|
||||
fn from(value: CustomBuiltPayload) -> Self {
|
||||
Self::from_block_unchecked(value.block().hash(), &value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CustomBuiltPayload> for OpExecutionPayloadEnvelopeV3 {
|
||||
fn from(value: CustomBuiltPayload) -> Self {
|
||||
Self {
|
||||
block_value: 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:
|
||||
// <https://github.com/ethereum/execution-apis/blob/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine/cancun.md#specification-2>
|
||||
should_override_builder: false,
|
||||
// No blobs for OP.
|
||||
blobs_bundle: BlobsBundleV1 { blobs: vec![], commitments: vec![], proofs: vec![] },
|
||||
parent_beacon_block_root: value.0.block().parent_beacon_block_root.unwrap_or_default(),
|
||||
execution_payload: ExecutionPayloadV3::from_block_unchecked(
|
||||
value.0.block().hash(),
|
||||
&value.into(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CustomBuiltPayload> for OpExecutionPayloadEnvelopeV4 {
|
||||
fn from(value: CustomBuiltPayload) -> Self {
|
||||
let fees = value.0.fees();
|
||||
let block = value.0.into_sealed_block();
|
||||
|
||||
let parent_beacon_block_root = block.parent_beacon_block_root.unwrap_or_default();
|
||||
|
||||
let l2_withdrawals_root = block.withdrawals_root.unwrap_or_default();
|
||||
let payload_v3 = ExecutionPayloadV3::from_block_unchecked(
|
||||
block.hash(),
|
||||
&Arc::unwrap_or_clone(block.into()).into_block(),
|
||||
);
|
||||
|
||||
Self {
|
||||
execution_payload: OpExecutionPayloadV4::from_v3_with_withdrawals_root(
|
||||
payload_v3,
|
||||
l2_withdrawals_root,
|
||||
),
|
||||
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:
|
||||
// <https://github.com/ethereum/execution-apis/blob/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine/cancun.md#specification-2>
|
||||
should_override_builder: false,
|
||||
// No blobs for OP.
|
||||
blobs_bundle: BlobsBundleV1 { blobs: vec![], commitments: vec![], proofs: vec![] },
|
||||
parent_beacon_block_root,
|
||||
execution_requests: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PayloadTypes for CustomEngineTypes {
|
||||
impl PayloadTypes for CustomPayloadTypes {
|
||||
type BuiltPayload = CustomBuiltPayload;
|
||||
type PayloadAttributes = CustomPayloadAttributes;
|
||||
type PayloadBuilderAttributes = CustomPayloadBuilderAttributes;
|
||||
@@ -254,10 +175,3 @@ impl PayloadTypes for CustomEngineTypes {
|
||||
CustomExecutionData { inner: OpExecutionData { payload, sidecar }, extension }
|
||||
}
|
||||
}
|
||||
|
||||
impl EngineTypes for CustomEngineTypes {
|
||||
type ExecutionPayloadEnvelopeV1 = ExecutionPayloadV1;
|
||||
type ExecutionPayloadEnvelopeV2 = ExecutionPayloadV2;
|
||||
type ExecutionPayloadEnvelopeV3 = OpExecutionPayloadEnvelopeV3;
|
||||
type ExecutionPayloadEnvelopeV4 = OpExecutionPayloadEnvelopeV4;
|
||||
}
|
||||
|
||||
94
examples/custom-node/src/engine_api.rs
Normal file
94
examples/custom-node/src/engine_api.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
use crate::{
|
||||
chainspec::CustomChainSpec,
|
||||
engine::{CustomPayloadAttributes, CustomPayloadTypes},
|
||||
primitives::CustomNodePrimitives,
|
||||
};
|
||||
use alloy_rpc_types_engine::{
|
||||
ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus, PayloadStatusEnum,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use jsonrpsee::{core::RpcResult, proc_macros::rpc, RpcModule};
|
||||
use reth_node_api::{AddOnsContext, FullNodeComponents, NodeTypes};
|
||||
use reth_node_builder::rpc::EngineApiBuilder;
|
||||
use reth_optimism_node::node::OpStorage;
|
||||
use reth_rpc_api::IntoEngineApiRpcModule;
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct CustomExecutionPayloadInput {}
|
||||
|
||||
#[derive(Clone, serde::Serialize)]
|
||||
pub struct CustomExecutionPayloadEnvelope {}
|
||||
|
||||
#[rpc(server, namespace = "engine")]
|
||||
pub trait CustomEngineApi {
|
||||
#[method(name = "newPayload")]
|
||||
async fn new_payload(&self, payload: CustomExecutionPayloadInput) -> RpcResult<PayloadStatus>;
|
||||
|
||||
#[method(name = "forkchoiceUpdated")]
|
||||
async fn fork_choice_updated(
|
||||
&self,
|
||||
fork_choice_state: ForkchoiceState,
|
||||
payload_attributes: Option<CustomPayloadAttributes>,
|
||||
) -> RpcResult<ForkchoiceUpdated>;
|
||||
|
||||
#[method(name = "getPayload")]
|
||||
async fn get_payload(&self, payload_id: PayloadId)
|
||||
-> RpcResult<CustomExecutionPayloadEnvelope>;
|
||||
}
|
||||
|
||||
pub struct CustomEngineApi {}
|
||||
|
||||
#[async_trait]
|
||||
impl CustomEngineApiServer for CustomEngineApi {
|
||||
async fn new_payload(&self, _payload: CustomExecutionPayloadInput) -> RpcResult<PayloadStatus> {
|
||||
Ok(PayloadStatus::from_status(PayloadStatusEnum::Valid))
|
||||
}
|
||||
|
||||
async fn fork_choice_updated(
|
||||
&self,
|
||||
_fork_choice_state: ForkchoiceState,
|
||||
_payload_attributes: Option<CustomPayloadAttributes>,
|
||||
) -> RpcResult<ForkchoiceUpdated> {
|
||||
Ok(ForkchoiceUpdated {
|
||||
payload_status: PayloadStatus::from_status(PayloadStatusEnum::Valid),
|
||||
payload_id: Some(PayloadId::default()),
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_payload(
|
||||
&self,
|
||||
_payload_id: PayloadId,
|
||||
) -> RpcResult<CustomExecutionPayloadEnvelope> {
|
||||
Ok(CustomExecutionPayloadEnvelope {})
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoEngineApiRpcModule for CustomEngineApi
|
||||
where
|
||||
Self: CustomEngineApiServer,
|
||||
{
|
||||
fn into_rpc_module(self) -> RpcModule<()> {
|
||||
self.into_rpc().remove_context()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CustomEngineApiBuilder {}
|
||||
|
||||
impl<N> EngineApiBuilder<N> for CustomEngineApiBuilder
|
||||
where
|
||||
N: FullNodeComponents<
|
||||
Types: NodeTypes<
|
||||
Payload = CustomPayloadTypes,
|
||||
ChainSpec = CustomChainSpec,
|
||||
Primitives = CustomNodePrimitives,
|
||||
Storage = OpStorage,
|
||||
>,
|
||||
>,
|
||||
{
|
||||
type EngineApi = CustomEngineApi;
|
||||
|
||||
async fn build_engine_api(self, _ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::EngineApi> {
|
||||
Ok(CustomEngineApi {})
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
|
||||
use chainspec::CustomChainSpec;
|
||||
use engine::CustomEngineTypes;
|
||||
use engine::CustomPayloadTypes;
|
||||
use primitives::CustomNodePrimitives;
|
||||
use reth_node_api::{FullNodeTypes, NodeTypes};
|
||||
use reth_node_builder::{components::ComponentsBuilder, Node, NodeComponentsBuilder};
|
||||
@@ -19,6 +19,7 @@ use reth_optimism_node::{
|
||||
|
||||
pub mod chainspec;
|
||||
pub mod engine;
|
||||
pub mod engine_api;
|
||||
pub mod primitives;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -29,14 +30,14 @@ impl NodeTypes for CustomNode {
|
||||
type ChainSpec = CustomChainSpec;
|
||||
type StateCommitment = <OpNode as NodeTypes>::StateCommitment;
|
||||
type Storage = <OpNode as NodeTypes>::Storage;
|
||||
type Payload = CustomEngineTypes;
|
||||
type Payload = CustomPayloadTypes;
|
||||
}
|
||||
|
||||
impl<N> Node<N> for CustomNode
|
||||
where
|
||||
N: FullNodeTypes<
|
||||
Types: NodeTypes<
|
||||
Payload = CustomEngineTypes,
|
||||
Payload = CustomPayloadTypes,
|
||||
ChainSpec = CustomChainSpec,
|
||||
Primitives = CustomNodePrimitives,
|
||||
Storage = OpStorage,
|
||||
|
||||
Reference in New Issue
Block a user