Skip to content

Commit 8903afe

Browse files
committed
wip
1 parent ccffa17 commit 8903afe

File tree

3 files changed

+156
-26
lines changed

3 files changed

+156
-26
lines changed

crates/rpc/src/ctx/full.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ use trevm::{helpers::Ctx, revm::Inspector};
1818
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1919
#[repr(i8)]
2020
pub enum LoadState {
21+
/// Load the state before the block's transactions (i.e. at the start of
22+
/// the block).
2123
Before = -1,
24+
/// Load the state after the block's transactions (i.e. at the end of the
25+
/// block).
2226
After = 0,
2327
}
2428

crates/rpc/src/debug/endpoints.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ use crate::{
33
utils::{await_handler, response_tri},
44
};
55
use ajj::{HandlerCtx, ResponsePayload};
6-
use alloy::primitives::B256;
6+
use alloy::{consensus::BlockHeader, primitives::B256};
77
use itertools::Itertools;
88
use reth::rpc::{
99
server_types::eth::EthApiError,
10-
types::trace::geth::{GethDebugTracingOptions, GethTrace},
10+
types::{
11+
TransactionInfo,
12+
trace::geth::{GethDebugTracingOptions, GethTrace},
13+
},
1114
};
1215
use reth_node_api::FullNodeComponents;
1316
use signet_evm::EvmErrored;
1417
use signet_node_types::Pnt;
18+
use signet_types::MagicSig;
1519

1620
// /// Params for the `debug_traceBlockByNumber` and `debug_traceBlockByHash`
1721
// /// endpoints.
@@ -60,11 +64,13 @@ where
6064
Signet: Pnt,
6165
{
6266
let fut = async move {
67+
// Load the transaction by hash
6368
let (tx, meta) = response_tri!(
6469
response_tri!(ctx.signet().raw_transaction_by_hash(tx_hash))
6570
.ok_or(EthApiError::TransactionNotFound)
6671
);
6772

73+
// Load the block containing the transaction
6874
let res = response_tri!(ctx.signet().raw_block(meta.block_hash).await);
6975
let (_, block) =
7076
response_tri!(res.ok_or_else(|| EthApiError::HeaderNotFound(meta.block_hash.into())));
@@ -74,17 +80,34 @@ where
7480
ctx.trevm(crate::LoadState::Before, block.header()).map_err(EthApiError::from)
7581
);
7682

77-
let mut txns = block.body().transactions().peekable();
83+
// Apply all transactions in the block up to (but not including) the
84+
// target one
85+
// TODO: check if the tx signature is a magic sig, and abort if so.
86+
let mut txns = block.body().transactions().enumerate().peekable();
87+
for (_idx, tx) in txns.by_ref().peeking_take_while(|(_, t)| t.hash() != tx.hash()) {
88+
if MagicSig::try_from_signature(tx.signature()).is_some() {
89+
return ResponsePayload::internal_error_message(
90+
EthApiError::TransactionNotFound.to_string().into(),
91+
);
92+
}
7893

79-
for tx in txns.by_ref().peeking_take_while(|t| t.hash() != tx.hash()) {
80-
// Apply all transactions before the target one
8194
trevm = response_tri!(trevm.run_tx(tx).map_err(EvmErrored::into_error)).accept_state();
8295
}
8396

84-
let tx = response_tri!(txns.next().ok_or(EthApiError::TransactionNotFound));
97+
let (index, tx) = response_tri!(txns.next().ok_or(EthApiError::TransactionNotFound));
98+
8599
let trevm = trevm.fill_tx(tx);
86100

87-
let res = response_tri!(crate::debug::tracer::trace(trevm, &opts.unwrap_or_default()));
101+
let tx_info = TransactionInfo {
102+
hash: Some(*tx.hash()),
103+
index: Some(index as u64),
104+
block_hash: Some(block.hash()),
105+
block_number: Some(block.header().number()),
106+
base_fee: block.header().base_fee_per_gas(),
107+
};
108+
109+
let res =
110+
response_tri!(crate::debug::tracer::trace(trevm, &opts.unwrap_or_default(), tx_info)).0;
88111

89112
ResponsePayload::Success(res)
90113
};

crates/rpc/src/debug/tracer.rs

Lines changed: 122 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
use crate::DebugError;
2-
use reth::rpc::{
3-
server_types::eth::EthApiError,
4-
types::trace::geth::{
5-
FourByteFrame, GethDebugBuiltInTracerType, GethDebugTracerConfig, GethDebugTracerType,
6-
GethDebugTracingOptions, GethTrace,
2+
use reth::{
3+
revm::{DatabaseRef, context::ContextTr},
4+
rpc::{
5+
server_types::eth::EthApiError,
6+
types::{
7+
TransactionInfo,
8+
trace::geth::{
9+
FourByteFrame, GethDebugBuiltInTracerType, GethDebugTracerConfig,
10+
GethDebugTracerType, GethDebugTracingOptions, GethTrace,
11+
},
12+
},
713
},
814
};
915
use revm_inspectors::tracing::{FourByteInspector, TracingInspector, TracingInspectorConfig};
10-
use signet_evm::EvmReady;
16+
use signet_evm::{EvmNeedsTx, EvmReady};
1117
use trevm::{
1218
helpers::Ctx,
1319
revm::{Database, DatabaseCommit, Inspector},
1420
};
1521

16-
pub(super) fn trace<Db: Database, Insp: Inspector<Ctx<Db>>>(
22+
pub(super) fn trace<Db, Insp>(
1723
trevm: EvmReady<Db, Insp>,
1824
config: &GethDebugTracingOptions,
19-
) -> Result<GethTrace, DebugError> {
25+
tx_info: TransactionInfo,
26+
) -> Result<(GethTrace, EvmNeedsTx<Db, Insp>), DebugError>
27+
where
28+
Db: Database + DatabaseCommit + DatabaseRef,
29+
Insp: Inspector<Ctx<Db>>,
30+
{
2031
let Some(tracer) = &config.tracer else { todo!() };
2132

2233
let GethDebugTracerType::BuiltInTracer(built_in) = tracer else {
@@ -28,41 +39,133 @@ pub(super) fn trace<Db: Database, Insp: Inspector<Ctx<Db>>>(
2839
GethDebugBuiltInTracerType::CallTracer => {
2940
trace_call(&config.tracer_config, trevm).map_err(Into::into)
3041
}
31-
GethDebugBuiltInTracerType::FlatCallTracer => todo!(),
32-
GethDebugBuiltInTracerType::PreStateTracer => todo!(),
33-
GethDebugBuiltInTracerType::NoopTracer => todo!(),
42+
GethDebugBuiltInTracerType::FlatCallTracer => {
43+
trace_flat_call(&config.tracer_config, trevm, tx_info).map_err(Into::into)
44+
}
45+
GethDebugBuiltInTracerType::PreStateTracer => {
46+
trace_pre_state(&config.tracer_config, trevm).map_err(Into::into)
47+
}
48+
GethDebugBuiltInTracerType::NoopTracer => Ok((
49+
Default::default(),
50+
trevm
51+
.run()
52+
.map_err(|err| EthApiError::EvmCustom(err.into_error().to_string()))?
53+
.accept_state(),
54+
)),
3455
GethDebugBuiltInTracerType::MuxTracer => todo!(),
3556
}
3657
}
3758

38-
fn trace_four_byte<Db: Database + DatabaseCommit, Insp: Inspector<Ctx<Db>>>(
59+
/// Traces a call using [`GethDebugBuiltInTracerType::FourByteTracer`].
60+
fn trace_four_byte<Db, Insp>(
3961
trevm: EvmReady<Db, Insp>,
40-
) -> Result<GethTrace, EthApiError> {
62+
) -> Result<(GethTrace, EvmNeedsTx<Db, Insp>), EthApiError>
63+
where
64+
Db: Database + DatabaseCommit,
65+
Insp: Inspector<Ctx<Db>>,
66+
{
4167
let mut four_byte = FourByteInspector::default();
4268

4369
let trevm = trevm.try_with_inspector(&mut four_byte, |trevm| trevm.run());
4470

4571
let trevm = trevm.map_err(|e| EthApiError::EvmCustom(e.into_error().to_string()))?;
4672

47-
trevm.accept_state();
48-
49-
Ok(FourByteFrame::from(four_byte).into())
73+
Ok((FourByteFrame::from(four_byte).into(), trevm.accept_state()))
5074
}
5175

52-
fn trace_call<Db: Database, Insp: Inspector<Ctx<Db>>>(
76+
/// Traces a call using [`GethDebugBuiltInTracerType::CallTracer`].
77+
fn trace_call<Db, Insp>(
5378
tracer_config: &GethDebugTracerConfig,
5479
trevm: EvmReady<Db, Insp>,
55-
) -> Result<GethTrace, EthApiError> {
80+
) -> Result<(GethTrace, EvmNeedsTx<Db, Insp>), EthApiError>
81+
where
82+
Db: Database + DatabaseCommit,
83+
Insp: Inspector<Ctx<Db>>,
84+
{
5685
let call_config =
5786
tracer_config.clone().into_call_config().map_err(|_| EthApiError::InvalidTracerConfig)?;
87+
5888
let mut inspector =
5989
TracingInspector::new(TracingInspectorConfig::from_geth_call_config(&call_config));
6090

6191
let trevm = trevm.try_with_inspector(&mut inspector, |trevm| trevm.run());
6292

6393
let trevm = trevm.map_err(|e| EthApiError::EvmCustom(e.into_error().to_string()))?;
6494

65-
inspector.set_transaction_gas_limit(trevm.gas_limit());
95+
let frame = inspector
96+
.with_transaction_gas_limit(trevm.gas_limit())
97+
.into_geth_builder()
98+
.geth_call_traces(call_config, trevm.gas_used());
99+
100+
Ok((frame.into(), trevm.accept_state()))
101+
}
102+
103+
/// Traces a call using [`GethDebugBuiltInTracerType::PreStateTracer`]
104+
fn trace_pre_state<Db, Insp>(
105+
tracer_config: &GethDebugTracerConfig,
106+
trevm: EvmReady<Db, Insp>,
107+
) -> Result<(GethTrace, EvmNeedsTx<Db, Insp>), EthApiError>
108+
where
109+
Db: Database + DatabaseCommit + DatabaseRef,
110+
Insp: Inspector<Ctx<Db>>,
111+
{
112+
let prestate_config = tracer_config
113+
.clone()
114+
.into_pre_state_config()
115+
.map_err(|_| EthApiError::InvalidTracerConfig)?;
116+
117+
let mut inspector =
118+
TracingInspector::new(TracingInspectorConfig::from_geth_prestate_config(&prestate_config));
119+
120+
let trevm = trevm.try_with_inspector(&mut inspector, |trevm| trevm.run());
121+
122+
let trevm = trevm.map_err(|e| EthApiError::EvmCustom(e.into_error().to_string()))?;
123+
let gas_limit = trevm.gas_limit();
124+
125+
// NB: Normally we would call `trevm.accept_state()` here, but we need the
126+
// state after execution to be UNCOMMITED when we compute the prestate
127+
// diffs.
128+
let (result, mut trevm) = trevm.take_result_and_state();
129+
130+
let frame = inspector
131+
.with_transaction_gas_limit(gas_limit)
132+
.into_geth_builder()
133+
.geth_prestate_traces(&result, &prestate_config, trevm.inner_mut_unchecked().db_mut())
134+
.map_err(|err| EthApiError::EvmCustom(err.to_string()))?;
135+
136+
// This is equivalent to calling `trevm.accept_state()`.
137+
trevm.inner_mut_unchecked().db_mut().commit(result.state);
138+
139+
Ok((frame.into(), trevm))
140+
}
141+
142+
fn trace_flat_call<Db, Insp>(
143+
tracer_config: &GethDebugTracerConfig,
144+
trevm: EvmReady<Db, Insp>,
145+
tx_info: TransactionInfo,
146+
) -> Result<(GethTrace, EvmNeedsTx<Db, Insp>), EthApiError>
147+
where
148+
Db: Database + DatabaseCommit,
149+
Insp: Inspector<Ctx<Db>>,
150+
{
151+
let flat_call_config = tracer_config
152+
.clone()
153+
.into_flat_call_config()
154+
.map_err(|_| EthApiError::InvalidTracerConfig)?;
155+
156+
let mut inspector =
157+
TracingInspector::new(TracingInspectorConfig::from_flat_call_config(&flat_call_config));
158+
159+
let trevm = trevm.try_with_inspector(&mut inspector, |trevm| trevm.run());
160+
161+
let trevm = trevm.map_err(|e| EthApiError::EvmCustom(e.into_error().to_string()))?;
162+
163+
let frame = inspector
164+
.with_transaction_gas_limit(trevm.gas_limit())
165+
.into_parity_builder()
166+
.into_localized_transaction_traces(tx_info);
167+
168+
Ok((frame.into(), trevm.accept_state()))
66169
}
67170

68171
// Some code in this file has been copied and modified from reth

0 commit comments

Comments
 (0)