Skip to content

Commit

Permalink
feat: add eth_getBlockByNumber support (#4627)
Browse files Browse the repository at this point in the history
  • Loading branch information
agostbiro authored Nov 29, 2023
1 parent 0bb89be commit e4f702d
Show file tree
Hide file tree
Showing 20 changed files with 359 additions and 138 deletions.
68 changes: 38 additions & 30 deletions crates/edr_eth/src/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,38 +94,44 @@ pub enum BlockSpec {
Eip1898(Eip1898BlockSpec),
}

impl BlockSpec {
/// Constructs an instance for the earliest block.
#[must_use]
pub fn earliest() -> Self {
Self::Tag(BlockTag::Earliest)
}

/// Constructs an instance for the latest block.
#[must_use]
pub fn latest() -> Self {
Self::Tag(BlockTag::Latest)
}

/// Constructs an instance for the pending block.
#[must_use]
pub fn pending() -> Self {
Self::Tag(BlockTag::Pending)
}

/// Constructs an instance for the safe block.
#[must_use]
pub fn safe() -> Self {
Self::Tag(BlockTag::Safe)
}

/// Constructs an instance for the finalized block.
#[must_use]
pub fn finalized() -> Self {
Self::Tag(BlockTag::Finalized)
}
macro_rules! impl_block_tags {
($type_name:ident) => {
impl $type_name {
/// Constructs an instance for the earliest block.
#[must_use]
pub fn earliest() -> Self {
Self::Tag(BlockTag::Earliest)
}

/// Constructs an instance for the latest block.
#[must_use]
pub fn latest() -> Self {
Self::Tag(BlockTag::Latest)
}

/// Constructs an instance for the pending block.
#[must_use]
pub fn pending() -> Self {
Self::Tag(BlockTag::Pending)
}

/// Constructs an instance for the safe block.
#[must_use]
pub fn safe() -> Self {
Self::Tag(BlockTag::Safe)
}

/// Constructs an instance for the finalized block.
#[must_use]
pub fn finalized() -> Self {
Self::Tag(BlockTag::Finalized)
}
}
};
}

impl_block_tags!(BlockSpec);

impl Display for BlockSpec {
fn fmt(&self, formatter: &mut Formatter<'_>) -> Result<(), fmt::Error> {
match self {
Expand Down Expand Up @@ -155,6 +161,8 @@ impl From<PreEip1898BlockSpec> for BlockSpec {
}
}

impl_block_tags!(PreEip1898BlockSpec);

#[cfg(test)]
mod tests {
use super::*;
Expand Down
24 changes: 12 additions & 12 deletions crates/edr_eth/src/remote/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use uuid::Uuid;
use super::{
eth, jsonrpc,
methods::{GetLogsInput, MethodInvocation},
BlockSpec,
BlockSpec, PreEip1898BlockSpec,
};
use crate::{
block::{block_time, is_safe_block_number, IsSafeBlockNumberArgs},
Expand Down Expand Up @@ -719,7 +719,7 @@ impl RpcClient {
/// Calls `eth_getBlockByNumber` and returns the transaction's hash.
pub async fn get_block_by_number(
&self,
spec: BlockSpec,
spec: PreEip1898BlockSpec,
) -> Result<Option<eth::Block<B256>>, RpcClientError> {
self.call_with_resolver(
MethodInvocation::GetBlockByNumber(spec, false),
Expand All @@ -731,7 +731,7 @@ impl RpcClient {
/// Calls `eth_getBlockByNumber` and returns the transaction's data.
pub async fn get_block_by_number_with_transaction_data(
&self,
spec: BlockSpec,
spec: PreEip1898BlockSpec,
) -> Result<eth::Block<eth::Transaction>, RpcClientError> {
self.call_with_resolver(
MethodInvocation::GetBlockByNumber(spec, true),
Expand Down Expand Up @@ -1360,7 +1360,7 @@ mod tests {
assert_eq!(client.files_in_cache().len(), 0);

client
.get_block_by_number(BlockSpec::finalized())
.get_block_by_number(PreEip1898BlockSpec::finalized())
.await
.expect("should have succeeded");

Expand All @@ -1375,7 +1375,7 @@ mod tests {
let block_number = 16222385;

let block = TestRpcClient::new(&alchemy_url)
.get_block_by_number(BlockSpec::Number(block_number))
.get_block_by_number(PreEip1898BlockSpec::Number(block_number))
.await
.expect("should have succeeded")
.expect("Block must exist");
Expand All @@ -1401,7 +1401,7 @@ mod tests {
assert_eq!(client.files_in_cache().len(), 0);

let block = client
.get_block_by_number(BlockSpec::Number(block_number))
.get_block_by_number(PreEip1898BlockSpec::Number(block_number))
.await
.expect("should have succeeded")
.expect("Block must exist");
Expand All @@ -1417,7 +1417,7 @@ mod tests {
let alchemy_url = get_alchemy_url();
let client = TestRpcClient::new(&alchemy_url);

let block_spec = BlockSpec::Number(16220843);
let block_spec = PreEip1898BlockSpec::Number(16220843);

assert_eq!(client.files_in_cache().len(), 0);

Expand All @@ -1444,7 +1444,7 @@ mod tests {
assert_eq!(client.files_in_cache().len(), 0);

client
.get_block_by_number_with_transaction_data(BlockSpec::earliest())
.get_block_by_number_with_transaction_data(PreEip1898BlockSpec::earliest())
.await
.expect("should have succeeded");

Expand All @@ -1457,7 +1457,7 @@ mod tests {
let alchemy_url = get_alchemy_url();

let _block = TestRpcClient::new(&alchemy_url)
.get_block_by_number(BlockSpec::latest())
.get_block_by_number(PreEip1898BlockSpec::latest())
.await
.expect("should have succeeded");
}
Expand All @@ -1467,7 +1467,7 @@ mod tests {
let alchemy_url = get_alchemy_url();

let _block = TestRpcClient::new(&alchemy_url)
.get_block_by_number_with_transaction_data(BlockSpec::latest())
.get_block_by_number_with_transaction_data(PreEip1898BlockSpec::latest())
.await
.expect("should have succeeded");
}
Expand All @@ -1477,7 +1477,7 @@ mod tests {
let alchemy_url = get_alchemy_url();

let _block = TestRpcClient::new(&alchemy_url)
.get_block_by_number(BlockSpec::pending())
.get_block_by_number(PreEip1898BlockSpec::pending())
.await
.expect("should have succeeded");
}
Expand All @@ -1487,7 +1487,7 @@ mod tests {
let alchemy_url = get_alchemy_url();

let _block = TestRpcClient::new(&alchemy_url)
.get_block_by_number_with_transaction_data(BlockSpec::pending())
.get_block_by_number_with_transaction_data(PreEip1898BlockSpec::pending())
.await
.expect("should have succeeded");
}
Expand Down
7 changes: 4 additions & 3 deletions crates/edr_eth/src/remote/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ pub struct Block<TX> {
/// the "extra data" field of this block
#[serde(with = "crate::serde::bytes")]
pub extra_data: Bytes,
/// the bloom filter for the logs of the block. None when its pending block.
/// the bloom filter for the logs of the block
pub logs_bloom: Bloom,
/// the unix timestamp for when the block was collated
#[serde(with = "crate::serde::u64")]
Expand All @@ -323,8 +323,9 @@ pub struct Block<TX> {
/// on the last given parameter
#[serde(default)]
pub transactions: Vec<TX>,
/// integer the size of this block in bytes
pub size: U256,
/// the length of the RLP encoding of this block in bytes
#[serde(with = "crate::serde::u64")]
pub size: u64,
/// mix hash
pub mix_hash: B256,
/// hash of the generated proof-of-work. null when its pending block.
Expand Down
2 changes: 1 addition & 1 deletion crates/edr_eth/src/remote/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub enum MethodInvocation {
/// eth_getBlockByNumber
#[serde(rename = "eth_getBlockByNumber")]
GetBlockByNumber(
BlockSpec,
PreEip1898BlockSpec,
/// include transaction data
bool,
),
Expand Down
4 changes: 2 additions & 2 deletions crates/edr_eth/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,15 @@ fn test_serde_eth_get_balance() {
#[test]
fn test_serde_eth_get_block_by_number() {
help_test_method_invocation_serde(MethodInvocation::GetBlockByNumber(
BlockSpec::Number(100),
PreEip1898BlockSpec::Number(100),
true,
));
}

#[test]
fn test_serde_eth_get_block_by_tag() {
help_test_method_invocation_serde(MethodInvocation::GetBlockByNumber(
BlockSpec::latest(),
PreEip1898BlockSpec::latest(),
true,
));
}
Expand Down
4 changes: 2 additions & 2 deletions crates/edr_eth/tests/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ mod remote {
#[tokio::test]
#[serial]
async fn [<test_remote_block_receipt_root_ $name>]() {
use edr_eth::{remote::{RpcClient, BlockSpec}, trie::ordered_trie_root};
use edr_eth::{remote::{RpcClient, PreEip1898BlockSpec}, trie::ordered_trie_root};
use edr_test_utils::env::get_alchemy_url;

let client = RpcClient::new(&get_alchemy_url(), CACHE_DIR.path().into());

let block = client
.get_block_by_number_with_transaction_data(BlockSpec::Number($block_number))
.get_block_by_number_with_transaction_data(PreEip1898BlockSpec::Number($block_number))
.await
.expect("Should succeed");

Expand Down
4 changes: 2 additions & 2 deletions crates/edr_eth/tests/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod alchemy {
#[tokio::test]
async fn [<test_transaction_remote_ $name _hash>]() {
use edr_eth::{
remote::{RpcClient, BlockSpec},
remote::{RpcClient, PreEip1898BlockSpec},
transaction::SignedTransaction,
Address
};
Expand All @@ -21,7 +21,7 @@ mod alchemy {
let client = RpcClient::new(&get_alchemy_url(), tempdir.path().into());

let block = client
.get_block_by_number_with_transaction_data(BlockSpec::Number($block_number))
.get_block_by_number_with_transaction_data(PreEip1898BlockSpec::Number($block_number))
.await
.expect("Should succeed");

Expand Down
8 changes: 5 additions & 3 deletions crates/edr_evm/benches/state/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::clone::Clone;
use std::sync::Arc;

use criterion::{BatchSize, BenchmarkId, Criterion};
use edr_eth::{Address, Bytes, U256};
use edr_eth::{remote::PreEip1898BlockSpec, Address, Bytes, U256};
#[cfg(all(test, feature = "test-remote"))]
use edr_evm::state::ForkState;
use edr_evm::state::{StateError, SyncState, TrieState};
Expand Down Expand Up @@ -41,7 +41,7 @@ impl EdrStates {

#[cfg(all(test, feature = "test-remote"))]
let fork = {
use edr_eth::remote::{BlockSpec, RpcClient};
use edr_eth::remote::RpcClient;
use edr_evm::RandomHashGenerator;
use parking_lot::Mutex;

Expand All @@ -54,7 +54,9 @@ impl EdrStates {
));

let block = runtime
.block_on(rpc_client.get_block_by_number(BlockSpec::Number(fork_block_number)))
.block_on(
rpc_client.get_block_by_number(PreEip1898BlockSpec::Number(fork_block_number)),
)
.expect("failed to retrieve block by number")
.expect("block should exist");

Expand Down
14 changes: 13 additions & 1 deletion crates/edr_evm/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ mod remote;
use std::{fmt::Debug, sync::Arc};

use auto_impl::auto_impl;
use edr_eth::{block, receipt::BlockReceipt, transaction::SignedTransaction, Address, B256};
use edr_eth::{
block, receipt::BlockReceipt, transaction::SignedTransaction, withdrawal::Withdrawal, Address,
B256,
};

pub use self::{
builder::{BlockBuilder, BlockBuilderCreationError, BlockTransactionError, BuildBlockResult},
Expand All @@ -25,6 +28,12 @@ pub trait Block: Debug {
/// Returns the block's header.
fn header(&self) -> &block::Header;

/// Ommer/uncle block hashes.
fn ommer_hashes(&self) -> &[B256];

/// The length of the RLP encoding of this block in bytes.
fn rlp_size(&self) -> u64;

/// Returns the block's transactions.
fn transactions(&self) -> &[SignedTransaction];

Expand All @@ -33,6 +42,9 @@ pub trait Block: Debug {

/// Returns the receipts of the block's transactions.
fn transaction_receipts(&self) -> Result<Vec<Arc<BlockReceipt>>, Self::Error>;

/// Withdrawals
fn withdrawals(&self) -> Option<&[Withdrawal]>;
}

/// Trait that meets all requirements for a synchronous block.
Expand Down
Loading

0 comments on commit e4f702d

Please sign in to comment.