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-db",
|
||||
"reth-db-common",
|
||||
"reth-ethereum-engine-primitives",
|
||||
"reth-evm",
|
||||
"reth-execution-types",
|
||||
"reth-exex",
|
||||
|
||||
@ -31,9 +31,6 @@ pub trait EngineTypes:
|
||||
+ Serialize
|
||||
+ 'static
|
||||
{
|
||||
/// The chain specification of the node.
|
||||
type ChainSpec: Send + Sync;
|
||||
|
||||
/// Execution Payload V1 type.
|
||||
type ExecutionPayloadV1: DeserializeOwned + Serialize + Clone + Unpin + Send + Sync + 'static;
|
||||
/// Execution Payload V2 type.
|
||||
@ -42,12 +39,22 @@ pub trait EngineTypes:
|
||||
type ExecutionPayloadV3: DeserializeOwned + Serialize + Clone + Unpin + Send + Sync + 'static;
|
||||
/// Execution Payload V4 type.
|
||||
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
|
||||
/// and the message version.
|
||||
fn validate_version_specific_fields(
|
||||
chain_spec: &Self::ChainSpec,
|
||||
&self,
|
||||
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>;
|
||||
}
|
||||
|
||||
@ -9,9 +9,11 @@
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
|
||||
mod payload;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use payload::{EthBuiltPayload, EthPayloadBuilderAttributes};
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_engine_primitives::EngineTypes;
|
||||
use reth_engine_primitives::{EngineTypes, EngineValidator};
|
||||
use reth_payload_primitives::{
|
||||
validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
|
||||
PayloadOrAttributes, PayloadTypes,
|
||||
@ -36,18 +38,42 @@ impl PayloadTypes for EthEngineTypes {
|
||||
}
|
||||
|
||||
impl EngineTypes for EthEngineTypes {
|
||||
type ChainSpec = ChainSpec;
|
||||
|
||||
type ExecutionPayloadV1 = ExecutionPayloadV1;
|
||||
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
|
||||
type ExecutionPayloadV3 = ExecutionPayloadEnvelopeV3;
|
||||
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(
|
||||
chain_spec: &ChainSpec,
|
||||
&self,
|
||||
version: EngineApiMessageVersion,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, EthPayloadAttributes>,
|
||||
) -> 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_chainspec::ChainSpec;
|
||||
use reth_ethereum_engine_primitives::{
|
||||
EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes,
|
||||
EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes, EthereumEngineValidator,
|
||||
};
|
||||
use reth_evm_ethereum::execute::EthExecutorProvider;
|
||||
use reth_network::NetworkHandle;
|
||||
use reth_node_api::{ConfigureEvm, FullNodeComponents, NodeAddOns};
|
||||
use reth_node_api::{ConfigureEvm, EngineValidator, FullNodeComponents, NodeAddOns};
|
||||
use reth_node_builder::{
|
||||
components::{
|
||||
ComponentsBuilder, ConsensusBuilder, ExecutorBuilder, NetworkBuilder,
|
||||
PayloadServiceBuilder, PoolBuilder,
|
||||
ComponentsBuilder, ConsensusBuilder, EngineValidatorBuilder, ExecutorBuilder,
|
||||
NetworkBuilder, PayloadServiceBuilder, PoolBuilder,
|
||||
},
|
||||
node::{FullNodeTypes, NodeTypes, NodeTypesWithEngine},
|
||||
BuilderContext, Node, PayloadBuilderConfig, PayloadTypes,
|
||||
@ -46,6 +46,7 @@ impl EthereumNode {
|
||||
EthereumNetworkBuilder,
|
||||
EthereumExecutorBuilder,
|
||||
EthereumConsensusBuilder,
|
||||
EthereumEngineValidatorBuilder,
|
||||
>
|
||||
where
|
||||
Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec>>,
|
||||
@ -62,6 +63,7 @@ impl EthereumNode {
|
||||
.network(EthereumNetworkBuilder::default())
|
||||
.executor(EthereumExecutorBuilder::default())
|
||||
.consensus(EthereumConsensusBuilder::default())
|
||||
.engine_validator(EthereumEngineValidatorBuilder::default())
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +96,7 @@ where
|
||||
EthereumNetworkBuilder,
|
||||
EthereumExecutorBuilder,
|
||||
EthereumConsensusBuilder,
|
||||
EthereumEngineValidatorBuilder,
|
||||
>;
|
||||
|
||||
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-tasks.workspace = true
|
||||
reth-transaction-pool = { workspace = true, features = ["test-utils"] }
|
||||
reth-ethereum-engine-primitives.workspace = true
|
||||
|
||||
## async
|
||||
futures-util.workspace = true
|
||||
|
||||
@ -17,6 +17,7 @@ use reth_db::{
|
||||
DatabaseEnv,
|
||||
};
|
||||
use reth_db_common::init::init_genesis;
|
||||
use reth_ethereum_engine_primitives::EthereumEngineValidator;
|
||||
use reth_evm::test_utils::MockExecutorProvider;
|
||||
use reth_execution_types::Chain;
|
||||
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_ethereum::{
|
||||
node::{EthereumAddOns, EthereumNetworkBuilder, EthereumPayloadBuilder},
|
||||
node::{
|
||||
EthereumAddOns, EthereumEngineValidatorBuilder, EthereumNetworkBuilder,
|
||||
EthereumPayloadBuilder,
|
||||
},
|
||||
EthEngineTypes, EthEvmConfig,
|
||||
};
|
||||
use reth_payload_builder::noop::NoopPayloadBuilderService;
|
||||
@ -133,6 +137,7 @@ where
|
||||
EthereumNetworkBuilder,
|
||||
TestExecutorBuilder,
|
||||
TestConsensusBuilder,
|
||||
EthereumEngineValidatorBuilder,
|
||||
>;
|
||||
type AddOns = EthereumAddOns;
|
||||
|
||||
@ -144,6 +149,7 @@ where
|
||||
.network(EthereumNetworkBuilder::default())
|
||||
.executor(TestExecutorBuilder::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 provider_factory = ProviderFactory::new(
|
||||
db,
|
||||
chain_spec,
|
||||
chain_spec.clone(),
|
||||
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 task_executor = tasks.executor();
|
||||
|
||||
let engine_validator = EthereumEngineValidator::new(chain_spec.clone());
|
||||
|
||||
let components = NodeAdapter::<FullNodeTypesAdapter<NodeTypesWithDBAdapter<TestNode, _>, _>, _> {
|
||||
components: Components {
|
||||
transaction_pool,
|
||||
@ -274,6 +282,7 @@ pub async fn test_exex_context_with_chain_spec(
|
||||
consensus,
|
||||
network,
|
||||
payload_builder,
|
||||
engine_validator,
|
||||
},
|
||||
task_executor,
|
||||
provider,
|
||||
|
||||
@ -4,6 +4,7 @@ use std::{future::Future, marker::PhantomData};
|
||||
|
||||
use reth_consensus::Consensus;
|
||||
use reth_evm::execute::BlockExecutorProvider;
|
||||
use reth_node_api::{EngineValidator, NodeTypesWithEngine};
|
||||
use reth_primitives::Header;
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
|
||||
@ -15,6 +16,8 @@ use crate::{
|
||||
BuilderContext, ConfigureEvm, FullNodeTypes,
|
||||
};
|
||||
|
||||
use super::EngineValidatorBuilder;
|
||||
|
||||
/// A generic, general purpose and customizable [`NodeComponentsBuilder`] implementation.
|
||||
///
|
||||
/// 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
|
||||
/// launched.
|
||||
#[derive(Debug)]
|
||||
pub struct ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB> {
|
||||
pub struct ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB> {
|
||||
pool_builder: PoolB,
|
||||
payload_builder: PayloadB,
|
||||
network_builder: NetworkB,
|
||||
executor_builder: ExecB,
|
||||
consensus_builder: ConsB,
|
||||
engine_validator_builder: EVB,
|
||||
_marker: PhantomData<Node>,
|
||||
}
|
||||
|
||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||
{
|
||||
/// Configures the node types.
|
||||
pub fn node_types<Types>(
|
||||
self,
|
||||
) -> ComponentsBuilder<Types, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
) -> ComponentsBuilder<Types, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||
where
|
||||
Types: FullNodeTypes,
|
||||
{
|
||||
@ -60,6 +64,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
network_builder,
|
||||
executor_builder: evm_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
} = self;
|
||||
ComponentsBuilder {
|
||||
@ -68,6 +73,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
payload_builder,
|
||||
network_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
@ -80,6 +86,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
network_builder: self.network_builder,
|
||||
executor_builder: self.executor_builder,
|
||||
consensus_builder: self.consensus_builder,
|
||||
engine_validator_builder: self.engine_validator_builder,
|
||||
_marker: self._marker,
|
||||
}
|
||||
}
|
||||
@ -92,6 +99,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
network_builder: self.network_builder,
|
||||
executor_builder: self.executor_builder,
|
||||
consensus_builder: self.consensus_builder,
|
||||
engine_validator_builder: self.engine_validator_builder,
|
||||
_marker: self._marker,
|
||||
}
|
||||
}
|
||||
@ -104,6 +112,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
network_builder: f(self.network_builder),
|
||||
executor_builder: self.executor_builder,
|
||||
consensus_builder: self.consensus_builder,
|
||||
engine_validator_builder: self.engine_validator_builder,
|
||||
_marker: self._marker,
|
||||
}
|
||||
}
|
||||
@ -116,6 +125,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
network_builder: self.network_builder,
|
||||
executor_builder: f(self.executor_builder),
|
||||
consensus_builder: self.consensus_builder,
|
||||
engine_validator_builder: self.engine_validator_builder,
|
||||
_marker: self._marker,
|
||||
}
|
||||
}
|
||||
@ -128,13 +138,14 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
network_builder: self.network_builder,
|
||||
executor_builder: self.executor_builder,
|
||||
consensus_builder: f(self.consensus_builder),
|
||||
engine_validator_builder: self.engine_validator_builder,
|
||||
_marker: self._marker,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||
where
|
||||
Node: FullNodeTypes,
|
||||
{
|
||||
@ -145,7 +156,7 @@ where
|
||||
pub fn pool<PB>(
|
||||
self,
|
||||
pool_builder: PB,
|
||||
) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||
where
|
||||
PB: PoolBuilder<Node>,
|
||||
{
|
||||
@ -155,6 +166,7 @@ where
|
||||
network_builder,
|
||||
executor_builder: evm_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
} = self;
|
||||
ComponentsBuilder {
|
||||
@ -163,13 +175,14 @@ where
|
||||
network_builder,
|
||||
executor_builder: evm_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||
where
|
||||
Node: FullNodeTypes,
|
||||
PoolB: PoolBuilder<Node>,
|
||||
@ -181,7 +194,7 @@ where
|
||||
pub fn network<NB>(
|
||||
self,
|
||||
network_builder: NB,
|
||||
) -> ComponentsBuilder<Node, PoolB, PayloadB, NB, ExecB, ConsB>
|
||||
) -> ComponentsBuilder<Node, PoolB, PayloadB, NB, ExecB, ConsB, EVB>
|
||||
where
|
||||
NB: NetworkBuilder<Node, PoolB::Pool>,
|
||||
{
|
||||
@ -191,6 +204,7 @@ where
|
||||
network_builder: _,
|
||||
executor_builder: evm_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
} = self;
|
||||
ComponentsBuilder {
|
||||
@ -199,6 +213,7 @@ where
|
||||
network_builder,
|
||||
executor_builder: evm_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
}
|
||||
}
|
||||
@ -210,7 +225,7 @@ where
|
||||
pub fn payload<PB>(
|
||||
self,
|
||||
payload_builder: PB,
|
||||
) -> ComponentsBuilder<Node, PoolB, PB, NetworkB, ExecB, ConsB>
|
||||
) -> ComponentsBuilder<Node, PoolB, PB, NetworkB, ExecB, ConsB, EVB>
|
||||
where
|
||||
PB: PayloadServiceBuilder<Node, PoolB::Pool>,
|
||||
{
|
||||
@ -220,6 +235,7 @@ where
|
||||
network_builder,
|
||||
executor_builder: evm_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
} = self;
|
||||
ComponentsBuilder {
|
||||
@ -228,6 +244,7 @@ where
|
||||
network_builder,
|
||||
executor_builder: evm_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
}
|
||||
}
|
||||
@ -239,7 +256,7 @@ where
|
||||
pub fn executor<EB>(
|
||||
self,
|
||||
executor_builder: EB,
|
||||
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, EB, ConsB>
|
||||
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, EB, ConsB, EVB>
|
||||
where
|
||||
EB: ExecutorBuilder<Node>,
|
||||
{
|
||||
@ -249,6 +266,7 @@ where
|
||||
network_builder,
|
||||
executor_builder: _,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
} = self;
|
||||
ComponentsBuilder {
|
||||
@ -257,6 +275,7 @@ where
|
||||
network_builder,
|
||||
executor_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
}
|
||||
}
|
||||
@ -268,7 +287,7 @@ where
|
||||
pub fn consensus<CB>(
|
||||
self,
|
||||
consensus_builder: CB,
|
||||
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, CB>
|
||||
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, CB, EVB>
|
||||
where
|
||||
CB: ConsensusBuilder<Node>,
|
||||
{
|
||||
@ -278,6 +297,7 @@ where
|
||||
network_builder,
|
||||
executor_builder,
|
||||
consensus_builder: _,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
} = self;
|
||||
ComponentsBuilder {
|
||||
@ -286,13 +306,45 @@ where
|
||||
network_builder,
|
||||
executor_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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB> NodeComponentsBuilder<Node>
|
||||
for ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
|
||||
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB> NodeComponentsBuilder<Node>
|
||||
for ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB, EVB>
|
||||
where
|
||||
Node: FullNodeTypes,
|
||||
PoolB: PoolBuilder<Node>,
|
||||
@ -300,8 +352,16 @@ where
|
||||
PayloadB: PayloadServiceBuilder<Node, PoolB::Pool>,
|
||||
ExecB: ExecutorBuilder<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(
|
||||
self,
|
||||
@ -313,6 +373,7 @@ where
|
||||
network_builder,
|
||||
executor_builder: evm_builder,
|
||||
consensus_builder,
|
||||
engine_validator_builder,
|
||||
_marker,
|
||||
} = self;
|
||||
|
||||
@ -321,6 +382,7 @@ where
|
||||
let network = network_builder.build_network(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 engine_validator = engine_validator_builder.build_validator(context).await?;
|
||||
|
||||
Ok(Components {
|
||||
transaction_pool: pool,
|
||||
@ -329,11 +391,12 @@ where
|
||||
payload_builder,
|
||||
executor,
|
||||
consensus,
|
||||
engine_validator,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ComponentsBuilder<(), (), (), (), (), ()> {
|
||||
impl Default for ComponentsBuilder<(), (), (), (), (), (), ()> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
pool_builder: (),
|
||||
@ -341,6 +404,7 @@ impl Default for ComponentsBuilder<(), (), (), (), (), ()> {
|
||||
network_builder: (),
|
||||
executor_builder: (),
|
||||
consensus_builder: (),
|
||||
engine_validator_builder: (),
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
@ -366,17 +430,18 @@ pub trait NodeComponentsBuilder<Node: FullNodeTypes>: 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
|
||||
Node: FullNodeTypes,
|
||||
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,
|
||||
EVM: ConfigureEvm<Header = Header>,
|
||||
Executor: BlockExecutorProvider,
|
||||
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(
|
||||
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 consensus;
|
||||
mod engine;
|
||||
mod execute;
|
||||
mod network;
|
||||
mod payload;
|
||||
@ -16,6 +17,7 @@ mod pool;
|
||||
|
||||
pub use builder::*;
|
||||
pub use consensus::*;
|
||||
pub use engine::*;
|
||||
pub use execute::*;
|
||||
pub use network::*;
|
||||
pub use payload::*;
|
||||
@ -25,7 +27,7 @@ use reth_consensus::Consensus;
|
||||
use reth_evm::execute::BlockExecutorProvider;
|
||||
use reth_network::NetworkHandle;
|
||||
use reth_network_api::FullNetwork;
|
||||
use reth_node_api::NodeTypesWithEngine;
|
||||
use reth_node_api::{EngineValidator, NodeTypesWithEngine};
|
||||
use reth_payload_builder::PayloadBuilderHandle;
|
||||
use reth_primitives::Header;
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
@ -53,6 +55,9 @@ pub trait NodeComponents<T: FullNodeTypes>: Clone + Unpin + Send + Sync + 'stati
|
||||
/// Network API.
|
||||
type Network: FullNetwork;
|
||||
|
||||
/// Validator for the engine API.
|
||||
type EngineValidator: EngineValidator<<T::Types as NodeTypesWithEngine>::Engine>;
|
||||
|
||||
/// Returns the transaction pool of the node.
|
||||
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.
|
||||
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.
|
||||
///
|
||||
/// This provides access to all the components of the node.
|
||||
#[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.
|
||||
pub transaction_pool: Pool,
|
||||
/// 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,
|
||||
/// The handle to the payload builder service.
|
||||
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>
|
||||
for Components<Node, Pool, EVM, Executor, Cons>
|
||||
impl<Node, Pool, EVM, Executor, Cons, Val> NodeComponents<Node>
|
||||
for Components<Node, Pool, EVM, Executor, Cons, Val>
|
||||
where
|
||||
Node: FullNodeTypes,
|
||||
Pool: TransactionPool + Unpin + 'static,
|
||||
EVM: ConfigureEvm<Header = Header>,
|
||||
Executor: BlockExecutorProvider,
|
||||
Cons: Consensus + Clone + Unpin + 'static,
|
||||
Val: EngineValidator<<Node::Types as NodeTypesWithEngine>::Engine> + Clone + Unpin + 'static,
|
||||
{
|
||||
type Pool = Pool;
|
||||
type Evm = EVM;
|
||||
type Executor = Executor;
|
||||
type Consensus = Cons;
|
||||
type Network = NetworkHandle;
|
||||
type EngineValidator = Val;
|
||||
|
||||
fn pool(&self) -> &Self::Pool {
|
||||
&self.transaction_pool
|
||||
@ -131,15 +143,21 @@ where
|
||||
) -> &PayloadBuilderHandle<<Node::Types as NodeTypesWithEngine>::Engine> {
|
||||
&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
|
||||
Node: FullNodeTypes,
|
||||
Pool: TransactionPool,
|
||||
EVM: ConfigureEvm<Header = Header>,
|
||||
Executor: BlockExecutorProvider,
|
||||
Cons: Consensus + Clone,
|
||||
Val: EngineValidator<<Node::Types as NodeTypesWithEngine>::Engine>,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
@ -149,6 +167,7 @@ where
|
||||
consensus: self.consensus.clone(),
|
||||
network: self.network.clone(),
|
||||
payload_builder: self.payload_builder.clone(),
|
||||
engine_validator: self.engine_validator.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,6 +275,7 @@ where
|
||||
Box::new(ctx.task_executor().clone()),
|
||||
client,
|
||||
EngineCapabilities::default(),
|
||||
ctx.components().engine_validator().clone(),
|
||||
);
|
||||
info!(target: "reth::cli", "Engine API handler initialized");
|
||||
|
||||
|
||||
@ -351,6 +351,7 @@ where
|
||||
Box::new(ctx.task_executor().clone()),
|
||||
client,
|
||||
EngineCapabilities::default(),
|
||||
ctx.components().engine_validator().clone(),
|
||||
);
|
||||
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.
|
||||
pub trait NodeTypesWithEngine: NodeTypes {
|
||||
/// 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
|
||||
@ -166,7 +166,7 @@ where
|
||||
impl<P, E, C> NodeTypesWithEngine for AnyNodeTypesWithEngine<P, E, C>
|
||||
where
|
||||
P: NodePrimitives + Send + Sync + Unpin + 'static,
|
||||
E: EngineTypes<ChainSpec = C> + Send + Sync + Unpin,
|
||||
E: EngineTypes + Send + Sync + Unpin,
|
||||
C: EthChainSpec,
|
||||
{
|
||||
type Engine = E;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use op_alloy_rpc_types_engine::{
|
||||
OptimismExecutionPayloadEnvelopeV3, OptimismExecutionPayloadEnvelopeV4,
|
||||
OptimismPayloadAttributes,
|
||||
@ -9,7 +11,7 @@ use reth_node_api::{
|
||||
EngineObjectValidationError, MessageValidationKind, PayloadOrAttributes, PayloadTypes,
|
||||
VersionSpecificValidationError,
|
||||
},
|
||||
EngineTypes,
|
||||
validate_version_specific_fields, EngineTypes, EngineValidator,
|
||||
};
|
||||
use reth_optimism_forks::OptimismHardfork;
|
||||
use reth_optimism_payload_builder::{OptimismBuiltPayload, OptimismPayloadBuilderAttributes};
|
||||
@ -20,6 +22,19 @@ use reth_rpc_types::{engine::ExecutionPayloadEnvelopeV2, ExecutionPayloadV1};
|
||||
#[non_exhaustive]
|
||||
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 {
|
||||
type BuiltPayload = OptimismBuiltPayload;
|
||||
type PayloadAttributes = OptimismPayloadAttributes;
|
||||
@ -27,33 +42,10 @@ impl PayloadTypes for OptimismEngineTypes {
|
||||
}
|
||||
|
||||
impl EngineTypes for OptimismEngineTypes {
|
||||
type ChainSpec = ChainSpec;
|
||||
|
||||
type ExecutionPayloadV1 = ExecutionPayloadV1;
|
||||
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
|
||||
type ExecutionPayloadV3 = OptimismExecutionPayloadEnvelopeV3;
|
||||
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.
|
||||
@ -97,3 +89,45 @@ pub fn validate_withdrawals_presence(
|
||||
|
||||
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_optimism::{OpExecutorProvider, OptimismEvmConfig};
|
||||
use reth_network::{NetworkHandle, NetworkManager};
|
||||
use reth_node_api::{FullNodeComponents, NodeAddOns};
|
||||
use reth_node_api::{EngineValidator, FullNodeComponents, NodeAddOns};
|
||||
use reth_node_builder::{
|
||||
components::{
|
||||
ComponentsBuilder, ConsensusBuilder, ExecutorBuilder, NetworkBuilder,
|
||||
PayloadServiceBuilder, PoolBuilder,
|
||||
ComponentsBuilder, ConsensusBuilder, EngineValidatorBuilder, ExecutorBuilder,
|
||||
NetworkBuilder, PayloadServiceBuilder, PoolBuilder,
|
||||
},
|
||||
node::{FullNodeTypes, NodeTypes, NodeTypesWithEngine},
|
||||
BuilderContext, Node, PayloadBuilderConfig,
|
||||
@ -30,6 +30,7 @@ use reth_transaction_pool::{
|
||||
|
||||
use crate::{
|
||||
args::RollupArgs,
|
||||
engine::OptimismEngineValidator,
|
||||
txpool::{OpTransactionPool, OpTransactionValidator},
|
||||
OptimismEngineTypes,
|
||||
};
|
||||
@ -58,6 +59,7 @@ impl OptimismNode {
|
||||
OptimismNetworkBuilder,
|
||||
OptimismExecutorBuilder,
|
||||
OptimismConsensusBuilder,
|
||||
OptimismEngineValidatorBuilder,
|
||||
>
|
||||
where
|
||||
Node: FullNodeTypes<
|
||||
@ -75,6 +77,7 @@ impl OptimismNode {
|
||||
})
|
||||
.executor(OptimismExecutorBuilder::default())
|
||||
.consensus(OptimismConsensusBuilder::default())
|
||||
.engine_validator(OptimismEngineValidatorBuilder::default())
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,6 +94,7 @@ where
|
||||
OptimismNetworkBuilder,
|
||||
OptimismExecutorBuilder,
|
||||
OptimismConsensusBuilder,
|
||||
OptimismEngineValidatorBuilder,
|
||||
>;
|
||||
|
||||
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::{
|
||||
validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
|
||||
PayloadBuilderError, PayloadEvents, PayloadTypes,
|
||||
};
|
||||
use crate::{PayloadBuilderError, PayloadEvents, PayloadTypes};
|
||||
use alloy_primitives::{Address, B256, U256};
|
||||
use alloy_rpc_types::{
|
||||
engine::{PayloadAttributes as EthPayloadAttributes, PayloadId},
|
||||
@ -9,7 +6,6 @@ use alloy_rpc_types::{
|
||||
};
|
||||
use op_alloy_rpc_types_engine::OptimismPayloadAttributes;
|
||||
use reth_chain_state::ExecutedBlock;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_primitives::{SealedBlock, Withdrawals};
|
||||
use std::{future::Future, pin::Pin};
|
||||
use tokio::sync::oneshot;
|
||||
@ -133,14 +129,6 @@ pub trait PayloadAttributes:
|
||||
|
||||
/// Return the parent beacon block root for the payload attributes.
|
||||
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 {
|
||||
@ -155,14 +143,6 @@ impl PayloadAttributes for EthPayloadAttributes {
|
||||
fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||
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 {
|
||||
@ -177,22 +157,6 @@ impl PayloadAttributes for OptimismPayloadAttributes {
|
||||
fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||
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.
|
||||
|
||||
@ -2,7 +2,7 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||
|
||||
use reth_beacon_consensus::BeaconConsensusEngineHandle;
|
||||
use reth_chainspec::MAINNET;
|
||||
use reth_ethereum_engine_primitives::EthEngineTypes;
|
||||
use reth_ethereum_engine_primitives::{EthEngineTypes, EthereumEngineValidator};
|
||||
use reth_evm_ethereum::EthEvmConfig;
|
||||
use reth_network_api::noop::NoopNetwork;
|
||||
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(),
|
||||
client,
|
||||
EngineCapabilities::default(),
|
||||
EthereumEngineValidator::new(MAINNET.clone()),
|
||||
);
|
||||
let module = AuthRpcModule::new(engine_api);
|
||||
module.start_server(config).await.unwrap()
|
||||
|
||||
@ -7,12 +7,12 @@ use async_trait::async_trait;
|
||||
use jsonrpsee_core::RpcResult;
|
||||
use reth_beacon_consensus::BeaconConsensusEngineHandle;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_engine_primitives::EngineTypes;
|
||||
use reth_engine_primitives::{EngineTypes, EngineValidator};
|
||||
use reth_evm::provider::EvmEnvProvider;
|
||||
use reth_payload_builder::PayloadStore;
|
||||
use reth_payload_primitives::{
|
||||
validate_payload_timestamp, EngineApiMessageVersion, PayloadAttributes,
|
||||
PayloadBuilderAttributes, PayloadOrAttributes,
|
||||
validate_payload_timestamp, EngineApiMessageVersion, PayloadBuilderAttributes,
|
||||
PayloadOrAttributes,
|
||||
};
|
||||
use reth_primitives::{Block, BlockHashOrNumber, EthereumHardfork};
|
||||
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
|
||||
/// functions in the Execution layer that are crucial for the consensus process.
|
||||
pub struct EngineApi<Provider, EngineT: EngineTypes, Pool> {
|
||||
inner: Arc<EngineApiInner<Provider, EngineT, Pool>>,
|
||||
pub struct EngineApi<Provider, EngineT: EngineTypes, Pool, Validator> {
|
||||
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.
|
||||
provider: Provider,
|
||||
/// Consensus configuration
|
||||
@ -66,13 +66,16 @@ struct EngineApiInner<Provider, EngineT: EngineTypes, Pool> {
|
||||
capabilities: EngineCapabilities,
|
||||
/// Transaction 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
|
||||
Provider: HeaderProvider + BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
|
||||
EngineT: EngineTypes<ChainSpec = ChainSpec>,
|
||||
EngineT: EngineTypes,
|
||||
Pool: TransactionPool + 'static,
|
||||
Validator: EngineValidator<EngineT>,
|
||||
{
|
||||
/// Create new instance of [`EngineApi`].
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@ -85,6 +88,7 @@ where
|
||||
task_spawner: Box<dyn TaskSpawner>,
|
||||
client: ClientVersionV1,
|
||||
capabilities: EngineCapabilities,
|
||||
validator: Validator,
|
||||
) -> Self {
|
||||
let inner = Arc::new(EngineApiInner {
|
||||
provider,
|
||||
@ -96,6 +100,7 @@ where
|
||||
client,
|
||||
capabilities,
|
||||
tx_pool,
|
||||
validator,
|
||||
});
|
||||
Self { inner }
|
||||
}
|
||||
@ -131,11 +136,9 @@ where
|
||||
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
||||
&payload, None,
|
||||
);
|
||||
EngineT::validate_version_specific_fields(
|
||||
&self.inner.chain_spec,
|
||||
EngineApiMessageVersion::V1,
|
||||
payload_or_attrs,
|
||||
)?;
|
||||
self.inner
|
||||
.validator
|
||||
.validate_version_specific_fields(EngineApiMessageVersion::V1, payload_or_attrs)?;
|
||||
Ok(self.inner.beacon_consensus.new_payload(payload, None).await?)
|
||||
}
|
||||
|
||||
@ -149,11 +152,9 @@ where
|
||||
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
||||
&payload, None,
|
||||
);
|
||||
EngineT::validate_version_specific_fields(
|
||||
&self.inner.chain_spec,
|
||||
EngineApiMessageVersion::V2,
|
||||
payload_or_attrs,
|
||||
)?;
|
||||
self.inner
|
||||
.validator
|
||||
.validate_version_specific_fields(EngineApiMessageVersion::V2, payload_or_attrs)?;
|
||||
Ok(self.inner.beacon_consensus.new_payload(payload, None).await?)
|
||||
}
|
||||
|
||||
@ -170,11 +171,9 @@ where
|
||||
&payload,
|
||||
Some(parent_beacon_block_root),
|
||||
);
|
||||
EngineT::validate_version_specific_fields(
|
||||
&self.inner.chain_spec,
|
||||
EngineApiMessageVersion::V3,
|
||||
payload_or_attrs,
|
||||
)?;
|
||||
self.inner
|
||||
.validator
|
||||
.validate_version_specific_fields(EngineApiMessageVersion::V3, payload_or_attrs)?;
|
||||
|
||||
let cancun_fields = CancunPayloadFields { versioned_hashes, parent_beacon_block_root };
|
||||
|
||||
@ -194,11 +193,9 @@ where
|
||||
&payload,
|
||||
Some(parent_beacon_block_root),
|
||||
);
|
||||
EngineT::validate_version_specific_fields(
|
||||
&self.inner.chain_spec,
|
||||
EngineApiMessageVersion::V4,
|
||||
payload_or_attrs,
|
||||
)?;
|
||||
self.inner
|
||||
.validator
|
||||
.validate_version_specific_fields(EngineApiMessageVersion::V4, payload_or_attrs)?;
|
||||
|
||||
let cancun_fields = CancunPayloadFields { versioned_hashes, parent_beacon_block_root };
|
||||
|
||||
@ -588,7 +585,7 @@ where
|
||||
) -> EngineApiResult<ForkchoiceUpdated> {
|
||||
if let Some(ref attrs) = payload_attrs {
|
||||
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:
|
||||
//
|
||||
@ -619,11 +616,13 @@ where
|
||||
}
|
||||
|
||||
#[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
|
||||
Provider: HeaderProvider + BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
|
||||
EngineT: EngineTypes<ChainSpec = ChainSpec>,
|
||||
EngineT: EngineTypes,
|
||||
Pool: TransactionPool + 'static,
|
||||
Validator: EngineValidator<EngineT>,
|
||||
{
|
||||
/// Handler for `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
|
||||
EngineT: EngineTypes,
|
||||
{
|
||||
@ -948,7 +948,7 @@ mod tests {
|
||||
use assert_matches::assert_matches;
|
||||
use reth_beacon_consensus::{BeaconConsensusEngineEvent, BeaconEngineMessage};
|
||||
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_primitives::SealedBlock;
|
||||
use reth_provider::test_utils::MockEthProvider;
|
||||
@ -960,9 +960,15 @@ mod tests {
|
||||
use reth_transaction_pool::noop::NoopTransactionPool;
|
||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
||||
|
||||
fn setup_engine_api(
|
||||
) -> (EngineApiTestHandle, EngineApi<Arc<MockEthProvider>, EthEngineTypes, NoopTransactionPool>)
|
||||
{
|
||||
fn setup_engine_api() -> (
|
||||
EngineApiTestHandle,
|
||||
EngineApi<
|
||||
Arc<MockEthProvider>,
|
||||
EthEngineTypes,
|
||||
NoopTransactionPool,
|
||||
EthereumEngineValidator,
|
||||
>,
|
||||
) {
|
||||
let client = ClientVersionV1 {
|
||||
code: ClientCode::RH,
|
||||
name: "Reth".to_string(),
|
||||
@ -985,6 +991,7 @@ mod tests {
|
||||
task_executor,
|
||||
client,
|
||||
EngineCapabilities::default(),
|
||||
EthereumEngineValidator::new(chain_spec.clone()),
|
||||
);
|
||||
let handle = EngineApiTestHandle { chain_spec, provider, from_api: engine_rx };
|
||||
(handle, api)
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
|
||||
use std::convert::Infallible;
|
||||
use std::{convert::Infallible, sync::Arc};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
@ -33,7 +33,7 @@ use alloy_rpc_types::{
|
||||
use reth::{
|
||||
api::PayloadTypes,
|
||||
builder::{
|
||||
components::{ComponentsBuilder, PayloadServiceBuilder},
|
||||
components::{ComponentsBuilder, EngineValidatorBuilder, PayloadServiceBuilder},
|
||||
node::{NodeTypes, NodeTypesWithEngine},
|
||||
BuilderContext, FullNodeTypes, Node, NodeBuilder, PayloadBuilderConfig,
|
||||
},
|
||||
@ -48,7 +48,8 @@ use reth_basic_payload_builder::{
|
||||
use reth_chainspec::{Chain, ChainSpec};
|
||||
use reth_node_api::{
|
||||
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_ethereum::{
|
||||
@ -94,23 +95,6 @@ impl PayloadAttributes for CustomPayloadAttributes {
|
||||
fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||
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
|
||||
@ -167,19 +151,61 @@ impl PayloadTypes for CustomEngineTypes {
|
||||
}
|
||||
|
||||
impl EngineTypes for CustomEngineTypes {
|
||||
type ChainSpec = ChainSpec;
|
||||
|
||||
type ExecutionPayloadV1 = ExecutionPayloadV1;
|
||||
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
|
||||
type ExecutionPayloadV3 = ExecutionPayloadEnvelopeV3;
|
||||
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(
|
||||
chain_spec: &ChainSpec,
|
||||
&self,
|
||||
version: EngineApiMessageVersion,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, CustomPayloadAttributes>,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, T::PayloadAttributes>,
|
||||
) -> 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,
|
||||
EthereumExecutorBuilder,
|
||||
EthereumConsensusBuilder,
|
||||
CustomEngineValidatorBuilder,
|
||||
>;
|
||||
type AddOns = EthereumAddOns;
|
||||
|
||||
@ -223,6 +250,7 @@ where
|
||||
.network(EthereumNetworkBuilder::default())
|
||||
.executor(EthereumExecutorBuilder::default())
|
||||
.consensus(EthereumConsensusBuilder::default())
|
||||
.engine_validator(CustomEngineValidatorBuilder::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user