diff --git a/account/account.go b/account/account.go index 99fd2549..1d526f2f 100644 --- a/account/account.go +++ b/account/account.go @@ -404,8 +404,8 @@ func (account *Account) TransactionReceipt(ctx context.Context, transactionHash return account.provider.TransactionReceipt(ctx, transactionHash) } -func (account *Account) TransactionTrace(ctx context.Context, transactionHash *felt.Felt) (rpc.TxnTrace, error) { - return account.provider.TransactionTrace(ctx, transactionHash) +func (account *Account) TraceTransaction(ctx context.Context, transactionHash *felt.Felt) (rpc.TxnTrace, error) { + return account.provider.TraceTransaction(ctx, transactionHash) } func (account *Account) TransactionByBlockIdAndIndex(ctx context.Context, blockID rpc.BlockID, index uint64) (rpc.Transaction, error) { diff --git a/mocks/mock_rpc_provider.go b/mocks/mock_rpc_provider.go index 2421c7e3..d31c760b 100644 --- a/mocks/mock_rpc_provider.go +++ b/mocks/mock_rpc_provider.go @@ -396,6 +396,21 @@ func (mr *MockRpcProviderMockRecorder) TraceBlockTransactions(ctx, blockID inter return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TraceBlockTransactions", reflect.TypeOf((*MockRpcProvider)(nil).TraceBlockTransactions), ctx, blockID) } +// TraceTransaction mocks base method. +func (m *MockRpcProvider) TraceTransaction(ctx context.Context, transactionHash *felt.Felt) (rpc.TxnTrace, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TraceTransaction", ctx, transactionHash) + ret0, _ := ret[0].(rpc.TxnTrace) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// TraceTransaction indicates an expected call of TraceTransaction. +func (mr *MockRpcProviderMockRecorder) TraceTransaction(ctx, transactionHash interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TraceTransaction", reflect.TypeOf((*MockRpcProvider)(nil).TraceTransaction), ctx, transactionHash) +} + // TransactionByBlockIdAndIndex mocks base method. func (m *MockRpcProvider) TransactionByBlockIdAndIndex(ctx context.Context, blockID rpc.BlockID, index uint64) (rpc.Transaction, error) { m.ctrl.T.Helper() @@ -440,18 +455,3 @@ func (mr *MockRpcProviderMockRecorder) TransactionReceipt(ctx, transactionHash i mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionReceipt", reflect.TypeOf((*MockRpcProvider)(nil).TransactionReceipt), ctx, transactionHash) } - -// TransactionTrace mocks base method. -func (m *MockRpcProvider) TransactionTrace(ctx context.Context, transactionHash *felt.Felt) (rpc.TxnTrace, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TransactionTrace", ctx, transactionHash) - ret0, _ := ret[0].(rpc.TxnTrace) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// TransactionTrace indicates an expected call of TransactionTrace. -func (mr *MockRpcProviderMockRecorder) TransactionTrace(ctx, transactionHash interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionTrace", reflect.TypeOf((*MockRpcProvider)(nil).TransactionTrace), ctx, transactionHash) -} diff --git a/rpc/provider.go b/rpc/provider.go index b31bdad4..a3a6249a 100644 --- a/rpc/provider.go +++ b/rpc/provider.go @@ -53,7 +53,7 @@ type RpcProvider interface { TransactionByBlockIdAndIndex(ctx context.Context, blockID BlockID, index uint64) (Transaction, error) TransactionByHash(ctx context.Context, hash *felt.Felt) (Transaction, error) TransactionReceipt(ctx context.Context, transactionHash *felt.Felt) (TransactionReceipt, error) - TransactionTrace(ctx context.Context, transactionHash *felt.Felt) (TxnTrace, error) + TraceTransaction(ctx context.Context, transactionHash *felt.Felt) (TxnTrace, error) } var _ RpcProvider = &Provider{} diff --git a/rpc/tests/trace/0xff66e14fc6a96f3289203690f5f876cb4b608868e8549b5f6a90a21d4d6329.json b/rpc/tests/trace/0xff66e14fc6a96f3289203690f5f876cb4b608868e8549b5f6a90a21d4d6329.json index 9f8edf11..5d6ae2c8 100644 --- a/rpc/tests/trace/0xff66e14fc6a96f3289203690f5f876cb4b608868e8549b5f6a90a21d4d6329.json +++ b/rpc/tests/trace/0xff66e14fc6a96f3289203690f5f876cb4b608868e8549b5f6a90a21d4d6329.json @@ -170,6 +170,7 @@ "calls": [], "events": [ { + "order": 0, "keys": [ "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" ], @@ -287,6 +288,7 @@ "calls": [], "events": [ { + "order": 1, "keys": [ "0x134692b230b9e1ffa39098904722134159652b09c5bc41d88d6698779d228ff" ], @@ -298,6 +300,7 @@ ] }, { + "order": 2, "keys": [ "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" ], @@ -345,6 +348,7 @@ "calls": [], "events": [ { + "order": 3, "keys": [ "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" ], @@ -396,6 +400,7 @@ "calls": [], "events": [ { + "order": 4, "keys": [ "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" ], @@ -424,6 +429,7 @@ ], "events": [ { + "order": 5, "keys": [ "0x5ad857f66a5b55f1301ff1ed7e098ac6d4433148f0b72ebc4a2945ab85ad53" ], @@ -482,6 +488,7 @@ "calls": [], "events": [ { + "order": 0, "keys": [ "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" ], @@ -498,6 +505,77 @@ ], "events": [], "messages": [] + }, + "type": "INVOKE", + "state_diff": { + "storage_diffs": [ + { + "address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "storage_entries": [ + { + "key": "0x49a8ef79cab313360767015d427d0307368eff5c2c81b019aff018ec638eef2", + "value": "0x763b821506b19086e9" + }, + { + "key": "0x625da4622cb73a56b1f10ac489e48b4e8af830a368fb3e21db8b7868c315ff0", + "value": "0x19094ba60d592b" + }, + { + "key": "0x5496768776e3db30053404f18067d81a6e06f5a2b0de326e21298fd9d569a9a", + "value": "0x11e93b002a1d5c717d" + } + ] + }, + { + "address": "0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28", + "storage_entries": [ + { + "key": "0x2487f67598912d31ab84d8fa97c9e78332d00795ecdad092ea09f9c9c14a9a3", + "value": "0x1e226129b7e" + }, + { + "key": "0x2487f67598912d31ab84d8fa97c9e78332d00795ecdad092ea09f9c9c14a9a0", + "value": "0x4477606da4ac2b7bef" + } + ] + }, + { + "address": "0x22b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", + "storage_entries": [ + { + "key": "0x110e2f729c9c2b988559994a3daccd838cf52faf88e18101373e67dd061455a", + "value": "0x7743be9a9d8fae" + }, + { + "key": "0x625da4622cb73a56b1f10ac489e48b4e8af830a368fb3e21db8b7868c315ff0", + "value": "0x631cb839" + } + ] + }, + { + "address": "0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "storage_entries": [ + { + "key": "0x625da4622cb73a56b1f10ac489e48b4e8af830a368fb3e21db8b7868c315ff0", + "value": "0x17fc5" + }, + { + "key": "0x49a8ef79cab313360767015d427d0307368eff5c2c81b019aff018ec638eef2", + "value": "0x257875e1c11" + } + ] + } + ], + "nonces": [ + { + "contract_address": "0x61d862eb8baf0dc8e14159d0dd16abcff933c798ecf252ce81685d74c237516", + "nonce": "0x58" + } + ], + "deployed_contracts": [], + "deprecated_declared_classes": [], + "declared_classes": [], + "replaced_classes": [] } }, "id": 1 diff --git a/rpc/trace.go b/rpc/trace.go index d42d0bbe..66496cef 100644 --- a/rpc/trace.go +++ b/rpc/trace.go @@ -3,12 +3,13 @@ package rpc import ( "context" "encoding/json" + "errors" "github.com/NethermindEth/juno/core/felt" ) // For a given executed transaction, return the trace of its execution, including internal calls -func (provider *Provider) TransactionTrace(ctx context.Context, transactionHash *felt.Felt) (TxnTrace, error) { +func (provider *Provider) TraceTransaction(ctx context.Context, transactionHash *felt.Felt) (TxnTrace, error) { var rawTxnTrace map[string]any if err := do(ctx, provider.c, "starknet_traceTransaction", &rawTxnTrace, transactionHash); err != nil { if noTraceAvailableError, ok := isErrNoTraceAvailableError(err); ok { @@ -22,28 +23,29 @@ func (provider *Provider) TransactionTrace(ctx context.Context, transactionHash return nil, err } - // if execute_invocation exists, then it's an InvokeTxnTrace type - if _, exists := rawTxnTrace["execute_invocation"]; exists { + switch rawTxnTrace["type"] { + case string(TransactionType_Invoke): var trace InvokeTxnTrace err = json.Unmarshal(rawTraceByte, &trace) if err != nil { return nil, err } return trace, nil - } - - // if constructor_invocation exists, then it's a DeployAccountTxnTrace type - if _, exists := rawTxnTrace["constructor_invocation"]; exists { + case string(TransactionType_Declare): + var trace DeclareTxnTrace + err = json.Unmarshal(rawTraceByte, &trace) + if err != nil { + return nil, err + } + return trace, nil + case string(TransactionType_DeployAccount): var trace DeployAccountTxnTrace err = json.Unmarshal(rawTraceByte, &trace) if err != nil { return nil, err } return trace, nil - } - - // if function_invocation exists, then it's an L1HandlerTxnTrace type - if _, exists := rawTxnTrace["function_invocation"]; exists { + case string(TransactionType_L1Handler): var trace L1HandlerTxnTrace err = json.Unmarshal(rawTraceByte, &trace) if err != nil { @@ -51,14 +53,8 @@ func (provider *Provider) TransactionTrace(ctx context.Context, transactionHash } return trace, nil } + return nil, errors.New("Unknown transaction type") - // the other possible choice is for it to be a DeclareTxnTrace type - var trace DeclareTxnTrace - err = json.Unmarshal(rawTraceByte, &trace) - if err != nil { - return nil, err - } - return trace, nil } // Retrieve traces for all transactions in the given block diff --git a/rpc/trace_test.go b/rpc/trace_test.go index 69ed9d51..62b746a6 100644 --- a/rpc/trace_test.go +++ b/rpc/trace_test.go @@ -63,7 +63,7 @@ func TestTransactionTrace(t *testing.T) { }[testEnv] for _, test := range testSet { - resp, err := testConfig.provider.TransactionTrace(context.Background(), test.TransactionHash) + resp, err := testConfig.provider.TraceTransaction(context.Background(), test.TransactionHash) if err != nil { require.Equal(t, test.ExpectedError, err) } else { diff --git a/rpc/types_trace.go b/rpc/types_trace.go index 17447c69..5c84c22a 100644 --- a/rpc/types_trace.go +++ b/rpc/types_trace.go @@ -37,28 +37,35 @@ var _ TxnTrace = L1HandlerTxnTrace{} type InvokeTxnTrace struct { ValidateInvocation FnInvocation `json:"validate_invocation"` //the trace of the __execute__ call or constructor call, depending on the transaction type (none for declare transactions) - ExecuteInvocation FnInvocation `json:"execute_invocation"` - FeeTransferInvocation FnInvocation `json:"fee_transfer_invocation"` + ExecuteInvocation ExecInvocation `json:"execute_invocation"` + FeeTransferInvocation FnInvocation `json:"fee_transfer_invocation"` + StateDiff StateDiff `json:"state_diff"` + Type TransactionType `json:"type"` } // the execution trace of a declare transaction type DeclareTxnTrace struct { - ValidateInvocation FnInvocation `json:"validate_invocation"` - FeeTransferInvocation FnInvocation `json:"fee_transfer_invocation"` + ValidateInvocation FnInvocation `json:"validate_invocation"` + FeeTransferInvocation FnInvocation `json:"fee_transfer_invocation"` + StateDiff StateDiff `json:"state_diff"` + Type TransactionType `json:"type"` } // the execution trace of a deploy account transaction type DeployAccountTxnTrace struct { ValidateInvocation FnInvocation `json:"validate_invocation"` //the trace of the __execute__ call or constructor call, depending on the transaction type (none for declare transactions) - ConstructorInvocation FnInvocation `json:"constructor_invocation"` - FeeTransferInvocation FnInvocation `json:"fee_transfer_invocation"` + ConstructorInvocation FnInvocation `json:"constructor_invocation"` + FeeTransferInvocation FnInvocation `json:"fee_transfer_invocation"` + StateDiff StateDiff `json:"state_diff"` + Type TransactionType `json:"type"` } // the execution trace of an L1 handler transaction type L1HandlerTxnTrace struct { //the trace of the __execute__ call or constructor call, depending on the transaction type (none for declare transactions) - FunctionInvocation FnInvocation `json:"function_invocation"` + FunctionInvocation FnInvocation `json:"function_invocation"` + Type TransactionType `json:"type"` } type EntryPointType string @@ -107,3 +114,8 @@ type Trace struct { TraceRoot TxnTrace `json:"trace_root,omitempty"` TxnHash *felt.Felt `json:"transaction_hash,omitempty"` } + +type ExecInvocation struct { + FunctionInvocation FnInvocation `json:"function_invocation,omitempty"` + RevertReason string `json:"revert_reason,omitempty"` +}