use crate::job::EmptyBlockPayloadJob; use reth::{ providers::{BlockReaderIdExt, BlockSource, StateProviderFactory}, tasks::TaskSpawner, transaction_pool::TransactionPool, }; use reth_basic_payload_builder::{BasicPayloadJobGeneratorConfig, PayloadBuilder, PayloadConfig}; use reth_chainspec::ChainSpec; use reth_node_api::PayloadBuilderAttributes; use reth_payload_builder::{error::PayloadBuilderError, PayloadJobGenerator}; use reth_primitives::{BlockNumberOrTag, Bytes}; use std::sync::Arc; /// The generator type that creates new jobs that builds empty blocks. #[derive(Debug)] pub struct EmptyBlockPayloadJobGenerator { /// The client that can interact with the chain. client: Client, /// txpool pool: Pool, /// How to spawn building tasks executor: Tasks, /// The configuration for the job generator. _config: BasicPayloadJobGeneratorConfig, /// The chain spec. chain_spec: Arc, /// The type responsible for building payloads. /// /// See [PayloadBuilder] builder: Builder, } // === impl EmptyBlockPayloadJobGenerator === impl EmptyBlockPayloadJobGenerator { /// Creates a new [EmptyBlockPayloadJobGenerator] with the given config and custom /// [PayloadBuilder] pub fn with_builder( client: Client, pool: Pool, executor: Tasks, config: BasicPayloadJobGeneratorConfig, chain_spec: Arc, builder: Builder, ) -> Self { Self { client, pool, executor, _config: config, builder, chain_spec } } } impl PayloadJobGenerator for EmptyBlockPayloadJobGenerator where Client: StateProviderFactory + BlockReaderIdExt + Clone + Unpin + 'static, Pool: TransactionPool + Unpin + 'static, Tasks: TaskSpawner + Clone + Unpin + 'static, Builder: PayloadBuilder + Unpin + 'static, >::Attributes: Unpin + Clone, >::BuiltPayload: Unpin + Clone, { type Job = EmptyBlockPayloadJob; /// This is invoked when the node receives payload attributes from the beacon node via /// `engine_forkchoiceUpdatedV1` fn new_payload_job( &self, attributes: >::Attributes, ) -> Result { let parent_block = if attributes.parent().is_zero() { // use latest block if parent is zero: genesis block self.client .block_by_number_or_tag(BlockNumberOrTag::Latest)? .ok_or_else(|| PayloadBuilderError::MissingParentBlock(attributes.parent()))? .seal_slow() } else { let block = self .client .find_block_by_hash(attributes.parent(), BlockSource::Any)? .ok_or_else(|| PayloadBuilderError::MissingParentBlock(attributes.parent()))?; // we already know the hash, so we can seal it block.seal(attributes.parent()) }; let config = PayloadConfig::new( Arc::new(parent_block), Bytes::default(), attributes, Arc::clone(&self.chain_spec), ); Ok(EmptyBlockPayloadJob { client: self.client.clone(), _pool: self.pool.clone(), _executor: self.executor.clone(), builder: self.builder.clone(), config, }) } }