feat: Port ReadPrecompileCalls struct from node-builder to main

- Add ReadPrecompileCalls struct to hyperliquid-types with helper methods
- Update BlockAndReceipts to use the new struct type
- Remove duplicate collect_block and BlockAndReceipts from evm/lib.rs
- Refactor EVM factory to avoid collect_block overhead during EVM creation
- Clean up unused imports (SealedBlock, Serialize, Deserialize)

This fixes issue #24 by removing the duplicate collect_block that caused
overhead during transaction tracing. The EVM factory now only reads from
the precompiles cache instead of loading block data on every EVM creation.
This commit is contained in:
kamalbuilds
2025-08-24 23:28:25 +05:30
parent a032ffceb3
commit a74fbc59fe
3 changed files with 28 additions and 25 deletions

View File

@ -207,7 +207,7 @@ impl BlockIngest {
let mut u_pre_cache = precompiles_cache.lock(); let mut u_pre_cache = precompiles_cache.lock();
for blk in new_blocks { for blk in new_blocks {
let precompiles = PrecompileData { let precompiles = PrecompileData {
precompiles: blk.read_precompile_calls.clone(), precompiles: blk.read_precompile_calls.0.clone(),
highest_precompile_address: blk.highest_precompile_address, highest_precompile_address: blk.highest_precompile_address,
}; };
let h = match &blk.block { let h = match &blk.block {

View File

@ -1,5 +1,5 @@
use alloy_primitives::{Address, Log}; use alloy_primitives::{Address, Log};
use reth_hyperliquid_types::{ReadPrecompileInput, ReadPrecompileResult}; use reth_hyperliquid_types::{ReadPrecompileInput, ReadPrecompileResult, ReadPrecompileCalls};
use reth_primitives::{SealedBlock, Transaction}; use reth_primitives::{SealedBlock, Transaction};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -10,7 +10,7 @@ pub(crate) struct BlockAndReceipts {
#[serde(default)] #[serde(default)]
pub system_txs: Vec<SystemTx>, pub system_txs: Vec<SystemTx>,
#[serde(default)] #[serde(default)]
pub read_precompile_calls: Vec<(Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>)>, pub read_precompile_calls: ReadPrecompileCalls,
pub highest_precompile_address: Option<Address>, pub highest_precompile_address: Option<Address>,
} }

View File

@ -30,7 +30,6 @@ use reth_evm::{ConfigureEvm, ConfigureEvmEnv, EvmEnv, EvmFactory, NextBlockEnvAt
use reth_hyperliquid_types::PrecompileData; use reth_hyperliquid_types::PrecompileData;
use reth_hyperliquid_types::{PrecompilesCache, ReadPrecompileInput, ReadPrecompileResult}; use reth_hyperliquid_types::{PrecompilesCache, ReadPrecompileInput, ReadPrecompileResult};
use reth_node_builder::HyperliquidSharedState; use reth_node_builder::HyperliquidSharedState;
use reth_primitives::SealedBlock;
use reth_primitives::TransactionSigned; use reth_primitives::TransactionSigned;
use reth_revm::context::result::{EVMError, HaltReason}; use reth_revm::context::result::{EVMError, HaltReason};
use reth_revm::handler::EthPrecompiles; use reth_revm::handler::EthPrecompiles;
@ -43,7 +42,6 @@ use reth_revm::{
specification::hardfork::SpecId, specification::hardfork::SpecId,
}; };
use reth_revm::{Context, Inspector, MainContext}; use reth_revm::{Context, Inspector, MainContext};
use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
@ -223,28 +221,33 @@ impl EvmFactory<EvmEnv> for HyperliquidEvmFactory {
type Context<DB: Database> = EthEvmContext<DB>; type Context<DB: Database> = EthEvmContext<DB>;
fn create_evm<DB: Database>(&self, db: DB, input: EvmEnv) -> Self::Evm<DB, NoOpInspector> { fn create_evm<DB: Database>(&self, db: DB, input: EvmEnv) -> Self::Evm<DB, NoOpInspector> {
let block = collect_block( // Try to get precompile data from the shared state cache
self.ingest_dir.clone().unwrap(), // This avoids the overhead of loading block data on every EVM creation
self.shared_state.clone(), let mut cache: HashMap<_, _> = HashMap::new();
input.block_env.number,
) if let Some(ref shared_state) = self.shared_state {
.expect("Failed to collect a submitted block. If sourcing locally, make sure your local hl-node is producing blocks."); if let Some(precompile_data) = get_locally_sourced_precompiles_for_height(
let mut cache: HashMap<_, _> = block shared_state.precompiles_cache.clone(),
.read_precompile_calls input.block_env.number,
.into_iter() ) {
.map(|(address, calls)| (address, HashMap::from_iter(calls.into_iter()))) cache = precompile_data
.collect(); .precompiles
.into_iter()
.map(|(address, calls)| (address, HashMap::from_iter(calls.into_iter())))
.collect();
if input.block_env.number >= WARM_PRECOMPILES_BLOCK_NUMBER { if input.block_env.number >= WARM_PRECOMPILES_BLOCK_NUMBER {
let highest_precompile_address = block let highest_precompile_address = precompile_data
.highest_precompile_address .highest_precompile_address
.unwrap_or(address!("0x000000000000000000000000000000000000080d")); .unwrap_or(address!("0x000000000000000000000000000000000000080d"));
for i in 0x800.. { for i in 0x800.. {
let address = Address::from(U160::from(i)); let address = Address::from(U160::from(i));
if address > highest_precompile_address { if address > highest_precompile_address {
break; break;
}
cache.entry(address).or_insert(HashMap::new());
}
} }
cache.entry(address).or_insert(HashMap::new());
} }
} }