mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
fix(rpc/trace): include block rewards in trace_filter rpc (#8868)
Signed-off-by: jsvisa <delweng@gmail.com> Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
@ -851,8 +851,8 @@ impl ChainSpec {
|
||||
self.fork(Hardfork::Homestead).active_at_block(block_number)
|
||||
}
|
||||
|
||||
/// The Paris hardfork (merge) is activated via ttd. If we have knowledge of the block, this
|
||||
/// function will return true if the block number is greater than or equal to the Paris
|
||||
/// The Paris hardfork (merge) is activated via block number. If we have knowledge of the block,
|
||||
/// this function will return true if the block number is greater than or equal to the Paris
|
||||
/// (merge) block.
|
||||
pub fn is_paris_active_at_block(&self, block_number: u64) -> Option<bool> {
|
||||
self.paris_block_and_final_difficulty.map(|(paris_block, _)| block_number >= paris_block)
|
||||
|
||||
@ -6,8 +6,10 @@ use crate::eth::{
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use jsonrpsee::core::RpcResult as Result;
|
||||
use reth_consensus_common::calc::{base_block_reward, block_reward, ommer_reward};
|
||||
use reth_primitives::{revm::env::tx_env_with_recovered, BlockId, Bytes, SealedHeader, B256, U256};
|
||||
use reth_consensus_common::calc::{
|
||||
base_block_reward, base_block_reward_pre_merge, block_reward, ommer_reward,
|
||||
};
|
||||
use reth_primitives::{revm::env::tx_env_with_recovered, BlockId, Bytes, Header, B256, U256};
|
||||
use reth_provider::{BlockReader, ChainSpecProvider, EvmEnvProvider, StateProviderFactory};
|
||||
use reth_revm::database::StateProviderDatabase;
|
||||
use reth_rpc_api::TraceApiServer;
|
||||
@ -266,7 +268,7 @@ where
|
||||
|
||||
// find relevant blocks to trace
|
||||
let mut target_blocks = Vec::new();
|
||||
for block in blocks {
|
||||
for block in &blocks {
|
||||
let mut transaction_indices = HashSet::new();
|
||||
let mut highest_matching_index = 0;
|
||||
for (tx_idx, tx) in block.body.iter().enumerate() {
|
||||
@ -308,11 +310,26 @@ where
|
||||
}
|
||||
|
||||
let block_traces = futures::future::try_join_all(block_traces).await?;
|
||||
let all_traces = block_traces
|
||||
let mut all_traces = block_traces
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|traces| traces.into_iter().flatten().flat_map(|traces| traces.into_iter()))
|
||||
.collect();
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// add reward traces for all blocks
|
||||
for block in &blocks {
|
||||
if let Some(base_block_reward) = self.calculate_base_block_reward(&block.header)? {
|
||||
all_traces.extend(self.extract_reward_traces(
|
||||
&block.header,
|
||||
&block.ommers,
|
||||
base_block_reward,
|
||||
));
|
||||
} else {
|
||||
// no block reward, means we're past the Paris hardfork and don't expect any rewards
|
||||
// because the blocks in ascending order
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Ok(all_traces)
|
||||
}
|
||||
@ -362,36 +379,12 @@ where
|
||||
maybe_traces.map(|traces| traces.into_iter().flatten().collect::<Vec<_>>());
|
||||
|
||||
if let (Some(block), Some(traces)) = (maybe_block, maybe_traces.as_mut()) {
|
||||
if let Some(header_td) = self.provider().header_td(&block.header.hash())? {
|
||||
if let Some(base_block_reward) = base_block_reward(
|
||||
self.provider().chain_spec().as_ref(),
|
||||
block.header.number,
|
||||
block.header.difficulty,
|
||||
header_td,
|
||||
) {
|
||||
let block_reward = block_reward(base_block_reward, block.ommers.len());
|
||||
traces.push(reward_trace(
|
||||
&block.header,
|
||||
RewardAction {
|
||||
author: block.header.beneficiary,
|
||||
reward_type: RewardType::Block,
|
||||
value: U256::from(block_reward),
|
||||
},
|
||||
));
|
||||
|
||||
for uncle in &block.ommers {
|
||||
let uncle_reward =
|
||||
ommer_reward(base_block_reward, block.header.number, uncle.number);
|
||||
traces.push(reward_trace(
|
||||
&block.header,
|
||||
RewardAction {
|
||||
author: uncle.beneficiary,
|
||||
reward_type: RewardType::Uncle,
|
||||
value: U256::from(uncle_reward),
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(base_block_reward) = self.calculate_base_block_reward(&block.header)? {
|
||||
traces.extend(self.extract_reward_traces(
|
||||
&block.header,
|
||||
&block.ommers,
|
||||
base_block_reward,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,10 +474,74 @@ where
|
||||
|
||||
Ok(Some(BlockOpcodeGas {
|
||||
block_hash: block.hash(),
|
||||
block_number: block.number,
|
||||
block_number: block.header.number,
|
||||
transactions,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Calculates the base block reward for the given block:
|
||||
///
|
||||
/// - if Paris hardfork is activated, no block rewards are given
|
||||
/// - if Paris hardfork is not activated, calculate block rewards with block number only
|
||||
/// - if Paris hardfork is unknown, calculate block rewards with block number and ttd
|
||||
fn calculate_base_block_reward(&self, header: &Header) -> EthResult<Option<u128>> {
|
||||
let chain_spec = self.provider().chain_spec();
|
||||
let is_paris_activated = chain_spec.is_paris_active_at_block(header.number);
|
||||
|
||||
Ok(match is_paris_activated {
|
||||
Some(true) => None,
|
||||
Some(false) => Some(base_block_reward_pre_merge(&chain_spec, header.number)),
|
||||
None => {
|
||||
// if Paris hardfork is unknown, we need to fetch the total difficulty at the
|
||||
// block's height and check if it is pre-merge to calculate the base block reward
|
||||
if let Some(header_td) = self.provider().header_td_by_number(header.number)? {
|
||||
base_block_reward(
|
||||
chain_spec.as_ref(),
|
||||
header.number,
|
||||
header.difficulty,
|
||||
header_td,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Extracts the reward traces for the given block:
|
||||
/// - block reward
|
||||
/// - uncle rewards
|
||||
fn extract_reward_traces(
|
||||
&self,
|
||||
header: &Header,
|
||||
ommers: &[Header],
|
||||
base_block_reward: u128,
|
||||
) -> Vec<LocalizedTransactionTrace> {
|
||||
let mut traces = Vec::with_capacity(ommers.len() + 1);
|
||||
|
||||
let block_reward = block_reward(base_block_reward, ommers.len());
|
||||
traces.push(reward_trace(
|
||||
header,
|
||||
RewardAction {
|
||||
author: header.beneficiary,
|
||||
reward_type: RewardType::Block,
|
||||
value: U256::from(block_reward),
|
||||
},
|
||||
));
|
||||
|
||||
for uncle in ommers {
|
||||
let uncle_reward = ommer_reward(base_block_reward, header.number, uncle.number);
|
||||
traces.push(reward_trace(
|
||||
header,
|
||||
RewardAction {
|
||||
author: uncle.beneficiary,
|
||||
reward_type: RewardType::Uncle,
|
||||
value: U256::from(uncle_reward),
|
||||
},
|
||||
));
|
||||
}
|
||||
traces
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@ -628,9 +685,9 @@ struct TraceApiInner<Provider, Eth> {
|
||||
|
||||
/// Helper to construct a [`LocalizedTransactionTrace`] that describes a reward to the block
|
||||
/// beneficiary.
|
||||
fn reward_trace(header: &SealedHeader, reward: RewardAction) -> LocalizedTransactionTrace {
|
||||
fn reward_trace(header: &Header, reward: RewardAction) -> LocalizedTransactionTrace {
|
||||
LocalizedTransactionTrace {
|
||||
block_hash: Some(header.hash()),
|
||||
block_hash: Some(header.hash_slow()),
|
||||
block_number: Some(header.number),
|
||||
transaction_hash: None,
|
||||
transaction_position: None,
|
||||
|
||||
Reference in New Issue
Block a user