Skip to content

Commit 552f47c

Browse files
authored
feat: upstream trace formatting from Foundry (#38)
Will need a follow-up to add the "decoded" fields. Ref #14
1 parent e564191 commit 552f47c

File tree

11 files changed

+564
-52
lines changed

11 files changed

+564
-52
lines changed

Cargo.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ alloy-sol-types = "0.6"
2525
alloy-primitives = "0.6"
2626
alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "b9dd518" }
2727
alloy-rpc-trace-types = { git = "https://github.com/alloy-rs/alloy", rev = "b9dd518" }
28-
29-
# revm
3028
revm = { version = "5.0", default-features = false, features = ["std"] }
3129

30+
anstyle = "1.0"
31+
colorchoice = "1.0"
32+
3233
# js-tracing-inspector
3334
boa_engine = { version = "0.17", optional = true }
3435
boa_gc = { version = "0.17", optional = true }
@@ -37,6 +38,8 @@ serde = { version = "1", features = ["derive"] }
3738
thiserror = { version = "1", optional = true }
3839
serde_json = { version = "1", optional = true }
3940

41+
[dev-dependencies]
42+
expect-test = "1.4"
43+
4044
[features]
41-
default = []
4245
js-tracer = ["boa_engine", "boa_gc", "thiserror", "serde_json"]

src/lib.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@
1111
html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
1212
issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
1313
)]
14-
#![warn(
15-
missing_copy_implementations,
16-
missing_debug_implementations,
17-
missing_docs,
18-
unreachable_pub,
19-
clippy::missing_const_for_fn,
20-
rustdoc::all
21-
)]
2214
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
2315
#![deny(unused_must_use, rust_2018_idioms)]
2416
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
@@ -28,9 +20,13 @@ pub mod access_list;
2820

2921
/// implementation of an opcode counter for the EVM.
3022
pub mod opcode;
23+
3124
/// An inspector stack abstracting the implementation details of
3225
/// each inspector and allowing to hook on block/transaction execution,
3326
/// used in the main RETH executor.
3427
pub mod stack;
28+
3529
/// An inspector for recording traces
3630
pub mod tracing;
31+
32+
pub use colorchoice::ColorChoice;

src/tracing/builder/walker.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
use crate::tracing::types::CallTraceNode;
22
use std::collections::VecDeque;
33

4-
/// Traverses Reths internal tracing structure breadth-first
4+
/// Traverses the internal tracing structure breadth-first.
55
///
6-
/// This is a lazy iterator
6+
/// This is a lazy iterator.
77
pub(crate) struct CallTraceNodeWalkerBF<'trace> {
8-
/// the entire arena
8+
/// The entire arena.
99
nodes: &'trace Vec<CallTraceNode>,
10-
11-
/// holds indexes of nodes to visit as we traverse
10+
/// Indexes of nodes to visit as we traverse.
1211
queue: VecDeque<usize>,
1312
}
1413

1514
impl<'trace> CallTraceNodeWalkerBF<'trace> {
1615
pub(crate) fn new(nodes: &'trace Vec<CallTraceNode>) -> Self {
1716
let mut queue = VecDeque::with_capacity(nodes.len());
1817
queue.push_back(0);
19-
2018
Self { nodes, queue }
2119
}
2220
}
@@ -25,15 +23,10 @@ impl<'trace> Iterator for CallTraceNodeWalkerBF<'trace> {
2523
type Item = &'trace CallTraceNode;
2624

2725
fn next(&mut self) -> Option<Self::Item> {
28-
match self.queue.pop_front() {
29-
Some(idx) => {
30-
let curr = self.nodes.get(idx).expect("there should be a node");
31-
32-
self.queue.extend(curr.children.iter());
33-
34-
Some(curr)
35-
}
36-
None => None,
37-
}
26+
self.queue.pop_front().map(|idx| {
27+
let curr = &self.nodes[idx];
28+
self.queue.extend(curr.children.iter().copied());
29+
curr
30+
})
3831
}
3932
}

src/tracing/mod.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::ops::Range;
2-
31
use self::parity::stack_push_count;
42
use crate::tracing::{
53
arena::PushTraceKind,
@@ -18,25 +16,34 @@ use revm::{
1816
primitives::SpecId,
1917
Database, EvmContext, Inspector, JournalEntry,
2018
};
21-
use types::{CallTrace, CallTraceStep};
19+
use std::ops::Range;
2220

2321
mod arena;
22+
pub use arena::CallTraceArena;
2423

2524
mod builder;
26-
mod config;
27-
mod fourbyte;
28-
mod opcount;
29-
pub mod types;
30-
mod utils;
31-
pub use arena::CallTraceArena;
3225
pub use builder::{
3326
geth::{self, GethTraceBuilder},
3427
parity::{self, ParityTraceBuilder},
3528
};
29+
30+
mod config;
3631
pub use config::{StackSnapshotType, TracingInspectorConfig};
32+
33+
mod fourbyte;
3734
pub use fourbyte::FourByteInspector;
35+
36+
mod opcount;
3837
pub use opcount::OpcodeCountInspector;
3938

39+
pub mod types;
40+
use types::{CallTrace, CallTraceStep};
41+
42+
mod utils;
43+
44+
mod writer;
45+
pub use writer::TraceWriter;
46+
4047
#[cfg(feature = "js-tracer")]
4148
pub mod js;
4249

@@ -391,7 +398,8 @@ impl TracingInspector {
391398

392399
// The gas cost is the difference between the recorded gas remaining at the start of the
393400
// step the remaining gas here, at the end of the step.
394-
step.gas_cost = step.gas_remaining - self.gas_inspector.gas_remaining();
401+
// TODO: Figure out why this can overflow. https://github.com/paradigmxyz/evm-inspectors/pull/38
402+
step.gas_cost = step.gas_remaining.saturating_sub(self.gas_inspector.gas_remaining());
395403

396404
// set the status
397405
step.status = interp.instruction_result;

src/tracing/utils.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,8 @@ pub(crate) fn maybe_revert_reason(output: &[u8]) -> Option<String> {
5454
let reason = match GenericRevertReason::decode(output)? {
5555
GenericRevertReason::ContractError(err) => {
5656
match err {
57-
ContractError::Revert(revert) => {
58-
// return the raw revert reason and don't use the revert's display message
59-
revert.reason
60-
}
57+
// return the raw revert reason and don't use the revert's display message
58+
ContractError::Revert(revert) => revert.reason,
6159
err => err.to_string(),
6260
}
6361
}
@@ -75,12 +73,6 @@ mod tests {
7573
use super::*;
7674
use alloy_sol_types::{GenericContractError, SolInterface};
7775

78-
#[test]
79-
fn decode_empty_revert() {
80-
let reason = GenericRevertReason::decode("".as_bytes()).map(|x| x.to_string());
81-
assert_eq!(reason, Some("".to_string()));
82-
}
83-
8476
#[test]
8577
fn decode_revert_reason() {
8678
let err = GenericContractError::Revert("my revert".into());

0 commit comments

Comments
 (0)