Skip to content

Commit ce4a769

Browse files
authored
Merge branch 'main' into akaladarshi/add-snapshot-sync-status
2 parents d37cc3a + 319793d commit ce4a769

File tree

5 files changed

+88
-53
lines changed

5 files changed

+88
-53
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131

3232
- [#5375](https://github.com/ChainSafe/forest/issues/5375) Add an RNG wrapper that that can be overriden by a reproducible seeded RNG.
3333

34+
- [#5386](https://github.com/ChainSafe/forest/pull/5386) Add support for the `Filecoin.EthTraceTransaction` RPC method.
35+
3436
- [#5383](https://github.com/ChainSafe/forest/pull/5383) Add support for `Filecoin.EthGetFilterChanges` RPC method.
3537

3638
### Changed

src/rpc/methods/eth.rs

+81-53
Original file line numberDiff line numberDiff line change
@@ -2237,7 +2237,7 @@ impl RpcMethod<1> for EthGetTransactionByHash {
22372237
ctx: Ctx<impl Blockstore + Send + Sync + 'static>,
22382238
(tx_hash,): Self::Params,
22392239
) -> Result<Self::Ok, ServerError> {
2240-
get_eth_transaction_by_hash(ctx, tx_hash, None).await
2240+
get_eth_transaction_by_hash(&ctx, &tx_hash, None).await
22412241
}
22422242
}
22432243

@@ -2256,16 +2256,16 @@ impl RpcMethod<2> for EthGetTransactionByHashLimited {
22562256
ctx: Ctx<impl Blockstore + Send + Sync + 'static>,
22572257
(tx_hash, limit): Self::Params,
22582258
) -> Result<Self::Ok, ServerError> {
2259-
get_eth_transaction_by_hash(ctx, tx_hash, Some(limit)).await
2259+
get_eth_transaction_by_hash(&ctx, &tx_hash, Some(limit)).await
22602260
}
22612261
}
22622262

22632263
async fn get_eth_transaction_by_hash(
2264-
ctx: Ctx<impl Blockstore + Send + Sync + 'static>,
2265-
tx_hash: EthHash,
2264+
ctx: &Ctx<impl Blockstore + Send + Sync + 'static>,
2265+
tx_hash: &EthHash,
22662266
limit: Option<ChainEpoch>,
22672267
) -> Result<Option<ApiEthTx>, ServerError> {
2268-
let message_cid = ctx.chain_store().get_mapping(&tx_hash)?.unwrap_or_else(|| {
2268+
let message_cid = ctx.chain_store().get_mapping(tx_hash)?.unwrap_or_else(|| {
22692269
tracing::debug!(
22702270
"could not find transaction hash {} in Ethereum mapping",
22712271
tx_hash
@@ -2289,7 +2289,7 @@ async fn get_eth_transaction_by_hash(
22892289
return_dec: ipld,
22902290
};
22912291

2292-
if let Ok(tx) = new_eth_tx_from_message_lookup(&ctx, &message_lookup, None) {
2292+
if let Ok(tx) = new_eth_tx_from_message_lookup(ctx, &message_lookup, None) {
22932293
return Ok(Some(tx));
22942294
}
22952295
}
@@ -3022,58 +3022,86 @@ impl RpcMethod<1> for EthTraceBlock {
30223022
ctx: Ctx<impl Blockstore + Send + Sync + 'static>,
30233023
(block_param,): Self::Params,
30243024
) -> Result<Self::Ok, ServerError> {
3025-
let ts = tipset_by_ext_block_number_or_hash(ctx.chain_store(), block_param)?;
3026-
3027-
let (state_root, trace) = ctx.state_manager.execution_trace(&ts)?;
3028-
3029-
let state = StateTree::new_from_root(ctx.store_owned(), &state_root)?;
3030-
3031-
let cid = ts.key().cid()?;
3032-
3033-
let block_hash: EthHash = cid.into();
3025+
trace_block(ctx, block_param).await
3026+
}
3027+
}
30343028

3035-
let mut all_traces = vec![];
3036-
let mut msg_idx = 0;
3037-
for ir in trace.into_iter() {
3038-
// ignore messages from system actor
3039-
if ir.msg.from == system::ADDRESS.into() {
3040-
continue;
3029+
async fn trace_block<B: Blockstore + Send + Sync + 'static>(
3030+
ctx: Ctx<B>,
3031+
block_param: ExtBlockNumberOrHash,
3032+
) -> Result<Vec<EthBlockTrace>, ServerError> {
3033+
let ts = tipset_by_ext_block_number_or_hash(ctx.chain_store(), block_param)?;
3034+
let (state_root, trace) = ctx.state_manager.execution_trace(&ts)?;
3035+
let state = StateTree::new_from_root(ctx.store_owned(), &state_root)?;
3036+
let cid = ts.key().cid()?;
3037+
let block_hash: EthHash = cid.into();
3038+
let mut all_traces = vec![];
3039+
let mut msg_idx = 0;
3040+
for ir in trace.into_iter() {
3041+
// ignore messages from system actor
3042+
if ir.msg.from == system::ADDRESS.into() {
3043+
continue;
3044+
}
3045+
msg_idx += 1;
3046+
let tx_hash = EthGetTransactionHashByCid::handle(ctx.clone(), (ir.msg_cid,)).await?;
3047+
let tx_hash = tx_hash
3048+
.with_context(|| format!("cannot find transaction hash for cid {}", ir.msg_cid))?;
3049+
let mut env = trace::base_environment(&state, &ir.msg.from)
3050+
.map_err(|e| format!("when processing message {}: {}", ir.msg_cid, e))?;
3051+
if let Some(execution_trace) = ir.execution_trace {
3052+
trace::build_traces(&mut env, &[], execution_trace)?;
3053+
for trace in env.traces {
3054+
all_traces.push(EthBlockTrace {
3055+
trace: EthTrace {
3056+
r#type: trace.r#type,
3057+
subtraces: trace.subtraces,
3058+
trace_address: trace.trace_address,
3059+
action: trace.action,
3060+
result: trace.result,
3061+
error: trace.error,
3062+
},
3063+
block_hash: block_hash.clone(),
3064+
block_number: ts.epoch(),
3065+
transaction_hash: tx_hash.clone(),
3066+
transaction_position: msg_idx as i64,
3067+
});
30413068
}
3069+
}
3070+
}
3071+
Ok(all_traces)
3072+
}
30423073

3043-
msg_idx += 1;
3044-
3045-
let tx_hash = EthGetTransactionHashByCid::handle(ctx.clone(), (ir.msg_cid,)).await?;
3046-
3047-
let tx_hash = tx_hash
3048-
.with_context(|| format!("cannot find transaction hash for cid {}", ir.msg_cid))?;
3049-
3050-
let mut env = trace::base_environment(&state, &ir.msg.from)
3051-
.map_err(|e| format!("when processing message {}: {}", ir.msg_cid, e))?;
3052-
3053-
if let Some(execution_trace) = ir.execution_trace {
3054-
trace::build_traces(&mut env, &[], execution_trace)?;
3074+
pub enum EthTraceTransaction {}
3075+
impl RpcMethod<1> for EthTraceTransaction {
3076+
const NAME: &'static str = "Filecoin.EthTraceTransaction";
3077+
const NAME_ALIAS: Option<&'static str> = Some("trace_transaction");
3078+
const N_REQUIRED_PARAMS: usize = 1;
3079+
const PARAM_NAMES: [&'static str; 1] = ["txHash"];
3080+
const API_PATHS: ApiPaths = ApiPaths::V1;
3081+
const PERMISSION: Permission = Permission::Read;
3082+
const DESCRIPTION: Option<&'static str> =
3083+
Some("Returns the traces for a specific transaction.");
30553084

3056-
for trace in env.traces {
3057-
all_traces.push(EthBlockTrace {
3058-
trace: EthTrace {
3059-
r#type: trace.r#type,
3060-
subtraces: trace.subtraces,
3061-
trace_address: trace.trace_address,
3062-
action: trace.action,
3063-
result: trace.result,
3064-
error: trace.error,
3065-
},
3066-
3067-
block_hash: block_hash.clone(),
3068-
block_number: ts.epoch(),
3069-
transaction_hash: tx_hash.clone(),
3070-
transaction_position: msg_idx as i64,
3071-
});
3072-
}
3073-
}
3074-
}
3085+
type Params = (String,);
3086+
type Ok = Vec<EthBlockTrace>;
3087+
async fn handle(
3088+
ctx: Ctx<impl Blockstore + Send + Sync + 'static>,
3089+
(tx_hash,): Self::Params,
3090+
) -> Result<Self::Ok, ServerError> {
3091+
let eth_hash = EthHash::from_str(&tx_hash)?;
3092+
let eth_txn = get_eth_transaction_by_hash(&ctx, &eth_hash, None)
3093+
.await?
3094+
.ok_or(ServerError::internal_error("transaction not found", None))?;
30753095

3076-
Ok(all_traces)
3096+
let traces = trace_block(
3097+
ctx,
3098+
ExtBlockNumberOrHash::from_block_number(eth_txn.block_number.0 as i64),
3099+
)
3100+
.await?
3101+
.into_iter()
3102+
.filter(|trace| trace.transaction_hash == eth_hash)
3103+
.collect();
3104+
Ok(traces)
30773105
}
30783106
}
30793107

src/rpc/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ macro_rules! for_each_rpc_method {
111111
$callback!($crate::rpc::eth::EthUninstallFilter);
112112
$callback!($crate::rpc::eth::EthSyncing);
113113
$callback!($crate::rpc::eth::EthTraceBlock);
114+
$callback!($crate::rpc::eth::EthTraceTransaction);
114115
$callback!($crate::rpc::eth::EthTraceReplayBlockTransactions);
115116
$callback!($crate::rpc::eth::Web3ClientVersion);
116117
$callback!($crate::rpc::eth::EthSendRawTransaction);

src/tool/subcommands/api_cmd/api_compare_tests.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1735,6 +1735,9 @@ fn eth_state_tests_with_tipset<DB: Blockstore>(
17351735
tests.push(RpcTest::identity(EthGetTransactionByHashLimited::request(
17361736
(tx.hash.clone(), shared_tipset.epoch()),
17371737
)?));
1738+
tests.push(RpcTest::identity(
1739+
EthTraceTransaction::request((tx.hash.to_string(),)).unwrap(),
1740+
));
17381741
if smsg.message.from.protocol() == Protocol::Delegated
17391742
&& smsg.message.to.protocol() == Protocol::Delegated
17401743
{

src/tool/subcommands/api_cmd/test_snapshots.txt

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ filecoin_ethgettransactionreceiptlimited_1741272955611272.rpcsnap.json.zst
4848
filecoin_ethprotocolversion_1737446676698826.rpcsnap.json.zst
4949
filecoin_ethtraceblock_1737446676736475.rpcsnap.json.zst
5050
filecoin_ethtracereplayblocktransactions_1740132538658376.rpcsnap.json.zst
51+
filecoin_ethtracetransaction_1741765677273941.rpcsnap.json.zst
5152
filecoin_ethuninstallfilter_1737446676698857.rpcsnap.json.zst
5253
filecoin_minergetbaseinfo_1737022538680883.rpcsnap.json.zst
5354
filecoin_minergetbaseinfo_1737022538681402.rpcsnap.json.zst

0 commit comments

Comments
 (0)