mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-11 00:08:13 -05:00
Added custom headers to NodePrimitives (#13995)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de> Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com> Co-authored-by: Federico Gimenez <federico.gimenez@gmail.com>
This commit is contained in:
28
Cargo.lock
generated
28
Cargo.lock
generated
@@ -3267,6 +3267,33 @@ dependencies = [
|
||||
"reth-node-ethereum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "example-custom-node"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-eips",
|
||||
"alloy-genesis",
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
"alloy-rpc-types-engine",
|
||||
"derive_more 2.0.1",
|
||||
"op-alloy-rpc-types-engine",
|
||||
"reth-chain-state",
|
||||
"reth-chainspec",
|
||||
"reth-codecs",
|
||||
"reth-network-peers",
|
||||
"reth-node-api",
|
||||
"reth-node-builder",
|
||||
"reth-optimism-chainspec",
|
||||
"reth-optimism-forks",
|
||||
"reth-optimism-node",
|
||||
"reth-optimism-primitives",
|
||||
"reth-primitives-traits",
|
||||
"revm-primitives",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "example-custom-node-components"
|
||||
version = "0.0.0"
|
||||
@@ -5826,6 +5853,7 @@ dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-rpc-types-engine",
|
||||
"alloy-serde",
|
||||
"arbitrary",
|
||||
"derive_more 1.0.0",
|
||||
"ethereum_ssz",
|
||||
"op-alloy-consensus",
|
||||
|
||||
@@ -135,12 +135,14 @@ members = [
|
||||
"examples/beacon-api-sse/",
|
||||
"examples/bsc-p2p",
|
||||
"examples/custom-dev-node/",
|
||||
"examples/custom-node/",
|
||||
"examples/custom-engine-types/",
|
||||
"examples/custom-evm/",
|
||||
"examples/custom-inspector/",
|
||||
"examples/custom-node-components/",
|
||||
"examples/custom-payload-builder/",
|
||||
"examples/custom-rlpx-subprotocol",
|
||||
"examples/custom-node",
|
||||
"examples/db-access",
|
||||
"examples/exex-hello-world",
|
||||
"examples/manual-p2p/",
|
||||
|
||||
@@ -54,7 +54,6 @@ pub trait EngineTypes:
|
||||
+ TryInto<Self::ExecutionPayloadEnvelopeV4>,
|
||||
> + DeserializeOwned
|
||||
+ Serialize
|
||||
+ 'static
|
||||
{
|
||||
/// Execution Payload V1 envelope type.
|
||||
type ExecutionPayloadEnvelopeV1: DeserializeOwned
|
||||
|
||||
@@ -54,8 +54,10 @@ pub struct OpEvmConfig<
|
||||
N: NodePrimitives = OpPrimitives,
|
||||
R = OpRethReceiptBuilder,
|
||||
> {
|
||||
executor_factory: OpBlockExecutorFactory<R, Arc<ChainSpec>>,
|
||||
block_assembler: OpBlockAssembler<ChainSpec>,
|
||||
/// Inner [`OpBlockExecutorFactory`].
|
||||
pub executor_factory: OpBlockExecutorFactory<R, Arc<ChainSpec>>,
|
||||
/// Optimism block assembler.
|
||||
pub block_assembler: OpBlockAssembler<ChainSpec>,
|
||||
_pd: core::marker::PhantomData<N>,
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ pub use reth_optimism_txpool as txpool;
|
||||
pub mod utils;
|
||||
|
||||
pub use reth_optimism_payload_builder::{
|
||||
OpBuiltPayload, OpPayloadBuilder, OpPayloadBuilderAttributes,
|
||||
OpBuiltPayload, OpPayloadAttributes, OpPayloadBuilder, OpPayloadBuilderAttributes,
|
||||
};
|
||||
|
||||
pub use reth_optimism_evm::*;
|
||||
|
||||
@@ -264,7 +264,8 @@ pub struct OpBuilder<'a, Txs> {
|
||||
}
|
||||
|
||||
impl<'a, Txs> OpBuilder<'a, Txs> {
|
||||
fn new(best: impl FnOnce(BestTransactionsAttributes) -> Txs + Send + Sync + 'a) -> Self {
|
||||
/// Creates a new [`OpBuilder`].
|
||||
pub fn new(best: impl FnOnce(BestTransactionsAttributes) -> Txs + Send + Sync + 'a) -> Self {
|
||||
Self { best: Box::new(best) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +193,11 @@ impl<N: NodePrimitives> OpBuiltPayload<N> {
|
||||
pub const fn fees(&self) -> U256 {
|
||||
self.fees
|
||||
}
|
||||
|
||||
/// Converts the value into [`SealedBlock`].
|
||||
pub fn into_sealed_block(self) -> SealedBlock<N::Block> {
|
||||
Arc::unwrap_or_clone(self.block)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NodePrimitives> BuiltPayload for OpBuiltPayload<N> {
|
||||
|
||||
@@ -125,6 +125,12 @@ impl<T: InMemorySize> InMemorySize for Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl InMemorySize for u64 {
|
||||
fn size(&self) -> usize {
|
||||
core::mem::size_of::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation for optimism types
|
||||
#[cfg(feature = "op")]
|
||||
mod op {
|
||||
|
||||
50
examples/custom-node/Cargo.toml
Normal file
50
examples/custom-node/Cargo.toml
Normal file
@@ -0,0 +1,50 @@
|
||||
[package]
|
||||
name = "example-custom-node"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
# reth
|
||||
reth-chain-state.workspace = true
|
||||
reth-chainspec.workspace = true
|
||||
reth-codecs.workspace = true
|
||||
reth-network-peers.workspace = true
|
||||
reth-node-api.workspace = true
|
||||
reth-node-builder.workspace = true
|
||||
reth-optimism-chainspec.workspace = true
|
||||
reth-optimism-forks.workspace = true
|
||||
reth-optimism-node.workspace = true
|
||||
reth-optimism-primitives = { workspace = true, features = ["serde", "reth-codec"] }
|
||||
reth-primitives-traits.workspace = true
|
||||
|
||||
# revm
|
||||
revm-primitives.workspace = true
|
||||
|
||||
# alloy
|
||||
alloy-consensus = { workspace = true, features = ["serde"] }
|
||||
alloy-eips.workspace = true
|
||||
alloy-genesis.workspace = true
|
||||
alloy-primitives.workspace = true
|
||||
alloy-rlp.workspace = true
|
||||
alloy-rpc-types-engine.workspace = true
|
||||
op-alloy-rpc-types-engine.workspace = true
|
||||
|
||||
# misc
|
||||
derive_more.workspace = true
|
||||
serde.workspace = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
arbitrary = [
|
||||
"alloy-consensus/arbitrary",
|
||||
"alloy-eips/arbitrary",
|
||||
"alloy-primitives/arbitrary",
|
||||
"op-alloy-rpc-types-engine/arbitrary",
|
||||
"reth-chainspec/arbitrary",
|
||||
"reth-codecs/arbitrary",
|
||||
"reth-optimism-primitives/arbitrary",
|
||||
"reth-primitives-traits/arbitrary",
|
||||
"revm-primitives/arbitrary",
|
||||
]
|
||||
105
examples/custom-node/src/chainspec.rs
Normal file
105
examples/custom-node/src/chainspec.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
use crate::primitives::CustomHeader;
|
||||
use alloy_genesis::Genesis;
|
||||
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardfork, Hardforks};
|
||||
use reth_network_peers::NodeRecord;
|
||||
use reth_optimism_chainspec::OpChainSpec;
|
||||
use reth_optimism_forks::OpHardforks;
|
||||
use reth_primitives_traits::SealedHeader;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CustomChainSpec {
|
||||
inner: OpChainSpec,
|
||||
genesis_header: SealedHeader<CustomHeader>,
|
||||
}
|
||||
|
||||
impl Hardforks for CustomChainSpec {
|
||||
fn fork<H: Hardfork>(&self, fork: H) -> reth_chainspec::ForkCondition {
|
||||
self.inner.fork(fork)
|
||||
}
|
||||
|
||||
fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, reth_chainspec::ForkCondition)> {
|
||||
self.inner.forks_iter()
|
||||
}
|
||||
|
||||
fn fork_id(&self, head: &reth_chainspec::Head) -> reth_chainspec::ForkId {
|
||||
self.inner.fork_id(head)
|
||||
}
|
||||
|
||||
fn latest_fork_id(&self) -> reth_chainspec::ForkId {
|
||||
self.inner.latest_fork_id()
|
||||
}
|
||||
|
||||
fn fork_filter(&self, head: reth_chainspec::Head) -> reth_chainspec::ForkFilter {
|
||||
self.inner.fork_filter(head)
|
||||
}
|
||||
}
|
||||
|
||||
impl EthChainSpec for CustomChainSpec {
|
||||
type Header = CustomHeader;
|
||||
|
||||
fn base_fee_params_at_block(&self, block_number: u64) -> reth_chainspec::BaseFeeParams {
|
||||
self.inner.base_fee_params_at_block(block_number)
|
||||
}
|
||||
|
||||
fn blob_params_at_timestamp(&self, timestamp: u64) -> Option<alloy_eips::eip7840::BlobParams> {
|
||||
self.inner.blob_params_at_timestamp(timestamp)
|
||||
}
|
||||
|
||||
fn base_fee_params_at_timestamp(&self, timestamp: u64) -> reth_chainspec::BaseFeeParams {
|
||||
self.inner.base_fee_params_at_timestamp(timestamp)
|
||||
}
|
||||
|
||||
fn bootnodes(&self) -> Option<Vec<NodeRecord>> {
|
||||
self.inner.bootnodes()
|
||||
}
|
||||
|
||||
fn chain(&self) -> reth_chainspec::Chain {
|
||||
self.inner.chain()
|
||||
}
|
||||
|
||||
fn deposit_contract(&self) -> Option<&reth_chainspec::DepositContract> {
|
||||
self.inner.deposit_contract()
|
||||
}
|
||||
|
||||
fn display_hardforks(&self) -> Box<dyn std::fmt::Display> {
|
||||
self.inner.display_hardforks()
|
||||
}
|
||||
|
||||
fn prune_delete_limit(&self) -> usize {
|
||||
self.inner.prune_delete_limit()
|
||||
}
|
||||
|
||||
fn genesis(&self) -> &Genesis {
|
||||
self.inner.genesis()
|
||||
}
|
||||
|
||||
fn genesis_hash(&self) -> revm_primitives::B256 {
|
||||
self.genesis_header.hash()
|
||||
}
|
||||
|
||||
fn genesis_header(&self) -> &Self::Header {
|
||||
&self.genesis_header
|
||||
}
|
||||
|
||||
fn final_paris_total_difficulty(&self) -> Option<revm_primitives::U256> {
|
||||
self.inner.get_final_paris_total_difficulty()
|
||||
}
|
||||
}
|
||||
|
||||
impl EthereumHardforks for CustomChainSpec {
|
||||
fn ethereum_fork_activation(
|
||||
&self,
|
||||
fork: reth_chainspec::EthereumHardfork,
|
||||
) -> reth_chainspec::ForkCondition {
|
||||
self.inner.ethereum_fork_activation(fork)
|
||||
}
|
||||
}
|
||||
|
||||
impl OpHardforks for CustomChainSpec {
|
||||
fn op_fork_activation(
|
||||
&self,
|
||||
fork: reth_optimism_forks::OpHardfork,
|
||||
) -> reth_chainspec::ForkCondition {
|
||||
self.inner.op_fork_activation(fork)
|
||||
}
|
||||
}
|
||||
263
examples/custom-node/src/engine.rs
Normal file
263
examples/custom-node/src/engine.rs
Normal file
@@ -0,0 +1,263 @@
|
||||
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 reth_chain_state::ExecutedBlockWithTrieUpdates;
|
||||
use reth_node_api::{
|
||||
BuiltPayload, EngineTypes, 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;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CustomExecutionData {
|
||||
inner: OpExecutionData,
|
||||
extension: u64,
|
||||
}
|
||||
|
||||
impl ExecutionPayload for CustomExecutionData {
|
||||
fn block_hash(&self) -> revm_primitives::B256 {
|
||||
self.inner.block_hash()
|
||||
}
|
||||
|
||||
fn block_number(&self) -> u64 {
|
||||
self.inner.block_number()
|
||||
}
|
||||
|
||||
fn parent_hash(&self) -> revm_primitives::B256 {
|
||||
self.inner.parent_hash()
|
||||
}
|
||||
|
||||
fn gas_used(&self) -> u64 {
|
||||
self.inner.gas_used()
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> u64 {
|
||||
self.inner.timestamp()
|
||||
}
|
||||
|
||||
fn parent_beacon_block_root(&self) -> Option<revm_primitives::B256> {
|
||||
self.inner.parent_beacon_block_root()
|
||||
}
|
||||
|
||||
fn withdrawals(&self) -> Option<&Vec<alloy_eips::eip4895::Withdrawal>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CustomPayloadAttributes {
|
||||
#[serde(flatten)]
|
||||
inner: OpPayloadAttributes,
|
||||
extension: u64,
|
||||
}
|
||||
|
||||
impl PayloadAttributes for CustomPayloadAttributes {
|
||||
fn parent_beacon_block_root(&self) -> Option<revm_primitives::B256> {
|
||||
self.inner.parent_beacon_block_root()
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> u64 {
|
||||
self.inner.timestamp()
|
||||
}
|
||||
|
||||
fn withdrawals(&self) -> Option<&Vec<alloy_eips::eip4895::Withdrawal>> {
|
||||
self.inner.withdrawals()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CustomPayloadBuilderAttributes {
|
||||
inner: OpPayloadBuilderAttributes<OpTransactionSigned>,
|
||||
_extension: u64,
|
||||
}
|
||||
|
||||
impl PayloadBuilderAttributes for CustomPayloadBuilderAttributes {
|
||||
type RpcPayloadAttributes = CustomPayloadAttributes;
|
||||
type Error = alloy_rlp::Error;
|
||||
|
||||
fn try_new(
|
||||
parent: revm_primitives::B256,
|
||||
rpc_payload_attributes: Self::RpcPayloadAttributes,
|
||||
version: u8,
|
||||
) -> Result<Self, Self::Error>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let CustomPayloadAttributes { inner, extension } = rpc_payload_attributes;
|
||||
|
||||
Ok(Self {
|
||||
inner: OpPayloadBuilderAttributes::try_new(parent, inner, version)?,
|
||||
_extension: extension,
|
||||
})
|
||||
}
|
||||
|
||||
fn parent(&self) -> revm_primitives::B256 {
|
||||
self.inner.parent()
|
||||
}
|
||||
|
||||
fn parent_beacon_block_root(&self) -> Option<revm_primitives::B256> {
|
||||
self.inner.parent_beacon_block_root()
|
||||
}
|
||||
|
||||
fn payload_id(&self) -> alloy_rpc_types_engine::PayloadId {
|
||||
self.inner.payload_id()
|
||||
}
|
||||
|
||||
fn prev_randao(&self) -> revm_primitives::B256 {
|
||||
self.inner.prev_randao()
|
||||
}
|
||||
|
||||
fn suggested_fee_recipient(&self) -> revm_primitives::Address {
|
||||
self.inner.suggested_fee_recipient()
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> u64 {
|
||||
self.inner.timestamp()
|
||||
}
|
||||
|
||||
fn withdrawals(&self) -> &alloy_eips::eip4895::Withdrawals {
|
||||
self.inner.withdrawals()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CustomBuiltPayload(pub OpBuiltPayload<CustomNodePrimitives>);
|
||||
|
||||
impl BuiltPayload for CustomBuiltPayload {
|
||||
type Primitives = CustomNodePrimitives;
|
||||
|
||||
fn block(&self) -> &SealedBlock<<Self::Primitives as NodePrimitives>::Block> {
|
||||
self.0.block()
|
||||
}
|
||||
|
||||
fn executed_block(&self) -> Option<ExecutedBlockWithTrieUpdates<Self::Primitives>> {
|
||||
self.0.executed_block()
|
||||
}
|
||||
|
||||
fn fees(&self) -> U256 {
|
||||
self.0.fees()
|
||||
}
|
||||
|
||||
fn requests(&self) -> Option<alloy_eips::eip7685::Requests> {
|
||||
self.0.requests()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CustomBuiltPayload>
|
||||
for alloy_consensus::Block<<CustomNodePrimitives as NodePrimitives>::SignedTx>
|
||||
{
|
||||
fn from(value: CustomBuiltPayload) -> Self {
|
||||
value.0.into_sealed_block().into_block().map_header(|header| header.inner)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
type BuiltPayload = CustomBuiltPayload;
|
||||
type PayloadAttributes = CustomPayloadAttributes;
|
||||
type PayloadBuilderAttributes = CustomPayloadBuilderAttributes;
|
||||
type ExecutionData = CustomExecutionData;
|
||||
|
||||
fn block_to_payload(
|
||||
block: SealedBlock<
|
||||
<<Self::BuiltPayload as BuiltPayload>::Primitives as NodePrimitives>::Block,
|
||||
>,
|
||||
) -> Self::ExecutionData {
|
||||
let extension = block.header().extension;
|
||||
let block_hash = block.hash();
|
||||
let block = block.into_block().map_header(|header| header.inner);
|
||||
let (payload, sidecar) = OpExecutionPayload::from_block_unchecked(block_hash, &block);
|
||||
CustomExecutionData { inner: OpExecutionData { payload, sidecar }, extension }
|
||||
}
|
||||
}
|
||||
|
||||
impl EngineTypes for CustomEngineTypes {
|
||||
type ExecutionPayloadEnvelopeV1 = ExecutionPayloadV1;
|
||||
type ExecutionPayloadEnvelopeV2 = ExecutionPayloadV2;
|
||||
type ExecutionPayloadEnvelopeV3 = OpExecutionPayloadEnvelopeV3;
|
||||
type ExecutionPayloadEnvelopeV4 = OpExecutionPayloadEnvelopeV4;
|
||||
}
|
||||
62
examples/custom-node/src/lib.rs
Normal file
62
examples/custom-node/src/lib.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
//! This example shows how implement a custom node.
|
||||
//!
|
||||
//! A node consists of:
|
||||
//! - primtives: block,header,transactions
|
||||
//! - components: network,pool,evm
|
||||
//! - engine: advances the node
|
||||
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
|
||||
use chainspec::CustomChainSpec;
|
||||
use engine::CustomEngineTypes;
|
||||
use primitives::CustomNodePrimitives;
|
||||
use reth_node_api::{FullNodeTypes, NodeTypes, NodeTypesWithEngine};
|
||||
use reth_node_builder::{components::ComponentsBuilder, Node, NodeComponentsBuilder};
|
||||
use reth_optimism_node::{
|
||||
node::{OpConsensusBuilder, OpPoolBuilder, OpStorage},
|
||||
OpNode,
|
||||
};
|
||||
|
||||
pub mod chainspec;
|
||||
pub mod engine;
|
||||
pub mod primitives;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CustomNode {}
|
||||
|
||||
impl NodeTypes for CustomNode {
|
||||
type Primitives = CustomNodePrimitives;
|
||||
type ChainSpec = CustomChainSpec;
|
||||
type StateCommitment = <OpNode as NodeTypes>::StateCommitment;
|
||||
type Storage = <OpNode as NodeTypes>::Storage;
|
||||
}
|
||||
|
||||
impl NodeTypesWithEngine for CustomNode {
|
||||
type Engine = CustomEngineTypes;
|
||||
}
|
||||
|
||||
impl<N> Node<N> for CustomNode
|
||||
where
|
||||
N: FullNodeTypes<
|
||||
Types: NodeTypesWithEngine<
|
||||
Engine = CustomEngineTypes,
|
||||
ChainSpec = CustomChainSpec,
|
||||
Primitives = CustomNodePrimitives,
|
||||
Storage = OpStorage,
|
||||
>,
|
||||
>,
|
||||
ComponentsBuilder<N, OpPoolBuilder, (), (), (), OpConsensusBuilder>: NodeComponentsBuilder<N>,
|
||||
{
|
||||
type ComponentsBuilder = ComponentsBuilder<N, OpPoolBuilder, (), (), (), OpConsensusBuilder>;
|
||||
|
||||
type AddOns = ();
|
||||
|
||||
fn components_builder(&self) -> Self::ComponentsBuilder {
|
||||
ComponentsBuilder::default()
|
||||
.node_types::<N>()
|
||||
.pool(OpPoolBuilder::default())
|
||||
.consensus(OpConsensusBuilder::default())
|
||||
}
|
||||
|
||||
fn add_ons(&self) -> Self::AddOns {}
|
||||
}
|
||||
8
examples/custom-node/src/primitives/block.rs
Normal file
8
examples/custom-node/src/primitives/block.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use crate::primitives::CustomHeader;
|
||||
use reth_optimism_primitives::OpTransactionSigned;
|
||||
|
||||
/// The Block type of this node
|
||||
pub type Block = alloy_consensus::Block<OpTransactionSigned, CustomHeader>;
|
||||
|
||||
/// The body type of this node
|
||||
pub type BlockBody = alloy_consensus::BlockBody<OpTransactionSigned, CustomHeader>;
|
||||
195
examples/custom-node/src/primitives/header.rs
Normal file
195
examples/custom-node/src/primitives/header.rs
Normal file
@@ -0,0 +1,195 @@
|
||||
use alloy_consensus::Header;
|
||||
use alloy_primitives::{
|
||||
private::derive_more, Address, BlockNumber, Bloom, Bytes, Sealable, B256, B64, U256,
|
||||
};
|
||||
use alloy_rlp::{Encodable, RlpDecodable, RlpEncodable};
|
||||
use reth_codecs::Compact;
|
||||
use reth_primitives_traits::{BlockHeader, InMemorySize};
|
||||
use revm_primitives::keccak256;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The header type of this node
|
||||
///
|
||||
/// This type extends the regular ethereum header with an extension.
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Hash,
|
||||
derive_more::AsRef,
|
||||
derive_more::Deref,
|
||||
Default,
|
||||
RlpEncodable,
|
||||
RlpDecodable,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomHeader {
|
||||
/// The regular eth header
|
||||
#[as_ref]
|
||||
#[deref]
|
||||
#[serde(flatten)]
|
||||
pub inner: Header,
|
||||
/// The extended header
|
||||
pub extension: u64,
|
||||
}
|
||||
|
||||
impl CustomHeader {}
|
||||
|
||||
impl AsRef<Self> for CustomHeader {
|
||||
fn as_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Sealable for CustomHeader {
|
||||
fn hash_slow(&self) -> B256 {
|
||||
let mut out = Vec::new();
|
||||
self.encode(&mut out);
|
||||
keccak256(&out)
|
||||
}
|
||||
}
|
||||
|
||||
impl alloy_consensus::BlockHeader for CustomHeader {
|
||||
fn parent_hash(&self) -> B256 {
|
||||
self.inner.parent_hash()
|
||||
}
|
||||
|
||||
fn ommers_hash(&self) -> B256 {
|
||||
self.inner.ommers_hash()
|
||||
}
|
||||
|
||||
fn beneficiary(&self) -> Address {
|
||||
self.inner.beneficiary()
|
||||
}
|
||||
|
||||
fn state_root(&self) -> B256 {
|
||||
self.inner.state_root()
|
||||
}
|
||||
|
||||
fn transactions_root(&self) -> B256 {
|
||||
self.inner.transactions_root()
|
||||
}
|
||||
|
||||
fn receipts_root(&self) -> B256 {
|
||||
self.inner.receipts_root()
|
||||
}
|
||||
|
||||
fn withdrawals_root(&self) -> Option<B256> {
|
||||
self.inner.withdrawals_root()
|
||||
}
|
||||
|
||||
fn logs_bloom(&self) -> Bloom {
|
||||
self.inner.logs_bloom()
|
||||
}
|
||||
|
||||
fn difficulty(&self) -> U256 {
|
||||
self.inner.difficulty()
|
||||
}
|
||||
|
||||
fn number(&self) -> BlockNumber {
|
||||
self.inner.number()
|
||||
}
|
||||
|
||||
fn gas_limit(&self) -> u64 {
|
||||
self.inner.gas_limit()
|
||||
}
|
||||
|
||||
fn gas_used(&self) -> u64 {
|
||||
self.inner.gas_used()
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> u64 {
|
||||
self.inner.timestamp()
|
||||
}
|
||||
|
||||
fn mix_hash(&self) -> Option<B256> {
|
||||
self.inner.mix_hash()
|
||||
}
|
||||
|
||||
fn nonce(&self) -> Option<B64> {
|
||||
self.inner.nonce()
|
||||
}
|
||||
|
||||
fn base_fee_per_gas(&self) -> Option<u64> {
|
||||
self.inner.base_fee_per_gas()
|
||||
}
|
||||
|
||||
fn blob_gas_used(&self) -> Option<u64> {
|
||||
self.inner.blob_gas_used()
|
||||
}
|
||||
|
||||
fn excess_blob_gas(&self) -> Option<u64> {
|
||||
self.inner.excess_blob_gas()
|
||||
}
|
||||
|
||||
fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||
self.inner.parent_beacon_block_root()
|
||||
}
|
||||
|
||||
fn requests_hash(&self) -> Option<B256> {
|
||||
self.inner.requests_hash()
|
||||
}
|
||||
|
||||
fn extra_data(&self) -> &Bytes {
|
||||
self.inner.extra_data()
|
||||
}
|
||||
}
|
||||
|
||||
impl InMemorySize for CustomHeader {
|
||||
fn size(&self) -> usize {
|
||||
self.inner.size() + self.extension.size()
|
||||
}
|
||||
}
|
||||
|
||||
impl reth_codecs::Compact for CustomHeader {
|
||||
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||
where
|
||||
B: alloy_rlp::bytes::BufMut + AsMut<[u8]>,
|
||||
{
|
||||
let identifier = self.inner.to_compact(buf);
|
||||
self.extension.to_compact(buf);
|
||||
|
||||
identifier
|
||||
}
|
||||
|
||||
fn from_compact(buf: &[u8], identifier: usize) -> (Self, &[u8]) {
|
||||
let (eth_header, buf) = Compact::from_compact(buf, identifier);
|
||||
let (extension, buf) = Compact::from_compact(buf, buf.len());
|
||||
(Self { inner: eth_header, extension }, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockHeader for CustomHeader {}
|
||||
|
||||
mod serde_bincode_compat {
|
||||
use alloy_consensus::serde_bincode_compat::Header;
|
||||
use reth_primitives_traits::serde_bincode_compat::SerdeBincodeCompat;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct CustomHeader<'a> {
|
||||
inner: Header<'a>,
|
||||
extension: u64,
|
||||
}
|
||||
|
||||
impl From<CustomHeader<'_>> for super::CustomHeader {
|
||||
fn from(value: CustomHeader) -> Self {
|
||||
Self { inner: value.inner.into(), extension: value.extension }
|
||||
}
|
||||
}
|
||||
|
||||
impl SerdeBincodeCompat for super::CustomHeader {
|
||||
type BincodeRepr<'a> = CustomHeader<'a>;
|
||||
|
||||
fn as_repr(&self) -> Self::BincodeRepr<'_> {
|
||||
CustomHeader { inner: self.inner.as_repr(), extension: self.extension }
|
||||
}
|
||||
|
||||
fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
|
||||
repr.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
20
examples/custom-node/src/primitives/mod.rs
Normal file
20
examples/custom-node/src/primitives/mod.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
//! Contains the primitive types of this node.
|
||||
|
||||
pub mod header;
|
||||
pub use header::*;
|
||||
pub mod block;
|
||||
pub use block::*;
|
||||
|
||||
use reth_optimism_primitives::{OpReceipt, OpTransactionSigned};
|
||||
use reth_primitives_traits::NodePrimitives;
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub struct CustomNodePrimitives;
|
||||
|
||||
impl NodePrimitives for CustomNodePrimitives {
|
||||
type Block = Block;
|
||||
type BlockHeader = CustomHeader;
|
||||
type BlockBody = BlockBody;
|
||||
type SignedTx = OpTransactionSigned;
|
||||
type Receipt = OpReceipt;
|
||||
}
|
||||
Reference in New Issue
Block a user