From d28923916fc25254455c4c7225d42048180c9154 Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 25 Sep 2023 14:34:02 +0400 Subject: [PATCH] Update trace api according to spec v0.5.0 (#1230) --- rpc/handlers.go | 16 ++++--- rpc/handlers_test.go | 8 ++-- vm/rust/src/jsonrpc.rs | 101 +++++++++++++++++++++++++---------------- 3 files changed, 75 insertions(+), 50 deletions(-) diff --git a/rpc/handlers.go b/rpc/handlers.go index b15a5af970..8e56320310 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -1244,15 +1244,19 @@ func (h *Handler) SimulateTransactions(id BlockID, transactions []BroadcastedTra return result, nil } -func (h *Handler) TraceBlockTransactions(blockHash felt.Felt) ([]TracedBlockTransaction, *jsonrpc.Error) { - block, err := h.bcReader.BlockByHash(&blockHash) - if err != nil { - return nil, ErrInvalidBlockHash +func (h *Handler) TraceBlockTransactions(id BlockID) ([]TracedBlockTransaction, *jsonrpc.Error) { + block, err := h.blockByID(&id) + if block == nil || err != nil { + return nil, ErrBlockNotFound } return h.traceBlockTransactions(block, len(block.Transactions)) } +func (h *Handler) LegacyTraceBlockTransactions(hash felt.Felt) ([]TracedBlockTransaction, *jsonrpc.Error) { + return h.TraceBlockTransactions(BlockID{Hash: &hash}) +} + func (h *Handler) traceBlockTransactions(block *core.Block, numTxns int) ([]TracedBlockTransaction, *jsonrpc.Error) { isPending := block.Hash == nil @@ -1473,7 +1477,7 @@ func (h *Handler) Methods() ([]jsonrpc.Method, string) { //nolint: funlen }, { Name: "starknet_traceBlockTransactions", - Params: []jsonrpc.Parameter{{Name: "block_hash"}}, + Params: []jsonrpc.Parameter{{Name: "block_id"}}, Handler: h.TraceBlockTransactions, }, { @@ -1622,7 +1626,7 @@ func (h *Handler) LegacyMethods() ([]jsonrpc.Method, string) { //nolint: funlen { Name: "starknet_traceBlockTransactions", Params: []jsonrpc.Parameter{{Name: "block_hash"}}, - Handler: h.TraceBlockTransactions, + Handler: h.LegacyTraceBlockTransactions, }, }, "/v0_4" } diff --git a/rpc/handlers_test.go b/rpc/handlers_test.go index ff87f1e6d0..f40e07c095 100644 --- a/rpc/handlers_test.go +++ b/rpc/handlers_test.go @@ -2163,8 +2163,8 @@ func TestTraceBlockTransactions(t *testing.T) { blockHash := utils.HexToFelt(t, "0x0001") mockReader.EXPECT().BlockByHash(blockHash).Return(nil, errors.New("some new err")) - result, err := handler.TraceBlockTransactions(*blockHash) - require.Equal(t, rpc.ErrInvalidBlockHash, err) + result, err := handler.TraceBlockTransactions(rpc.BlockID{Hash: blockHash}) + require.Equal(t, rpc.ErrBlockNotFound, err) assert.Nil(t, result) }) t.Run("pending block", func(t *testing.T) { @@ -2210,7 +2210,7 @@ func TestTraceBlockTransactions(t *testing.T) { mockVM.EXPECT().Execute(block.Transactions, []core.Class{declaredClass.Class}, height+1, header.Timestamp, sequencerAddress, state, network, paidL1Fees, false, header.GasPrice).Return(nil, []json.RawMessage{vmTrace, vmTrace}, nil) - result, err := handler.TraceBlockTransactions(*blockHash) + result, err := handler.TraceBlockTransactions(rpc.BlockID{Hash: blockHash}) require.Nil(t, err) assert.Equal(t, vmTrace, result[0].TraceRoot) assert.Equal(t, l1Tx.TransactionHash, result[0].TransactionHash) @@ -2259,7 +2259,7 @@ func TestTraceBlockTransactions(t *testing.T) { TraceRoot: vmTrace, }, } - result, err := handler.TraceBlockTransactions(*blockHash) + result, err := handler.TraceBlockTransactions(rpc.BlockID{Hash: blockHash}) require.Nil(t, err) assert.Equal(t, expectedResult, result) }) diff --git a/vm/rust/src/jsonrpc.rs b/vm/rust/src/jsonrpc.rs index 676ce003a7..f521029809 100644 --- a/vm/rust/src/jsonrpc.rs +++ b/vm/rust/src/jsonrpc.rs @@ -8,28 +8,43 @@ use starknet_api::transaction::{Calldata, EthAddress, EventContent, L2ToL1Payloa use starknet_api::transaction::{Transaction as StarknetApiTransaction}; #[derive(Serialize)] -#[serde(untagged)] -pub enum TransactionTrace { - // used for INVOKE_TXN_TRACE and DECLARE_TXN_TRACE - Common { - #[serde(skip_serializing_if = "Option::is_none")] - validate_invocation: Option, - #[serde(skip_serializing_if = "Option::is_none")] - execute_invocation: Option, - #[serde(skip_serializing_if = "Option::is_none")] - fee_transfer_invocation: Option, - }, - DeployAccount { - #[serde(skip_serializing_if = "Option::is_none")] - validate_invocation: Option, - #[serde(skip_serializing_if = "Option::is_none")] - constructor_invocation: Option, - #[serde(skip_serializing_if = "Option::is_none")] - fee_transfer_invocation: Option, - }, - L1Handler { - #[serde(skip_serializing_if = "Option::is_none")] - function_invocation: Option +#[serde(rename_all = "UPPERCASE")] +pub enum TransactionType { + // dummy type for implementing Default trait + Unknown, + Invoke, + Declare, + #[serde(rename = "DEPLOY_ACCOUNT")] + DeployAccount, + #[serde(rename = "L1_HANDLER")] + L1Handler, +} + +#[derive(Serialize)] +pub struct TransactionTrace { + #[serde(skip_serializing_if = "Option::is_none")] + validate_invocation: Option, + #[serde(skip_serializing_if = "Option::is_none")] + execute_invocation: Option, + #[serde(skip_serializing_if = "Option::is_none")] + fee_transfer_invocation: Option, + #[serde(skip_serializing_if = "Option::is_none")] + constructor_invocation: Option, + #[serde(skip_serializing_if = "Option::is_none")] + function_invocation: Option, + r#type: TransactionType, +} + +impl Default for TransactionTrace { + fn default() -> Self { + Self { + validate_invocation: None, + execute_invocation: None, + fee_transfer_invocation: None, + constructor_invocation: None, + function_invocation: None, + r#type: TransactionType::Unknown, + } } } @@ -44,34 +59,40 @@ pub enum ExecuteInvocation { type BlockifierTxInfo = blockifier::transaction::objects::TransactionExecutionInfo; pub fn new_transaction_trace(tx: StarknetApiTransaction, info: BlockifierTxInfo) -> TransactionTrace { + let mut trace = TransactionTrace::default(); + match tx { StarknetApiTransaction::L1Handler(_) => { - TransactionTrace::L1Handler { - function_invocation: info.execute_call_info.map(|v| v.into()), - } + trace.function_invocation = info.execute_call_info.map(|v| v.into()); + trace.r#type = TransactionType::L1Handler; }, StarknetApiTransaction::DeployAccount(_) => { - TransactionTrace::DeployAccount { - validate_invocation: info.validate_call_info.map(|v| v.into()), - constructor_invocation: info.execute_call_info.map(|v| v.into()), - fee_transfer_invocation: info.fee_transfer_call_info.map(|v| v.into()), - } + trace.validate_invocation = info.validate_call_info.map(|v| v.into()); + trace.constructor_invocation = info.execute_call_info.map(|v| v.into()); + trace.fee_transfer_invocation = info.fee_transfer_call_info.map(|v| v.into()); + trace.r#type = TransactionType::DeployAccount; }, - StarknetApiTransaction::Declare(_) | StarknetApiTransaction::Invoke(_) => { - TransactionTrace::Common { - validate_invocation: info.validate_call_info.map(|v| v.into()), - execute_invocation: match info.revert_error { - Some(str) => Some(ExecuteInvocation::Revert{revert_reason: str}), - None => info.execute_call_info.map(|v| ExecuteInvocation::Ok(v.into())), - }, - fee_transfer_invocation: info.fee_transfer_call_info.map(|v| v.into()), - } + StarknetApiTransaction::Invoke(_) => { + trace.validate_invocation = info.validate_call_info.map(|v| v.into()); + trace.execute_invocation = match info.revert_error { + Some(str) => Some(ExecuteInvocation::Revert{revert_reason: str}), + None => info.execute_call_info.map(|v| ExecuteInvocation::Ok(v.into())), + }; + trace.fee_transfer_invocation = info.fee_transfer_call_info.map(|v| v.into()); + trace.r#type = TransactionType::Invoke; + }, + StarknetApiTransaction::Declare(_) => { + trace.validate_invocation = info.validate_call_info.map(|v| v.into()); + trace.fee_transfer_invocation = info.fee_transfer_call_info.map(|v| v.into()); + trace.r#type = TransactionType::Declare; }, StarknetApiTransaction::Deploy(_) => { // shouldn't happen since we don't support deploy panic!("Can't create transaction trace for deploy transaction (unsupported)"); } - } + }; + + trace } #[derive(Serialize)]