Skip to content

Commit

Permalink
get trace from pending block tx
Browse files Browse the repository at this point in the history
  • Loading branch information
kariy committed Sep 30, 2024
1 parent 7ef1d2c commit 8dbc84d
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 6 deletions.
19 changes: 16 additions & 3 deletions crates/katana/rpc/rpc/src/starknet/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,21 @@ impl<EF: ExecutorFactory> StarknetApi<EF> {

fn trace(&self, tx_hash: TxHash) -> Result<TransactionTrace, StarknetApiError> {
use StarknetApiError::TxnHashNotFound;

// Check in the pending block first
if let Some(state) = self.pending_executor() {
let pending_block = state.read();
let tx = pending_block.transactions().iter().find(|(t, _)| t.hash == tx_hash);

if let Some(trace) = tx.and_then(|(_, res)| res.trace()) {
return Ok(to_rpc_trace(trace.clone()));
}
}

// If not found in pending block, fallback to the provider
let provider = self.inner.backend.blockchain.provider();
let trace = provider.transaction_execution(tx_hash)?.ok_or(TxnHashNotFound)?;

Ok(to_rpc_trace(trace))
}
}
Expand Down Expand Up @@ -220,28 +233,28 @@ fn to_rpc_trace(trace: TxExecInfo) -> TransactionTrace {
};

TransactionTrace::Invoke(InvokeTransactionTrace {
execution_resources: execution_resources.clone(),
fee_transfer_invocation,
execution_resources,
validate_invocation,
execute_invocation,
state_diff,
})
}

TxType::Declare => TransactionTrace::Declare(DeclareTransactionTrace {
execution_resources: execution_resources.clone(),
fee_transfer_invocation,
validate_invocation,
execution_resources,
state_diff,
}),

TxType::DeployAccount => {
let constructor_invocation = execute_invocation.expect("should exist if not reverted");
TransactionTrace::DeployAccount(DeployAccountTransactionTrace {
execution_resources: execution_resources.clone(),
fee_transfer_invocation,
constructor_invocation,
validate_invocation,
execution_resources,
state_diff,
})
}
Expand Down
32 changes: 29 additions & 3 deletions crates/katana/rpc/rpc/tests/starknet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,11 +759,15 @@ async fn get_events_with_pending() -> Result<()> {

#[tokio::test]
async fn trace() -> Result<()> {
let sequencer =
TestSequencer::start(SequencerConfig::default(), get_default_test_starknet_config()).await;
let sequencer = TestSequencer::start(
SequencerConfig { no_mining: true, ..Default::default() },
get_default_test_starknet_config(),
)
.await;

let provider = sequencer.provider();
let account = sequencer.account();
let rpc_client = HttpClientBuilder::default().build(sequencer.url())?;

// setup contract to interact with (can be any existing contract that can be interacted with)
let contract = Erc20Contract::new(DEFAULT_FEE_TOKEN_ADDRESS.into(), &account);
Expand All @@ -772,6 +776,28 @@ async fn trace() -> Result<()> {
let recipient = felt!("0x1");
let amount = Uint256 { low: felt!("0x1"), high: Felt::ZERO };

// -----------------------------------------------------------------------
// Transactions not in pending block

let mut hashes = Vec::new();

for _ in 0..2 {
let res = contract.transfer(&recipient, &amount).send().await?;
dojo_utils::TransactionWaiter::new(res.transaction_hash, &provider).await?;
hashes.push(res.transaction_hash);
}

// Generate a block to include the transactions. The generated block will have block number 1.
rpc_client.generate_block().await?;

for hash in hashes {
let trace = provider.trace_transaction(hash).await?;
assert_matches!(trace, TransactionTrace::Invoke(_));
}

// -----------------------------------------------------------------------
// Transactions in pending block

for _ in 0..2 {
let res = contract.transfer(&recipient, &amount).send().await?;
dojo_utils::TransactionWaiter::new(res.transaction_hash, &provider).await?;
Expand All @@ -793,10 +819,10 @@ async fn block_traces() -> Result<()> {

let provider = sequencer.provider();
let account = sequencer.account();
let rpc_client = HttpClientBuilder::default().build(sequencer.url())?;

// setup contract to interact with (can be any existing contract that can be interacted with)
let contract = Erc20Contract::new(DEFAULT_FEE_TOKEN_ADDRESS.into(), &account);
let rpc_client = HttpClientBuilder::default().build(sequencer.url())?;

// setup contract function params
let recipient = felt!("0x1");
Expand Down

0 comments on commit 8dbc84d

Please sign in to comment.