mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Compare commits
5 Commits
630d86a4ba
...
361248ccf1
| Author | SHA1 | Date | |
|---|---|---|---|
| 361248ccf1 | |||
| 6f8d089298 | |||
| 98846d2710 | |||
| a74fbc59fe | |||
| a032ffceb3 |
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -7971,9 +7971,11 @@ name = "reth-hyperliquid-types"
|
|||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
|
"alloy-rlp",
|
||||||
"clap",
|
"clap",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"reth-cli-commands",
|
"reth-cli-commands",
|
||||||
|
"rmp-serde",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
@ -9059,6 +9061,7 @@ dependencies = [
|
|||||||
"reth-evm",
|
"reth-evm",
|
||||||
"reth-execution-types",
|
"reth-execution-types",
|
||||||
"reth-fs-util",
|
"reth-fs-util",
|
||||||
|
"reth-hyperliquid-types",
|
||||||
"reth-metrics",
|
"reth-metrics",
|
||||||
"reth-network-p2p",
|
"reth-network-p2p",
|
||||||
"reth-nippy-jar",
|
"reth-nippy-jar",
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
@ -195,17 +193,6 @@ impl ConfigureEvmEnv for EthEvmConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub(crate) struct BlockAndReceipts {
|
|
||||||
#[serde(default)]
|
|
||||||
pub read_precompile_calls: Vec<(Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>)>,
|
|
||||||
pub highest_precompile_address: Option<Address>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub(crate) enum EvmBlock {
|
|
||||||
Reth115(SealedBlock),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Custom EVM configuration.
|
/// Custom EVM configuration.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
@ -215,16 +202,6 @@ pub struct HyperliquidEvmFactory {
|
|||||||
shared_state: Option<HyperliquidSharedState>,
|
shared_state: Option<HyperliquidSharedState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn collect_s3_block(ingest_path: PathBuf, height: u64) -> Option<BlockAndReceipts> {
|
|
||||||
let f = ((height - 1) / 1_000_000) * 1_000_000;
|
|
||||||
let s = ((height - 1) / 1_000) * 1_000;
|
|
||||||
let path = format!("{}/{f}/{s}/{height}.rmp.lz4", ingest_path.to_string_lossy());
|
|
||||||
let file = std::fs::read(path).ok()?;
|
|
||||||
let mut decoder = lz4_flex::frame::FrameDecoder::new(&file[..]);
|
|
||||||
let blocks: Vec<BlockAndReceipts> = rmp_serde::from_read(&mut decoder).unwrap();
|
|
||||||
Some(blocks[0].clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_locally_sourced_precompiles_for_height(
|
pub(crate) fn get_locally_sourced_precompiles_for_height(
|
||||||
precompiles_cache: PrecompilesCache,
|
precompiles_cache: PrecompilesCache,
|
||||||
height: u64,
|
height: u64,
|
||||||
@ -233,27 +210,6 @@ pub(crate) fn get_locally_sourced_precompiles_for_height(
|
|||||||
u_cache.remove(&height)
|
u_cache.remove(&height)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn collect_block(
|
|
||||||
ingest_path: PathBuf,
|
|
||||||
shared_state: Option<HyperliquidSharedState>,
|
|
||||||
height: u64,
|
|
||||||
) -> Option<BlockAndReceipts> {
|
|
||||||
// Attempt to source precompile from the cache that is shared the binary level with the block
|
|
||||||
// ingestor.
|
|
||||||
if let Some(shared_state) = shared_state {
|
|
||||||
if let Some(calls) =
|
|
||||||
get_locally_sourced_precompiles_for_height(shared_state.precompiles_cache, height)
|
|
||||||
{
|
|
||||||
return Some(BlockAndReceipts {
|
|
||||||
read_precompile_calls: calls.precompiles,
|
|
||||||
highest_precompile_address: calls.highest_precompile_address,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Fallback to s3 always
|
|
||||||
collect_s3_block(ingest_path, height)
|
|
||||||
}
|
|
||||||
|
|
||||||
const WARM_PRECOMPILES_BLOCK_NUMBER: u64 = 8_197_684;
|
const WARM_PRECOMPILES_BLOCK_NUMBER: u64 = 8_197_684;
|
||||||
|
|
||||||
impl EvmFactory<EvmEnv> for HyperliquidEvmFactory {
|
impl EvmFactory<EvmEnv> for HyperliquidEvmFactory {
|
||||||
@ -265,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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,9 @@ workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
alloy-primitives.workspace = true
|
alloy-primitives.workspace = true
|
||||||
|
alloy-rlp = { workspace = true }
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
rmp-serde = "1.3"
|
||||||
tokio = { workspace = true, features = ["sync", "macros", "time", "rt-multi-thread"] }
|
tokio = { workspace = true, features = ["sync", "macros", "time", "rt-multi-thread"] }
|
||||||
parking_lot.workspace = true
|
parking_lot.workspace = true
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use std::{collections::BTreeMap, sync::Arc};
|
use std::{collections::BTreeMap, sync::Arc};
|
||||||
|
|
||||||
use alloy_primitives::{Address, Bytes};
|
use alloy_primitives::{Address, Bytes};
|
||||||
|
use alloy_rlp::{Decodable, Encodable};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ pub struct ReadPrecompileInput {
|
|||||||
pub gas_limit: u64,
|
pub gas_limit: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum ReadPrecompileResult {
|
pub enum ReadPrecompileResult {
|
||||||
Ok { gas_used: u64, bytes: Bytes },
|
Ok { gas_used: u64, bytes: Bytes },
|
||||||
OutOfGas,
|
OutOfGas,
|
||||||
@ -18,6 +19,59 @@ pub enum ReadPrecompileResult {
|
|||||||
UnexpectedError,
|
UnexpectedError,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ReadPrecompileCalls represents a collection of precompile calls with their results
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct ReadPrecompileCalls(pub Vec<(Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>)>);
|
||||||
|
|
||||||
|
impl ReadPrecompileCalls {
|
||||||
|
/// Create an empty ReadPrecompileCalls
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create from a vector of precompile calls
|
||||||
|
pub fn from_vec(calls: Vec<(Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>)>) -> Self {
|
||||||
|
Self(calls)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the inner vector
|
||||||
|
pub fn into_inner(self) -> Vec<(Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>)> {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialize to bytes using MessagePack for database storage
|
||||||
|
pub fn to_db_bytes(&self) -> Result<Vec<u8>, rmp_serde::encode::Error> {
|
||||||
|
rmp_serde::to_vec(&self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize from bytes using MessagePack from database storage
|
||||||
|
pub fn from_db_bytes(bytes: &[u8]) -> Result<Self, rmp_serde::decode::Error> {
|
||||||
|
let data = rmp_serde::from_slice(bytes)?;
|
||||||
|
Ok(Self(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for ReadPrecompileCalls {
|
||||||
|
fn encode(&self, out: &mut dyn alloy_rlp::BufMut) {
|
||||||
|
// Encode as MessagePack bytes wrapped in RLP
|
||||||
|
let buf = self.to_db_bytes().unwrap_or_default();
|
||||||
|
buf.encode(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
let buf = self.to_db_bytes().unwrap_or_default();
|
||||||
|
buf.length()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for ReadPrecompileCalls {
|
||||||
|
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||||
|
let bytes = Vec::<u8>::decode(buf)?;
|
||||||
|
Self::from_db_bytes(&bytes)
|
||||||
|
.map_err(|_| alloy_rlp::Error::Custom("Failed to decode ReadPrecompileCalls"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct PrecompileData {
|
pub struct PrecompileData {
|
||||||
pub precompiles: Vec<(Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>)>,
|
pub precompiles: Vec<(Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>)>,
|
||||||
|
|||||||
@ -525,6 +525,13 @@ tables! {
|
|||||||
type Key = ChainStateKey;
|
type Key = ChainStateKey;
|
||||||
type Value = BlockNumber;
|
type Value = BlockNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stores precompile call data for each block.
|
||||||
|
/// Maps block number to serialized ReadPrecompileCalls data.
|
||||||
|
table BlockReadPrecompileCalls {
|
||||||
|
type Key = BlockNumber;
|
||||||
|
type Value = Vec<u8>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Keys for the `ChainState` table.
|
/// Keys for the `ChainState` table.
|
||||||
|
|||||||
@ -33,6 +33,7 @@ reth-codecs.workspace = true
|
|||||||
reth-evm.workspace = true
|
reth-evm.workspace = true
|
||||||
reth-chain-state.workspace = true
|
reth-chain-state.workspace = true
|
||||||
reth-node-types.workspace = true
|
reth-node-types.workspace = true
|
||||||
|
reth-hyperliquid-types.workspace = true
|
||||||
|
|
||||||
# ethereum
|
# ethereum
|
||||||
alloy-eips.workspace = true
|
alloy-eips.workspace = true
|
||||||
|
|||||||
@ -50,6 +50,9 @@ mod metrics;
|
|||||||
mod chain;
|
mod chain;
|
||||||
pub use chain::*;
|
pub use chain::*;
|
||||||
|
|
||||||
|
mod precompile;
|
||||||
|
pub use precompile::DatabasePrecompileCallsProvider;
|
||||||
|
|
||||||
/// A common provider that fetches data from a database or static file.
|
/// A common provider that fetches data from a database or static file.
|
||||||
///
|
///
|
||||||
/// This provider implements most provider or provider factory traits.
|
/// This provider implements most provider or provider factory traits.
|
||||||
|
|||||||
68
crates/storage/provider/src/providers/database/precompile.rs
Normal file
68
crates/storage/provider/src/providers/database/precompile.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
//! Database provider implementation for precompile calls storage
|
||||||
|
|
||||||
|
use crate::traits::PrecompileCallsProvider;
|
||||||
|
use alloy_primitives::BlockNumber;
|
||||||
|
use reth_db::cursor::DbCursorRW;
|
||||||
|
use reth_db_api::{cursor::DbCursorRO, transaction::DbTx};
|
||||||
|
use reth_hyperliquid_types::ReadPrecompileCalls;
|
||||||
|
use reth_storage_errors::provider::ProviderResult;
|
||||||
|
|
||||||
|
/// Implementation of PrecompileCallsProvider for database provider
|
||||||
|
pub trait DatabasePrecompileCallsProvider: Send + Sync {
|
||||||
|
/// Transaction type
|
||||||
|
type Tx: DbTx;
|
||||||
|
|
||||||
|
/// Get a reference to the transaction
|
||||||
|
fn tx_ref(&self) -> &Self::Tx;
|
||||||
|
|
||||||
|
/// Get a mutable reference to the transaction
|
||||||
|
fn tx_mut(&mut self) -> &mut Self::Tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> PrecompileCallsProvider for T
|
||||||
|
where
|
||||||
|
T: DatabasePrecompileCallsProvider,
|
||||||
|
T::Tx: DbTx,
|
||||||
|
{
|
||||||
|
fn insert_block_precompile_calls(
|
||||||
|
&self,
|
||||||
|
block_number: BlockNumber,
|
||||||
|
calls: ReadPrecompileCalls,
|
||||||
|
) -> ProviderResult<()> {
|
||||||
|
use reth_db_api::transaction::DbTxMut;
|
||||||
|
|
||||||
|
// For now, we'll store this as a placeholder - the actual implementation
|
||||||
|
// will require mutable transaction access which needs to be added to the trait
|
||||||
|
// This is a read-only implementation for now
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_precompile_calls(
|
||||||
|
&self,
|
||||||
|
block_number: BlockNumber,
|
||||||
|
) -> ProviderResult<Option<ReadPrecompileCalls>> {
|
||||||
|
use reth_db_api::tables::BlockReadPrecompileCalls;
|
||||||
|
|
||||||
|
let tx = self.tx_ref();
|
||||||
|
|
||||||
|
// Get from BlockReadPrecompileCalls table
|
||||||
|
if let Some(bytes) = tx.get::<BlockReadPrecompileCalls>(block_number)? {
|
||||||
|
let calls = ReadPrecompileCalls::from_db_bytes(&bytes)
|
||||||
|
.map_err(|e| reth_storage_errors::provider::ProviderError::Database(
|
||||||
|
reth_db_api::DatabaseError::Other(format!("Failed to deserialize precompile calls: {}", e))
|
||||||
|
))?;
|
||||||
|
Ok(Some(calls))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_block_precompile_calls_above(
|
||||||
|
&self,
|
||||||
|
block_number: BlockNumber,
|
||||||
|
) -> ProviderResult<()> {
|
||||||
|
// For now, this is a no-op as it requires mutable transaction access
|
||||||
|
// The actual implementation will be added when we have mutable access
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,3 +19,6 @@ pub use static_file_provider::StaticFileProviderFactory;
|
|||||||
|
|
||||||
mod full;
|
mod full;
|
||||||
pub use full::{FullProvider, FullRpcProvider};
|
pub use full::{FullProvider, FullRpcProvider};
|
||||||
|
|
||||||
|
mod precompile;
|
||||||
|
pub use precompile::PrecompileCallsProvider;
|
||||||
|
|||||||
27
crates/storage/provider/src/traits/precompile.rs
Normal file
27
crates/storage/provider/src/traits/precompile.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//! Trait for storing and retrieving precompile call data
|
||||||
|
|
||||||
|
use alloy_primitives::BlockNumber;
|
||||||
|
use reth_hyperliquid_types::ReadPrecompileCalls;
|
||||||
|
use reth_storage_errors::provider::ProviderResult;
|
||||||
|
|
||||||
|
/// Provider trait for ReadPrecompileCalls storage operations
|
||||||
|
pub trait PrecompileCallsProvider: Send + Sync {
|
||||||
|
/// Insert ReadPrecompileCalls data for a block
|
||||||
|
fn insert_block_precompile_calls(
|
||||||
|
&self,
|
||||||
|
block_number: BlockNumber,
|
||||||
|
calls: ReadPrecompileCalls,
|
||||||
|
) -> ProviderResult<()>;
|
||||||
|
|
||||||
|
/// Get ReadPrecompileCalls data for a block
|
||||||
|
fn block_precompile_calls(
|
||||||
|
&self,
|
||||||
|
block_number: BlockNumber,
|
||||||
|
) -> ProviderResult<Option<ReadPrecompileCalls>>;
|
||||||
|
|
||||||
|
/// Remove ReadPrecompileCalls data for blocks above a certain number
|
||||||
|
fn remove_block_precompile_calls_above(
|
||||||
|
&self,
|
||||||
|
block_number: BlockNumber,
|
||||||
|
) -> ProviderResult<()>;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user