mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 19:09:54 +00:00
feat: add canonical_headers_range (#1795)
Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5109,7 +5109,6 @@ dependencies = [
|
||||
"auto_impl",
|
||||
"bytes",
|
||||
"criterion",
|
||||
"enr 0.8.0",
|
||||
"ethereum-types",
|
||||
"ethnum",
|
||||
"hex-literal",
|
||||
|
||||
@ -516,8 +516,8 @@ pub fn verify_receipt<'a>(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use reth_primitives::{
|
||||
hex_literal::hex, keccak256, Account, Address, Bytecode, Bytes, ChainSpecBuilder,
|
||||
ForkCondition, StorageKey, H256, MAINNET, U256,
|
||||
hex_literal::hex, keccak256, Account, Address, BlockNumber, Bytecode, Bytes,
|
||||
ChainSpecBuilder, ForkCondition, StorageKey, H256, MAINNET, U256,
|
||||
};
|
||||
use reth_provider::{
|
||||
post_state::{Change, Storage},
|
||||
@ -531,7 +531,7 @@ mod tests {
|
||||
struct StateProviderTest {
|
||||
accounts: HashMap<Address, (HashMap<StorageKey, U256>, Account)>,
|
||||
contracts: HashMap<H256, Bytecode>,
|
||||
block_hash: HashMap<U256, H256>,
|
||||
block_hash: HashMap<u64, H256>,
|
||||
}
|
||||
|
||||
impl StateProviderTest {
|
||||
@ -560,9 +560,22 @@ mod tests {
|
||||
}
|
||||
|
||||
impl BlockHashProvider for StateProviderTest {
|
||||
fn block_hash(&self, number: U256) -> reth_interfaces::Result<Option<H256>> {
|
||||
fn block_hash(&self, number: u64) -> reth_interfaces::Result<Option<H256>> {
|
||||
Ok(self.block_hash.get(&number).cloned())
|
||||
}
|
||||
|
||||
fn canonical_hashes_range(
|
||||
&self,
|
||||
start: BlockNumber,
|
||||
end: BlockNumber,
|
||||
) -> reth_interfaces::Result<Vec<H256>> {
|
||||
let range = start..end;
|
||||
Ok(self
|
||||
.block_hash
|
||||
.iter()
|
||||
.filter_map(|(block, hash)| if range.contains(block) { Some(*hash) } else { None })
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl StateProvider for StateProviderTest {
|
||||
|
||||
@ -30,10 +30,10 @@ impl<'a, SP: StateProvider> PostStateProvider<'a, SP> {
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement StateProvider traits */
|
||||
|
||||
impl<'a, SP: StateProvider> BlockHashProvider for PostStateProvider<'a, SP> {
|
||||
fn block_hash(&self, number: U256) -> Result<Option<H256>> {
|
||||
// All block numbers fit inside u64 and revm checks if it is last 256 block numbers.
|
||||
let block_number = number.as_limbs()[0];
|
||||
fn block_hash(&self, block_number: BlockNumber) -> Result<Option<H256>> {
|
||||
if let Some(sidechain_block_hash) = self.sidechain_block_hashes.get(&block_number).cloned()
|
||||
{
|
||||
return Ok(Some(sidechain_block_hash))
|
||||
@ -46,6 +46,10 @@ impl<'a, SP: StateProvider> BlockHashProvider for PostStateProvider<'a, SP> {
|
||||
.ok_or(ProviderError::BlockchainTreeBlockHash { block_number })?,
|
||||
))
|
||||
}
|
||||
|
||||
fn canonical_hashes_range(&self, _start: BlockNumber, _end: BlockNumber) -> Result<Vec<H256>> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, SP: StateProvider> AccountProvider for PostStateProvider<'a, SP> {
|
||||
|
||||
@ -7,7 +7,7 @@ use reth_eth_wire::{
|
||||
GetReceipts, NodeData, Receipts,
|
||||
};
|
||||
use reth_interfaces::p2p::error::RequestResult;
|
||||
use reth_primitives::{BlockHashOrNumber, Header, HeadersDirection, PeerId, U256};
|
||||
use reth_primitives::{BlockHashOrNumber, Header, HeadersDirection, PeerId};
|
||||
use reth_provider::{BlockProvider, HeaderProvider};
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
@ -82,7 +82,7 @@ where
|
||||
let mut block: BlockHashOrNumber = match start_block {
|
||||
BlockHashOrNumber::Hash(start) => start.into(),
|
||||
BlockHashOrNumber::Number(num) => {
|
||||
if let Some(hash) = self.client.block_hash(U256::from(num)).unwrap_or_default() {
|
||||
if let Some(hash) = self.client.block_hash(num).unwrap_or_default() {
|
||||
hash.into()
|
||||
} else {
|
||||
return headers
|
||||
|
||||
@ -63,6 +63,7 @@ impl<DB: StateProvider> DatabaseRef for State<DB> {
|
||||
}
|
||||
|
||||
fn block_hash(&self, number: U256) -> Result<H256, Self::Error> {
|
||||
Ok(self.0.block_hash(number)?.unwrap_or_default())
|
||||
// Note: this unwrap is potentially unsafe
|
||||
Ok(self.0.block_hash(number.try_into().unwrap())?.unwrap_or_default())
|
||||
}
|
||||
}
|
||||
|
||||
@ -462,7 +462,7 @@ impl<Client: HeaderProvider + BlockProvider + StateProviderFactory + EvmEnvProvi
|
||||
}
|
||||
|
||||
// Attempt to look up terminal block hash
|
||||
let local_hash = self.client.block_hash(U256::from(terminal_block_number.as_u64()))?;
|
||||
let local_hash = self.client.block_hash(terminal_block_number.as_u64())?;
|
||||
|
||||
// Transition configuration exchange is successful if block hashes match
|
||||
match local_hash {
|
||||
|
||||
@ -310,8 +310,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let oldest_block_hash =
|
||||
self.inner.client.block_hash(start_block.try_into().unwrap()).to_rpc_result()?.unwrap();
|
||||
let oldest_block_hash = self.inner.client.block_hash(start_block).to_rpc_result()?.unwrap();
|
||||
|
||||
fee_history_cache_items.get_mut(&start_block).unwrap().hash = Some(oldest_block_hash);
|
||||
fee_history_cache.get_mut(&start_block).unwrap().hash = Some(oldest_block_hash);
|
||||
|
||||
@ -5,10 +5,7 @@ use crate::{
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use jsonrpsee::{core::RpcResult, server::IdProvider};
|
||||
use reth_primitives::{
|
||||
filter::{Filter, FilterBlockOption, FilteredParams},
|
||||
U256,
|
||||
};
|
||||
use reth_primitives::filter::{Filter, FilterBlockOption, FilteredParams};
|
||||
use reth_provider::{BlockProvider, EvmEnvProvider};
|
||||
use reth_rpc_api::EthFilterApiServer;
|
||||
use reth_rpc_types::{FilterChanges, FilterId, Log};
|
||||
@ -96,7 +93,7 @@ where
|
||||
let block_hash = self
|
||||
.inner
|
||||
.client
|
||||
.block_hash(U256::from(block_num))
|
||||
.block_hash(block_num)
|
||||
.to_rpc_result()?
|
||||
.ok_or(EthApiError::UnknownBlockNumber)?;
|
||||
block_hashes.push(block_hash);
|
||||
|
||||
@ -94,10 +94,20 @@ impl<DB: Database> HeaderProvider for ShareableDatabase<DB> {
|
||||
}
|
||||
|
||||
impl<DB: Database> BlockHashProvider for ShareableDatabase<DB> {
|
||||
fn block_hash(&self, number: U256) -> Result<Option<H256>> {
|
||||
// TODO: This unwrap is potentially unsafe
|
||||
fn block_hash(&self, number: u64) -> Result<Option<H256>> {
|
||||
self.db.view(|tx| tx.get::<tables::CanonicalHeaders>(number))?.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn canonical_hashes_range(&self, start: BlockNumber, end: BlockNumber) -> Result<Vec<H256>> {
|
||||
let range = start..end;
|
||||
self.db
|
||||
.view(|tx| tx.get::<tables::CanonicalHeaders>(number.try_into().unwrap()))?
|
||||
.view(|tx| {
|
||||
let mut cursor = tx.cursor_read::<tables::CanonicalHeaders>()?;
|
||||
cursor
|
||||
.walk_range(range)?
|
||||
.map(|result| result.map(|(_, hash)| hash).map_err(Into::into))
|
||||
.collect::<Result<Vec<_>>>()
|
||||
})?
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
@ -109,7 +119,7 @@ impl<DB: Database> BlockIdProvider for ShareableDatabase<DB> {
|
||||
.view(|tx| tx.get::<tables::SyncStage>("Finish".to_string()))?
|
||||
.map_err(Into::<reth_interfaces::db::Error>::into)?
|
||||
.unwrap_or_default();
|
||||
let best_hash = self.block_hash(U256::from(best_number))?.unwrap_or_default();
|
||||
let best_hash = self.block_hash(best_number)?.unwrap_or_default();
|
||||
Ok(ChainInfo { best_hash, best_number, last_finalized: None, safe_finalized: None })
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ use reth_db::{
|
||||
};
|
||||
use reth_interfaces::Result;
|
||||
use reth_primitives::{
|
||||
Account, Address, Bytecode, Bytes, StorageKey, StorageValue, TransitionId, H256, U256,
|
||||
Account, Address, BlockNumber, Bytecode, Bytes, StorageKey, StorageValue, TransitionId, H256,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@ -72,8 +72,21 @@ impl<'a, 'b, TX: DbTx<'a>> AccountProvider for HistoricalStateProviderRef<'a, 'b
|
||||
|
||||
impl<'a, 'b, TX: DbTx<'a>> BlockHashProvider for HistoricalStateProviderRef<'a, 'b, TX> {
|
||||
/// Get block hash by number.
|
||||
fn block_hash(&self, number: U256) -> Result<Option<H256>> {
|
||||
self.tx.get::<tables::CanonicalHeaders>(number.to::<u64>()).map_err(Into::into)
|
||||
fn block_hash(&self, number: u64) -> Result<Option<H256>> {
|
||||
self.tx.get::<tables::CanonicalHeaders>(number).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn canonical_hashes_range(&self, start: BlockNumber, end: BlockNumber) -> Result<Vec<H256>> {
|
||||
let range = start..end;
|
||||
self.tx
|
||||
.cursor_read::<tables::CanonicalHeaders>()
|
||||
.map(|mut cursor| {
|
||||
cursor
|
||||
.walk_range(range)?
|
||||
.map(|result| result.map(|(_, hash)| hash).map_err(Into::into))
|
||||
.collect::<Result<Vec<_>>>()
|
||||
})?
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,8 +9,8 @@ use reth_db::{
|
||||
};
|
||||
use reth_interfaces::{provider::ProviderError, Result};
|
||||
use reth_primitives::{
|
||||
keccak256, Account, Address, Bytecode, Bytes, StorageKey, StorageValue, H256, KECCAK_EMPTY,
|
||||
U256,
|
||||
keccak256, Account, Address, BlockNumber, Bytecode, Bytes, StorageKey, StorageValue, H256,
|
||||
KECCAK_EMPTY,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@ -38,8 +38,21 @@ impl<'a, 'b, TX: DbTx<'a>> AccountProvider for LatestStateProviderRef<'a, 'b, TX
|
||||
|
||||
impl<'a, 'b, TX: DbTx<'a>> BlockHashProvider for LatestStateProviderRef<'a, 'b, TX> {
|
||||
/// Get block hash by number.
|
||||
fn block_hash(&self, number: U256) -> Result<Option<H256>> {
|
||||
self.db.get::<tables::CanonicalHeaders>(number.to::<u64>()).map_err(Into::into)
|
||||
fn block_hash(&self, number: u64) -> Result<Option<H256>> {
|
||||
self.db.get::<tables::CanonicalHeaders>(number).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn canonical_hashes_range(&self, start: BlockNumber, end: BlockNumber) -> Result<Vec<H256>> {
|
||||
let range = start..end;
|
||||
self.db
|
||||
.cursor_read::<tables::CanonicalHeaders>()
|
||||
.map(|mut cursor| {
|
||||
cursor
|
||||
.walk_range(range)?
|
||||
.map(|result| result.map(|(_, hash)| hash).map_err(Into::into))
|
||||
.collect::<Result<Vec<_>>>()
|
||||
})?
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,12 +5,12 @@
|
||||
///
|
||||
/// Used to implement provider traits.
|
||||
macro_rules! delegate_impls_to_as_ref {
|
||||
(for $target:ty => $($trait:ident $(where [$($generics:tt)*])? { $(fn $func:ident(&self, $($arg:ident: $argty:ty),*) -> $ret:path;)* })* ) => {
|
||||
(for $target:ty => $($trait:ident $(where [$($generics:tt)*])? { $(fn $func:ident$(<$($generic_arg:ident: $generic_arg_ty:path),*>)?(&self, $($arg:ident: $argty:ty),*) -> $ret:path;)* })* ) => {
|
||||
|
||||
$(
|
||||
impl<'a, $($($generics)*)?> $trait for $target {
|
||||
$(
|
||||
fn $func(&self, $($arg: $argty),*) -> $ret {
|
||||
fn $func$(<$($generic_arg: $generic_arg_ty),*>)?(&self, $($arg: $argty),*) -> $ret {
|
||||
self.as_ref().$func($($arg),*)
|
||||
}
|
||||
)*
|
||||
@ -34,7 +34,8 @@ macro_rules! delegate_provider_impls {
|
||||
fn basic_account(&self, address: reth_primitives::Address) -> reth_interfaces::Result<Option<reth_primitives::Account>>;
|
||||
}
|
||||
BlockHashProvider $(where [$($generics)*])? {
|
||||
fn block_hash(&self, number: reth_primitives::U256) -> reth_interfaces::Result<Option<reth_primitives::H256>>;
|
||||
fn block_hash(&self, number: u64) -> reth_interfaces::Result<Option<reth_primitives::H256>>;
|
||||
fn canonical_hashes_range(&self, start: reth_primitives::BlockNumber, end: reth_primitives::BlockNumber) -> reth_interfaces::Result<Vec<reth_primitives::H256>>;
|
||||
}
|
||||
StateProvider $(where [$($generics)*])?{
|
||||
fn storage(&self, account: reth_primitives::Address, storage_key: reth_primitives::StorageKey) -> reth_interfaces::Result<Option<reth_primitives::StorageValue>>;
|
||||
|
||||
@ -124,7 +124,12 @@ impl HeaderProvider for MockEthProvider {
|
||||
range: impl RangeBounds<reth_primitives::BlockNumber>,
|
||||
) -> Result<Vec<Header>> {
|
||||
let lock = self.headers.lock();
|
||||
Ok(lock.values().filter(|header| range.contains(&header.number)).cloned().collect())
|
||||
|
||||
let mut headers: Vec<_> =
|
||||
lock.values().filter(|header| range.contains(&header.number)).cloned().collect();
|
||||
headers.sort_by_key(|header| header.number);
|
||||
|
||||
Ok(headers)
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,21 +176,24 @@ impl ReceiptProvider for MockEthProvider {
|
||||
}
|
||||
|
||||
impl BlockHashProvider for MockEthProvider {
|
||||
fn block_hash(&self, number: U256) -> Result<Option<H256>> {
|
||||
fn block_hash(&self, number: u64) -> Result<Option<H256>> {
|
||||
let lock = self.blocks.lock();
|
||||
|
||||
let hash =
|
||||
lock.iter().find_map(
|
||||
|(hash, b)| {
|
||||
if b.number == number.to::<u64>() {
|
||||
Some(*hash)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
);
|
||||
lock.iter().find_map(|(hash, b)| if b.number == number { Some(*hash) } else { None });
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
fn canonical_hashes_range(&self, start: BlockNumber, end: BlockNumber) -> Result<Vec<H256>> {
|
||||
let range = start..end;
|
||||
let lock = self.blocks.lock();
|
||||
|
||||
let mut hashes: Vec<_> =
|
||||
lock.iter().filter(|(_, block)| range.contains(&block.number)).collect();
|
||||
hashes.sort_by_key(|(_, block)| block.number);
|
||||
|
||||
Ok(hashes.into_iter().map(|(hash, _)| *hash).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockIdProvider for MockEthProvider {
|
||||
|
||||
@ -18,9 +18,13 @@ pub struct NoopProvider;
|
||||
|
||||
/// Noop implementation for testing purposes
|
||||
impl BlockHashProvider for NoopProvider {
|
||||
fn block_hash(&self, _number: U256) -> Result<Option<H256>> {
|
||||
fn block_hash(&self, _number: u64) -> Result<Option<H256>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn canonical_hashes_range(&self, _start: BlockNumber, _end: BlockNumber) -> Result<Vec<H256>> {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockIdProvider for NoopProvider {
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
use auto_impl::auto_impl;
|
||||
use reth_interfaces::Result;
|
||||
use reth_primitives::{H256, U256};
|
||||
use reth_primitives::{BlockNumber, H256};
|
||||
|
||||
/// Client trait for fetching block hashes by number.
|
||||
#[auto_impl(&, Arc, Box)]
|
||||
pub trait BlockHashProvider: Send + Sync {
|
||||
/// Get the hash of the block with the given number. Returns `None` if no block with this number
|
||||
/// exists.
|
||||
fn block_hash(&self, number: U256) -> Result<Option<H256>>;
|
||||
fn block_hash(&self, number: BlockNumber) -> Result<Option<H256>>;
|
||||
|
||||
/// Get headers in range of block hashes or numbers
|
||||
fn canonical_hashes_range(&self, start: BlockNumber, end: BlockNumber) -> Result<Vec<H256>>;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use super::BlockHashProvider;
|
||||
use reth_interfaces::Result;
|
||||
use reth_primitives::{BlockId, BlockNumberOrTag, ChainInfo, H256, U256};
|
||||
use reth_primitives::{BlockId, BlockNumberOrTag, ChainInfo, H256};
|
||||
|
||||
/// Client trait for transforming [BlockId].
|
||||
#[auto_impl::auto_impl(&, Arc)]
|
||||
@ -33,7 +33,7 @@ pub trait BlockIdProvider: BlockHashProvider + Send + Sync {
|
||||
return Ok(Some(self.chain_info()?.best_hash))
|
||||
}
|
||||
self.convert_block_number(num)?
|
||||
.map(|num| self.block_hash(U256::from(num)))
|
||||
.map(|num| self.block_hash(num))
|
||||
.transpose()
|
||||
.map(|maybe_hash| maybe_hash.flatten())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user