feat: add trace opcode gas (#6977)

This commit is contained in:
Matthias Seitz
2024-03-05 22:57:43 +01:00
committed by GitHub
parent f2da01fd88
commit 6725d43f05
4 changed files with 112 additions and 16 deletions

14
Cargo.lock generated
View File

@ -174,7 +174,7 @@ dependencies = [
[[package]]
name = "alloy-eips"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d"
source = "git+https://github.com/alloy-rs/alloy?rev=975a52a#975a52a31727618a0a27f27091656c59eb9714bb"
dependencies = [
"alloy-primitives",
"alloy-rlp",
@ -184,7 +184,7 @@ dependencies = [
[[package]]
name = "alloy-genesis"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d"
source = "git+https://github.com/alloy-rs/alloy?rev=975a52a#975a52a31727618a0a27f27091656c59eb9714bb"
dependencies = [
"alloy-primitives",
"alloy-rpc-types",
@ -206,7 +206,7 @@ dependencies = [
[[package]]
name = "alloy-node-bindings"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d"
source = "git+https://github.com/alloy-rs/alloy?rev=975a52a#975a52a31727618a0a27f27091656c59eb9714bb"
dependencies = [
"alloy-genesis",
"alloy-primitives",
@ -267,7 +267,7 @@ dependencies = [
[[package]]
name = "alloy-rpc-engine-types"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d"
source = "git+https://github.com/alloy-rs/alloy?rev=975a52a#975a52a31727618a0a27f27091656c59eb9714bb"
dependencies = [
"alloy-primitives",
"alloy-rlp",
@ -282,7 +282,7 @@ dependencies = [
[[package]]
name = "alloy-rpc-trace-types"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d"
source = "git+https://github.com/alloy-rs/alloy?rev=975a52a#975a52a31727618a0a27f27091656c59eb9714bb"
dependencies = [
"alloy-primitives",
"alloy-rpc-types",
@ -293,7 +293,7 @@ dependencies = [
[[package]]
name = "alloy-rpc-types"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d"
source = "git+https://github.com/alloy-rs/alloy?rev=975a52a#975a52a31727618a0a27f27091656c59eb9714bb"
dependencies = [
"alloy-primitives",
"alloy-rlp",
@ -7041,7 +7041,7 @@ dependencies = [
[[package]]
name = "revm-inspectors"
version = "0.1.0"
source = "git+https://github.com/paradigmxyz/evm-inspectors?rev=7068d39#7068d395eb56ee5fee8e6acc7c32d3dbc4616f3b"
source = "git+https://github.com/paradigmxyz/evm-inspectors?rev=7cdbe2e#7cdbe2ec1bd34444ae828725d6cd53ceea632ccc"
dependencies = [
"alloy-primitives",
"alloy-rpc-trace-types",

View File

@ -178,7 +178,7 @@ reth-trie = { path = "crates/trie" }
# revm
revm = { version = "6.1.0", features = ["std", "secp256k1"], default-features = false }
revm-primitives = { version = "2.1.0", features = ["std"], default-features = false }
revm-inspectors = { git = "https://github.com/paradigmxyz/evm-inspectors", rev = "7068d39" }
revm-inspectors = { git = "https://github.com/paradigmxyz/evm-inspectors", rev = "7cdbe2e" }
# eth
alloy-chains = { version = "0.1", feature = ["serde", "rlp", "arbitrary"] }
@ -187,12 +187,12 @@ alloy-dyn-abi = "0.6"
alloy-sol-types = "0.6"
alloy-rlp = "0.3"
alloy-trie = "0.3"
alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "785c667" }
alloy-rpc-trace-types = { git = "https://github.com/alloy-rs/alloy", rev = "785c667" }
alloy-rpc-engine-types = { git = "https://github.com/alloy-rs/alloy", rev = "785c667" }
alloy-genesis = { git = "https://github.com/alloy-rs/alloy", rev = "785c667" }
alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy", rev = "785c667" }
alloy-eips = { git = "https://github.com/alloy-rs/alloy", rev = "785c667" }
alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "975a52a" }
alloy-rpc-trace-types = { git = "https://github.com/alloy-rs/alloy", rev = "975a52a" }
alloy-rpc-engine-types = { git = "https://github.com/alloy-rs/alloy", rev = "975a52a" }
alloy-genesis = { git = "https://github.com/alloy-rs/alloy", rev = "975a52a" }
alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy", rev = "975a52a" }
alloy-eips = { git = "https://github.com/alloy-rs/alloy", rev = "975a52a" }
ethers-core = { version = "2.0", default-features = false }
ethers-providers = { version = "2.0", default-features = false }
ethers-signers = { version = "2.0", default-features = false }

View File

@ -2,7 +2,11 @@ use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use reth_primitives::{BlockId, Bytes, B256};
use reth_rpc_types::{
state::StateOverride,
trace::{filter::TraceFilter, parity::*},
trace::{
filter::TraceFilter,
opcode::{BlockOpcodeGas, TransactionOpcodeGas},
parity::*,
},
BlockOverrides, Index, TransactionRequest,
};
use std::collections::HashSet;
@ -91,4 +95,18 @@ pub trait TraceApi {
&self,
hash: B256,
) -> RpcResult<Option<Vec<LocalizedTransactionTrace>>>;
/// Returns all opcodes with their count and combined gas usage for the given transaction in no
/// particular order.
#[method(name = "transactionOpcodeGas")]
async fn trace_transaction_opcode_gas(
&self,
tx_hash: B256,
) -> RpcResult<Option<TransactionOpcodeGas>>;
/// Returns the opcodes of all transactions in the given block.
///
/// This is the same as `trace_transactionOpcodeGas` but for all transactions in a block.
#[method(name = "blockOpcodeGas")]
async fn trace_block_opcode_gas(&self, block_id: BlockId) -> RpcResult<Option<BlockOpcodeGas>>;
}

View File

@ -18,7 +18,12 @@ use reth_revm::{
use reth_rpc_api::TraceApiServer;
use reth_rpc_types::{
state::StateOverride,
trace::{filter::TraceFilter, parity::*, tracerequest::TraceCallRequest},
trace::{
filter::TraceFilter,
opcode::{BlockOpcodeGas, TransactionOpcodeGas},
parity::*,
tracerequest::TraceCallRequest,
},
BlockError, BlockOverrides, Index, TransactionRequest,
};
use reth_tasks::pool::BlockingTaskGuard;
@ -26,6 +31,7 @@ use revm::{
db::{CacheDB, DatabaseCommit},
primitives::EnvWithHandlerCfg,
};
use revm_inspectors::opcode::OpcodeGasInspector;
use std::{collections::HashSet, sync::Arc};
use tokio::sync::{AcquireError, OwnedSemaphorePermit};
@ -417,6 +423,63 @@ where
)
.await
}
/// Returns all opcodes with their count and combined gas usage for the given transaction in no
/// particular order.
pub async fn trace_transaction_opcode_gas(
&self,
tx_hash: B256,
) -> EthResult<Option<TransactionOpcodeGas>> {
self.inner
.eth_api
.spawn_trace_transaction_in_block_with_inspector(
tx_hash,
OpcodeGasInspector::default(),
move |_tx_info, inspector, _res, _| {
let trace = TransactionOpcodeGas {
transaction_hash: tx_hash,
opcode_gas: inspector.opcode_gas_iter().collect(),
};
Ok(trace)
},
)
.await
}
/// Returns the opcodes of all transactions in the given block.
///
/// This is the same as [Self::trace_transaction_opcode_gas] but for all transactions in a
/// block.
pub async fn trace_block_opcode_gas(
&self,
block_id: BlockId,
) -> EthResult<Option<BlockOpcodeGas>> {
let res = self
.inner
.eth_api
.trace_block_with_inspector(
block_id,
OpcodeGasInspector::default,
move |tx_info, inspector, _res, _, _| {
let trace = TransactionOpcodeGas {
transaction_hash: tx_info.hash.expect("tx hash is set"),
opcode_gas: inspector.opcode_gas_iter().collect(),
};
Ok(trace)
},
)
.await?;
let Some(transactions) = res else { return Ok(None) };
let Some(block) = self.inner.eth_api.block_by_id(block_id).await? else { return Ok(None) };
Ok(Some(BlockOpcodeGas {
block_hash: block.hash(),
block_number: block.number,
transactions,
}))
}
}
#[async_trait]
@ -521,6 +584,21 @@ where
let _permit = self.acquire_trace_permit().await;
Ok(TraceApi::trace_transaction(self, hash).await?)
}
/// Handler for `trace_transactionOpcodeGas`
async fn trace_transaction_opcode_gas(
&self,
tx_hash: B256,
) -> Result<Option<TransactionOpcodeGas>> {
let _permit = self.acquire_trace_permit().await;
Ok(TraceApi::trace_transaction_opcode_gas(self, tx_hash).await?)
}
/// Handler for `trace_blockOpcodeGas`
async fn trace_block_opcode_gas(&self, block_id: BlockId) -> Result<Option<BlockOpcodeGas>> {
let _permit = self.acquire_trace_permit().await;
Ok(TraceApi::trace_block_opcode_gas(self, block_id).await?)
}
}
impl<Provider, Eth> std::fmt::Debug for TraceApi<Provider, Eth> {