diff --git a/src/node/rpc/block.rs b/src/node/rpc/block.rs index 98495ce66..95b3bdd20 100644 --- a/src/node/rpc/block.rs +++ b/src/node/rpc/block.rs @@ -1,9 +1,12 @@ +use std::{future::Future, sync::Arc}; + use crate::{ chainspec::HlChainSpec, node::{ primitives::TransactionSigned, rpc::{HlEthApi, HlNodeCore}, }, + HlBlock, }; use alloy_consensus::{BlockHeader, ReceiptEnvelope, TxType}; use alloy_primitives::B256; @@ -23,11 +26,11 @@ use reth::{ }; use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_evm::{ConfigureEvm, NextBlockEnvAttributes}; -use reth_primitives::NodePrimitives; -use reth_primitives_traits::{BlockBody as _, SignedTransaction as _}; +use reth_primitives::{NodePrimitives, SealedBlock}; +use reth_primitives_traits::{BlockBody as _, RecoveredBlock, SignedTransaction as _}; use reth_provider::{ - BlockReader, ChainSpecProvider, HeaderProvider, ProviderBlock, ProviderReceipt, ProviderTx, - StateProviderFactory, + BlockIdReader, BlockReader, ChainSpecProvider, HeaderProvider, ProviderBlock, ProviderReceipt, + ProviderTx, StateProviderFactory, }; use reth_rpc_eth_api::{ helpers::{EthBlocks, LoadBlock, LoadPendingBlock, LoadReceipt, SpawnBlocking}, @@ -35,6 +38,10 @@ use reth_rpc_eth_api::{ FromEthApiError, RpcConvert, RpcNodeCore, RpcNodeCoreExt, RpcReceipt, }; +fn is_system_tx(tx: &TransactionSigned) -> bool { + tx.is_system_transaction() +} + impl EthBlocks for HlEthApi where Self: LoadBlock< @@ -64,6 +71,7 @@ where .transactions() .iter() .zip(receipts.iter()) + .filter(|(tx, _)| !is_system_tx(tx)) .enumerate() .map(|(idx, (tx, receipt))| { let meta = TransactionMeta { @@ -101,9 +109,70 @@ where Pool: TransactionPool< Transaction: PoolTransaction>, >, - >, + > + RpcNodeCore>, N: HlNodeCore, { + fn recovered_block( + &self, + block_id: BlockId, + ) -> impl Future< + Output = Result< + Option::Block>>>, + Self::Error, + >, + > + Send { + let hl_node_compliant = self.hl_node_compliant; + async move { + // Copy of LoadBlock::recovered_block, but with --hl-node-compliant support + if block_id.is_pending() { + return Ok(None); + } + + let block_hash = match self + .provider() + .block_hash_for_id(block_id) + .map_err(Self::Error::from_eth_err)? + { + Some(block_hash) => block_hash, + None => return Ok(None), + }; + + let recovered_block = self + .cache() + .get_recovered_block(block_hash) + .await + .map_err(Self::Error::from_eth_err)?; + + if let Some(recovered_block) = recovered_block { + let recovered_block = if hl_node_compliant { + filter_if_hl_node_compliant(&*recovered_block) + } else { + (*recovered_block).clone() + }; + return Ok(Some(std::sync::Arc::new(recovered_block))); + } + + Ok(None) + } + } +} + +fn filter_if_hl_node_compliant( + recovered_block: &RecoveredBlock, +) -> RecoveredBlock { + let sealed_block = recovered_block.sealed_block(); + let transactions = sealed_block.body().transactions(); + let to_skip = transactions + .iter() + .position(|tx| !tx.is_system_transaction()) + .unwrap_or(transactions.len()); + + let mut new_block: HlBlock = sealed_block.clone_block().into(); + new_block.body.transactions.drain(..to_skip); + let new_sealed_block = SealedBlock::new_unchecked(new_block, sealed_block.hash()); + let new_senders = recovered_block.senders()[to_skip..].to_vec(); + + RecoveredBlock::new_sealed(new_sealed_block, new_senders) } impl LoadPendingBlock for HlEthApi