mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: EngineValidator (#11144)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -7401,6 +7401,7 @@ dependencies = [
|
|||||||
"reth-consensus",
|
"reth-consensus",
|
||||||
"reth-db",
|
"reth-db",
|
||||||
"reth-db-common",
|
"reth-db-common",
|
||||||
|
"reth-ethereum-engine-primitives",
|
||||||
"reth-evm",
|
"reth-evm",
|
||||||
"reth-execution-types",
|
"reth-execution-types",
|
||||||
"reth-exex",
|
"reth-exex",
|
||||||
|
|||||||
@ -31,9 +31,6 @@ pub trait EngineTypes:
|
|||||||
+ Serialize
|
+ Serialize
|
||||||
+ 'static
|
+ 'static
|
||||||
{
|
{
|
||||||
/// The chain specification of the node.
|
|
||||||
type ChainSpec: Send + Sync;
|
|
||||||
|
|
||||||
/// Execution Payload V1 type.
|
/// Execution Payload V1 type.
|
||||||
type ExecutionPayloadV1: DeserializeOwned + Serialize + Clone + Unpin + Send + Sync + 'static;
|
type ExecutionPayloadV1: DeserializeOwned + Serialize + Clone + Unpin + Send + Sync + 'static;
|
||||||
/// Execution Payload V2 type.
|
/// Execution Payload V2 type.
|
||||||
@ -42,12 +39,22 @@ pub trait EngineTypes:
|
|||||||
type ExecutionPayloadV3: DeserializeOwned + Serialize + Clone + Unpin + Send + Sync + 'static;
|
type ExecutionPayloadV3: DeserializeOwned + Serialize + Clone + Unpin + Send + Sync + 'static;
|
||||||
/// Execution Payload V4 type.
|
/// Execution Payload V4 type.
|
||||||
type ExecutionPayloadV4: DeserializeOwned + Serialize + Clone + Unpin + Send + Sync + 'static;
|
type ExecutionPayloadV4: DeserializeOwned + Serialize + Clone + Unpin + Send + Sync + 'static;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Type that validates the payloads sent to the engine.
|
||||||
|
pub trait EngineValidator<Types: EngineTypes>: Clone + Send + Sync + Unpin + 'static {
|
||||||
/// Validates the presence or exclusion of fork-specific fields based on the payload attributes
|
/// Validates the presence or exclusion of fork-specific fields based on the payload attributes
|
||||||
/// and the message version.
|
/// and the message version.
|
||||||
fn validate_version_specific_fields(
|
fn validate_version_specific_fields(
|
||||||
chain_spec: &Self::ChainSpec,
|
&self,
|
||||||
version: EngineApiMessageVersion,
|
version: EngineApiMessageVersion,
|
||||||
payload_or_attrs: PayloadOrAttributes<'_, Self::PayloadAttributes>,
|
payload_or_attrs: PayloadOrAttributes<'_, <Types as PayloadTypes>::PayloadAttributes>,
|
||||||
|
) -> Result<(), EngineObjectValidationError>;
|
||||||
|
|
||||||
|
/// Ensures that the payload attributes are valid for the given [`EngineApiMessageVersion`].
|
||||||
|
fn ensure_well_formed_attributes(
|
||||||
|
&self,
|
||||||
|
version: EngineApiMessageVersion,
|
||||||
|
attributes: &<Types as PayloadTypes>::PayloadAttributes,
|
||||||
) -> Result<(), EngineObjectValidationError>;
|
) -> Result<(), EngineObjectValidationError>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,9 +9,11 @@
|
|||||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||||
|
|
||||||
mod payload;
|
mod payload;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub use payload::{EthBuiltPayload, EthPayloadBuilderAttributes};
|
pub use payload::{EthBuiltPayload, EthPayloadBuilderAttributes};
|
||||||
use reth_chainspec::ChainSpec;
|
use reth_chainspec::ChainSpec;
|
||||||
use reth_engine_primitives::EngineTypes;
|
use reth_engine_primitives::{EngineTypes, EngineValidator};
|
||||||
use reth_payload_primitives::{
|
use reth_payload_primitives::{
|
||||||
validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
|
validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
|
||||||
PayloadOrAttributes, PayloadTypes,
|
PayloadOrAttributes, PayloadTypes,
|
||||||
@ -36,18 +38,42 @@ impl PayloadTypes for EthEngineTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EngineTypes for EthEngineTypes {
|
impl EngineTypes for EthEngineTypes {
|
||||||
type ChainSpec = ChainSpec;
|
|
||||||
|
|
||||||
type ExecutionPayloadV1 = ExecutionPayloadV1;
|
type ExecutionPayloadV1 = ExecutionPayloadV1;
|
||||||
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
|
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
|
||||||
type ExecutionPayloadV3 = ExecutionPayloadEnvelopeV3;
|
type ExecutionPayloadV3 = ExecutionPayloadEnvelopeV3;
|
||||||
type ExecutionPayloadV4 = ExecutionPayloadEnvelopeV4;
|
type ExecutionPayloadV4 = ExecutionPayloadEnvelopeV4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Validator for the ethereum engine API.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EthereumEngineValidator {
|
||||||
|
chain_spec: Arc<ChainSpec>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EthereumEngineValidator {
|
||||||
|
/// Instantiates a new validator.
|
||||||
|
pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
|
||||||
|
Self { chain_spec }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Types> EngineValidator<Types> for EthereumEngineValidator
|
||||||
|
where
|
||||||
|
Types: EngineTypes<PayloadAttributes = EthPayloadAttributes>,
|
||||||
|
{
|
||||||
fn validate_version_specific_fields(
|
fn validate_version_specific_fields(
|
||||||
chain_spec: &ChainSpec,
|
&self,
|
||||||
version: EngineApiMessageVersion,
|
version: EngineApiMessageVersion,
|
||||||
payload_or_attrs: PayloadOrAttributes<'_, EthPayloadAttributes>,
|
payload_or_attrs: PayloadOrAttributes<'_, EthPayloadAttributes>,
|
||||||
) -> Result<(), EngineObjectValidationError> {
|
) -> Result<(), EngineObjectValidationError> {
|
||||||
validate_version_specific_fields(chain_spec, version, payload_or_attrs)
|
validate_version_specific_fields(&self.chain_spec, version, payload_or_attrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ensure_well_formed_attributes(
|
||||||
|
&self,
|
||||||
|
version: EngineApiMessageVersion,
|
||||||
|
attributes: &EthPayloadAttributes,
|
||||||
|
) -> Result<(), EngineObjectValidationError> {
|
||||||
|
validate_version_specific_fields(&self.chain_spec, version, attributes.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,15 +7,15 @@ use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGenera
|
|||||||
use reth_beacon_consensus::EthBeaconConsensus;
|
use reth_beacon_consensus::EthBeaconConsensus;
|
||||||
use reth_chainspec::ChainSpec;
|
use reth_chainspec::ChainSpec;
|
||||||
use reth_ethereum_engine_primitives::{
|
use reth_ethereum_engine_primitives::{
|
||||||
EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes,
|
EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes, EthereumEngineValidator,
|
||||||
};
|
};
|
||||||
use reth_evm_ethereum::execute::EthExecutorProvider;
|
use reth_evm_ethereum::execute::EthExecutorProvider;
|
||||||
use reth_network::NetworkHandle;
|
use reth_network::NetworkHandle;
|
||||||
use reth_node_api::{ConfigureEvm, FullNodeComponents, NodeAddOns};
|
use reth_node_api::{ConfigureEvm, EngineValidator, FullNodeComponents, NodeAddOns};
|
||||||
use reth_node_builder::{
|
use reth_node_builder::{
|
||||||
components::{
|
components::{
|
||||||
ComponentsBuilder, ConsensusBuilder, ExecutorBuilder, NetworkBuilder,
|
ComponentsBuilder, ConsensusBuilder, EngineValidatorBuilder, ExecutorBuilder,
|
||||||
PayloadServiceBuilder, PoolBuilder,
|
NetworkBuilder, PayloadServiceBuilder, PoolBuilder,
|
||||||
},
|
},
|
||||||
node::{FullNodeTypes, NodeTypes, NodeTypesWithEngine},
|
node::{FullNodeTypes, NodeTypes, NodeTypesWithEngine},
|
||||||
BuilderContext, Node, PayloadBuilderConfig, PayloadTypes,
|
BuilderContext, Node, PayloadBuilderConfig, PayloadTypes,
|
||||||
@ -46,6 +46,7 @@ impl EthereumNode {
|
|||||||
EthereumNetworkBuilder,
|
EthereumNetworkBuilder,
|
||||||
EthereumExecutorBuilder,
|
EthereumExecutorBuilder,
|
||||||
EthereumConsensusBuilder,
|
EthereumConsensusBuilder,
|
||||||
|
EthereumEngineValidatorBuilder,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec>>,
|
Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec>>,
|
||||||
@ -62,6 +63,7 @@ impl EthereumNode {
|
|||||||
.network(EthereumNetworkBuilder::default())
|
.network(EthereumNetworkBuilder::default())
|
||||||
.executor(EthereumExecutorBuilder::default())
|
.executor(EthereumExecutorBuilder::default())
|
||||||
.consensus(EthereumConsensusBuilder::default())
|
.consensus(EthereumConsensusBuilder::default())
|
||||||
|
.engine_validator(EthereumEngineValidatorBuilder::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +96,7 @@ where
|
|||||||
EthereumNetworkBuilder,
|
EthereumNetworkBuilder,
|
||||||
EthereumExecutorBuilder,
|
EthereumExecutorBuilder,
|
||||||
EthereumConsensusBuilder,
|
EthereumConsensusBuilder,
|
||||||
|
EthereumEngineValidatorBuilder,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type AddOns = EthereumAddOns;
|
type AddOns = EthereumAddOns;
|
||||||
@ -316,3 +319,21 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Builder for [`EthereumEngineValidator`].
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct EthereumEngineValidatorBuilder;
|
||||||
|
|
||||||
|
impl<Node, Types> EngineValidatorBuilder<Node> for EthereumEngineValidatorBuilder
|
||||||
|
where
|
||||||
|
Types: NodeTypesWithEngine<ChainSpec = ChainSpec>,
|
||||||
|
Node: FullNodeTypes<Types = Types>,
|
||||||
|
EthereumEngineValidator: EngineValidator<Types::Engine>,
|
||||||
|
{
|
||||||
|
type Validator = EthereumEngineValidator;
|
||||||
|
|
||||||
|
async fn build_validator(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Validator> {
|
||||||
|
Ok(EthereumEngineValidator::new(ctx.chain_spec()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@ reth-primitives.workspace = true
|
|||||||
reth-provider = { workspace = true, features = ["test-utils"] }
|
reth-provider = { workspace = true, features = ["test-utils"] }
|
||||||
reth-tasks.workspace = true
|
reth-tasks.workspace = true
|
||||||
reth-transaction-pool = { workspace = true, features = ["test-utils"] }
|
reth-transaction-pool = { workspace = true, features = ["test-utils"] }
|
||||||
|
reth-ethereum-engine-primitives.workspace = true
|
||||||
|
|
||||||
## async
|
## async
|
||||||
futures-util.workspace = true
|
futures-util.workspace = true
|
||||||
|
|||||||
@ -17,6 +17,7 @@ use reth_db::{
|
|||||||
DatabaseEnv,
|
DatabaseEnv,
|
||||||
};
|
};
|
||||||
use reth_db_common::init::init_genesis;
|
use reth_db_common::init::init_genesis;
|
||||||
|
use reth_ethereum_engine_primitives::EthereumEngineValidator;
|
||||||
use reth_evm::test_utils::MockExecutorProvider;
|
use reth_evm::test_utils::MockExecutorProvider;
|
||||||
use reth_execution_types::Chain;
|
use reth_execution_types::Chain;
|
||||||
use reth_exex::{ExExContext, ExExEvent, ExExNotification, ExExNotifications};
|
use reth_exex::{ExExContext, ExExEvent, ExExNotification, ExExNotifications};
|
||||||
@ -33,7 +34,10 @@ use reth_node_builder::{
|
|||||||
};
|
};
|
||||||
use reth_node_core::node_config::NodeConfig;
|
use reth_node_core::node_config::NodeConfig;
|
||||||
use reth_node_ethereum::{
|
use reth_node_ethereum::{
|
||||||
node::{EthereumAddOns, EthereumNetworkBuilder, EthereumPayloadBuilder},
|
node::{
|
||||||
|
EthereumAddOns, EthereumEngineValidatorBuilder, EthereumNetworkBuilder,
|
||||||
|
EthereumPayloadBuilder,
|
||||||
|
},
|
||||||
EthEngineTypes, EthEvmConfig,
|
EthEngineTypes, EthEvmConfig,
|
||||||
};
|
};
|
||||||
use reth_payload_builder::noop::NoopPayloadBuilderService;
|
use reth_payload_builder::noop::NoopPayloadBuilderService;
|
||||||
@ -133,6 +137,7 @@ where
|
|||||||
EthereumNetworkBuilder,
|
EthereumNetworkBuilder,
|
||||||
TestExecutorBuilder,
|
TestExecutorBuilder,
|
||||||
TestConsensusBuilder,
|
TestConsensusBuilder,
|
||||||
|
EthereumEngineValidatorBuilder,
|
||||||
>;
|
>;
|
||||||
type AddOns = EthereumAddOns;
|
type AddOns = EthereumAddOns;
|
||||||
|
|
||||||
@ -144,6 +149,7 @@ where
|
|||||||
.network(EthereumNetworkBuilder::default())
|
.network(EthereumNetworkBuilder::default())
|
||||||
.executor(TestExecutorBuilder::default())
|
.executor(TestExecutorBuilder::default())
|
||||||
.consensus(TestConsensusBuilder::default())
|
.consensus(TestConsensusBuilder::default())
|
||||||
|
.engine_validator(EthereumEngineValidatorBuilder::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +252,7 @@ pub async fn test_exex_context_with_chain_spec(
|
|||||||
let db = create_test_rw_db();
|
let db = create_test_rw_db();
|
||||||
let provider_factory = ProviderFactory::new(
|
let provider_factory = ProviderFactory::new(
|
||||||
db,
|
db,
|
||||||
chain_spec,
|
chain_spec.clone(),
|
||||||
StaticFileProvider::read_write(static_dir.into_path()).expect("static file provider"),
|
StaticFileProvider::read_write(static_dir.into_path()).expect("static file provider"),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -266,6 +272,8 @@ pub async fn test_exex_context_with_chain_spec(
|
|||||||
let tasks = TaskManager::current();
|
let tasks = TaskManager::current();
|
||||||
let task_executor = tasks.executor();
|
let task_executor = tasks.executor();
|
||||||
|
|
||||||
|
let engine_validator = EthereumEngineValidator::new(chain_spec.clone());
|
||||||
|
|
||||||
let components = NodeAdapter::<FullNodeTypesAdapter<NodeTypesWithDBAdapter<TestNode, _>, _>, _> {
|
let components = NodeAdapter::<FullNodeTypesAdapter<NodeTypesWithDBAdapter<TestNode, _>, _>, _> {
|
||||||
components: Components {
|
components: Components {
|
||||||
transaction_pool,
|
transaction_pool,
|
||||||
@ -274,6 +282,7 @@ pub async fn test_exex_context_with_chain_spec(
|
|||||||
consensus,
|
consensus,
|
||||||
network,
|
network,
|
||||||
payload_builder,
|
payload_builder,
|
||||||
|
engine_validator,
|
||||||
},
|
},
|
||||||
task_executor,
|
task_executor,
|
||||||
provider,
|
provider,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use std::{future::Future, marker::PhantomData};
|
|||||||
|
|
||||||
use reth_consensus::Consensus;
|
use reth_consensus::Consensus;
|
||||||
use reth_evm::execute::BlockExecutorProvider;
|
use reth_evm::execute::BlockExecutorProvider;
|
||||||
|
use reth_node_api::{EngineValidator, NodeTypesWithEngine};
|
||||||
use reth_primitives::Header;
|
use reth_primitives::Header;
|
||||||
use reth_transaction_pool::TransactionPool;
|
use reth_transaction_pool::TransactionPool;
|
||||||
|
|
||||||
@ -15,6 +16,8 @@ use crate::{
|
|||||||
BuilderContext, ConfigureEvm, FullNodeTypes,
|
BuilderContext, ConfigureEvm, FullNodeTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::EngineValidatorBuilder;
|
||||||
|
|
||||||
/// A generic, general purpose and customizable [`NodeComponentsBuilder`] implementation.
|
/// A generic, general purpose and customizable [`NodeComponentsBuilder`] implementation.
|
||||||
///
|
///
|
||||||
/// This type is stateful and captures the configuration of the node's components.
|
/// This type is stateful and captures the configuration of the node's components.
|
||||||
@ -35,22 +38,23 @@ use crate::{
|
|||||||
/// All component builders are captured in the builder state and will be consumed once the node is
|
/// All component builders are captured in the builder state and will be consumed once the node is
|
||||||
/// launched.
|
/// launched.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB> {
|
pub struct ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB> {
|
||||||
pool_builder: PoolB,
|
pool_builder: PoolB,
|
||||||
payload_builder: PayloadB,
|
payload_builder: PayloadB,
|
||||||
network_builder: NetworkB,
|
network_builder: NetworkB,
|
||||||
executor_builder: ExecB,
|
executor_builder: ExecB,
|
||||||
consensus_builder: ConsB,
|
consensus_builder: ConsB,
|
||||||
|
engine_validator_builder: EVB,
|
||||||
_marker: PhantomData<Node>,
|
_marker: PhantomData<Node>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||||
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||||
{
|
{
|
||||||
/// Configures the node types.
|
/// Configures the node types.
|
||||||
pub fn node_types<Types>(
|
pub fn node_types<Types>(
|
||||||
self,
|
self,
|
||||||
) -> ComponentsBuilder<Types, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
) -> ComponentsBuilder<Types, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||||
where
|
where
|
||||||
Types: FullNodeTypes,
|
Types: FullNodeTypes,
|
||||||
{
|
{
|
||||||
@ -60,6 +64,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder: evm_builder,
|
executor_builder: evm_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
} = self;
|
} = self;
|
||||||
ComponentsBuilder {
|
ComponentsBuilder {
|
||||||
@ -68,6 +73,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
|||||||
payload_builder,
|
payload_builder,
|
||||||
network_builder,
|
network_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker: Default::default(),
|
_marker: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,6 +86,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
|||||||
network_builder: self.network_builder,
|
network_builder: self.network_builder,
|
||||||
executor_builder: self.executor_builder,
|
executor_builder: self.executor_builder,
|
||||||
consensus_builder: self.consensus_builder,
|
consensus_builder: self.consensus_builder,
|
||||||
|
engine_validator_builder: self.engine_validator_builder,
|
||||||
_marker: self._marker,
|
_marker: self._marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,6 +99,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
|||||||
network_builder: self.network_builder,
|
network_builder: self.network_builder,
|
||||||
executor_builder: self.executor_builder,
|
executor_builder: self.executor_builder,
|
||||||
consensus_builder: self.consensus_builder,
|
consensus_builder: self.consensus_builder,
|
||||||
|
engine_validator_builder: self.engine_validator_builder,
|
||||||
_marker: self._marker,
|
_marker: self._marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,6 +112,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
|||||||
network_builder: f(self.network_builder),
|
network_builder: f(self.network_builder),
|
||||||
executor_builder: self.executor_builder,
|
executor_builder: self.executor_builder,
|
||||||
consensus_builder: self.consensus_builder,
|
consensus_builder: self.consensus_builder,
|
||||||
|
engine_validator_builder: self.engine_validator_builder,
|
||||||
_marker: self._marker,
|
_marker: self._marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,6 +125,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
|||||||
network_builder: self.network_builder,
|
network_builder: self.network_builder,
|
||||||
executor_builder: f(self.executor_builder),
|
executor_builder: f(self.executor_builder),
|
||||||
consensus_builder: self.consensus_builder,
|
consensus_builder: self.consensus_builder,
|
||||||
|
engine_validator_builder: self.engine_validator_builder,
|
||||||
_marker: self._marker,
|
_marker: self._marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,13 +138,14 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
|||||||
network_builder: self.network_builder,
|
network_builder: self.network_builder,
|
||||||
executor_builder: self.executor_builder,
|
executor_builder: self.executor_builder,
|
||||||
consensus_builder: f(self.consensus_builder),
|
consensus_builder: f(self.consensus_builder),
|
||||||
|
engine_validator_builder: self.engine_validator_builder,
|
||||||
_marker: self._marker,
|
_marker: self._marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||||
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||||
where
|
where
|
||||||
Node: FullNodeTypes,
|
Node: FullNodeTypes,
|
||||||
{
|
{
|
||||||
@ -145,7 +156,7 @@ where
|
|||||||
pub fn pool<PB>(
|
pub fn pool<PB>(
|
||||||
self,
|
self,
|
||||||
pool_builder: PB,
|
pool_builder: PB,
|
||||||
) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB, ExecB, ConsB>
|
) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||||
where
|
where
|
||||||
PB: PoolBuilder<Node>,
|
PB: PoolBuilder<Node>,
|
||||||
{
|
{
|
||||||
@ -155,6 +166,7 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder: evm_builder,
|
executor_builder: evm_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
} = self;
|
} = self;
|
||||||
ComponentsBuilder {
|
ComponentsBuilder {
|
||||||
@ -163,13 +175,14 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder: evm_builder,
|
executor_builder: evm_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||||
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||||
where
|
where
|
||||||
Node: FullNodeTypes,
|
Node: FullNodeTypes,
|
||||||
PoolB: PoolBuilder<Node>,
|
PoolB: PoolBuilder<Node>,
|
||||||
@ -181,7 +194,7 @@ where
|
|||||||
pub fn network<NB>(
|
pub fn network<NB>(
|
||||||
self,
|
self,
|
||||||
network_builder: NB,
|
network_builder: NB,
|
||||||
) -> ComponentsBuilder<Node, PoolB, PayloadB, NB, ExecB, ConsB>
|
) -> ComponentsBuilder<Node, PoolB, PayloadB, NB, ExecB, ConsB, EVB>
|
||||||
where
|
where
|
||||||
NB: NetworkBuilder<Node, PoolB::Pool>,
|
NB: NetworkBuilder<Node, PoolB::Pool>,
|
||||||
{
|
{
|
||||||
@ -191,6 +204,7 @@ where
|
|||||||
network_builder: _,
|
network_builder: _,
|
||||||
executor_builder: evm_builder,
|
executor_builder: evm_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
} = self;
|
} = self;
|
||||||
ComponentsBuilder {
|
ComponentsBuilder {
|
||||||
@ -199,6 +213,7 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder: evm_builder,
|
executor_builder: evm_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,7 +225,7 @@ where
|
|||||||
pub fn payload<PB>(
|
pub fn payload<PB>(
|
||||||
self,
|
self,
|
||||||
payload_builder: PB,
|
payload_builder: PB,
|
||||||
) -> ComponentsBuilder<Node, PoolB, PB, NetworkB, ExecB, ConsB>
|
) -> ComponentsBuilder<Node, PoolB, PB, NetworkB, ExecB, ConsB, EVB>
|
||||||
where
|
where
|
||||||
PB: PayloadServiceBuilder<Node, PoolB::Pool>,
|
PB: PayloadServiceBuilder<Node, PoolB::Pool>,
|
||||||
{
|
{
|
||||||
@ -220,6 +235,7 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder: evm_builder,
|
executor_builder: evm_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
} = self;
|
} = self;
|
||||||
ComponentsBuilder {
|
ComponentsBuilder {
|
||||||
@ -228,6 +244,7 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder: evm_builder,
|
executor_builder: evm_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,7 +256,7 @@ where
|
|||||||
pub fn executor<EB>(
|
pub fn executor<EB>(
|
||||||
self,
|
self,
|
||||||
executor_builder: EB,
|
executor_builder: EB,
|
||||||
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, EB, ConsB>
|
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, EB, ConsB, EVB>
|
||||||
where
|
where
|
||||||
EB: ExecutorBuilder<Node>,
|
EB: ExecutorBuilder<Node>,
|
||||||
{
|
{
|
||||||
@ -249,6 +266,7 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder: _,
|
executor_builder: _,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
} = self;
|
} = self;
|
||||||
ComponentsBuilder {
|
ComponentsBuilder {
|
||||||
@ -257,6 +275,7 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder,
|
executor_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,7 +287,7 @@ where
|
|||||||
pub fn consensus<CB>(
|
pub fn consensus<CB>(
|
||||||
self,
|
self,
|
||||||
consensus_builder: CB,
|
consensus_builder: CB,
|
||||||
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, CB>
|
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, CB, EVB>
|
||||||
where
|
where
|
||||||
CB: ConsensusBuilder<Node>,
|
CB: ConsensusBuilder<Node>,
|
||||||
{
|
{
|
||||||
@ -278,6 +297,7 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder,
|
executor_builder,
|
||||||
consensus_builder: _,
|
consensus_builder: _,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
} = self;
|
} = self;
|
||||||
ComponentsBuilder {
|
ComponentsBuilder {
|
||||||
@ -286,13 +306,45 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder,
|
executor_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
|
_marker,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configures the consensus builder.
|
||||||
|
///
|
||||||
|
/// This accepts a [`ConsensusBuilder`] instance that will be used to create the node's
|
||||||
|
/// components for consensus.
|
||||||
|
pub fn engine_validator<EngineVB>(
|
||||||
|
self,
|
||||||
|
engine_validator_builder: EngineVB,
|
||||||
|
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EngineVB>
|
||||||
|
where
|
||||||
|
EngineVB: EngineValidatorBuilder<Node>,
|
||||||
|
{
|
||||||
|
let Self {
|
||||||
|
pool_builder,
|
||||||
|
payload_builder,
|
||||||
|
network_builder,
|
||||||
|
executor_builder,
|
||||||
|
consensus_builder,
|
||||||
|
engine_validator_builder: _,
|
||||||
|
_marker,
|
||||||
|
} = self;
|
||||||
|
ComponentsBuilder {
|
||||||
|
pool_builder,
|
||||||
|
payload_builder,
|
||||||
|
network_builder,
|
||||||
|
executor_builder,
|
||||||
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB> NodeComponentsBuilder<Node>
|
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB> NodeComponentsBuilder<Node>
|
||||||
for ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
for ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||||
where
|
where
|
||||||
Node: FullNodeTypes,
|
Node: FullNodeTypes,
|
||||||
PoolB: PoolBuilder<Node>,
|
PoolB: PoolBuilder<Node>,
|
||||||
@ -300,8 +352,16 @@ where
|
|||||||
PayloadB: PayloadServiceBuilder<Node, PoolB::Pool>,
|
PayloadB: PayloadServiceBuilder<Node, PoolB::Pool>,
|
||||||
ExecB: ExecutorBuilder<Node>,
|
ExecB: ExecutorBuilder<Node>,
|
||||||
ConsB: ConsensusBuilder<Node>,
|
ConsB: ConsensusBuilder<Node>,
|
||||||
|
EVB: EngineValidatorBuilder<Node>,
|
||||||
{
|
{
|
||||||
type Components = Components<Node, PoolB::Pool, ExecB::EVM, ExecB::Executor, ConsB::Consensus>;
|
type Components = Components<
|
||||||
|
Node,
|
||||||
|
PoolB::Pool,
|
||||||
|
ExecB::EVM,
|
||||||
|
ExecB::Executor,
|
||||||
|
ConsB::Consensus,
|
||||||
|
EVB::Validator,
|
||||||
|
>;
|
||||||
|
|
||||||
async fn build_components(
|
async fn build_components(
|
||||||
self,
|
self,
|
||||||
@ -313,6 +373,7 @@ where
|
|||||||
network_builder,
|
network_builder,
|
||||||
executor_builder: evm_builder,
|
executor_builder: evm_builder,
|
||||||
consensus_builder,
|
consensus_builder,
|
||||||
|
engine_validator_builder,
|
||||||
_marker,
|
_marker,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
@ -321,6 +382,7 @@ where
|
|||||||
let network = network_builder.build_network(context, pool.clone()).await?;
|
let network = network_builder.build_network(context, pool.clone()).await?;
|
||||||
let payload_builder = payload_builder.spawn_payload_service(context, pool.clone()).await?;
|
let payload_builder = payload_builder.spawn_payload_service(context, pool.clone()).await?;
|
||||||
let consensus = consensus_builder.build_consensus(context).await?;
|
let consensus = consensus_builder.build_consensus(context).await?;
|
||||||
|
let engine_validator = engine_validator_builder.build_validator(context).await?;
|
||||||
|
|
||||||
Ok(Components {
|
Ok(Components {
|
||||||
transaction_pool: pool,
|
transaction_pool: pool,
|
||||||
@ -329,11 +391,12 @@ where
|
|||||||
payload_builder,
|
payload_builder,
|
||||||
executor,
|
executor,
|
||||||
consensus,
|
consensus,
|
||||||
|
engine_validator,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ComponentsBuilder<(), (), (), (), (), ()> {
|
impl Default for ComponentsBuilder<(), (), (), (), (), (), ()> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
pool_builder: (),
|
pool_builder: (),
|
||||||
@ -341,6 +404,7 @@ impl Default for ComponentsBuilder<(), (), (), (), (), ()> {
|
|||||||
network_builder: (),
|
network_builder: (),
|
||||||
executor_builder: (),
|
executor_builder: (),
|
||||||
consensus_builder: (),
|
consensus_builder: (),
|
||||||
|
engine_validator_builder: (),
|
||||||
_marker: Default::default(),
|
_marker: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,17 +430,18 @@ pub trait NodeComponentsBuilder<Node: FullNodeTypes>: Send {
|
|||||||
) -> impl Future<Output = eyre::Result<Self::Components>> + Send;
|
) -> impl Future<Output = eyre::Result<Self::Components>> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node, F, Fut, Pool, EVM, Executor, Cons> NodeComponentsBuilder<Node> for F
|
impl<Node, F, Fut, Pool, EVM, Executor, Cons, Val> NodeComponentsBuilder<Node> for F
|
||||||
where
|
where
|
||||||
Node: FullNodeTypes,
|
Node: FullNodeTypes,
|
||||||
F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
|
F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
|
||||||
Fut: Future<Output = eyre::Result<Components<Node, Pool, EVM, Executor, Cons>>> + Send,
|
Fut: Future<Output = eyre::Result<Components<Node, Pool, EVM, Executor, Cons, Val>>> + Send,
|
||||||
Pool: TransactionPool + Unpin + 'static,
|
Pool: TransactionPool + Unpin + 'static,
|
||||||
EVM: ConfigureEvm<Header = Header>,
|
EVM: ConfigureEvm<Header = Header>,
|
||||||
Executor: BlockExecutorProvider,
|
Executor: BlockExecutorProvider,
|
||||||
Cons: Consensus + Clone + Unpin + 'static,
|
Cons: Consensus + Clone + Unpin + 'static,
|
||||||
|
Val: EngineValidator<<Node::Types as NodeTypesWithEngine>::Engine> + Clone + Unpin + 'static,
|
||||||
{
|
{
|
||||||
type Components = Components<Node, Pool, EVM, Executor, Cons>;
|
type Components = Components<Node, Pool, EVM, Executor, Cons, Val>;
|
||||||
|
|
||||||
fn build_components(
|
fn build_components(
|
||||||
self,
|
self,
|
||||||
|
|||||||
38
crates/node/builder/src/components/engine.rs
Normal file
38
crates/node/builder/src/components/engine.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//! Consensus component for the node builder.
|
||||||
|
use reth_node_api::{EngineValidator, NodeTypesWithEngine};
|
||||||
|
|
||||||
|
use crate::{BuilderContext, FullNodeTypes};
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
|
/// A type that knows how to build the engine validator.
|
||||||
|
pub trait EngineValidatorBuilder<Node: FullNodeTypes>: Send {
|
||||||
|
/// The consensus implementation to build.
|
||||||
|
type Validator: EngineValidator<<Node::Types as NodeTypesWithEngine>::Engine>
|
||||||
|
+ Clone
|
||||||
|
+ Unpin
|
||||||
|
+ 'static;
|
||||||
|
|
||||||
|
/// Creates the engine validator.
|
||||||
|
fn build_validator(
|
||||||
|
self,
|
||||||
|
ctx: &BuilderContext<Node>,
|
||||||
|
) -> impl Future<Output = eyre::Result<Self::Validator>> + Send;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Node, F, Fut, Validator> EngineValidatorBuilder<Node> for F
|
||||||
|
where
|
||||||
|
Node: FullNodeTypes,
|
||||||
|
Validator:
|
||||||
|
EngineValidator<<Node::Types as NodeTypesWithEngine>::Engine> + Clone + Unpin + 'static,
|
||||||
|
F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
|
||||||
|
Fut: Future<Output = eyre::Result<Validator>> + Send,
|
||||||
|
{
|
||||||
|
type Validator = Validator;
|
||||||
|
|
||||||
|
fn build_validator(
|
||||||
|
self,
|
||||||
|
ctx: &BuilderContext<Node>,
|
||||||
|
) -> impl Future<Output = eyre::Result<Self::Validator>> {
|
||||||
|
self(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
mod builder;
|
mod builder;
|
||||||
mod consensus;
|
mod consensus;
|
||||||
|
mod engine;
|
||||||
mod execute;
|
mod execute;
|
||||||
mod network;
|
mod network;
|
||||||
mod payload;
|
mod payload;
|
||||||
@ -16,6 +17,7 @@ mod pool;
|
|||||||
|
|
||||||
pub use builder::*;
|
pub use builder::*;
|
||||||
pub use consensus::*;
|
pub use consensus::*;
|
||||||
|
pub use engine::*;
|
||||||
pub use execute::*;
|
pub use execute::*;
|
||||||
pub use network::*;
|
pub use network::*;
|
||||||
pub use payload::*;
|
pub use payload::*;
|
||||||
@ -25,7 +27,7 @@ use reth_consensus::Consensus;
|
|||||||
use reth_evm::execute::BlockExecutorProvider;
|
use reth_evm::execute::BlockExecutorProvider;
|
||||||
use reth_network::NetworkHandle;
|
use reth_network::NetworkHandle;
|
||||||
use reth_network_api::FullNetwork;
|
use reth_network_api::FullNetwork;
|
||||||
use reth_node_api::NodeTypesWithEngine;
|
use reth_node_api::{EngineValidator, NodeTypesWithEngine};
|
||||||
use reth_payload_builder::PayloadBuilderHandle;
|
use reth_payload_builder::PayloadBuilderHandle;
|
||||||
use reth_primitives::Header;
|
use reth_primitives::Header;
|
||||||
use reth_transaction_pool::TransactionPool;
|
use reth_transaction_pool::TransactionPool;
|
||||||
@ -53,6 +55,9 @@ pub trait NodeComponents<T: FullNodeTypes>: Clone + Unpin + Send + Sync + 'stati
|
|||||||
/// Network API.
|
/// Network API.
|
||||||
type Network: FullNetwork;
|
type Network: FullNetwork;
|
||||||
|
|
||||||
|
/// Validator for the engine API.
|
||||||
|
type EngineValidator: EngineValidator<<T::Types as NodeTypesWithEngine>::Engine>;
|
||||||
|
|
||||||
/// Returns the transaction pool of the node.
|
/// Returns the transaction pool of the node.
|
||||||
fn pool(&self) -> &Self::Pool;
|
fn pool(&self) -> &Self::Pool;
|
||||||
|
|
||||||
@ -70,13 +75,16 @@ pub trait NodeComponents<T: FullNodeTypes>: Clone + Unpin + Send + Sync + 'stati
|
|||||||
|
|
||||||
/// Returns the handle to the payload builder service.
|
/// Returns the handle to the payload builder service.
|
||||||
fn payload_builder(&self) -> &PayloadBuilderHandle<<T::Types as NodeTypesWithEngine>::Engine>;
|
fn payload_builder(&self) -> &PayloadBuilderHandle<<T::Types as NodeTypesWithEngine>::Engine>;
|
||||||
|
|
||||||
|
/// Returns the engine validator.
|
||||||
|
fn engine_validator(&self) -> &Self::EngineValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All the components of the node.
|
/// All the components of the node.
|
||||||
///
|
///
|
||||||
/// This provides access to all the components of the node.
|
/// This provides access to all the components of the node.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Components<Node: FullNodeTypes, Pool, EVM, Executor, Consensus> {
|
pub struct Components<Node: FullNodeTypes, Pool, EVM, Executor, Consensus, Validator> {
|
||||||
/// The transaction pool of the node.
|
/// The transaction pool of the node.
|
||||||
pub transaction_pool: Pool,
|
pub transaction_pool: Pool,
|
||||||
/// The node's EVM configuration, defining settings for the Ethereum Virtual Machine.
|
/// The node's EVM configuration, defining settings for the Ethereum Virtual Machine.
|
||||||
@ -89,22 +97,26 @@ pub struct Components<Node: FullNodeTypes, Pool, EVM, Executor, Consensus> {
|
|||||||
pub network: NetworkHandle,
|
pub network: NetworkHandle,
|
||||||
/// The handle to the payload builder service.
|
/// The handle to the payload builder service.
|
||||||
pub payload_builder: PayloadBuilderHandle<<Node::Types as NodeTypesWithEngine>::Engine>,
|
pub payload_builder: PayloadBuilderHandle<<Node::Types as NodeTypesWithEngine>::Engine>,
|
||||||
|
/// The validator for the engine API.
|
||||||
|
pub engine_validator: Validator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node, Pool, EVM, Executor, Cons> NodeComponents<Node>
|
impl<Node, Pool, EVM, Executor, Cons, Val> NodeComponents<Node>
|
||||||
for Components<Node, Pool, EVM, Executor, Cons>
|
for Components<Node, Pool, EVM, Executor, Cons, Val>
|
||||||
where
|
where
|
||||||
Node: FullNodeTypes,
|
Node: FullNodeTypes,
|
||||||
Pool: TransactionPool + Unpin + 'static,
|
Pool: TransactionPool + Unpin + 'static,
|
||||||
EVM: ConfigureEvm<Header = Header>,
|
EVM: ConfigureEvm<Header = Header>,
|
||||||
Executor: BlockExecutorProvider,
|
Executor: BlockExecutorProvider,
|
||||||
Cons: Consensus + Clone + Unpin + 'static,
|
Cons: Consensus + Clone + Unpin + 'static,
|
||||||
|
Val: EngineValidator<<Node::Types as NodeTypesWithEngine>::Engine> + Clone + Unpin + 'static,
|
||||||
{
|
{
|
||||||
type Pool = Pool;
|
type Pool = Pool;
|
||||||
type Evm = EVM;
|
type Evm = EVM;
|
||||||
type Executor = Executor;
|
type Executor = Executor;
|
||||||
type Consensus = Cons;
|
type Consensus = Cons;
|
||||||
type Network = NetworkHandle;
|
type Network = NetworkHandle;
|
||||||
|
type EngineValidator = Val;
|
||||||
|
|
||||||
fn pool(&self) -> &Self::Pool {
|
fn pool(&self) -> &Self::Pool {
|
||||||
&self.transaction_pool
|
&self.transaction_pool
|
||||||
@ -131,15 +143,21 @@ where
|
|||||||
) -> &PayloadBuilderHandle<<Node::Types as NodeTypesWithEngine>::Engine> {
|
) -> &PayloadBuilderHandle<<Node::Types as NodeTypesWithEngine>::Engine> {
|
||||||
&self.payload_builder
|
&self.payload_builder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn engine_validator(&self) -> &Self::EngineValidator {
|
||||||
|
&self.engine_validator
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node, Pool, EVM, Executor, Cons> Clone for Components<Node, Pool, EVM, Executor, Cons>
|
impl<Node, Pool, EVM, Executor, Cons, Val> Clone
|
||||||
|
for Components<Node, Pool, EVM, Executor, Cons, Val>
|
||||||
where
|
where
|
||||||
Node: FullNodeTypes,
|
Node: FullNodeTypes,
|
||||||
Pool: TransactionPool,
|
Pool: TransactionPool,
|
||||||
EVM: ConfigureEvm<Header = Header>,
|
EVM: ConfigureEvm<Header = Header>,
|
||||||
Executor: BlockExecutorProvider,
|
Executor: BlockExecutorProvider,
|
||||||
Cons: Consensus + Clone,
|
Cons: Consensus + Clone,
|
||||||
|
Val: EngineValidator<<Node::Types as NodeTypesWithEngine>::Engine>,
|
||||||
{
|
{
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -149,6 +167,7 @@ where
|
|||||||
consensus: self.consensus.clone(),
|
consensus: self.consensus.clone(),
|
||||||
network: self.network.clone(),
|
network: self.network.clone(),
|
||||||
payload_builder: self.payload_builder.clone(),
|
payload_builder: self.payload_builder.clone(),
|
||||||
|
engine_validator: self.engine_validator.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -275,6 +275,7 @@ where
|
|||||||
Box::new(ctx.task_executor().clone()),
|
Box::new(ctx.task_executor().clone()),
|
||||||
client,
|
client,
|
||||||
EngineCapabilities::default(),
|
EngineCapabilities::default(),
|
||||||
|
ctx.components().engine_validator().clone(),
|
||||||
);
|
);
|
||||||
info!(target: "reth::cli", "Engine API handler initialized");
|
info!(target: "reth::cli", "Engine API handler initialized");
|
||||||
|
|
||||||
|
|||||||
@ -351,6 +351,7 @@ where
|
|||||||
Box::new(ctx.task_executor().clone()),
|
Box::new(ctx.task_executor().clone()),
|
||||||
client,
|
client,
|
||||||
EngineCapabilities::default(),
|
EngineCapabilities::default(),
|
||||||
|
ctx.components().engine_validator().clone(),
|
||||||
);
|
);
|
||||||
info!(target: "reth::cli", "Engine API handler initialized");
|
info!(target: "reth::cli", "Engine API handler initialized");
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ pub trait NodeTypes: Send + Sync + Unpin + 'static {
|
|||||||
/// The type that configures an Ethereum-like node with an engine for consensus.
|
/// The type that configures an Ethereum-like node with an engine for consensus.
|
||||||
pub trait NodeTypesWithEngine: NodeTypes {
|
pub trait NodeTypesWithEngine: NodeTypes {
|
||||||
/// The node's engine types, defining the interaction with the consensus engine.
|
/// The node's engine types, defining the interaction with the consensus engine.
|
||||||
type Engine: EngineTypes<ChainSpec = Self::ChainSpec>;
|
type Engine: EngineTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A helper trait that is downstream of the [`NodeTypesWithEngine`] trait and adds database to the
|
/// A helper trait that is downstream of the [`NodeTypesWithEngine`] trait and adds database to the
|
||||||
@ -166,7 +166,7 @@ where
|
|||||||
impl<P, E, C> NodeTypesWithEngine for AnyNodeTypesWithEngine<P, E, C>
|
impl<P, E, C> NodeTypesWithEngine for AnyNodeTypesWithEngine<P, E, C>
|
||||||
where
|
where
|
||||||
P: NodePrimitives + Send + Sync + Unpin + 'static,
|
P: NodePrimitives + Send + Sync + Unpin + 'static,
|
||||||
E: EngineTypes<ChainSpec = C> + Send + Sync + Unpin,
|
E: EngineTypes + Send + Sync + Unpin,
|
||||||
C: EthChainSpec,
|
C: EthChainSpec,
|
||||||
{
|
{
|
||||||
type Engine = E;
|
type Engine = E;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use op_alloy_rpc_types_engine::{
|
use op_alloy_rpc_types_engine::{
|
||||||
OptimismExecutionPayloadEnvelopeV3, OptimismExecutionPayloadEnvelopeV4,
|
OptimismExecutionPayloadEnvelopeV3, OptimismExecutionPayloadEnvelopeV4,
|
||||||
OptimismPayloadAttributes,
|
OptimismPayloadAttributes,
|
||||||
@ -9,7 +11,7 @@ use reth_node_api::{
|
|||||||
EngineObjectValidationError, MessageValidationKind, PayloadOrAttributes, PayloadTypes,
|
EngineObjectValidationError, MessageValidationKind, PayloadOrAttributes, PayloadTypes,
|
||||||
VersionSpecificValidationError,
|
VersionSpecificValidationError,
|
||||||
},
|
},
|
||||||
EngineTypes,
|
validate_version_specific_fields, EngineTypes, EngineValidator,
|
||||||
};
|
};
|
||||||
use reth_optimism_forks::OptimismHardfork;
|
use reth_optimism_forks::OptimismHardfork;
|
||||||
use reth_optimism_payload_builder::{OptimismBuiltPayload, OptimismPayloadBuilderAttributes};
|
use reth_optimism_payload_builder::{OptimismBuiltPayload, OptimismPayloadBuilderAttributes};
|
||||||
@ -20,6 +22,19 @@ use reth_rpc_types::{engine::ExecutionPayloadEnvelopeV2, ExecutionPayloadV1};
|
|||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct OptimismEngineTypes;
|
pub struct OptimismEngineTypes;
|
||||||
|
|
||||||
|
/// Validator for Optimism engine API.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct OptimismEngineValidator {
|
||||||
|
chain_spec: Arc<ChainSpec>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OptimismEngineValidator {
|
||||||
|
/// Instantiates a new validator.
|
||||||
|
pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
|
||||||
|
Self { chain_spec }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PayloadTypes for OptimismEngineTypes {
|
impl PayloadTypes for OptimismEngineTypes {
|
||||||
type BuiltPayload = OptimismBuiltPayload;
|
type BuiltPayload = OptimismBuiltPayload;
|
||||||
type PayloadAttributes = OptimismPayloadAttributes;
|
type PayloadAttributes = OptimismPayloadAttributes;
|
||||||
@ -27,33 +42,10 @@ impl PayloadTypes for OptimismEngineTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EngineTypes for OptimismEngineTypes {
|
impl EngineTypes for OptimismEngineTypes {
|
||||||
type ChainSpec = ChainSpec;
|
|
||||||
|
|
||||||
type ExecutionPayloadV1 = ExecutionPayloadV1;
|
type ExecutionPayloadV1 = ExecutionPayloadV1;
|
||||||
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
|
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
|
||||||
type ExecutionPayloadV3 = OptimismExecutionPayloadEnvelopeV3;
|
type ExecutionPayloadV3 = OptimismExecutionPayloadEnvelopeV3;
|
||||||
type ExecutionPayloadV4 = OptimismExecutionPayloadEnvelopeV4;
|
type ExecutionPayloadV4 = OptimismExecutionPayloadEnvelopeV4;
|
||||||
|
|
||||||
fn validate_version_specific_fields(
|
|
||||||
chain_spec: &ChainSpec,
|
|
||||||
version: EngineApiMessageVersion,
|
|
||||||
payload_or_attrs: PayloadOrAttributes<'_, Self::PayloadAttributes>,
|
|
||||||
) -> Result<(), EngineObjectValidationError> {
|
|
||||||
validate_withdrawals_presence(
|
|
||||||
chain_spec,
|
|
||||||
version,
|
|
||||||
payload_or_attrs.message_validation_kind(),
|
|
||||||
payload_or_attrs.timestamp(),
|
|
||||||
payload_or_attrs.withdrawals().is_some(),
|
|
||||||
)?;
|
|
||||||
validate_parent_beacon_block_root_presence(
|
|
||||||
chain_spec,
|
|
||||||
version,
|
|
||||||
payload_or_attrs.message_validation_kind(),
|
|
||||||
payload_or_attrs.timestamp(),
|
|
||||||
payload_or_attrs.parent_beacon_block_root().is_some(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates the presence of the `withdrawals` field according to the payload timestamp.
|
/// Validates the presence of the `withdrawals` field according to the payload timestamp.
|
||||||
@ -97,3 +89,45 @@ pub fn validate_withdrawals_presence(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Types> EngineValidator<Types> for OptimismEngineValidator
|
||||||
|
where
|
||||||
|
Types: EngineTypes<PayloadAttributes = OptimismPayloadAttributes>,
|
||||||
|
{
|
||||||
|
fn validate_version_specific_fields(
|
||||||
|
&self,
|
||||||
|
version: EngineApiMessageVersion,
|
||||||
|
payload_or_attrs: PayloadOrAttributes<'_, OptimismPayloadAttributes>,
|
||||||
|
) -> Result<(), EngineObjectValidationError> {
|
||||||
|
validate_withdrawals_presence(
|
||||||
|
&self.chain_spec,
|
||||||
|
version,
|
||||||
|
payload_or_attrs.message_validation_kind(),
|
||||||
|
payload_or_attrs.timestamp(),
|
||||||
|
payload_or_attrs.withdrawals().is_some(),
|
||||||
|
)?;
|
||||||
|
validate_parent_beacon_block_root_presence(
|
||||||
|
&self.chain_spec,
|
||||||
|
version,
|
||||||
|
payload_or_attrs.message_validation_kind(),
|
||||||
|
payload_or_attrs.timestamp(),
|
||||||
|
payload_or_attrs.parent_beacon_block_root().is_some(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ensure_well_formed_attributes(
|
||||||
|
&self,
|
||||||
|
version: EngineApiMessageVersion,
|
||||||
|
attributes: &OptimismPayloadAttributes,
|
||||||
|
) -> Result<(), EngineObjectValidationError> {
|
||||||
|
validate_version_specific_fields(&self.chain_spec, version, attributes.into())?;
|
||||||
|
|
||||||
|
if attributes.gas_limit.is_none() {
|
||||||
|
return Err(EngineObjectValidationError::InvalidParams(
|
||||||
|
"MissingGasLimitInPayloadAttributes".to_string().into(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -7,11 +7,11 @@ use reth_chainspec::ChainSpec;
|
|||||||
use reth_evm::ConfigureEvm;
|
use reth_evm::ConfigureEvm;
|
||||||
use reth_evm_optimism::{OpExecutorProvider, OptimismEvmConfig};
|
use reth_evm_optimism::{OpExecutorProvider, OptimismEvmConfig};
|
||||||
use reth_network::{NetworkHandle, NetworkManager};
|
use reth_network::{NetworkHandle, NetworkManager};
|
||||||
use reth_node_api::{FullNodeComponents, NodeAddOns};
|
use reth_node_api::{EngineValidator, FullNodeComponents, NodeAddOns};
|
||||||
use reth_node_builder::{
|
use reth_node_builder::{
|
||||||
components::{
|
components::{
|
||||||
ComponentsBuilder, ConsensusBuilder, ExecutorBuilder, NetworkBuilder,
|
ComponentsBuilder, ConsensusBuilder, EngineValidatorBuilder, ExecutorBuilder,
|
||||||
PayloadServiceBuilder, PoolBuilder,
|
NetworkBuilder, PayloadServiceBuilder, PoolBuilder,
|
||||||
},
|
},
|
||||||
node::{FullNodeTypes, NodeTypes, NodeTypesWithEngine},
|
node::{FullNodeTypes, NodeTypes, NodeTypesWithEngine},
|
||||||
BuilderContext, Node, PayloadBuilderConfig,
|
BuilderContext, Node, PayloadBuilderConfig,
|
||||||
@ -30,6 +30,7 @@ use reth_transaction_pool::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
args::RollupArgs,
|
args::RollupArgs,
|
||||||
|
engine::OptimismEngineValidator,
|
||||||
txpool::{OpTransactionPool, OpTransactionValidator},
|
txpool::{OpTransactionPool, OpTransactionValidator},
|
||||||
OptimismEngineTypes,
|
OptimismEngineTypes,
|
||||||
};
|
};
|
||||||
@ -58,6 +59,7 @@ impl OptimismNode {
|
|||||||
OptimismNetworkBuilder,
|
OptimismNetworkBuilder,
|
||||||
OptimismExecutorBuilder,
|
OptimismExecutorBuilder,
|
||||||
OptimismConsensusBuilder,
|
OptimismConsensusBuilder,
|
||||||
|
OptimismEngineValidatorBuilder,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
Node: FullNodeTypes<
|
Node: FullNodeTypes<
|
||||||
@ -75,6 +77,7 @@ impl OptimismNode {
|
|||||||
})
|
})
|
||||||
.executor(OptimismExecutorBuilder::default())
|
.executor(OptimismExecutorBuilder::default())
|
||||||
.consensus(OptimismConsensusBuilder::default())
|
.consensus(OptimismConsensusBuilder::default())
|
||||||
|
.engine_validator(OptimismEngineValidatorBuilder::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +94,7 @@ where
|
|||||||
OptimismNetworkBuilder,
|
OptimismNetworkBuilder,
|
||||||
OptimismExecutorBuilder,
|
OptimismExecutorBuilder,
|
||||||
OptimismConsensusBuilder,
|
OptimismConsensusBuilder,
|
||||||
|
OptimismEngineValidatorBuilder,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type AddOns = OptimismAddOns;
|
type AddOns = OptimismAddOns;
|
||||||
@ -386,3 +390,21 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Builder for [`OptimismEngineValidator`].
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct OptimismEngineValidatorBuilder;
|
||||||
|
|
||||||
|
impl<Node, Types> EngineValidatorBuilder<Node> for OptimismEngineValidatorBuilder
|
||||||
|
where
|
||||||
|
Types: NodeTypesWithEngine<ChainSpec = ChainSpec>,
|
||||||
|
Node: FullNodeTypes<Types = Types>,
|
||||||
|
OptimismEngineValidator: EngineValidator<Types::Engine>,
|
||||||
|
{
|
||||||
|
type Validator = OptimismEngineValidator;
|
||||||
|
|
||||||
|
async fn build_validator(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Validator> {
|
||||||
|
Ok(OptimismEngineValidator::new(ctx.chain_spec()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
use crate::{
|
use crate::{PayloadBuilderError, PayloadEvents, PayloadTypes};
|
||||||
validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
|
|
||||||
PayloadBuilderError, PayloadEvents, PayloadTypes,
|
|
||||||
};
|
|
||||||
use alloy_primitives::{Address, B256, U256};
|
use alloy_primitives::{Address, B256, U256};
|
||||||
use alloy_rpc_types::{
|
use alloy_rpc_types::{
|
||||||
engine::{PayloadAttributes as EthPayloadAttributes, PayloadId},
|
engine::{PayloadAttributes as EthPayloadAttributes, PayloadId},
|
||||||
@ -9,7 +6,6 @@ use alloy_rpc_types::{
|
|||||||
};
|
};
|
||||||
use op_alloy_rpc_types_engine::OptimismPayloadAttributes;
|
use op_alloy_rpc_types_engine::OptimismPayloadAttributes;
|
||||||
use reth_chain_state::ExecutedBlock;
|
use reth_chain_state::ExecutedBlock;
|
||||||
use reth_chainspec::ChainSpec;
|
|
||||||
use reth_primitives::{SealedBlock, Withdrawals};
|
use reth_primitives::{SealedBlock, Withdrawals};
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
@ -133,14 +129,6 @@ pub trait PayloadAttributes:
|
|||||||
|
|
||||||
/// Return the parent beacon block root for the payload attributes.
|
/// Return the parent beacon block root for the payload attributes.
|
||||||
fn parent_beacon_block_root(&self) -> Option<B256>;
|
fn parent_beacon_block_root(&self) -> Option<B256>;
|
||||||
|
|
||||||
/// Ensures that the payload attributes are valid for the given [`ChainSpec`] and
|
|
||||||
/// [`EngineApiMessageVersion`].
|
|
||||||
fn ensure_well_formed_attributes(
|
|
||||||
&self,
|
|
||||||
chain_spec: &ChainSpec,
|
|
||||||
version: EngineApiMessageVersion,
|
|
||||||
) -> Result<(), EngineObjectValidationError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PayloadAttributes for EthPayloadAttributes {
|
impl PayloadAttributes for EthPayloadAttributes {
|
||||||
@ -155,14 +143,6 @@ impl PayloadAttributes for EthPayloadAttributes {
|
|||||||
fn parent_beacon_block_root(&self) -> Option<B256> {
|
fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||||
self.parent_beacon_block_root
|
self.parent_beacon_block_root
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_well_formed_attributes(
|
|
||||||
&self,
|
|
||||||
chain_spec: &ChainSpec,
|
|
||||||
version: EngineApiMessageVersion,
|
|
||||||
) -> Result<(), EngineObjectValidationError> {
|
|
||||||
validate_version_specific_fields(chain_spec, version, self.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PayloadAttributes for OptimismPayloadAttributes {
|
impl PayloadAttributes for OptimismPayloadAttributes {
|
||||||
@ -177,22 +157,6 @@ impl PayloadAttributes for OptimismPayloadAttributes {
|
|||||||
fn parent_beacon_block_root(&self) -> Option<B256> {
|
fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||||
self.payload_attributes.parent_beacon_block_root
|
self.payload_attributes.parent_beacon_block_root
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_well_formed_attributes(
|
|
||||||
&self,
|
|
||||||
chain_spec: &ChainSpec,
|
|
||||||
version: EngineApiMessageVersion,
|
|
||||||
) -> Result<(), EngineObjectValidationError> {
|
|
||||||
validate_version_specific_fields(chain_spec, version, self.into())?;
|
|
||||||
|
|
||||||
if self.gas_limit.is_none() {
|
|
||||||
return Err(EngineObjectValidationError::InvalidParams(
|
|
||||||
"MissingGasLimitInPayloadAttributes".to_string().into(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A builder that can return the current payload attribute.
|
/// A builder that can return the current payload attribute.
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
|||||||
|
|
||||||
use reth_beacon_consensus::BeaconConsensusEngineHandle;
|
use reth_beacon_consensus::BeaconConsensusEngineHandle;
|
||||||
use reth_chainspec::MAINNET;
|
use reth_chainspec::MAINNET;
|
||||||
use reth_ethereum_engine_primitives::EthEngineTypes;
|
use reth_ethereum_engine_primitives::{EthEngineTypes, EthereumEngineValidator};
|
||||||
use reth_evm_ethereum::EthEvmConfig;
|
use reth_evm_ethereum::EthEvmConfig;
|
||||||
use reth_network_api::noop::NoopNetwork;
|
use reth_network_api::noop::NoopNetwork;
|
||||||
use reth_payload_builder::test_utils::spawn_test_payload_service;
|
use reth_payload_builder::test_utils::spawn_test_payload_service;
|
||||||
@ -50,6 +50,7 @@ pub async fn launch_auth(secret: JwtSecret) -> AuthServerHandle {
|
|||||||
Box::<TokioTaskExecutor>::default(),
|
Box::<TokioTaskExecutor>::default(),
|
||||||
client,
|
client,
|
||||||
EngineCapabilities::default(),
|
EngineCapabilities::default(),
|
||||||
|
EthereumEngineValidator::new(MAINNET.clone()),
|
||||||
);
|
);
|
||||||
let module = AuthRpcModule::new(engine_api);
|
let module = AuthRpcModule::new(engine_api);
|
||||||
module.start_server(config).await.unwrap()
|
module.start_server(config).await.unwrap()
|
||||||
|
|||||||
@ -7,12 +7,12 @@ use async_trait::async_trait;
|
|||||||
use jsonrpsee_core::RpcResult;
|
use jsonrpsee_core::RpcResult;
|
||||||
use reth_beacon_consensus::BeaconConsensusEngineHandle;
|
use reth_beacon_consensus::BeaconConsensusEngineHandle;
|
||||||
use reth_chainspec::ChainSpec;
|
use reth_chainspec::ChainSpec;
|
||||||
use reth_engine_primitives::EngineTypes;
|
use reth_engine_primitives::{EngineTypes, EngineValidator};
|
||||||
use reth_evm::provider::EvmEnvProvider;
|
use reth_evm::provider::EvmEnvProvider;
|
||||||
use reth_payload_builder::PayloadStore;
|
use reth_payload_builder::PayloadStore;
|
||||||
use reth_payload_primitives::{
|
use reth_payload_primitives::{
|
||||||
validate_payload_timestamp, EngineApiMessageVersion, PayloadAttributes,
|
validate_payload_timestamp, EngineApiMessageVersion, PayloadBuilderAttributes,
|
||||||
PayloadBuilderAttributes, PayloadOrAttributes,
|
PayloadOrAttributes,
|
||||||
};
|
};
|
||||||
use reth_primitives::{Block, BlockHashOrNumber, EthereumHardfork};
|
use reth_primitives::{Block, BlockHashOrNumber, EthereumHardfork};
|
||||||
use reth_rpc_api::EngineApiServer;
|
use reth_rpc_api::EngineApiServer;
|
||||||
@ -43,11 +43,11 @@ const MAX_BLOB_LIMIT: usize = 128;
|
|||||||
|
|
||||||
/// The Engine API implementation that grants the Consensus layer access to data and
|
/// The Engine API implementation that grants the Consensus layer access to data and
|
||||||
/// functions in the Execution layer that are crucial for the consensus process.
|
/// functions in the Execution layer that are crucial for the consensus process.
|
||||||
pub struct EngineApi<Provider, EngineT: EngineTypes, Pool> {
|
pub struct EngineApi<Provider, EngineT: EngineTypes, Pool, Validator> {
|
||||||
inner: Arc<EngineApiInner<Provider, EngineT, Pool>>,
|
inner: Arc<EngineApiInner<Provider, EngineT, Pool, Validator>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EngineApiInner<Provider, EngineT: EngineTypes, Pool> {
|
struct EngineApiInner<Provider, EngineT: EngineTypes, Pool, Validator> {
|
||||||
/// The provider to interact with the chain.
|
/// The provider to interact with the chain.
|
||||||
provider: Provider,
|
provider: Provider,
|
||||||
/// Consensus configuration
|
/// Consensus configuration
|
||||||
@ -66,13 +66,16 @@ struct EngineApiInner<Provider, EngineT: EngineTypes, Pool> {
|
|||||||
capabilities: EngineCapabilities,
|
capabilities: EngineCapabilities,
|
||||||
/// Transaction pool.
|
/// Transaction pool.
|
||||||
tx_pool: Pool,
|
tx_pool: Pool,
|
||||||
|
/// Engine validator.
|
||||||
|
validator: Validator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Provider, EngineT, Pool> EngineApi<Provider, EngineT, Pool>
|
impl<Provider, EngineT, Pool, Validator> EngineApi<Provider, EngineT, Pool, Validator>
|
||||||
where
|
where
|
||||||
Provider: HeaderProvider + BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
|
Provider: HeaderProvider + BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
|
||||||
EngineT: EngineTypes<ChainSpec = ChainSpec>,
|
EngineT: EngineTypes,
|
||||||
Pool: TransactionPool + 'static,
|
Pool: TransactionPool + 'static,
|
||||||
|
Validator: EngineValidator<EngineT>,
|
||||||
{
|
{
|
||||||
/// Create new instance of [`EngineApi`].
|
/// Create new instance of [`EngineApi`].
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@ -85,6 +88,7 @@ where
|
|||||||
task_spawner: Box<dyn TaskSpawner>,
|
task_spawner: Box<dyn TaskSpawner>,
|
||||||
client: ClientVersionV1,
|
client: ClientVersionV1,
|
||||||
capabilities: EngineCapabilities,
|
capabilities: EngineCapabilities,
|
||||||
|
validator: Validator,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let inner = Arc::new(EngineApiInner {
|
let inner = Arc::new(EngineApiInner {
|
||||||
provider,
|
provider,
|
||||||
@ -96,6 +100,7 @@ where
|
|||||||
client,
|
client,
|
||||||
capabilities,
|
capabilities,
|
||||||
tx_pool,
|
tx_pool,
|
||||||
|
validator,
|
||||||
});
|
});
|
||||||
Self { inner }
|
Self { inner }
|
||||||
}
|
}
|
||||||
@ -131,11 +136,9 @@ where
|
|||||||
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
||||||
&payload, None,
|
&payload, None,
|
||||||
);
|
);
|
||||||
EngineT::validate_version_specific_fields(
|
self.inner
|
||||||
&self.inner.chain_spec,
|
.validator
|
||||||
EngineApiMessageVersion::V1,
|
.validate_version_specific_fields(EngineApiMessageVersion::V1, payload_or_attrs)?;
|
||||||
payload_or_attrs,
|
|
||||||
)?;
|
|
||||||
Ok(self.inner.beacon_consensus.new_payload(payload, None).await?)
|
Ok(self.inner.beacon_consensus.new_payload(payload, None).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,11 +152,9 @@ where
|
|||||||
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
||||||
&payload, None,
|
&payload, None,
|
||||||
);
|
);
|
||||||
EngineT::validate_version_specific_fields(
|
self.inner
|
||||||
&self.inner.chain_spec,
|
.validator
|
||||||
EngineApiMessageVersion::V2,
|
.validate_version_specific_fields(EngineApiMessageVersion::V2, payload_or_attrs)?;
|
||||||
payload_or_attrs,
|
|
||||||
)?;
|
|
||||||
Ok(self.inner.beacon_consensus.new_payload(payload, None).await?)
|
Ok(self.inner.beacon_consensus.new_payload(payload, None).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,11 +171,9 @@ where
|
|||||||
&payload,
|
&payload,
|
||||||
Some(parent_beacon_block_root),
|
Some(parent_beacon_block_root),
|
||||||
);
|
);
|
||||||
EngineT::validate_version_specific_fields(
|
self.inner
|
||||||
&self.inner.chain_spec,
|
.validator
|
||||||
EngineApiMessageVersion::V3,
|
.validate_version_specific_fields(EngineApiMessageVersion::V3, payload_or_attrs)?;
|
||||||
payload_or_attrs,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let cancun_fields = CancunPayloadFields { versioned_hashes, parent_beacon_block_root };
|
let cancun_fields = CancunPayloadFields { versioned_hashes, parent_beacon_block_root };
|
||||||
|
|
||||||
@ -194,11 +193,9 @@ where
|
|||||||
&payload,
|
&payload,
|
||||||
Some(parent_beacon_block_root),
|
Some(parent_beacon_block_root),
|
||||||
);
|
);
|
||||||
EngineT::validate_version_specific_fields(
|
self.inner
|
||||||
&self.inner.chain_spec,
|
.validator
|
||||||
EngineApiMessageVersion::V4,
|
.validate_version_specific_fields(EngineApiMessageVersion::V4, payload_or_attrs)?;
|
||||||
payload_or_attrs,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let cancun_fields = CancunPayloadFields { versioned_hashes, parent_beacon_block_root };
|
let cancun_fields = CancunPayloadFields { versioned_hashes, parent_beacon_block_root };
|
||||||
|
|
||||||
@ -588,7 +585,7 @@ where
|
|||||||
) -> EngineApiResult<ForkchoiceUpdated> {
|
) -> EngineApiResult<ForkchoiceUpdated> {
|
||||||
if let Some(ref attrs) = payload_attrs {
|
if let Some(ref attrs) = payload_attrs {
|
||||||
let attr_validation_res =
|
let attr_validation_res =
|
||||||
attrs.ensure_well_formed_attributes(&self.inner.chain_spec, version);
|
self.inner.validator.ensure_well_formed_attributes(version, attrs);
|
||||||
|
|
||||||
// From the engine API spec:
|
// From the engine API spec:
|
||||||
//
|
//
|
||||||
@ -619,11 +616,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<Provider, EngineT, Pool> EngineApiServer<EngineT> for EngineApi<Provider, EngineT, Pool>
|
impl<Provider, EngineT, Pool, Validator> EngineApiServer<EngineT>
|
||||||
|
for EngineApi<Provider, EngineT, Pool, Validator>
|
||||||
where
|
where
|
||||||
Provider: HeaderProvider + BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
|
Provider: HeaderProvider + BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
|
||||||
EngineT: EngineTypes<ChainSpec = ChainSpec>,
|
EngineT: EngineTypes,
|
||||||
Pool: TransactionPool + 'static,
|
Pool: TransactionPool + 'static,
|
||||||
|
Validator: EngineValidator<EngineT>,
|
||||||
{
|
{
|
||||||
/// Handler for `engine_newPayloadV1`
|
/// Handler for `engine_newPayloadV1`
|
||||||
/// See also <https://github.com/ethereum/execution-apis/blob/3d627c95a4d3510a8187dd02e0250ecb4331d27e/src/engine/paris.md#engine_newpayloadv1>
|
/// See also <https://github.com/ethereum/execution-apis/blob/3d627c95a4d3510a8187dd02e0250ecb4331d27e/src/engine/paris.md#engine_newpayloadv1>
|
||||||
@ -933,7 +932,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Provider, EngineT, Pool> std::fmt::Debug for EngineApi<Provider, EngineT, Pool>
|
impl<Provider, EngineT, Pool, Validator> std::fmt::Debug
|
||||||
|
for EngineApi<Provider, EngineT, Pool, Validator>
|
||||||
where
|
where
|
||||||
EngineT: EngineTypes,
|
EngineT: EngineTypes,
|
||||||
{
|
{
|
||||||
@ -948,7 +948,7 @@ mod tests {
|
|||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
use reth_beacon_consensus::{BeaconConsensusEngineEvent, BeaconEngineMessage};
|
use reth_beacon_consensus::{BeaconConsensusEngineEvent, BeaconEngineMessage};
|
||||||
use reth_chainspec::MAINNET;
|
use reth_chainspec::MAINNET;
|
||||||
use reth_ethereum_engine_primitives::EthEngineTypes;
|
use reth_ethereum_engine_primitives::{EthEngineTypes, EthereumEngineValidator};
|
||||||
use reth_payload_builder::test_utils::spawn_test_payload_service;
|
use reth_payload_builder::test_utils::spawn_test_payload_service;
|
||||||
use reth_primitives::SealedBlock;
|
use reth_primitives::SealedBlock;
|
||||||
use reth_provider::test_utils::MockEthProvider;
|
use reth_provider::test_utils::MockEthProvider;
|
||||||
@ -960,9 +960,15 @@ mod tests {
|
|||||||
use reth_transaction_pool::noop::NoopTransactionPool;
|
use reth_transaction_pool::noop::NoopTransactionPool;
|
||||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
||||||
|
|
||||||
fn setup_engine_api(
|
fn setup_engine_api() -> (
|
||||||
) -> (EngineApiTestHandle, EngineApi<Arc<MockEthProvider>, EthEngineTypes, NoopTransactionPool>)
|
EngineApiTestHandle,
|
||||||
{
|
EngineApi<
|
||||||
|
Arc<MockEthProvider>,
|
||||||
|
EthEngineTypes,
|
||||||
|
NoopTransactionPool,
|
||||||
|
EthereumEngineValidator,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
let client = ClientVersionV1 {
|
let client = ClientVersionV1 {
|
||||||
code: ClientCode::RH,
|
code: ClientCode::RH,
|
||||||
name: "Reth".to_string(),
|
name: "Reth".to_string(),
|
||||||
@ -985,6 +991,7 @@ mod tests {
|
|||||||
task_executor,
|
task_executor,
|
||||||
client,
|
client,
|
||||||
EngineCapabilities::default(),
|
EngineCapabilities::default(),
|
||||||
|
EthereumEngineValidator::new(chain_spec.clone()),
|
||||||
);
|
);
|
||||||
let handle = EngineApiTestHandle { chain_spec, provider, from_api: engine_rx };
|
let handle = EngineApiTestHandle { chain_spec, provider, from_api: engine_rx };
|
||||||
(handle, api)
|
(handle, api)
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||||
|
|
||||||
use std::convert::Infallible;
|
use std::{convert::Infallible, sync::Arc};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@ -33,7 +33,7 @@ use alloy_rpc_types::{
|
|||||||
use reth::{
|
use reth::{
|
||||||
api::PayloadTypes,
|
api::PayloadTypes,
|
||||||
builder::{
|
builder::{
|
||||||
components::{ComponentsBuilder, PayloadServiceBuilder},
|
components::{ComponentsBuilder, EngineValidatorBuilder, PayloadServiceBuilder},
|
||||||
node::{NodeTypes, NodeTypesWithEngine},
|
node::{NodeTypes, NodeTypesWithEngine},
|
||||||
BuilderContext, FullNodeTypes, Node, NodeBuilder, PayloadBuilderConfig,
|
BuilderContext, FullNodeTypes, Node, NodeBuilder, PayloadBuilderConfig,
|
||||||
},
|
},
|
||||||
@ -48,7 +48,8 @@ use reth_basic_payload_builder::{
|
|||||||
use reth_chainspec::{Chain, ChainSpec};
|
use reth_chainspec::{Chain, ChainSpec};
|
||||||
use reth_node_api::{
|
use reth_node_api::{
|
||||||
payload::{EngineApiMessageVersion, EngineObjectValidationError, PayloadOrAttributes},
|
payload::{EngineApiMessageVersion, EngineObjectValidationError, PayloadOrAttributes},
|
||||||
validate_version_specific_fields, EngineTypes, PayloadAttributes, PayloadBuilderAttributes,
|
validate_version_specific_fields, EngineTypes, EngineValidator, PayloadAttributes,
|
||||||
|
PayloadBuilderAttributes,
|
||||||
};
|
};
|
||||||
use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};
|
use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};
|
||||||
use reth_node_ethereum::{
|
use reth_node_ethereum::{
|
||||||
@ -94,23 +95,6 @@ impl PayloadAttributes for CustomPayloadAttributes {
|
|||||||
fn parent_beacon_block_root(&self) -> Option<B256> {
|
fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||||
self.inner.parent_beacon_block_root()
|
self.inner.parent_beacon_block_root()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_well_formed_attributes(
|
|
||||||
&self,
|
|
||||||
chain_spec: &ChainSpec,
|
|
||||||
version: EngineApiMessageVersion,
|
|
||||||
) -> Result<(), EngineObjectValidationError> {
|
|
||||||
validate_version_specific_fields(chain_spec, version, self.into())?;
|
|
||||||
|
|
||||||
// custom validation logic - ensure that the custom field is not zero
|
|
||||||
if self.custom == 0 {
|
|
||||||
return Err(EngineObjectValidationError::invalid_params(
|
|
||||||
CustomError::CustomFieldIsNotZero,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// New type around the payload builder attributes type
|
/// New type around the payload builder attributes type
|
||||||
@ -167,19 +151,61 @@ impl PayloadTypes for CustomEngineTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EngineTypes for CustomEngineTypes {
|
impl EngineTypes for CustomEngineTypes {
|
||||||
type ChainSpec = ChainSpec;
|
|
||||||
|
|
||||||
type ExecutionPayloadV1 = ExecutionPayloadV1;
|
type ExecutionPayloadV1 = ExecutionPayloadV1;
|
||||||
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
|
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
|
||||||
type ExecutionPayloadV3 = ExecutionPayloadEnvelopeV3;
|
type ExecutionPayloadV3 = ExecutionPayloadEnvelopeV3;
|
||||||
type ExecutionPayloadV4 = ExecutionPayloadEnvelopeV4;
|
type ExecutionPayloadV4 = ExecutionPayloadEnvelopeV4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Custom engine validator
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CustomEngineValidator {
|
||||||
|
chain_spec: Arc<ChainSpec>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> EngineValidator<T> for CustomEngineValidator
|
||||||
|
where
|
||||||
|
T: EngineTypes<PayloadAttributes = CustomPayloadAttributes>,
|
||||||
|
{
|
||||||
fn validate_version_specific_fields(
|
fn validate_version_specific_fields(
|
||||||
chain_spec: &ChainSpec,
|
&self,
|
||||||
version: EngineApiMessageVersion,
|
version: EngineApiMessageVersion,
|
||||||
payload_or_attrs: PayloadOrAttributes<'_, CustomPayloadAttributes>,
|
payload_or_attrs: PayloadOrAttributes<'_, T::PayloadAttributes>,
|
||||||
) -> Result<(), EngineObjectValidationError> {
|
) -> Result<(), EngineObjectValidationError> {
|
||||||
validate_version_specific_fields(chain_spec, version, payload_or_attrs)
|
validate_version_specific_fields(&self.chain_spec, version, payload_or_attrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ensure_well_formed_attributes(
|
||||||
|
&self,
|
||||||
|
version: EngineApiMessageVersion,
|
||||||
|
attributes: &T::PayloadAttributes,
|
||||||
|
) -> Result<(), EngineObjectValidationError> {
|
||||||
|
validate_version_specific_fields(&self.chain_spec, version, attributes.into())?;
|
||||||
|
|
||||||
|
// custom validation logic - ensure that the custom field is not zero
|
||||||
|
if attributes.custom == 0 {
|
||||||
|
return Err(EngineObjectValidationError::invalid_params(
|
||||||
|
CustomError::CustomFieldIsNotZero,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Custom engine validator builder
|
||||||
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct CustomEngineValidatorBuilder;
|
||||||
|
|
||||||
|
impl<N> EngineValidatorBuilder<N> for CustomEngineValidatorBuilder
|
||||||
|
where
|
||||||
|
N: FullNodeTypes<Types: NodeTypesWithEngine<Engine = CustomEngineTypes, ChainSpec = ChainSpec>>,
|
||||||
|
{
|
||||||
|
type Validator = CustomEngineValidator;
|
||||||
|
|
||||||
|
async fn build_validator(self, ctx: &BuilderContext<N>) -> eyre::Result<Self::Validator> {
|
||||||
|
Ok(CustomEngineValidator { chain_spec: ctx.chain_spec() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,6 +238,7 @@ where
|
|||||||
EthereumNetworkBuilder,
|
EthereumNetworkBuilder,
|
||||||
EthereumExecutorBuilder,
|
EthereumExecutorBuilder,
|
||||||
EthereumConsensusBuilder,
|
EthereumConsensusBuilder,
|
||||||
|
CustomEngineValidatorBuilder,
|
||||||
>;
|
>;
|
||||||
type AddOns = EthereumAddOns;
|
type AddOns = EthereumAddOns;
|
||||||
|
|
||||||
@ -223,6 +250,7 @@ where
|
|||||||
.network(EthereumNetworkBuilder::default())
|
.network(EthereumNetworkBuilder::default())
|
||||||
.executor(EthereumExecutorBuilder::default())
|
.executor(EthereumExecutorBuilder::default())
|
||||||
.consensus(EthereumConsensusBuilder::default())
|
.consensus(EthereumConsensusBuilder::default())
|
||||||
|
.engine_validator(CustomEngineValidatorBuilder::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user