Skip to content

Commit

Permalink
Split Status field into FinalityStatus and ExecutionStatus in RPCs
Browse files Browse the repository at this point in the history
- Add ExecutionStatus to receipt type
- Replace Status with FinalityStatus on receipt type
- Return a struct from juno_getTransactionStatus containing the
  execution and finality statuses
  • Loading branch information
joshklop committed Jul 19, 2023
1 parent 9d4a64d commit fb0f3ba
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 49 deletions.
19 changes: 0 additions & 19 deletions rpc/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package rpc
import (
"encoding/json"
"errors"
"fmt"

"github.com/NethermindEth/juno/core/felt"
)
Expand Down Expand Up @@ -33,24 +32,6 @@ func (s BlockStatus) MarshalJSON() ([]byte, error) {
}
}

func (s *BlockStatus) UnmarshalJSON(bytes []byte) (err error) {
str := string(bytes)
switch str {
case "PENDING":
*s = BlockPending
case "ACCEPTED_ON_L2":
*s = BlockAcceptedL2
case "ACCEPTED_ON_L1":
*s = BlockAcceptedL1
case "REJECTED":
*s = BlockRejected
default:
err = fmt.Errorf("unknown block status %q", str)
}

return
}

// https://github.com/starkware-libs/starknet-specs/blob/a789ccc3432c57777beceaa53a34a7ae2f25fda0/api/starknet_api_openrpc.json#L520-L534
type BlockHashAndNumber struct {
Hash *felt.Felt `json:"block_hash"`
Expand Down
55 changes: 41 additions & 14 deletions rpc/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ func (h *Handler) TransactionReceiptByHash(hash felt.Felt) (*TransactionReceipt,
}

var receiptBlockNumber *uint64
status := BlockAcceptedL2
status := TxnAcceptedOnL2

if blockHash != nil {
receiptBlockNumber = &blockNumber
Expand All @@ -432,12 +432,20 @@ func (h *Handler) TransactionReceiptByHash(hash felt.Felt) (*TransactionReceipt,
}

if isL1Verified(blockNumber, l1H) {
status = BlockAcceptedL1
status = TxnAcceptedOnL1
}
}

var es TxnExecutionStatus
if receipt.Reverted {
es = TxnFailure
} else {
es = TxnSuccess
}

return &TransactionReceipt{
Status: status,
FinalityStatus: status,
ExecutionStatus: es,
Type: txn.Type,
Hash: txn.Hash,
ActualFee: receipt.Fee,
Expand Down Expand Up @@ -1039,24 +1047,43 @@ func (h *Handler) Call(call FunctionCall, id BlockID) ([]*felt.Felt, *jsonrpc.Er
return res, nil
}

func (h *Handler) TransactionStatus(hash felt.Felt) (BlockStatus, *jsonrpc.Error) {
var status BlockStatus
func (h *Handler) TransactionStatus(hash felt.Felt) (*TransactionStatus, *jsonrpc.Error) {
var status *TransactionStatus

receipt, txErr := h.TransactionReceiptByHash(hash)
if txErr == nil {
status = receipt.Status
} else if txErr == ErrTxnHashNotFound {
switch txErr {
case nil:
status = &TransactionStatus{
Finality: receipt.FinalityStatus,
Execution: receipt.ExecutionStatus,
}
case ErrTxnHashNotFound:
txStatus, err := h.feederClient.Transaction(context.Background(), &hash)
if err != nil {
return 0, jsonrpc.Err(jsonrpc.InternalError, err.Error())
return nil, jsonrpc.Err(jsonrpc.InternalError, err.Error())
}

err = status.UnmarshalJSON([]byte(txStatus.Status))
if err != nil {
return 0, jsonrpc.Err(jsonrpc.InternalError, err.Error())
status = new(TransactionStatus)

switch txStatus.FinalityStatus {
case feeder.AcceptedOnL1:
status.Finality = TxnAcceptedOnL1
case feeder.AcceptedOnL2:
status.Finality = TxnAcceptedOnL2
default:
return nil, jsonrpc.Err(jsonrpc.InternalError, "unknown FinalityStatus")
}
} else {
return 0, txErr

switch txStatus.ExecutionStatus {
case feeder.Succeeded:
status.Execution = TxnSuccess
case feeder.Reverted:
status.Execution = TxnFailure
default:
return nil, jsonrpc.Err(jsonrpc.InternalError, "unknown ExecutionStatus")
}
default:
return nil, txErr
}

return status, nil
Expand Down
27 changes: 20 additions & 7 deletions rpc/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,8 @@ func TestTransactionReceiptByHash(t *testing.T) {
"type": "DEPLOY",
"transaction_hash": "0xe0a2e45a80bb827967e096bcf58874f6c01c191e0a0530624cba66a508ae75",
"actual_fee": "0x0",
"status": "ACCEPTED_ON_L2",
"finality_status": "ACCEPTED_ON_L2",
"execution_status": "SUCCESS",
"block_hash": "0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943",
"block_number": 0,
"messages_sent": [],
Expand All @@ -852,7 +853,8 @@ func TestTransactionReceiptByHash(t *testing.T) {
"type": "INVOKE",
"transaction_hash": "0xce54bbc5647e1c1ea4276c01a708523f740db0ff5474c77734f73beec2624",
"actual_fee": "0x0",
"status": "ACCEPTED_ON_L2",
"finality_status": "ACCEPTED_ON_L2",
"execution_status": "SUCCESS",
"block_hash": "0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943",
"block_number": 0,
"messages_sent": [
Expand Down Expand Up @@ -886,7 +888,8 @@ func TestTransactionReceiptByHash(t *testing.T) {
"type": "INVOKE",
"transaction_hash": "0xce54bbc5647e1c1ea4276c01a708523f740db0ff5474c77734f73beec2624",
"actual_fee": "0x0",
"status": "ACCEPTED_ON_L2",
"finality_status": "ACCEPTED_ON_L2",
"execution_status": "SUCCESS",
"messages_sent": [
{
"from_address": "0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6",
Expand All @@ -913,7 +916,8 @@ func TestTransactionReceiptByHash(t *testing.T) {
"type": "INVOKE",
"transaction_hash": "0xce54bbc5647e1c1ea4276c01a708523f740db0ff5474c77734f73beec2624",
"actual_fee": "0x0",
"status": "ACCEPTED_ON_L1",
"finality_status": "ACCEPTED_ON_L1",
"execution_status": "SUCCESS",
"block_hash": "0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943",
"block_number": 0,
"messages_sent": [
Expand Down Expand Up @@ -1974,9 +1978,13 @@ func TestTransactionStatus(t *testing.T) {

handler := rpc.New(mockReader, nil, utils.MAINNET, nil, nil, "", nil)

want := &rpc.TransactionStatus{
Finality: rpc.TxnAcceptedOnL2,
Execution: rpc.TxnSuccess,
}
status, rpcErr := handler.TransactionStatus(*tx.Hash())
require.Nil(t, rpcErr)
require.Equal(t, rpc.BlockAcceptedL2, status)
require.Equal(t, want, status)
})
t.Run("verified", func(t *testing.T) {
mockReader := mocks.NewMockReader(mockCtrl)
Expand All @@ -1988,9 +1996,13 @@ func TestTransactionStatus(t *testing.T) {

handler := rpc.New(mockReader, nil, utils.MAINNET, nil, nil, "", nil)

want := &rpc.TransactionStatus{
Finality: rpc.TxnAcceptedOnL1,
Execution: rpc.TxnSuccess,
}
status, rpcErr := handler.TransactionStatus(*tx.Hash())
require.Nil(t, rpcErr)
require.Equal(t, rpc.BlockAcceptedL1, status)
require.Equal(t, want, status)
})
})
t.Run("transaction not found in db", func(t *testing.T) {
Expand All @@ -2000,7 +2012,8 @@ func TestTransactionStatus(t *testing.T) {

status, err := handler.TransactionStatus(*hash)
require.Nil(t, err)
require.Equal(t, rpc.BlockAcceptedL1, status)
require.Equal(t, rpc.TxnAcceptedOnL1, status.Finality)
require.Equal(t, rpc.TxnSuccess, status.Execution)
})
}

Expand Down
60 changes: 51 additions & 9 deletions rpc/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,42 @@ func (t *TransactionType) UnmarshalJSON(data []byte) error {
return nil
}

type TxnExecutionStatus uint8

const (
TxnSuccess TxnExecutionStatus = iota + 1
TxnFailure
)

func (es TxnExecutionStatus) MarshalJSON() ([]byte, error) {
switch es {
case TxnSuccess:
return []byte("\"SUCCESS\""), nil
case TxnFailure:
return []byte("\"FAILURE\""), nil
default:
return nil, errors.New("unknown ExecutionStatus")
}
}

type TxnFinalityStatus uint8

const (
TxnAcceptedOnL1 TxnFinalityStatus = iota + 1
TxnAcceptedOnL2
)

func (fs TxnFinalityStatus) MarshalJSON() ([]byte, error) {
switch fs {
case TxnAcceptedOnL1:
return []byte("\"ACCEPTED_ON_L1\""), nil
case TxnAcceptedOnL2:
return []byte("\"ACCEPTED_ON_L2\""), nil
default:
return nil, errors.New("unknown FinalityStatus")
}
}

// https://github.com/starkware-libs/starknet-specs/blob/a789ccc3432c57777beceaa53a34a7ae2f25fda0/api/starknet_api_openrpc.json#L1252
//
//nolint:lll
Expand All @@ -85,6 +121,11 @@ type Transaction struct {
CompiledClassHash *felt.Felt `json:"compiled_class_hash,omitempty" validate:"required_if=Type DECLARE Version 0x2"`
}

type TransactionStatus struct {
Finality TxnFinalityStatus `json:"finality_status"`
Execution TxnExecutionStatus `json:"execution_status"`
}

type MsgToL1 struct {
From *felt.Felt `json:"from_address"`
To common.Address `json:"to_address"`
Expand All @@ -99,15 +140,16 @@ type Event struct {

// https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json#L1871
type TransactionReceipt struct {
Type TransactionType `json:"type"`
Hash *felt.Felt `json:"transaction_hash"`
ActualFee *felt.Felt `json:"actual_fee"`
Status BlockStatus `json:"status"`
BlockHash *felt.Felt `json:"block_hash,omitempty"`
BlockNumber *uint64 `json:"block_number,omitempty"`
MessagesSent []*MsgToL1 `json:"messages_sent"`
Events []*Event `json:"events"`
ContractAddress *felt.Felt `json:"contract_address,omitempty"`
Type TransactionType `json:"type"`
Hash *felt.Felt `json:"transaction_hash"`
ActualFee *felt.Felt `json:"actual_fee"`
ExecutionStatus TxnExecutionStatus `json:"execution_status"`
FinalityStatus TxnFinalityStatus `json:"finality_status"`
BlockHash *felt.Felt `json:"block_hash,omitempty"`
BlockNumber *uint64 `json:"block_number,omitempty"`
MessagesSent []*MsgToL1 `json:"messages_sent"`
Events []*Event `json:"events"`
ContractAddress *felt.Felt `json:"contract_address,omitempty"`
}

type AddInvokeTxResponse struct {
Expand Down

0 comments on commit fb0f3ba

Please sign in to comment.