mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(rpc): rpc handler for eth_getUncleByBlock{Hash/Number}AndIndex (#1595)
Co-authored-by: lambdaclass-user <github@lambdaclass.com>
This commit is contained in:
committed by
GitHub
parent
92a0ebbf04
commit
ce2b83e774
@ -73,19 +73,11 @@ where
|
||||
EthApiClient::block_transaction_count_by_hash(client, hash).await.unwrap();
|
||||
EthApiClient::block_uncles_count_by_hash(client, hash).await.unwrap();
|
||||
EthApiClient::block_uncles_count_by_number(client, block_number).await.unwrap();
|
||||
|
||||
EthApiClient::uncle_by_block_hash_and_index(client, hash, index).await.unwrap();
|
||||
EthApiClient::uncle_by_block_number_and_index(client, block_number, index).await.unwrap();
|
||||
// Unimplemented
|
||||
assert!(is_unimplemented(EthApiClient::syncing(client).await.err().unwrap()));
|
||||
assert!(is_unimplemented(EthApiClient::author(client).await.err().unwrap()));
|
||||
assert!(is_unimplemented(
|
||||
EthApiClient::uncle_by_block_hash_and_index(client, hash, index).await.err().unwrap()
|
||||
));
|
||||
assert!(is_unimplemented(
|
||||
EthApiClient::uncle_by_block_number_and_index(client, block_number, index)
|
||||
.await
|
||||
.err()
|
||||
.unwrap()
|
||||
));
|
||||
assert!(is_unimplemented(EthApiClient::transaction_by_hash(client, hash).await.err().unwrap()));
|
||||
assert!(is_unimplemented(
|
||||
EthApiClient::transaction_by_block_hash_and_index(client, hash, index).await.err().unwrap()
|
||||
|
||||
@ -8,7 +8,8 @@ use reth_rlp::Encodable;
|
||||
use serde::{ser::Error, Deserialize, Serialize, Serializer};
|
||||
use std::{collections::BTreeMap, ops::Deref};
|
||||
|
||||
/// Block Transactions depending on the boolean attribute of `eth_getBlockBy*`
|
||||
/// Block Transactions depending on the boolean attribute of `eth_getBlockBy*`,
|
||||
/// or if used by `eth_getUncle*`
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum BlockTransactions {
|
||||
@ -16,8 +17,16 @@ pub enum BlockTransactions {
|
||||
Hashes(Vec<H256>),
|
||||
/// Full transactions
|
||||
Full(Vec<Transaction>),
|
||||
/// Special case for uncle response.
|
||||
Uncle,
|
||||
}
|
||||
impl BlockTransactions {
|
||||
/// Check if the enum variant is
|
||||
/// used for an uncle response.
|
||||
pub fn is_uncle(&self) -> bool {
|
||||
matches!(self, Self::Uncle)
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines how the `transactions` field of [Block] should be filled.
|
||||
///
|
||||
/// This essentially represents the `full:bool` argument in RPC calls that determine whether the
|
||||
@ -55,11 +64,14 @@ pub struct Block {
|
||||
/// Header of the block
|
||||
#[serde(flatten)]
|
||||
pub header: Header,
|
||||
/// Total difficulty
|
||||
pub total_difficulty: U256,
|
||||
/// Total difficulty, this field is None only if representing
|
||||
/// an Uncle block.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub total_difficulty: Option<U256>,
|
||||
/// Uncles' hashes
|
||||
pub uncles: Vec<H256>,
|
||||
/// Transactions
|
||||
#[serde(skip_serializing_if = "BlockTransactions::is_uncle")]
|
||||
pub transactions: BlockTransactions,
|
||||
/// Integer the size of this block in bytes.
|
||||
pub size: Option<U256>,
|
||||
@ -67,6 +79,7 @@ pub struct Block {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub base_fee_per_gas: Option<U256>,
|
||||
/// Withdrawals
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub withdrawals: Option<Vec<Withdrawal>>,
|
||||
}
|
||||
|
||||
@ -160,11 +173,29 @@ impl Block {
|
||||
uncles,
|
||||
transactions,
|
||||
base_fee_per_gas: base_fee_per_gas.map(U256::from),
|
||||
total_difficulty,
|
||||
total_difficulty: Some(total_difficulty),
|
||||
size: Some(U256::from(block_length)),
|
||||
withdrawals: block.withdrawals,
|
||||
}
|
||||
}
|
||||
|
||||
/// Build an RPC block response representing
|
||||
/// an Uncle from its header.
|
||||
pub fn uncle_block_from_header(header: PrimitiveHeader) -> Self {
|
||||
let hash = header.hash_slow();
|
||||
let rpc_header = Header::from_primitive_with_hash(header.clone(), hash);
|
||||
let uncle_block = PrimitiveBlock { header, ..Default::default() };
|
||||
let size = Some(U256::from(uncle_block.length()));
|
||||
Self {
|
||||
uncles: vec![],
|
||||
header: rpc_header,
|
||||
transactions: BlockTransactions::Uncle,
|
||||
base_fee_per_gas: None,
|
||||
withdrawals: None,
|
||||
size,
|
||||
total_difficulty: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Block header representation.
|
||||
@ -189,6 +220,7 @@ pub struct Header {
|
||||
/// Transactions receipts root hash
|
||||
pub receipts_root: H256,
|
||||
/// Withdrawals root hash
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub withdrawals_root: Option<H256>,
|
||||
/// Block number
|
||||
pub number: Option<U256>,
|
||||
@ -354,7 +386,7 @@ mod tests {
|
||||
mix_hash: H256::from_low_u64_be(14),
|
||||
nonce: Some(H64::from_low_u64_be(15)),
|
||||
},
|
||||
total_difficulty: U256::from(100000),
|
||||
total_difficulty: Some(U256::from(100000)),
|
||||
uncles: vec![H256::from_low_u64_be(17)],
|
||||
transactions: BlockTransactions::Hashes(vec![H256::from_low_u64_be(18)]),
|
||||
size: Some(U256::from(19)),
|
||||
@ -364,7 +396,7 @@ mod tests {
|
||||
let serialized = serde_json::to_string(&block).unwrap();
|
||||
assert_eq!(
|
||||
serialized,
|
||||
r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000001","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000002","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000003","author":"0x0000000000000000000000000000000000000004","miner":"0x0000000000000000000000000000000000000004","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000005","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000006","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000007","withdrawalsRoot":"0x0000000000000000000000000000000000000000000000000000000000000008","number":"0x9","gasUsed":"0xa","gasLimit":"0xb","extraData":"0x010203","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","timestamp":"0xc","difficulty":"0xd","mixHash":"0x000000000000000000000000000000000000000000000000000000000000000e","nonce":"0x000000000000000f","totalDifficulty":"0x186a0","uncles":["0x0000000000000000000000000000000000000000000000000000000000000011"],"transactions":["0x0000000000000000000000000000000000000000000000000000000000000012"],"size":"0x13","baseFeePerGas":"0x14","withdrawals":null}"#
|
||||
r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000001","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000002","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000003","author":"0x0000000000000000000000000000000000000004","miner":"0x0000000000000000000000000000000000000004","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000005","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000006","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000007","withdrawalsRoot":"0x0000000000000000000000000000000000000000000000000000000000000008","number":"0x9","gasUsed":"0xa","gasLimit":"0xb","extraData":"0x010203","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","timestamp":"0xc","difficulty":"0xd","mixHash":"0x000000000000000000000000000000000000000000000000000000000000000e","nonce":"0x000000000000000f","totalDifficulty":"0x186a0","uncles":["0x0000000000000000000000000000000000000000000000000000000000000011"],"transactions":["0x0000000000000000000000000000000000000000000000000000000000000012"],"size":"0x13","baseFeePerGas":"0x14"}"#
|
||||
);
|
||||
let deserialized: Block = serde_json::from_str(&serialized).unwrap();
|
||||
assert_eq!(block, deserialized);
|
||||
|
||||
@ -6,7 +6,7 @@ use crate::{
|
||||
};
|
||||
use reth_primitives::BlockId;
|
||||
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderFactory};
|
||||
use reth_rpc_types::{Block, RichBlock};
|
||||
use reth_rpc_types::{Block, Index, RichBlock};
|
||||
|
||||
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
|
||||
where
|
||||
@ -23,6 +23,20 @@ where
|
||||
Ok(self.client().ommers(block_id)?)
|
||||
}
|
||||
|
||||
pub(crate) async fn ommer_by_block_and_index(
|
||||
&self,
|
||||
block_id: impl Into<BlockId>,
|
||||
index: Index,
|
||||
) -> EthResult<Option<RichBlock>> {
|
||||
let block_id = block_id.into();
|
||||
let index = usize::from(index);
|
||||
let uncles = self.client().ommers(block_id)?.unwrap_or_default();
|
||||
let uncle = uncles
|
||||
.into_iter()
|
||||
.nth(index)
|
||||
.map(|header| Block::uncle_block_from_header(header).into());
|
||||
Ok(uncle)
|
||||
}
|
||||
pub(crate) async fn block_transaction_count(
|
||||
&self,
|
||||
block_id: impl Into<BlockId>,
|
||||
|
||||
@ -102,19 +102,19 @@ where
|
||||
/// Handler for: `eth_getUncleByBlockHashAndIndex`
|
||||
async fn uncle_by_block_hash_and_index(
|
||||
&self,
|
||||
_hash: H256,
|
||||
_index: Index,
|
||||
hash: H256,
|
||||
index: Index,
|
||||
) -> Result<Option<RichBlock>> {
|
||||
Err(internal_rpc_err("unimplemented"))
|
||||
Ok(EthApi::ommer_by_block_and_index(self, hash, index).await?)
|
||||
}
|
||||
|
||||
/// Handler for: `eth_getUncleByBlockNumberAndIndex`
|
||||
async fn uncle_by_block_number_and_index(
|
||||
&self,
|
||||
_number: BlockNumberOrTag,
|
||||
_index: Index,
|
||||
number: BlockNumberOrTag,
|
||||
index: Index,
|
||||
) -> Result<Option<RichBlock>> {
|
||||
Err(internal_rpc_err("unimplemented"))
|
||||
Ok(EthApi::ommer_by_block_and_index(self, number, index).await?)
|
||||
}
|
||||
|
||||
/// Handler for: `eth_getTransactionByHash`
|
||||
|
||||
Reference in New Issue
Block a user