fix: add block rewards to trace_block (#3491)

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
This commit is contained in:
Bjerg
2023-07-02 17:06:52 +02:00
committed by GitHub
parent 951fd0ae0c
commit 4f32f5627c
12 changed files with 160 additions and 34 deletions

1
Cargo.lock generated
View File

@ -5651,6 +5651,7 @@ dependencies = [
"jsonwebtoken",
"pin-project",
"rand 0.8.5",
"reth-consensus-common",
"reth-interfaces",
"reth-metrics",
"reth-network-api",

View File

@ -8,7 +8,8 @@ use clap::{
use futures::TryFutureExt;
use reth_network_api::{NetworkInfo, Peers};
use reth_provider::{
BlockReaderIdExt, CanonStateSubscriptions, EvmEnvProvider, HeaderProvider, StateProviderFactory,
BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider, EvmEnvProvider, HeaderProvider,
StateProviderFactory,
};
use reth_rpc::{
eth::{
@ -235,6 +236,7 @@ impl RpcServerArgs {
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider
+ ChainSpecProvider
+ Clone
+ Unpin
+ 'static,
@ -295,6 +297,7 @@ impl RpcServerArgs {
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider
+ ChainSpecProvider
+ Clone
+ Unpin
+ 'static,

View File

@ -31,13 +31,13 @@
//!
//! ```
//! use reth_network_api::{NetworkInfo, Peers};
//! use reth_provider::{BlockReaderIdExt, CanonStateSubscriptions, StateProviderFactory, EvmEnvProvider};
//! use reth_provider::{BlockReaderIdExt, ChainSpecProvider, CanonStateSubscriptions, StateProviderFactory, EvmEnvProvider};
//! use reth_rpc_builder::{RethRpcModule, RpcModuleBuilder, RpcServerConfig, ServerBuilder, TransportRpcModuleConfig};
//! use reth_tasks::TokioTaskExecutor;
//! use reth_transaction_pool::TransactionPool;
//! pub async fn launch<Provider, Pool, Network, Events>(provider: Provider, pool: Pool, network: Network, events: Events)
//! where
//! Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
//! Provider: BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
//! Pool: TransactionPool + Clone + 'static,
//! Network: NetworkInfo + Peers + Clone + 'static,
//! Events: CanonStateSubscriptions + Clone + 'static,
@ -64,7 +64,7 @@
//! ```
//! use tokio::try_join;
//! use reth_network_api::{NetworkInfo, Peers};
//! use reth_provider::{BlockReaderIdExt, CanonStateSubscriptions, StateProviderFactory, EvmEnvProvider};
//! use reth_provider::{BlockReaderIdExt, ChainSpecProvider, CanonStateSubscriptions, StateProviderFactory, EvmEnvProvider};
//! use reth_rpc::JwtSecret;
//! use reth_rpc_builder::{RethRpcModule, RpcModuleBuilder, RpcServerConfig, TransportRpcModuleConfig};
//! use reth_tasks::TokioTaskExecutor;
@ -73,7 +73,7 @@
//! use reth_rpc_builder::auth::AuthServerConfig;
//! pub async fn launch<Provider, Pool, Network, Events, EngineApi>(provider: Provider, pool: Pool, network: Network, events: Events, engine_api: EngineApi)
//! where
//! Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
//! Provider: BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
//! Pool: TransactionPool + Clone + 'static,
//! Network: NetworkInfo + Peers + Clone + 'static,
//! Events: CanonStateSubscriptions + Clone + 'static,
@ -113,7 +113,8 @@ use jsonrpsee::{
use reth_ipc::server::IpcServer;
use reth_network_api::{NetworkInfo, Peers};
use reth_provider::{
BlockReader, BlockReaderIdExt, CanonStateSubscriptions, EvmEnvProvider, StateProviderFactory,
BlockReader, BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider, EvmEnvProvider,
StateProviderFactory,
};
use reth_rpc::{
eth::{
@ -169,7 +170,13 @@ pub async fn launch<Provider, Pool, Network, Tasks, Events>(
events: Events,
) -> Result<RpcServerHandle, RpcError>
where
Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Provider: BlockReaderIdExt
+ StateProviderFactory
+ EvmEnvProvider
+ ChainSpecProvider
+ Clone
+ Unpin
+ 'static,
Pool: TransactionPool + Clone + 'static,
Network: NetworkInfo + Peers + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
@ -268,7 +275,13 @@ impl<Provider, Pool, Network, Tasks, Events>
impl<Provider, Pool, Network, Tasks, Events>
RpcModuleBuilder<Provider, Pool, Network, Tasks, Events>
where
Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Provider: BlockReaderIdExt
+ StateProviderFactory
+ EvmEnvProvider
+ ChainSpecProvider
+ Clone
+ Unpin
+ 'static,
Pool: TransactionPool + Clone + 'static,
Network: NetworkInfo + Peers + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
@ -485,8 +498,13 @@ impl RpcModuleSelection {
config: RpcModuleConfig,
) -> RpcModule<()>
where
Provider:
BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Provider: BlockReaderIdExt
+ StateProviderFactory
+ EvmEnvProvider
+ ChainSpecProvider
+ Clone
+ Unpin
+ 'static,
Pool: TransactionPool + Clone + 'static,
Network: NetworkInfo + Peers + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
@ -692,7 +710,13 @@ where
impl<Provider, Pool, Network, Tasks, Events>
RethModuleRegistry<Provider, Pool, Network, Tasks, Events>
where
Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Provider: BlockReaderIdExt
+ StateProviderFactory
+ EvmEnvProvider
+ ChainSpecProvider
+ Clone
+ Unpin
+ 'static,
Pool: TransactionPool + Clone + 'static,
Network: NetworkInfo + Peers + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,

View File

@ -23,6 +23,7 @@ reth-rpc-engine-api = { path = "../rpc-engine-api" }
reth-revm = { path = "../../revm" }
reth-tasks = { workspace = true }
reth-metrics = { workspace = true }
reth-consensus-common = { path = "../../consensus/common" }
# eth
revm = { workspace = true, features = [

View File

@ -11,8 +11,11 @@ use crate::{
};
use async_trait::async_trait;
use jsonrpsee::core::RpcResult as Result;
use reth_primitives::{BlockId, BlockNumberOrTag, Bytes, H256};
use reth_provider::{BlockReader, EvmEnvProvider, StateProviderBox, StateProviderFactory};
use reth_consensus_common::calc::{base_block_reward, block_reward};
use reth_primitives::{BlockId, BlockNumberOrTag, Bytes, SealedHeader, H256, U256};
use reth_provider::{
BlockReader, ChainSpecProvider, EvmEnvProvider, StateProviderBox, StateProviderFactory,
};
use reth_revm::{
database::{State, SubState},
env::tx_env_with_recovered,
@ -77,7 +80,7 @@ impl<Provider, Eth> TraceApi<Provider, Eth> {
impl<Provider, Eth> TraceApi<Provider, Eth>
where
Provider: BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
Provider: BlockReader + StateProviderFactory + EvmEnvProvider + ChainSpecProvider + 'static,
Eth: EthTransactions + 'static,
{
/// Executes the future on a new blocking task.
@ -396,7 +399,7 @@ where
&self,
block_id: BlockId,
) -> EthResult<Option<Vec<LocalizedTransactionTrace>>> {
let traces = self
let mut traces: Option<Vec<LocalizedTransactionTrace>> = self
.trace_block_with(
block_id,
TracingInspectorConfig::default_parity(),
@ -408,6 +411,43 @@ where
)
.await?
.map(|traces| traces.into_iter().flatten().collect());
// Add block reward traces
// TODO: We only really need the header and ommers here to determine the reward
if let (Some(block), Some(traces)) =
(self.inner.eth_api.block_by_id(block_id).await?, 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,
) {
traces.push(reward_trace(
&block.header,
RewardAction {
author: block.header.beneficiary,
reward_type: RewardType::Block,
value: U256::from(base_block_reward),
},
));
if !block.ommers.is_empty() {
traces.push(reward_trace(
&block.header,
RewardAction {
author: block.header.beneficiary,
reward_type: RewardType::Uncle,
value: block_reward(base_block_reward, block.ommers.len()) -
U256::from(base_block_reward),
},
));
}
}
}
}
Ok(traces)
}
@ -448,7 +488,7 @@ where
#[async_trait]
impl<Provider, Eth> TraceApiServer for TraceApi<Provider, Eth>
where
Provider: BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
Provider: BlockReader + StateProviderFactory + EvmEnvProvider + ChainSpecProvider + 'static,
Eth: EthTransactions + 'static,
{
/// Executes the given call and returns a number of possible traces for it.
@ -581,3 +621,20 @@ fn tracing_config(trace_types: &HashSet<TraceType>) -> TracingInspectorConfig {
.set_state_diffs(trace_types.contains(&TraceType::StateDiff))
.set_steps(trace_types.contains(&TraceType::VmTrace))
}
/// Helper to construct a [`LocalizedTransactionTrace`] that describes a reward to the block
/// beneficiary.
fn reward_trace(header: &SealedHeader, reward: RewardAction) -> LocalizedTransactionTrace {
LocalizedTransactionTrace {
block_hash: Some(header.hash),
block_number: Some(header.number),
transaction_hash: None,
transaction_position: None,
trace: TransactionTrace {
trace_address: vec![],
subtraces: 0,
action: Action::Reward(reward),
result: None,
},
}
}

View File

@ -24,11 +24,12 @@ pub use traits::{
AccountExtReader, AccountReader, BlockExecutionWriter, BlockExecutor, BlockHashReader,
BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, BlockSource, BlockWriter,
BlockchainTreePendingStateProvider, CanonChainTracker, CanonStateNotification,
CanonStateNotificationSender, CanonStateNotifications, CanonStateSubscriptions, EvmEnvProvider,
ExecutorFactory, HashingWriter, HeaderProvider, HistoryWriter, PostStateDataProvider,
ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StageCheckpointWriter,
StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider, StorageReader,
TransactionsProvider, WithdrawalsProvider,
CanonStateNotificationSender, CanonStateNotifications, CanonStateSubscriptions,
ChainSpecProvider, EvmEnvProvider, ExecutorFactory, HashingWriter, HeaderProvider,
HistoryWriter, PostStateDataProvider, ReceiptProvider, ReceiptProviderIdExt,
StageCheckpointReader, StageCheckpointWriter, StateProvider, StateProviderBox,
StateProviderFactory, StateRootProvider, StorageReader, TransactionsProvider,
WithdrawalsProvider,
};
/// Provider trait implementations.

View File

@ -1,8 +1,9 @@
use crate::{
providers::state::{historical::HistoricalStateProvider, latest::LatestStateProvider},
traits::{BlockSource, ReceiptProvider},
BlockHashReader, BlockNumReader, BlockReader, EvmEnvProvider, HeaderProvider, ProviderError,
StageCheckpointReader, StateProviderBox, TransactionsProvider, WithdrawalsProvider,
BlockHashReader, BlockNumReader, BlockReader, ChainSpecProvider, EvmEnvProvider,
HeaderProvider, ProviderError, StageCheckpointReader, StateProviderBox, TransactionsProvider,
WithdrawalsProvider,
};
use reth_db::{database::Database, init_db, models::StoredBlockBodyIndices, DatabaseEnv};
use reth_interfaces::Result;
@ -343,6 +344,15 @@ impl<DB: Database> EvmEnvProvider for ProviderFactory<DB> {
}
}
impl<DB> ChainSpecProvider for ProviderFactory<DB>
where
DB: Send + Sync,
{
fn chain_spec(&self) -> Arc<ChainSpec> {
self.chain_spec.clone()
}
}
#[cfg(test)]
mod tests {
use super::ProviderFactory;

View File

@ -1,9 +1,10 @@
use crate::{
BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
BlockchainTreePendingStateProvider, CanonChainTracker, CanonStateNotifications,
CanonStateSubscriptions, EvmEnvProvider, HeaderProvider, PostStateDataProvider, ProviderError,
ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProviderBox,
StateProviderFactory, TransactionsProvider, WithdrawalsProvider,
CanonStateSubscriptions, ChainSpecProvider, EvmEnvProvider, HeaderProvider,
PostStateDataProvider, ProviderError, ReceiptProvider, ReceiptProviderIdExt,
StageCheckpointReader, StateProviderBox, StateProviderFactory, TransactionsProvider,
WithdrawalsProvider,
};
use reth_db::{database::Database, models::StoredBlockBodyIndices};
use reth_interfaces::{
@ -14,7 +15,7 @@ use reth_interfaces::{
use reth_primitives::{
stage::{StageCheckpoint, StageId},
Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumber,
BlockNumberOrTag, BlockWithSenders, ChainInfo, Header, Receipt, SealedBlock,
BlockNumberOrTag, BlockWithSenders, ChainInfo, ChainSpec, Header, Receipt, SealedBlock,
SealedBlockWithSenders, SealedHeader, TransactionMeta, TransactionSigned,
TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, H256, U256,
};
@ -26,6 +27,7 @@ pub use state::{
use std::{
collections::{BTreeMap, HashSet},
ops::RangeBounds,
sync::Arc,
time::Instant,
};
use tracing::trace;
@ -431,6 +433,16 @@ where
}
}
impl<DB, Tree> ChainSpecProvider for BlockchainProvider<DB, Tree>
where
DB: Send + Sync,
Tree: Send + Sync,
{
fn chain_spec(&self) -> Arc<ChainSpec> {
self.database.chain_spec()
}
}
impl<DB, Tree> StateProviderFactory for BlockchainProvider<DB, Tree>
where
DB: Database,

View File

@ -1,26 +1,32 @@
use crate::{
traits::{BlockSource, ReceiptProvider},
AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
EvmEnvProvider, HeaderProvider, PostState, ReceiptProviderIdExt, StageCheckpointReader,
StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider, TransactionsProvider,
WithdrawalsProvider,
ChainSpecProvider, EvmEnvProvider, HeaderProvider, PostState, ReceiptProviderIdExt,
StageCheckpointReader, StateProvider, StateProviderBox, StateProviderFactory,
StateRootProvider, TransactionsProvider, WithdrawalsProvider,
};
use reth_db::models::StoredBlockBodyIndices;
use reth_interfaces::Result;
use reth_primitives::{
stage::{StageCheckpoint, StageId},
Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, Bytecode, Bytes,
ChainInfo, Header, Receipt, SealedBlock, SealedHeader, StorageKey, StorageValue,
TransactionMeta, TransactionSigned, TxHash, TxNumber, H256, KECCAK_EMPTY, U256,
ChainInfo, ChainSpec, Header, Receipt, SealedBlock, SealedHeader, StorageKey, StorageValue,
TransactionMeta, TransactionSigned, TxHash, TxNumber, H256, KECCAK_EMPTY, MAINNET, U256,
};
use reth_revm_primitives::primitives::{BlockEnv, CfgEnv};
use std::ops::RangeBounds;
use std::{ops::RangeBounds, sync::Arc};
/// Supports various api interfaces for testing purposes.
#[derive(Debug, Clone, Default, Copy)]
#[non_exhaustive]
pub struct NoopProvider;
impl ChainSpecProvider for NoopProvider {
fn chain_spec(&self) -> Arc<ChainSpec> {
MAINNET.clone()
}
}
/// Noop implementation for testing purposes
impl BlockHashReader for NoopProvider {
fn block_hash(&self, _number: u64) -> Result<Option<H256>> {

View File

@ -48,6 +48,9 @@ pub use chain::{
CanonStateSubscriptions,
};
mod spec;
pub use spec::ChainSpecProvider;
mod stage_checkpoint;
pub use stage_checkpoint::{StageCheckpointReader, StageCheckpointWriter};

View File

@ -0,0 +1,8 @@
use reth_primitives::ChainSpec;
use std::sync::Arc;
/// A trait for reading the current chainspec.
pub trait ChainSpecProvider: Send + Sync {
/// Get an [`Arc`] to the chainspec.
fn chain_spec(&self) -> Arc<ChainSpec>;
}