Skip to content

Commit

Permalink
feat: add get transaction by index methods
Browse files Browse the repository at this point in the history
  • Loading branch information
agostbiro committed Nov 10, 2023
1 parent 37d7fc3 commit 49ca51a
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 83 deletions.
19 changes: 19 additions & 0 deletions crates/edr_eth/src/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,25 @@ impl Display for BlockSpec {
}
}

/// A block spec without EIP-1898 support.
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(untagged)]
pub enum PreEip1898BlockSpec {
/// as a block number
Number(#[serde(with = "crate::serde::u64")] u64),
/// as a block tag (eg "latest")
Tag(BlockTag),
}

impl From<PreEip1898BlockSpec> for BlockSpec {
fn from(value: PreEip1898BlockSpec) -> Self {
match value {
PreEip1898BlockSpec::Number(block_number) => BlockSpec::Number(block_number),
PreEip1898BlockSpec::Tag(block_tag) => BlockSpec::Tag(block_tag),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
49 changes: 39 additions & 10 deletions crates/edr_eth/src/remote/cacheable_method_invocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
block::{is_safe_block_number, IsSafeBlockNumberArgs},
remote::{
methods::{GetLogsInput, MethodInvocation},
BlockSpec, BlockTag, Eip1898BlockSpec,
BlockSpec, BlockTag, Eip1898BlockSpec, PreEip1898BlockSpec,
},
U256,
};
Expand Down Expand Up @@ -70,7 +70,7 @@ enum CacheableMethodInvocation<'a> {
},
/// eth_getTransactionByBlockNumberAndIndex
GetTransactionByBlockNumberAndIndex {
block_number: &'a U256,
block_spec: CacheableBlockSpec<'a>,
index: &'a U256,
},
/// eth_getTransactionByHash
Expand Down Expand Up @@ -134,7 +134,7 @@ impl<'a> CacheableMethodInvocation<'a> {
index: _,
} => Some(WriteCacheKey::finalize(hasher)),
CacheableMethodInvocation::GetTransactionByBlockNumberAndIndex {
block_number: _,
block_spec: _,
index: _,
} => Some(WriteCacheKey::finalize(hasher)),
CacheableMethodInvocation::GetTransactionByHash {
Expand All @@ -156,12 +156,14 @@ impl<'a> CacheableMethodInvocation<'a> {
/// Error type for [`CacheableMethodInvocation::try_from`].
#[derive(thiserror::Error, Debug)]
enum MethodNotCacheableError {
#[error(transparent)]
BlockSpec(#[from] BlockSpecNotCacheableError),
#[error("Method is not cacheable: {0:?}")]
MethodInvocation(MethodInvocation),
#[error("Block spec is not cacheable: {0:?}")]
BlockSpec(#[from] BlockSpecNotCacheableError),
#[error("Get logs input is not cacheable: {0:?}")]
GetLogsInput(#[from] GetLogsInputNotCacheableError),
#[error(transparent)]
PreEip18989BlockSpec(#[from] PreEip1898BlockSpecNotCacheableError),
}

impl<'a> TryFrom<&'a MethodInvocation> for CacheableMethodInvocation<'a> {
Expand Down Expand Up @@ -215,9 +217,9 @@ impl<'a> TryFrom<&'a MethodInvocation> for CacheableMethodInvocation<'a> {
MethodInvocation::GetTransactionByBlockHashAndIndex(block_hash, index) => Ok(
CacheableMethodInvocation::GetTransactionByBlockHashAndIndex { block_hash, index },
),
MethodInvocation::GetTransactionByBlockNumberAndIndex(block_number, index) => Ok(
MethodInvocation::GetTransactionByBlockNumberAndIndex(block_spec, index) => Ok(
CacheableMethodInvocation::GetTransactionByBlockNumberAndIndex {
block_number,
block_spec: block_spec.try_into()?,
index,
},
),
Expand Down Expand Up @@ -294,7 +296,7 @@ enum CacheableBlockSpec<'a> {

/// Error type for [`CacheableBlockSpec::try_from`].
#[derive(thiserror::Error, Debug)]
#[error("Method is not cacheable: {0:?}")]
#[error("Block spec is not cacheable: {0:?}")]
struct BlockSpecNotCacheableError(Option<BlockSpec>);

impl<'a> TryFrom<&'a BlockSpec> for CacheableBlockSpec<'a> {
Expand Down Expand Up @@ -342,6 +344,33 @@ impl<'a> TryFrom<&'a Option<BlockSpec>> for CacheableBlockSpec<'a> {
}
}

/// Error type for [`CacheableBlockSpec::try_from`].
#[derive(thiserror::Error, Debug)]
#[error("Block spec is not cacheable: {0:?}")]
struct PreEip1898BlockSpecNotCacheableError(PreEip1898BlockSpec);

impl<'a> TryFrom<&'a PreEip1898BlockSpec> for CacheableBlockSpec<'a> {
type Error = PreEip1898BlockSpecNotCacheableError;

fn try_from(value: &'a PreEip1898BlockSpec) -> Result<Self, Self::Error> {
match value {
PreEip1898BlockSpec::Number(block_number) => Ok(CacheableBlockSpec::Number {
block_number: *block_number,
}),
PreEip1898BlockSpec::Tag(tag) => match tag {
// Latest and pending can be never resolved to a safe block number.
BlockTag::Latest | BlockTag::Pending => {
Err(PreEip1898BlockSpecNotCacheableError(value.clone()))
}
// Earliest, safe and finalized are potentially resolvable to a safe block number.
BlockTag::Earliest => Ok(CacheableBlockSpec::Earliest),
BlockTag::Safe => Ok(CacheableBlockSpec::Safe),
BlockTag::Finalized => Ok(CacheableBlockSpec::Finalized),
},
}
}
}

/// A cacheable input for the `eth_getLogs` method.
#[derive(Clone, Debug)]
struct CacheableGetLogsInput<'a> {
Expand Down Expand Up @@ -665,9 +694,9 @@ impl Hasher {
this.hash_b256(block_hash).hash_u256(index)
}
CacheableMethodInvocation::GetTransactionByBlockNumberAndIndex {
block_number,
block_spec,
index,
} => this.hash_u256(block_number).hash_u256(index),
} => this.hash_block_spec(block_spec)?.hash_u256(index),
CacheableMethodInvocation::GetTransactionByHash { transaction_hash } => {
this.hash_b256(transaction_hash)
}
Expand Down
6 changes: 4 additions & 2 deletions crates/edr_eth/src/remote/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
remote::{
eth::eip712,
filter::{FilterOptions, SubscriptionType},
BlockSpec,
BlockSpec, PreEip1898BlockSpec,
},
serde::{
optional_single_to_sequence, sequence_to_optional_single, sequence_to_single,
Expand Down Expand Up @@ -180,8 +180,10 @@ pub enum MethodInvocation {
#[serde(rename = "eth_getTransactionByBlockHashAndIndex")]
GetTransactionByBlockHashAndIndex(B256, U256),
/// eth_getTransactionByBlockNumberAndIndex
// Matching Hardhat behavior in not accepting EIP-1898 block tags
// https://github.com/NomicFoundation/hardhat/blob/06474681f72e1cd895abbec419f6f10be3d8e4ed/packages/hardhat-core/src/internal/hardhat-network/provider/modules/eth.ts#L775
#[serde(rename = "eth_getTransactionByBlockNumberAndIndex")]
GetTransactionByBlockNumberAndIndex(U256, U256),
GetTransactionByBlockNumberAndIndex(PreEip1898BlockSpec, U256),
/// eth_getTransactionByHash
#[serde(
rename = "eth_getTransactionByHash",
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 @@ -5,7 +5,7 @@ use edr_eth::{
FilterBlockTarget, FilterOptions, LogOutput, OneOrMoreAddresses, SubscriptionType,
},
methods::{GetLogsInput, MethodInvocation, OneUsizeOrTwo, TransactionInput, U64OrUsize},
BlockSpec, BlockTag,
BlockSpec, BlockTag, PreEip1898BlockSpec,
},
transaction::EthTransactionRequest,
Address, B256, U256, U64,
Expand Down Expand Up @@ -222,7 +222,7 @@ fn test_serde_eth_get_tx_by_block_hash_and_index() {
#[test]
fn test_serde_eth_get_tx_by_block_number_and_index() {
help_test_method_invocation_serde(MethodInvocation::GetTransactionByBlockNumberAndIndex(
U256::from(100),
PreEip1898BlockSpec::Number(100),
U256::from(1),
));
}
Expand Down
Loading

0 comments on commit 49ca51a

Please sign in to comment.