use crate::{HlBlock, HlBlockBody, HlPrimitives, hardforks::HlHardforks, node::HlNode}; use alloy_consensus::Header; use reth::{ api::{FullNodeTypes, NodeTypes}, beacon_consensus::EthBeaconConsensus, builder::{BuilderContext, components::ConsensusBuilder}, consensus::{Consensus, ConsensusError, FullConsensus, HeaderValidator}, consensus_common::validation::{ validate_against_parent_4844, validate_against_parent_hash_number, }, }; use reth_chainspec::EthChainSpec; use reth_primitives::{Receipt, RecoveredBlock, SealedBlock, SealedHeader}; use reth_primitives_traits::BlockHeader; use reth_provider::BlockExecutionResult; use std::sync::Arc; /// A basic Hl consensus builder. #[derive(Debug, Default, Clone, Copy)] #[non_exhaustive] pub struct HlConsensusBuilder; impl ConsensusBuilder for HlConsensusBuilder where Node: FullNodeTypes, { type Consensus = Arc::ChainSpec>>; async fn build_consensus(self, ctx: &BuilderContext) -> eyre::Result { Ok(Arc::new(HlConsensus::new(ctx.chain_spec()))) } } /// HL consensus implementation. /// /// Provides basic checks as outlined in the execution specs. #[derive(Debug, Clone)] pub struct HlConsensus { inner: EthBeaconConsensus, chain_spec: Arc, } impl HlConsensus where ChainSpec: EthChainSpec + HlHardforks, { /// Create a new instance of [`HlConsensus`] pub fn new(chain_spec: Arc) -> Self { Self { inner: EthBeaconConsensus::new(chain_spec.clone()), chain_spec } } } /// Validates the timestamp against the parent to make sure it is in the past. #[inline] pub fn validate_against_parent_timestamp( header: &H, parent: &H, ) -> Result<(), ConsensusError> { // NOTE: HyperEVM allows the timestamp to be the same as the parent (big and small blocks) if header.timestamp() < parent.timestamp() { return Err(ConsensusError::TimestampIsInPast { parent_timestamp: parent.timestamp(), timestamp: header.timestamp(), }); } Ok(()) } impl HeaderValidator for HlConsensus where H: BlockHeader, ChainSpec: EthChainSpec
+ HlHardforks, { fn validate_header(&self, header: &SealedHeader) -> Result<(), ConsensusError> { self.inner.validate_header(header) } fn validate_header_against_parent( &self, header: &SealedHeader, parent: &SealedHeader, ) -> Result<(), ConsensusError> { validate_against_parent_hash_number(header.header(), parent)?; validate_against_parent_timestamp(header.header(), parent.header())?; // validate_against_parent_eip1559_base_fee( // header.header(), // parent.header(), // &self.chain_spec, // )?; // ensure that the blob gas fields for this block if let Some(blob_params) = self.chain_spec.blob_params_at_timestamp(header.timestamp()) { validate_against_parent_4844(header.header(), parent.header(), blob_params)?; } Ok(()) } } impl Consensus for HlConsensus where ChainSpec: EthChainSpec
+ HlHardforks, { type Error = ConsensusError; fn validate_body_against_header( &self, body: &HlBlockBody, header: &SealedHeader, ) -> Result<(), ConsensusError> { Consensus::::validate_body_against_header(&self.inner, body, header) } fn validate_block_pre_execution( &self, _block: &SealedBlock, ) -> Result<(), ConsensusError> { // Check ommers hash // let ommers_hash = block.body().calculate_ommers_root(); // if Some(block.ommers_hash()) != ommers_hash { // return Err(ConsensusError::BodyOmmersHashDiff( // GotExpected { // got: ommers_hash.unwrap_or(EMPTY_OMMER_ROOT_HASH), // expected: block.ommers_hash(), // } // .into(), // )) // } // // Check transaction root // if let Err(error) = block.ensure_transaction_root_valid() { // return Err(ConsensusError::BodyTransactionRootDiff(error.into())) // } // if self.chain_spec.is_cancun_active_at_timestamp(block.timestamp()) { // validate_cancun_gas(block)?; // } else { // return Ok(()) // } Ok(()) } } mod reth_copy; impl FullConsensus for HlConsensus where ChainSpec: EthChainSpec
+ HlHardforks, { fn validate_block_post_execution( &self, block: &RecoveredBlock, result: &BlockExecutionResult, ) -> Result<(), ConsensusError> { reth_copy::validate_block_post_execution( block, &self.chain_spec, &result.receipts, &result.requests, ) } }