From 742893af0f7ae792df261fd7372fadebb4632a47 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 28 Jan 2025 17:18:06 +0300 Subject: [PATCH 1/8] Fix e2e --- adapters/core2p2p/receipt.go | 1 - adapters/p2p2core/receipt.go | 1 - core/transaction.go | 1 - rpc/block.go | 10 +- rpc/block_test.go | 4 +- rpc/estimate_fee.go | 68 ++-- rpc/estimate_fee_pkg_test.go | 43 --- rpc/handlers.go | 15 +- rpc/helpers.go | 56 ++- rpc/simulation.go | 9 +- rpc/simulation_pkg_test.go | 2 +- rpc/transaction.go | 41 ++- rpc/transaction_test.go | 661 +++++++++++++++++++++++++---------- starknet/transaction.go | 1 - 14 files changed, 612 insertions(+), 301 deletions(-) delete mode 100644 rpc/estimate_fee_pkg_test.go diff --git a/adapters/core2p2p/receipt.go b/adapters/core2p2p/receipt.go index 8a3c36f244..76734de675 100644 --- a/adapters/core2p2p/receipt.go +++ b/adapters/core2p2p/receipt.go @@ -107,7 +107,6 @@ func AdaptExecutionResources(er *core.ExecutionResources) *gen.Receipt_Execution var l1Gas, l1DataGas, l2Gas, totalL1Gas, totalL1DataGas *felt.Felt if da := er.DataAvailability; da != nil { // todo(kirill) check that it might be null l1Gas = new(felt.Felt).SetUint64(da.L1Gas) - l2Gas = new(felt.Felt).SetUint64(da.L2Gas) l1DataGas = new(felt.Felt).SetUint64(da.L1DataGas) } if tgs := er.TotalGasConsumed; tgs != nil { diff --git a/adapters/p2p2core/receipt.go b/adapters/p2p2core/receipt.go index e804cca9b8..05753b391b 100644 --- a/adapters/p2p2core/receipt.go +++ b/adapters/p2p2core/receipt.go @@ -58,7 +58,6 @@ func adaptExecutionResources(er *gen.Receipt_ExecutionResources) *core.Execution }, DataAvailability: &core.DataAvailability{ L1Gas: feltToUint64(er.L1Gas), - L2Gas: feltToUint64(er.L2Gas), L1DataGas: feltToUint64(er.L1DataGas), }, MemoryHoles: uint64(er.MemoryHoles), diff --git a/core/transaction.go b/core/transaction.go index 38d2fe67cf..c65bc0d205 100644 --- a/core/transaction.go +++ b/core/transaction.go @@ -105,7 +105,6 @@ type ExecutionResources struct { type DataAvailability struct { L1Gas uint64 L1DataGas uint64 - L2Gas uint64 } type BuiltinInstanceCounter struct { diff --git a/rpc/block.go b/rpc/block.go index 936f3f8a53..0f0678eef7 100644 --- a/rpc/block.go +++ b/rpc/block.go @@ -207,7 +207,15 @@ func (h *Handler) BlockTransactionCount(id BlockID) (uint64, *jsonrpc.Error) { return header.TransactionCount, nil } +func (h *Handler) BlockWithReceiptsV0_7(id BlockID) (*BlockWithReceipts, *jsonrpc.Error) { + return h.blockWithReceipts(id, V0_7) +} + func (h *Handler) BlockWithReceipts(id BlockID) (*BlockWithReceipts, *jsonrpc.Error) { + return h.blockWithReceipts(id, V0_8) +} + +func (h *Handler) blockWithReceipts(id BlockID, rpcVersion version) (*BlockWithReceipts, *jsonrpc.Error) { block, rpcErr := h.blockByID(&id) if rpcErr != nil { return nil, rpcErr @@ -232,7 +240,7 @@ func (h *Handler) BlockWithReceipts(id BlockID) (*BlockWithReceipts, *jsonrpc.Er txsWithReceipts[index] = TransactionWithReceipt{ Transaction: t, // block_hash, block_number are optional in BlockWithReceipts response - Receipt: AdaptReceipt(r, txn, finalityStatus, nil, 0), + Receipt: AdaptReceipt(r, txn, finalityStatus, nil, 0, rpcVersion), } } diff --git a/rpc/block_test.go b/rpc/block_test.go index 5a89f07c0a..b42388077d 100644 --- a/rpc/block_test.go +++ b/rpc/block_test.go @@ -632,7 +632,7 @@ func TestBlockWithReceipts(t *testing.T) { txsWithReceipt = append(txsWithReceipt, rpc.TransactionWithReceipt{ Transaction: adaptedTx, - Receipt: rpc.AdaptReceipt(receipt, tx, rpc.TxnAcceptedOnL2, nil, 0), + Receipt: rpc.AdaptReceipt(receipt, tx, rpc.TxnAcceptedOnL2, nil, 0, rpc.V0_8), }) } @@ -678,7 +678,7 @@ func TestBlockWithReceipts(t *testing.T) { transactions = append(transactions, rpc.TransactionWithReceipt{ Transaction: adaptedTx, - Receipt: rpc.AdaptReceipt(receipt, tx, rpc.TxnAcceptedOnL1, nil, 0), + Receipt: rpc.AdaptReceipt(receipt, tx, rpc.TxnAcceptedOnL1, nil, 0, rpc.V0_8), }) } diff --git a/rpc/estimate_fee.go b/rpc/estimate_fee.go index 5923703dd8..ab311344a6 100644 --- a/rpc/estimate_fee.go +++ b/rpc/estimate_fee.go @@ -1,6 +1,7 @@ package rpc import ( + "encoding/json" "errors" "fmt" "net/http" @@ -28,15 +29,6 @@ func (u FeeUnit) MarshalText() ([]byte, error) { } } -type FeeEstimateV0_7 struct { - GasConsumed *felt.Felt `json:"gas_consumed"` - GasPrice *felt.Felt `json:"gas_price"` - DataGasConsumed *felt.Felt `json:"data_gas_consumed"` - DataGasPrice *felt.Felt `json:"data_gas_price"` - OverallFee *felt.Felt `json:"overall_fee"` - Unit *FeeUnit `json:"unit,omitempty"` -} - type FeeEstimate struct { L1GasConsumed *felt.Felt `json:"l1_gas_consumed,omitempty"` L1GasPrice *felt.Felt `json:"l1_gas_price,omitempty"` @@ -46,40 +38,55 @@ type FeeEstimate struct { L1DataGasPrice *felt.Felt `json:"l1_data_gas_price,omitempty"` OverallFee *felt.Felt `json:"overall_fee"` Unit *FeeUnit `json:"unit,omitempty"` + rpcVersion version +} + +func (f FeeEstimate) MarshalJSON() ([]byte, error) { + switch f.rpcVersion { + case V0_7: + return json.Marshal(struct { + GasConsumed *felt.Felt `json:"gas_consumed"` + GasPrice *felt.Felt `json:"gas_price"` + DataGasConsumed *felt.Felt `json:"data_gas_consumed"` + DataGasPrice *felt.Felt `json:"data_gas_price"` + OverallFee *felt.Felt `json:"overall_fee"` + Unit *FeeUnit `json:"unit,omitempty"` + }{ + GasConsumed: f.L1GasConsumed, + GasPrice: f.L1GasPrice, + DataGasConsumed: f.L1DataGasConsumed, + DataGasPrice: f.L1DataGasPrice, + OverallFee: f.OverallFee, + Unit: f.Unit, + }) + case V0_8: + type alias FeeEstimate // avoid infinite recursion + return json.Marshal(alias(f)) + default: + return nil, errors.New("unknown FeeEstimate version") + } } /**************************************************** Estimate Fee Handlers *****************************************************/ -func feeEstimateToV0_7(feeEstimate FeeEstimate) FeeEstimateV0_7 { - return FeeEstimateV0_7{ - GasConsumed: feeEstimate.L1GasConsumed, - GasPrice: feeEstimate.L1GasPrice, - DataGasConsumed: feeEstimate.L1DataGasConsumed, - DataGasPrice: feeEstimate.L1DataGasPrice, - OverallFee: feeEstimate.OverallFee, - Unit: feeEstimate.Unit, - } -} - func (h *Handler) EstimateFeeV0_7(broadcastedTxns []BroadcastedTransaction, simulationFlags []SimulationFlag, id BlockID, -) ([]FeeEstimateV0_7, http.Header, *jsonrpc.Error) { - result, httpHeader, err := h.simulateTransactions(id, broadcastedTxns, append(simulationFlags, SkipFeeChargeFlag), true) +) ([]FeeEstimate, http.Header, *jsonrpc.Error) { + result, httpHeader, err := h.simulateTransactions(id, broadcastedTxns, append(simulationFlags, SkipFeeChargeFlag), true, V0_7) if err != nil { return nil, httpHeader, err } - return utils.Map(result, func(tx SimulatedTransaction) FeeEstimateV0_7 { - return feeEstimateToV0_7(tx.FeeEstimation) + return utils.Map(result, func(tx SimulatedTransaction) FeeEstimate { + return tx.FeeEstimation }), httpHeader, nil } - func (h *Handler) EstimateFee(broadcastedTxns []BroadcastedTransaction, simulationFlags []SimulationFlag, id BlockID, ) ([]FeeEstimate, http.Header, *jsonrpc.Error) { - result, httpHeader, err := h.simulateTransactions(id, broadcastedTxns, append(simulationFlags, SkipFeeChargeFlag), true) + result, httpHeader, err := h.simulateTransactions(id, broadcastedTxns, append(simulationFlags, SkipFeeChargeFlag), true, V0_8) if err != nil { return nil, httpHeader, err } @@ -90,13 +97,8 @@ func (h *Handler) EstimateFee(broadcastedTxns []BroadcastedTransaction, } //nolint:gocritic -func (h *Handler) EstimateMessageFeeV0_7(msg MsgFromL1, id BlockID) (*FeeEstimateV0_7, http.Header, *jsonrpc.Error) { - estimate, header, err := estimateMessageFee(msg, id, h.EstimateFee) - if err != nil { - return nil, header, err - } - estimateV0_7 := feeEstimateToV0_7(*estimate) - return &estimateV0_7, header, nil +func (h *Handler) EstimateMessageFeeV0_7(msg MsgFromL1, id BlockID) (*FeeEstimate, http.Header, *jsonrpc.Error) { + return estimateMessageFee(msg, id, h.EstimateFeeV0_7) } //nolint:gocritic diff --git a/rpc/estimate_fee_pkg_test.go b/rpc/estimate_fee_pkg_test.go deleted file mode 100644 index 43530e545a..0000000000 --- a/rpc/estimate_fee_pkg_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package rpc - -import ( - "testing" - - "github.com/NethermindEth/juno/core/felt" - "github.com/stretchr/testify/assert" -) - -func TestFeeEstimateToV0_7(t *testing.T) { - t.Run("empty", func(t *testing.T) { - assert.Equal(t, FeeEstimateV0_7{}, feeEstimateToV0_7(FeeEstimate{})) - }) - - t.Run("full", func(t *testing.T) { - gasConsumed := new(felt.Felt).SetUint64(1) - gasPrice := new(felt.Felt).SetUint64(2) - dataGasConsumed := new(felt.Felt).SetUint64(3) - dataGasPrice := new(felt.Felt).SetUint64(4) - overallFee := new(felt.Felt).SetUint64(5) - unit := WEI - assert.Equal( - t, - FeeEstimateV0_7{ - GasConsumed: gasConsumed, - GasPrice: gasPrice, - DataGasConsumed: dataGasConsumed, - DataGasPrice: dataGasPrice, - OverallFee: overallFee, - Unit: &unit, - }, - feeEstimateToV0_7(FeeEstimate{ - L1GasConsumed: gasConsumed, - L1GasPrice: gasPrice, - L2GasConsumed: new(felt.Felt).SetUint64(6), - L2GasPrice: new(felt.Felt).SetUint64(7), - L1DataGasConsumed: dataGasConsumed, - L1DataGasPrice: dataGasPrice, - OverallFee: overallFee, - Unit: &unit, - })) - }) -} diff --git a/rpc/handlers.go b/rpc/handlers.go index cba34ed396..83759b9528 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "log" + "maps" "math" "strings" stdsync "sync" @@ -81,6 +82,13 @@ const ( throttledVMErr = "VM throughput limit reached" ) +type version uint32 + +const ( + V0_7 version = iota + 1 + V0_8 +) + type traceCacheKey struct { blockHash felt.Felt } @@ -195,7 +203,12 @@ func (h *Handler) Run(ctx context.Context) error { feed.Tee(l1HeadsSub, h.l1Heads) <-ctx.Done() - for _, sub := range h.subscriptions { + + h.mu.Lock() + subscriptions := maps.Values(h.subscriptions) + h.mu.Unlock() + + for sub := range subscriptions { sub.wg.Wait() } return nil diff --git a/rpc/helpers.go b/rpc/helpers.go index 4408ef00dc..7f5a981869 100644 --- a/rpc/helpers.go +++ b/rpc/helpers.go @@ -90,41 +90,39 @@ func (h *Handler) blockHeaderByID(id *BlockID) (*core.Header, *jsonrpc.Error) { return header, nil } -func adaptExecutionResources(resources *core.ExecutionResources) *ExecutionResources { - if resources == nil { - return &ExecutionResources{ - DataAvailability: &DataAvailability{}, - } - } - - res := &ExecutionResources{ - ComputationResources: ComputationResources{ - Steps: resources.Steps, - MemoryHoles: resources.MemoryHoles, - Pedersen: resources.BuiltinInstanceCounter.Pedersen, - RangeCheck: resources.BuiltinInstanceCounter.RangeCheck, - Bitwise: resources.BuiltinInstanceCounter.Bitwise, - Ecsda: resources.BuiltinInstanceCounter.Ecsda, - EcOp: resources.BuiltinInstanceCounter.EcOp, - Keccak: resources.BuiltinInstanceCounter.Keccak, - Poseidon: resources.BuiltinInstanceCounter.Poseidon, - SegmentArena: resources.BuiltinInstanceCounter.SegmentArena, - }, +func adaptExecutionResources(coreResources *core.ExecutionResources, rpcVersion version) *ExecutionResources { + resources := &ExecutionResources{ DataAvailability: &DataAvailability{}, - } - if da := resources.DataAvailability; da != nil { - res.DataAvailability = &DataAvailability{ + rpcVersion: rpcVersion, + } + if coreResources == nil { + return resources + } + + resources.ComputationResources = ComputationResources{ + Steps: coreResources.Steps, + MemoryHoles: coreResources.MemoryHoles, + Pedersen: coreResources.BuiltinInstanceCounter.Pedersen, + RangeCheck: coreResources.BuiltinInstanceCounter.RangeCheck, + Bitwise: coreResources.BuiltinInstanceCounter.Bitwise, + Ecsda: coreResources.BuiltinInstanceCounter.Ecsda, + EcOp: coreResources.BuiltinInstanceCounter.EcOp, + Keccak: coreResources.BuiltinInstanceCounter.Keccak, + Poseidon: coreResources.BuiltinInstanceCounter.Poseidon, + SegmentArena: coreResources.BuiltinInstanceCounter.SegmentArena, + } + if da := coreResources.DataAvailability; da != nil { + resources.DataAvailability = &DataAvailability{ L1Gas: da.L1Gas, - L2Gas: da.L2Gas, L1DataGas: da.L1DataGas, } } - if tgc := resources.TotalGasConsumed; tgc != nil { - res.L1Gas = tgc.L1Gas - res.L2Gas = tgc.L2Gas - res.L1DataGas = tgc.L1DataGas + if tgc := coreResources.TotalGasConsumed; tgc != nil { + resources.L1Gas = tgc.L1Gas + resources.L2Gas = tgc.L2Gas + resources.L1DataGas = tgc.L1DataGas } - return res + return resources } func (h *Handler) getRevealedBlockHash(blockNumber uint64) (*felt.Felt, error) { diff --git a/rpc/simulation.go b/rpc/simulation.go index 2327662193..743610b3f6 100644 --- a/rpc/simulation.go +++ b/rpc/simulation.go @@ -53,11 +53,11 @@ type TracedBlockTransaction struct { func (h *Handler) SimulateTransactions(id BlockID, transactions []BroadcastedTransaction, simulationFlags []SimulationFlag, ) ([]SimulatedTransaction, http.Header, *jsonrpc.Error) { - return h.simulateTransactions(id, transactions, simulationFlags, false) + return h.simulateTransactions(id, transactions, simulationFlags, false, V0_8) } func (h *Handler) simulateTransactions(id BlockID, transactions []BroadcastedTransaction, - simulationFlags []SimulationFlag, errOnRevert bool, + simulationFlags []SimulationFlag, errOnRevert bool, rpcVersion version, ) ([]SimulatedTransaction, http.Header, *jsonrpc.Error) { skipFeeCharge := slices.Contains(simulationFlags, SkipFeeChargeFlag) skipValidate := slices.Contains(simulationFlags, SkipValidateFlag) @@ -124,7 +124,7 @@ func (h *Handler) simulateTransactions(id BlockID, transactions []BroadcastedTra for i, overallFee := range overallFees { feeUnit := feeUnit(txns[i]) - estimate := calculateFeeEstimate(overallFee, daGas[i].L1DataGas, feeUnit, header) + estimate := calculateFeeEstimate(overallFee, daGas[i].L1DataGas, feeUnit, header, rpcVersion) trace := traces[i] executionResources := trace.TotalExecutionResources() @@ -143,7 +143,7 @@ func (h *Handler) simulateTransactions(id BlockID, transactions []BroadcastedTra return result, httpHeader, nil } -func calculateFeeEstimate(overallFee *felt.Felt, l1DataGas uint64, feeUnit FeeUnit, header *core.Header) FeeEstimate { +func calculateFeeEstimate(overallFee *felt.Felt, l1DataGas uint64, feeUnit FeeUnit, header *core.Header, rpcVersion version) FeeEstimate { var l1GasPrice, l2GasPrice, l1DataGasPrice *felt.Felt switch feeUnit { @@ -171,6 +171,7 @@ func calculateFeeEstimate(overallFee *felt.Felt, l1DataGas uint64, feeUnit FeeUn L1DataGasPrice: l1DataGasPrice, OverallFee: overallFee, Unit: utils.Ptr(feeUnit), + rpcVersion: rpcVersion, } } diff --git a/rpc/simulation_pkg_test.go b/rpc/simulation_pkg_test.go index c167fefed3..ad29be9f36 100644 --- a/rpc/simulation_pkg_test.go +++ b/rpc/simulation_pkg_test.go @@ -28,7 +28,7 @@ func TestCalculateFeeEstimate(t *testing.T) { l1DataGas := uint64(500) overallFee := new(felt.Felt).SetUint64(6000) - feeEstimate := calculateFeeEstimate(overallFee, l1DataGas, FRI, header) + feeEstimate := calculateFeeEstimate(overallFee, l1DataGas, FRI, header, V0_8) assert.Equal(t, l1GasPriceSTRK, feeEstimate.L1GasPrice) assert.Equal(t, l2GasPrice.PriceInFri, feeEstimate.L2GasPrice) diff --git a/rpc/transaction.go b/rpc/transaction.go index 0aad707896..e2281dc77a 100644 --- a/rpc/transaction.go +++ b/rpc/transaction.go @@ -262,7 +262,6 @@ type ComputationResources struct { type DataAvailability struct { L1Gas uint64 `json:"l1_gas"` L1DataGas uint64 `json:"l1_data_gas"` - L2Gas uint64 `json:"l2_gas"` } type ExecutionResources struct { @@ -273,6 +272,32 @@ type ExecutionResources struct { // TODO: Remove this field once the API is updated. ComputationResources DataAvailability *DataAvailability `json:"data_availability,omitempty"` + rpcVersion version +} + +func (r ExecutionResources) MarshalJSON() ([]byte, error) { //nolint:gocritic + switch r.rpcVersion { + case V0_7: + return json.Marshal(struct { + ComputationResources + DataAvailability *DataAvailability `json:"data_availability,omitempty"` + }{ + ComputationResources: r.ComputationResources, + DataAvailability: r.DataAvailability, + }) + case V0_8: + return json.Marshal(struct { + L1Gas uint64 `json:"l1_gas"` + L1DataGas uint64 `json:"l1_data_gas"` + L2Gas uint64 `json:"l2_gas"` + }{ + L1Gas: r.L1Gas, + L1DataGas: r.L1DataGas, + L2Gas: r.L2Gas, + }) + default: + return nil, fmt.Errorf("unknown rpc version %v", r.rpcVersion) + } } // https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json#L1871 @@ -498,6 +523,14 @@ func (h *Handler) TransactionByBlockIDAndIndex(id BlockID, txIndex int) (*Transa // It follows the specification defined here: // https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json#L222 func (h *Handler) TransactionReceiptByHash(hash felt.Felt) (*TransactionReceipt, *jsonrpc.Error) { + return h.transactionReceiptByHash(hash, V0_8) +} + +func (h *Handler) TransactionReceiptByHashV0_7(hash felt.Felt) (*TransactionReceipt, *jsonrpc.Error) { + return h.transactionReceiptByHash(hash, V0_7) +} + +func (h *Handler) transactionReceiptByHash(hash felt.Felt, rpcVersion version) (*TransactionReceipt, *jsonrpc.Error) { var ( pendingB *core.Block pendingBIndex int @@ -555,7 +588,7 @@ func (h *Handler) TransactionReceiptByHash(hash felt.Felt) (*TransactionReceipt, } } - return AdaptReceipt(receipt, txn, status, blockHash, blockNumber), nil + return AdaptReceipt(receipt, txn, status, blockHash, blockNumber, rpcVersion), nil } // AddTransaction relays a transaction to the gateway. @@ -758,7 +791,7 @@ func AdaptTransaction(t core.Transaction) *Transaction { // todo(Kirill): try to replace core.Transaction with rpc.Transaction type func AdaptReceipt(receipt *core.TransactionReceipt, txn core.Transaction, finalityStatus TxnFinalityStatus, - blockHash *felt.Felt, blockNumber uint64, + blockHash *felt.Felt, blockNumber uint64, rpcVersion version, ) *TransactionReceipt { messages := make([]*MsgToL1, len(receipt.L2ToL1Message)) for idx, msg := range receipt.L2ToL1Message { @@ -817,7 +850,7 @@ func AdaptReceipt(receipt *core.TransactionReceipt, txn core.Transaction, finali Events: events, ContractAddress: contractAddress, RevertReason: receipt.RevertReason, - ExecutionResources: adaptExecutionResources(receipt.ExecutionResources), + ExecutionResources: adaptExecutionResources(receipt.ExecutionResources, rpcVersion), MessageHash: messageHash, } } diff --git a/rpc/transaction_test.go b/rpc/transaction_test.go index 56cb07f9a0..0170bf55b7 100644 --- a/rpc/transaction_test.go +++ b/rpc/transaction_test.go @@ -11,6 +11,7 @@ import ( "github.com/NethermindEth/juno/core" "github.com/NethermindEth/juno/core/felt" "github.com/NethermindEth/juno/db" + "github.com/NethermindEth/juno/jsonrpc" "github.com/NethermindEth/juno/mocks" "github.com/NethermindEth/juno/rpc" "github.com/NethermindEth/juno/starknet" @@ -519,15 +520,14 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) { //nolint:dupl func TestTransactionReceiptByHash(t *testing.T) { - mockCtrl := gomock.NewController(t) - t.Cleanup(mockCtrl.Finish) + t.Run("transaction not found", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + t.Cleanup(mockCtrl.Finish) - n := utils.Ptr(utils.Mainnet) - mockReader := mocks.NewMockReader(mockCtrl) - mockSyncReader := mocks.NewMockSyncReader(mockCtrl) - handler := rpc.New(mockReader, mockSyncReader, nil, "", nil) + mockReader := mocks.NewMockReader(mockCtrl) + mockSyncReader := mocks.NewMockSyncReader(mockCtrl) + handler := rpc.New(mockReader, mockSyncReader, nil, "", nil) - t.Run("transaction not found", func(t *testing.T) { txHash := new(felt.Felt).SetBytes([]byte("random hash")) mockReader.EXPECT().TransactionByHash(txHash).Return(nil, db.ErrKeyNotFound) mockSyncReader.EXPECT().PendingBlock().Return(nil) @@ -537,34 +537,53 @@ func TestTransactionReceiptByHash(t *testing.T) { assert.Equal(t, rpc.ErrTxnHashNotFound, rpcErr) }) - client := feeder.NewTestClient(t, n) - mainnetGw := adaptfeeder.New(client) - - block0, err := mainnetGw.BlockByNumber(context.Background(), 0) - require.NoError(t, err) - - checkTxReceipt := func(t *testing.T, h *felt.Felt, expected string) { - t.Helper() - - expectedMap := make(map[string]any) - require.NoError(t, json.Unmarshal([]byte(expected), &expectedMap)) - - receipt, err := handler.TransactionReceiptByHash(*h) - require.Nil(t, err) - receiptJSON, jsonErr := json.Marshal(receipt) - require.NoError(t, jsonErr) - - receiptMap := make(map[string]any) - require.NoError(t, json.Unmarshal(receiptJSON, &receiptMap)) - assert.Equal(t, expectedMap, receiptMap) - } - - tests := map[string]struct { - index int - expected string + tests := []struct { + name string + network *utils.Network + blockNumber uint64 + index int + expected string + mockBehavior func(*mocks.MockReader, int, *core.Block) *felt.Felt + rpcVersion string }{ - "with contract addr": { - index: 0, + { + name: "with contract addr 0.7", + network: &utils.Mainnet, + blockNumber: 0, + index: 0, + expected: `{ + "type": "DEPLOY", + "transaction_hash": "0xe0a2e45a80bb827967e096bcf58874f6c01c191e0a0530624cba66a508ae75", + "actual_fee": {"amount": "0x0", "unit": "WEI"}, + "finality_status": "ACCEPTED_ON_L2", + "execution_status": "SUCCEEDED", + "block_hash": "0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943", + "block_number": 0, + "messages_sent": [], + "events": [], + "contract_address": "0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6", + "execution_resources": { + "data_availability": { + "l1_data_gas": 0, + "l1_gas": 0 + }, + "steps": 29 + } + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + rpcVersion: "0.7", + }, + { + name: "with contract addr 0.8", + network: &utils.Mainnet, + blockNumber: 0, + index: 0, expected: `{ "type": "DEPLOY", "transaction_hash": "0xe0a2e45a80bb827967e096bcf58874f6c01c191e0a0530624cba66a508ae75", @@ -579,18 +598,65 @@ func TestTransactionReceiptByHash(t *testing.T) { "execution_resources": { "l1_data_gas": 0, "l1_gas": 0, - "l2_gas": 0, + "l2_gas": 0 + } + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + + rpcVersion: "0.8", + }, + { + name: "without contract addr 0.7", + network: &utils.Mainnet, + blockNumber: 0, + index: 2, + expected: `{ + "type": "INVOKE", + "transaction_hash": "0xce54bbc5647e1c1ea4276c01a708523f740db0ff5474c77734f73beec2624", + "actual_fee": {"amount": "0x0", "unit": "WEI"}, + "finality_status": "ACCEPTED_ON_L2", + "execution_status": "SUCCEEDED", + "block_hash": "0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943", + "block_number": 0, + "messages_sent": [ + { + "from_address": "0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6", + "to_address": "0xc84dd7fd43a7defb5b7a15c4fbbe11cbba6db1ba", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_resources": { "data_availability": { "l1_data_gas": 0, - "l1_gas": 0, - "l2_gas": 0 + "l1_gas": 0 }, - "steps": 29 + "steps": 31 } }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + rpcVersion: "0.7", }, - "without contract addr": { - index: 2, + { + name: "without contract addr 0.8", + network: &utils.Mainnet, + blockNumber: 0, + index: 2, expected: `{ "type": "INVOKE", "transaction_hash": "0xce54bbc5647e1c1ea4276c01a708523f740db0ff5474c77734f73beec2624", @@ -613,31 +679,62 @@ func TestTransactionReceiptByHash(t *testing.T) { "execution_resources": { "l1_data_gas": 0, "l1_gas": 0, - "l2_gas": 0, + "l2_gas": 0 + } + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + rpcVersion: "0.8", + }, + { + name: "pending receipt 0.7", + network: &utils.Mainnet, + blockNumber: 0, + index: 2, + expected: `{ + "type": "INVOKE", + "transaction_hash": "0xce54bbc5647e1c1ea4276c01a708523f740db0ff5474c77734f73beec2624", + "actual_fee": {"amount": "0x0", "unit": "WEI"}, + "finality_status": "ACCEPTED_ON_L2", + "execution_status": "SUCCEEDED", + "messages_sent": [ + { + "from_address": "0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6", + "to_address": "0xc84dd7fd43a7defb5b7a15c4fbbe11cbba6db1ba", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_resources": { "data_availability": { "l1_data_gas": 0, - "l1_gas": 0, - "l2_gas": 0 + "l1_gas": 0 }, "steps": 31 } }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], nil, uint64(0), nil) + return txHash + }, + rpcVersion: "0.7", }, - } - for name, test := range tests { - t.Run(name, func(t *testing.T) { - txHash := block0.Transactions[test.index].Hash() - mockReader.EXPECT().TransactionByHash(txHash).Return(block0.Transactions[test.index], nil) - mockReader.EXPECT().Receipt(txHash).Return(block0.Receipts[test.index], block0.Hash, block0.Number, nil) - mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) - - checkTxReceipt(t, txHash, test.expected) - }) - } - - t.Run("pending receipt", func(t *testing.T) { - i := 2 - expected := `{ + { + name: "pending receipt 0.8", + network: &utils.Mainnet, + blockNumber: 0, + index: 2, + expected: `{ "type": "INVOKE", "transaction_hash": "0xce54bbc5647e1c1ea4276c01a708523f740db0ff5474c77734f73beec2624", "actual_fee": {"amount": "0x0", "unit": "WEI"}, @@ -657,26 +754,68 @@ func TestTransactionReceiptByHash(t *testing.T) { "execution_resources": { "l1_data_gas": 0, "l1_gas": 0, - "l2_gas": 0, + "l2_gas": 0 + } + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], nil, uint64(0), nil) + return txHash + }, + rpcVersion: "0.8", + }, + { + name: "accepted on l1 receipt 0.7", + network: &utils.Mainnet, + blockNumber: 0, + index: 2, + expected: `{ + "type": "INVOKE", + "transaction_hash": "0xce54bbc5647e1c1ea4276c01a708523f740db0ff5474c77734f73beec2624", + "actual_fee": {"amount": "0x0", "unit": "WEI"}, + "finality_status": "ACCEPTED_ON_L1", + "execution_status": "SUCCEEDED", + "block_hash": "0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943", + "block_number": 0, + "messages_sent": [ + { + "from_address": "0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6", + "to_address": "0xc84dd7fd43a7defb5b7a15c4fbbe11cbba6db1ba", + "payload": [ + "0xc", + "0x22" + ] + } + ], + "events": [], + "execution_resources": { "data_availability": { "l1_data_gas": 0, - "l1_gas": 0, - "l2_gas": 0 + "l1_gas": 0 }, "steps": 31 } - }` - - txHash := block0.Transactions[i].Hash() - mockReader.EXPECT().TransactionByHash(txHash).Return(block0.Transactions[i], nil) - mockReader.EXPECT().Receipt(txHash).Return(block0.Receipts[i], nil, uint64(0), nil) - - checkTxReceipt(t, txHash, expected) - }) - - t.Run("accepted on l1 receipt", func(t *testing.T) { - i := 2 - expected := `{ + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(&core.L1Head{ + BlockNumber: block.Number, + BlockHash: block.Hash, + StateRoot: block.GlobalStateRoot, + }, nil) + return txHash + }, + rpcVersion: "0.7", + }, + { + name: "accepted on l1 receipt 0.8", + network: &utils.Mainnet, + blockNumber: 0, + index: 2, + expected: `{ "type": "INVOKE", "transaction_hash": "0xce54bbc5647e1c1ea4276c01a708523f740db0ff5474c77734f73beec2624", "actual_fee": {"amount": "0x0", "unit": "WEI"}, @@ -698,71 +837,170 @@ func TestTransactionReceiptByHash(t *testing.T) { "execution_resources": { "l1_data_gas": 0, "l1_gas": 0, - "l2_gas": 0, - "data_availability": { - "l1_data_gas": 0, - "l1_gas": 0, - "l2_gas": 0 + "l2_gas": 0 + } + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(&core.L1Head{ + BlockNumber: block.Number, + BlockHash: block.Hash, + StateRoot: block.GlobalStateRoot, + }, nil) + return txHash + }, + rpcVersion: "0.8", + }, + { + name: "reverted 0.7", + network: &utils.Integration, + blockNumber: 304740, + index: 1, + expected: `{ + "type":"INVOKE", + "transaction_hash":"0x19abec18bbacec23c2eee160c70190a48e4b41dd5ff98ad8f247f9393559998", + "actual_fee":{ + "amount":"0x247aff6e224", + "unit":"WEI" + }, + "execution_status":"REVERTED", + "finality_status":"ACCEPTED_ON_L2", + "block_hash":"0x76e0229fd0c36dda2ee7905f7e4c9b3ebb78d98c4bfab550bcb3a03bf859a6", + "block_number":304740, + "messages_sent":[ + + ], + "events":[ + + ], + "revert_reason":"Error in the called contract (0x00b1461de04c6a1aa3375bdf9b7723a8779c082ffe21311d683a0b15c078b5dc):\nError at pc=0:25:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:731)\nUnknown location (pc=0:677)\nUnknown location (pc=0:291)\nUnknown location (pc=0:314)\n\nError in the called contract (0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7):\nError at pc=0:104:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1678)\nUnknown location (pc=0:1664)\n\nError in the called contract (0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7):\nError at pc=0:6:\nGot an exception while executing a hint: Assertion failed, 0 % 0x800000000000011000000000000000000000000000000000000000000000001 is equal to 0\nCairo traceback (most recent call last):\nUnknown location (pc=0:1238)\nUnknown location (pc=0:1215)\nUnknown location (pc=0:836)\n", + "execution_resources":{ + "data_availability":{ + "l1_data_gas":0, + "l1_gas":0 }, - "steps": 31 + "steps":0 } - }` - - txHash := block0.Transactions[i].Hash() - mockReader.EXPECT().TransactionByHash(txHash).Return(block0.Transactions[i], nil) - mockReader.EXPECT().Receipt(txHash).Return(block0.Receipts[i], block0.Hash, block0.Number, nil) - mockReader.EXPECT().L1Head().Return(&core.L1Head{ - BlockNumber: block0.Number, - BlockHash: block0.Hash, - StateRoot: block0.GlobalStateRoot, - }, nil) - - checkTxReceipt(t, txHash, expected) - }) - t.Run("reverted", func(t *testing.T) { - expected := `{ - "type": "INVOKE", - "transaction_hash": "0x19abec18bbacec23c2eee160c70190a48e4b41dd5ff98ad8f247f9393559998", - "actual_fee": {"amount": "0x247aff6e224", "unit": "WEI"}, - "execution_status": "REVERTED", + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + rpcVersion: "0.7", + }, + { + name: "reverted 0.8", + network: &utils.Integration, + blockNumber: 304740, + index: 1, + expected: `{ + "type":"INVOKE", + "transaction_hash":"0x19abec18bbacec23c2eee160c70190a48e4b41dd5ff98ad8f247f9393559998", + "actual_fee":{ + "amount":"0x247aff6e224", + "unit":"WEI" + }, + "execution_status":"REVERTED", + "finality_status":"ACCEPTED_ON_L2", + "block_hash":"0x76e0229fd0c36dda2ee7905f7e4c9b3ebb78d98c4bfab550bcb3a03bf859a6", + "block_number":304740, + "messages_sent":[ + + ], + "events":[ + + ], + "revert_reason":"Error in the called contract (0x00b1461de04c6a1aa3375bdf9b7723a8779c082ffe21311d683a0b15c078b5dc):\nError at pc=0:25:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:731)\nUnknown location (pc=0:677)\nUnknown location (pc=0:291)\nUnknown location (pc=0:314)\n\nError in the called contract (0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7):\nError at pc=0:104:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1678)\nUnknown location (pc=0:1664)\n\nError in the called contract (0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7):\nError at pc=0:6:\nGot an exception while executing a hint: Assertion failed, 0 % 0x800000000000011000000000000000000000000000000000000000000000001 is equal to 0\nCairo traceback (most recent call last):\nUnknown location (pc=0:1238)\nUnknown location (pc=0:1215)\nUnknown location (pc=0:836)\n", + "execution_resources":{ + "l1_data_gas":0, + "l1_gas":0, + "l2_gas":0 + } + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + rpcVersion: "0.8", + }, + { + name: "v3 tx 0.7", + network: &utils.Integration, + blockNumber: 319132, + index: 0, + expected: `{ + "block_hash": "0x50e864db6b81ce69fbeb70e6a7284ee2febbb9a2e707415de7adab83525e9cd", + "block_number": 319132, + "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "block_hash": "0x76e0229fd0c36dda2ee7905f7e4c9b3ebb78d98c4bfab550bcb3a03bf859a6", - "block_number": 304740, + "transaction_hash": "0x49728601e0bb2f48ce506b0cbd9c0e2a9e50d95858aa41463f46386dca489fd", "messages_sent": [], - "events": [], - "revert_reason": "Error in the called contract (0x00b1461de04c6a1aa3375bdf9b7723a8779c082ffe21311d683a0b15c078b5dc):\nError at pc=0:25:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:731)\nUnknown location (pc=0:677)\nUnknown location (pc=0:291)\nUnknown location (pc=0:314)\n\nError in the called contract (0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7):\nError at pc=0:104:\nGot an exception while executing a hint.\nCairo traceback (most recent call last):\nUnknown location (pc=0:1678)\nUnknown location (pc=0:1664)\n\nError in the called contract (0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7):\nError at pc=0:6:\nGot an exception while executing a hint: Assertion failed, 0 % 0x800000000000011000000000000000000000000000000000000000000000001 is equal to 0\nCairo traceback (most recent call last):\nUnknown location (pc=0:1238)\nUnknown location (pc=0:1215)\nUnknown location (pc=0:836)\n", + "events": [ + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x3f6f3bc663aedc5285d6013cc3ffcbc4341d86ab488b8b68d297f8258793c41", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x16d8b4ad4000", + "0x0" + ] + }, + { + "from_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "keys": [ + "0xa9fa878c35cd3d0191318f89033ca3e5501a3d90e21e3cc9256bdd5cd17fdd" + ], + "data": [ + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0x18ad8494375bc00", + "0x0", + "0x18aef21f822fc00", + "0x0" + ] + } + ], "execution_resources": { - "l1_data_gas": 0, - "l1_gas": 0, - "l2_gas": 0, + "steps": 615, + "range_check_builtin_applications": 19, + "memory_holes": 4, "data_availability": { "l1_data_gas": 0, - "l1_gas": 0, - "l2_gas": 0 - }, - "steps": 0 - } - }` - - integClient := feeder.NewTestClient(t, &utils.Integration) - integGw := adaptfeeder.New(integClient) - - blockWithRevertedTxn, err := integGw.BlockByNumber(context.Background(), 304740) - require.NoError(t, err) - - revertedTxnIdx := 1 - revertedTxnHash := blockWithRevertedTxn.Transactions[revertedTxnIdx].Hash() - - mockReader.EXPECT().TransactionByHash(revertedTxnHash).Return(blockWithRevertedTxn.Transactions[revertedTxnIdx], nil) - mockReader.EXPECT().Receipt(revertedTxnHash).Return(blockWithRevertedTxn.Receipts[revertedTxnIdx], - blockWithRevertedTxn.Hash, blockWithRevertedTxn.Number, nil) - mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) - - checkTxReceipt(t, revertedTxnHash, expected) - }) - - t.Run("v3 tx", func(t *testing.T) { - expected := `{ + "l1_gas": 0 + } + }, + "actual_fee": { + "amount": "0x16d8b4ad4000", + "unit": "FRI" + }, + "type": "INVOKE" + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], + block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + rpcVersion: "0.7", + }, + { + name: "v3 tx 0.8", + network: &utils.Integration, + blockNumber: 319132, + index: 0, + expected: `{ "block_hash": "0x50e864db6b81ce69fbeb70e6a7284ee2febbb9a2e707415de7adab83525e9cd", "block_number": 319132, "execution_status": "SUCCEEDED", @@ -797,44 +1035,32 @@ func TestTransactionReceiptByHash(t *testing.T) { } ], "execution_resources": { - "steps": 615, - "range_check_builtin_applications": 19, - "memory_holes": 4, "l1_data_gas": 0, "l1_gas": 0, - "l2_gas": 0, - "data_availability": { - "l1_data_gas": 0, - "l1_gas": 0, - "l2_gas": 0 - } + "l2_gas": 0 }, "actual_fee": { "amount": "0x16d8b4ad4000", "unit": "FRI" }, "type": "INVOKE" - }` - - integClient := feeder.NewTestClient(t, &utils.Integration) - integGw := adaptfeeder.New(integClient) - - block, err := integGw.BlockByNumber(context.Background(), 319132) - require.NoError(t, err) - - index := 0 - txnHash := block.Transactions[index].Hash() - - mockReader.EXPECT().TransactionByHash(txnHash).Return(block.Transactions[index], nil) - mockReader.EXPECT().Receipt(txnHash).Return(block.Receipts[index], - block.Hash, block.Number, nil) - mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) - - checkTxReceipt(t, txnHash, expected) - }) - - t.Run("tx with non empty data_availability", func(t *testing.T) { - expected := `{ + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], + block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + rpcVersion: "0.8", + }, + { + name: "tx with non empty data_availability 0.7", + network: &utils.SepoliaIntegration, + blockNumber: 35748, + index: 0, + expected: `{ "type": "DECLARE", "transaction_hash": "0x5ac644bbd6ae98d3be2d988439854e33f0961e24f349a63b43e16d172bfe747", "actual_fee": { @@ -866,32 +1092,109 @@ func TestTransactionReceiptByHash(t *testing.T) { "pedersen_builtin_applications": 16, "poseidon_builtin_applications": 4, "range_check_builtin_applications": 157, - "l1_data_gas": 192, - "l1_gas": 117620, - "l2_gas": 0, "data_availability": { "l1_gas": 0, - "l1_data_gas": 192, - "l2_gas": 0 + "l1_data_gas": 192 + } + } + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], + block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + rpcVersion: "0.7", + }, + { + name: "tx with non empty data_availability 0.8", + network: &utils.SepoliaIntegration, + blockNumber: 35748, + index: 0, + expected: `{ + "type": "DECLARE", + "transaction_hash": "0x5ac644bbd6ae98d3be2d988439854e33f0961e24f349a63b43e16d172bfe747", + "actual_fee": { + "amount": "0xd07af45c84550", + "unit": "WEI" + }, + "execution_status": "SUCCEEDED", + "finality_status": "ACCEPTED_ON_L2", + "block_hash": "0x1ea2a9cfa3df5297d58c0a04d09d276bc68d40fe64701305bbe2ed8f417e869", + "block_number": 35748, + "messages_sent": [], + "events": [ + { + "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ], + "data": [ + "0x472aa8128e01eb0df145810c9511a92852d62a68ba8198ce5fa414e6337a365", + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "0xd07af45c84550", + "0x0" + ] } + ], + "execution_resources": { + "l1_data_gas": 192, + "l1_gas": 117620, + "l2_gas": 0 } - }` + }`, + mockBehavior: func(mockReader *mocks.MockReader, index int, block *core.Block) *felt.Felt { + txHash := block.Transactions[index].Hash() + mockReader.EXPECT().TransactionByHash(txHash).Return(block.Transactions[index], nil) + mockReader.EXPECT().Receipt(txHash).Return(block.Receipts[index], + block.Hash, block.Number, nil) + mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + return txHash + }, + rpcVersion: "0.8", + }, + } - netClient := feeder.NewTestClient(t, utils.Ptr(utils.SepoliaIntegration)) - netGW := adaptfeeder.New(netClient) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + mockCtrl := gomock.NewController(t) + t.Cleanup(mockCtrl.Finish) - block, err := netGW.BlockByNumber(context.Background(), 35748) - require.NoError(t, err) + mockReader := mocks.NewMockReader(mockCtrl) + mockSyncReader := mocks.NewMockSyncReader(mockCtrl) + handler := rpc.New(mockReader, mockSyncReader, nil, "", nil) - index := 0 - txnHash := block.Transactions[index].Hash() - mockReader.EXPECT().TransactionByHash(txnHash).Return(block.Transactions[index], nil) - mockReader.EXPECT().Receipt(txnHash).Return(block.Receipts[index], - block.Hash, block.Number, nil) - mockReader.EXPECT().L1Head().Return(nil, db.ErrKeyNotFound) + client := feeder.NewTestClient(t, test.network) + mainnetGw := adaptfeeder.New(client) - checkTxReceipt(t, txnHash, expected) - }) + block, err := mainnetGw.BlockByNumber(context.Background(), test.blockNumber) + require.NoError(t, err) + + txHash := test.mockBehavior(mockReader, test.index, block) + expectedMap := make(map[string]any) + require.NoError(t, json.Unmarshal([]byte(test.expected), &expectedMap)) + + var receipt *rpc.TransactionReceipt + var rErr *jsonrpc.Error + switch test.rpcVersion { + case "0.7": + receipt, rErr = handler.TransactionReceiptByHashV0_7(*txHash) + case "0.8": + receipt, rErr = handler.TransactionReceiptByHash(*txHash) + default: + t.Fatalf("unsupported rpc version: %s", test.rpcVersion) + } + require.Nil(t, rErr) + receiptJSON, jsonErr := json.Marshal(receipt) + require.NoError(t, jsonErr) + + receiptMap := make(map[string]any) + require.NoError(t, json.Unmarshal(receiptJSON, &receiptMap)) + assert.Equal(t, expectedMap, receiptMap) + }) + } } func TestAddTransactionUnmarshal(t *testing.T) { diff --git a/starknet/transaction.go b/starknet/transaction.go index 9b35a083a7..baa81d015d 100644 --- a/starknet/transaction.go +++ b/starknet/transaction.go @@ -220,7 +220,6 @@ type ExecutionResources struct { type DataAvailability struct { L1Gas uint64 `json:"l1_gas"` L1DataGas uint64 `json:"l1_data_gas"` - L2Gas uint64 `json:"l2_gas"` } type BuiltinInstanceCounter struct { From ae3633aab44b8c4861e8435d8fc61dbc225b6e02 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 28 Jan 2025 18:03:51 +0300 Subject: [PATCH 2/8] Fix e2e --- rpc/handlers.go | 6 +++--- rpc/simulation.go | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/rpc/handlers.go b/rpc/handlers.go index 83759b9528..6fbc3d4028 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -442,7 +442,7 @@ func (h *Handler) MethodsV0_7() ([]jsonrpc.Method, string) { //nolint: funlen { Name: "starknet_getTransactionReceipt", Params: []jsonrpc.Parameter{{Name: "transaction_hash"}}, - Handler: h.TransactionReceiptByHash, + Handler: h.TransactionReceiptByHashV0_7, }, { Name: "starknet_getBlockTransactionCount", @@ -550,7 +550,7 @@ func (h *Handler) MethodsV0_7() ([]jsonrpc.Method, string) { //nolint: funlen { Name: "starknet_simulateTransactions", Params: []jsonrpc.Parameter{{Name: "block_id"}, {Name: "transactions"}, {Name: "simulation_flags"}}, - Handler: h.SimulateTransactions, + Handler: h.SimulateTransactionsV0_7, }, { Name: "starknet_traceBlockTransactions", @@ -574,7 +574,7 @@ func (h *Handler) MethodsV0_7() ([]jsonrpc.Method, string) { //nolint: funlen { Name: "starknet_getBlockWithReceipts", Params: []jsonrpc.Parameter{{Name: "block_id"}}, - Handler: h.BlockWithReceipts, + Handler: h.BlockWithReceiptsV0_7, }, }, "/v0_7" } diff --git a/rpc/simulation.go b/rpc/simulation.go index 743610b3f6..92afe4b96a 100644 --- a/rpc/simulation.go +++ b/rpc/simulation.go @@ -56,6 +56,12 @@ func (h *Handler) SimulateTransactions(id BlockID, transactions []BroadcastedTra return h.simulateTransactions(id, transactions, simulationFlags, false, V0_8) } +func (h *Handler) SimulateTransactionsV0_7(id BlockID, transactions []BroadcastedTransaction, + simulationFlags []SimulationFlag, +) ([]SimulatedTransaction, http.Header, *jsonrpc.Error) { + return h.simulateTransactions(id, transactions, simulationFlags, false, V0_7) +} + func (h *Handler) simulateTransactions(id BlockID, transactions []BroadcastedTransaction, simulationFlags []SimulationFlag, errOnRevert bool, rpcVersion version, ) ([]SimulatedTransaction, http.Header, *jsonrpc.Error) { From a54343af6385881cbd4f4aaaed530cd299824eb8 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 28 Jan 2025 19:47:02 +0300 Subject: [PATCH 3/8] Fix e2e --- rpc/block.go | 60 +++++++++++++++++++++++++++++++++++++++++--- rpc/estimate_fee.go | 18 ++++++------- rpc/handlers.go | 4 +-- rpc/subscriptions.go | 23 +++++++++++------ 4 files changed, 83 insertions(+), 22 deletions(-) diff --git a/rpc/block.go b/rpc/block.go index 0f0678eef7..fcbebab10d 100644 --- a/rpc/block.go +++ b/rpc/block.go @@ -111,6 +111,41 @@ type BlockHeader struct { L1DataGasPrice *ResourcePrice `json:"l1_data_gas_price,omitempty"` L1DAMode *L1DAMode `json:"l1_da_mode,omitempty"` StarknetVersion string `json:"starknet_version"` + rpcVersion version +} + +func (h BlockHeader) MarshalJSON() ([]byte, error) { //nolint:gocritic + switch h.rpcVersion { + case V0_7: + return json.Marshal(struct { + Hash *felt.Felt `json:"block_hash,omitempty"` + ParentHash *felt.Felt `json:"parent_hash"` + Number *uint64 `json:"block_number,omitempty"` + NewRoot *felt.Felt `json:"new_root,omitempty"` + Timestamp uint64 `json:"timestamp"` + SequencerAddress *felt.Felt `json:"sequencer_address,omitempty"` + L1GasPrice *ResourcePrice `json:"l1_gas_price"` + L1DataGasPrice *ResourcePrice `json:"l1_data_gas_price,omitempty"` + L1DAMode *L1DAMode `json:"l1_da_mode,omitempty"` + StarknetVersion string `json:"starknet_version"` + }{ + Hash: h.Hash, + ParentHash: h.ParentHash, + Number: h.Number, + NewRoot: h.NewRoot, + Timestamp: h.Timestamp, + SequencerAddress: h.SequencerAddress, + L1GasPrice: h.L1GasPrice, + L1DataGasPrice: h.L1DataGasPrice, + L1DAMode: h.L1DAMode, + StarknetVersion: h.StarknetVersion, + }) + case V0_8: + type alias BlockHeader // avoid infinite recursion + return json.Marshal(alias(h)) + default: + return nil, errors.New("unknown BlockHeader version") + } } // https://github.com/starkware-libs/starknet-specs/blob/a789ccc3432c57777beceaa53a34a7ae2f25fda0/api/starknet_api_openrpc.json#L1131 @@ -172,6 +207,14 @@ func (h *Handler) BlockHashAndNumber() (*BlockHashAndNumber, *jsonrpc.Error) { // It follows the specification defined here: // https://github.com/starkware-libs/starknet-specs/blob/a789ccc3432c57777beceaa53a34a7ae2f25fda0/api/starknet_api_openrpc.json#L11 func (h *Handler) BlockWithTxHashes(id BlockID) (*BlockWithTxHashes, *jsonrpc.Error) { + return h.blockWithTxHashes(id, V0_8) +} + +func (h *Handler) BlockWithTxHashesV0_7(id BlockID) (*BlockWithTxHashes, *jsonrpc.Error) { + return h.blockWithTxHashes(id, V0_7) +} + +func (h *Handler) blockWithTxHashes(id BlockID, rpcVersion version) (*BlockWithTxHashes, *jsonrpc.Error) { block, rpcErr := h.blockByID(&id) if rpcErr != nil { return nil, rpcErr @@ -189,7 +232,7 @@ func (h *Handler) BlockWithTxHashes(id BlockID) (*BlockWithTxHashes, *jsonrpc.Er return &BlockWithTxHashes{ Status: status, - BlockHeader: adaptBlockHeader(block.Header), + BlockHeader: adaptBlockHeader(block.Header, rpcVersion), TxnHashes: txnHashes, }, nil } @@ -246,7 +289,7 @@ func (h *Handler) blockWithReceipts(id BlockID, rpcVersion version) (*BlockWithR return &BlockWithReceipts{ Status: blockStatus, - BlockHeader: adaptBlockHeader(block.Header), + BlockHeader: adaptBlockHeader(block.Header, rpcVersion), Transactions: txsWithReceipts, }, nil } @@ -256,6 +299,14 @@ func (h *Handler) blockWithReceipts(id BlockID, rpcVersion version) (*BlockWithR // It follows the specification defined here: // https://github.com/starkware-libs/starknet-specs/blob/a789ccc3432c57777beceaa53a34a7ae2f25fda0/api/starknet_api_openrpc.json#L44 func (h *Handler) BlockWithTxs(id BlockID) (*BlockWithTxs, *jsonrpc.Error) { + return h.blockWithTxs(id, V0_8) +} + +func (h *Handler) BlockWithTxsV0_7(id BlockID) (*BlockWithTxs, *jsonrpc.Error) { + return h.blockWithTxs(id, V0_7) +} + +func (h *Handler) blockWithTxs(id BlockID, rpcVersion version) (*BlockWithTxs, *jsonrpc.Error) { block, rpcErr := h.blockByID(&id) if rpcErr != nil { return nil, rpcErr @@ -273,7 +324,7 @@ func (h *Handler) BlockWithTxs(id BlockID) (*BlockWithTxs, *jsonrpc.Error) { return &BlockWithTxs{ Status: status, - BlockHeader: adaptBlockHeader(block.Header), + BlockHeader: adaptBlockHeader(block.Header, rpcVersion), Transactions: txs, }, nil } @@ -294,7 +345,7 @@ func (h *Handler) blockStatus(id BlockID, block *core.Block) (BlockStatus, *json return status, nil } -func adaptBlockHeader(header *core.Header) BlockHeader { +func adaptBlockHeader(header *core.Header, rpcVersion version) BlockHeader { var blockNumber *uint64 // if header.Hash == nil it's a pending block if header.Hash != nil { @@ -355,6 +406,7 @@ func adaptBlockHeader(header *core.Header) BlockHeader { L1DataGasPrice: &l1DataGasPrice, L1DAMode: &l1DAMode, StarknetVersion: header.ProtocolVersion, + rpcVersion: rpcVersion, } } diff --git a/rpc/estimate_fee.go b/rpc/estimate_fee.go index ab311344a6..5bf077c75a 100644 --- a/rpc/estimate_fee.go +++ b/rpc/estimate_fee.go @@ -74,19 +74,19 @@ func (f FeeEstimate) MarshalJSON() ([]byte, error) { func (h *Handler) EstimateFeeV0_7(broadcastedTxns []BroadcastedTransaction, simulationFlags []SimulationFlag, id BlockID, ) ([]FeeEstimate, http.Header, *jsonrpc.Error) { - result, httpHeader, err := h.simulateTransactions(id, broadcastedTxns, append(simulationFlags, SkipFeeChargeFlag), true, V0_7) - if err != nil { - return nil, httpHeader, err - } - - return utils.Map(result, func(tx SimulatedTransaction) FeeEstimate { - return tx.FeeEstimation - }), httpHeader, nil + return h.estimateFee(broadcastedTxns, simulationFlags, id, V0_7) } + func (h *Handler) EstimateFee(broadcastedTxns []BroadcastedTransaction, simulationFlags []SimulationFlag, id BlockID, ) ([]FeeEstimate, http.Header, *jsonrpc.Error) { - result, httpHeader, err := h.simulateTransactions(id, broadcastedTxns, append(simulationFlags, SkipFeeChargeFlag), true, V0_8) + return h.estimateFee(broadcastedTxns, simulationFlags, id, V0_8) +} + +func (h *Handler) estimateFee(broadcastedTxns []BroadcastedTransaction, + simulationFlags []SimulationFlag, id BlockID, rpcVersion version, +) ([]FeeEstimate, http.Header, *jsonrpc.Error) { + result, httpHeader, err := h.simulateTransactions(id, broadcastedTxns, append(simulationFlags, SkipFeeChargeFlag), true, rpcVersion) if err != nil { return nil, httpHeader, err } diff --git a/rpc/handlers.go b/rpc/handlers.go index 6fbc3d4028..2ab8f04fd5 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -427,7 +427,7 @@ func (h *Handler) MethodsV0_7() ([]jsonrpc.Method, string) { //nolint: funlen { Name: "starknet_getBlockWithTxHashes", Params: []jsonrpc.Parameter{{Name: "block_id"}}, - Handler: h.BlockWithTxHashes, + Handler: h.BlockWithTxHashesV0_7, }, { Name: "starknet_getBlockWithTxs", @@ -564,7 +564,7 @@ func (h *Handler) MethodsV0_7() ([]jsonrpc.Method, string) { //nolint: funlen { Name: "starknet_subscribeNewHeads", Params: []jsonrpc.Parameter{{Name: "block", Optional: true}}, - Handler: h.SubscribeNewHeads, + Handler: h.SubscribeNewHeadsV0_7, }, { Name: "starknet_unsubscribe", diff --git a/rpc/subscriptions.go b/rpc/subscriptions.go index 13e2a6f43b..9cd882a813 100644 --- a/rpc/subscriptions.go +++ b/rpc/subscriptions.go @@ -331,6 +331,14 @@ func sendEvents(ctx context.Context, w jsonrpc.Conn, events []*blockchain.Filter // SubscribeNewHeads creates a WebSocket stream which will fire events when a new block header is added. func (h *Handler) SubscribeNewHeads(ctx context.Context, blockID *BlockID) (*SubscriptionID, *jsonrpc.Error) { + return h.subscribeNewHeads(ctx, blockID, V0_8) +} + +func (h *Handler) SubscribeNewHeadsV0_7(ctx context.Context, blockID *BlockID) (*SubscriptionID, *jsonrpc.Error) { + return h.subscribeNewHeads(ctx, blockID, V0_7) +} + +func (h *Handler) subscribeNewHeads(ctx context.Context, blockID *BlockID, rpcVersion version) (*SubscriptionID, *jsonrpc.Error) { w, ok := jsonrpc.ConnFromContext(ctx) if !ok { return nil, jsonrpc.Err(jsonrpc.MethodNotFound, nil) @@ -367,7 +375,7 @@ func (h *Handler) SubscribeNewHeads(ctx context.Context, blockID *BlockID) (*Sub var wg conc.WaitGroup wg.Go(func() { - if err := h.sendHistoricalHeaders(subscriptionCtx, startHeader, latestHeader, w, id); err != nil { + if err := h.sendHistoricalHeaders(subscriptionCtx, startHeader, latestHeader, w, id, rpcVersion); err != nil { h.log.Errorw("Error sending old headers", "err", err) return } @@ -378,7 +386,7 @@ func (h *Handler) SubscribeNewHeads(ctx context.Context, blockID *BlockID) (*Sub }) wg.Go(func() { - h.processNewHeaders(subscriptionCtx, headerSub, w, id) + h.processNewHeaders(subscriptionCtx, headerSub, w, id, rpcVersion) }) wg.Wait() @@ -546,6 +554,7 @@ func (h *Handler) sendHistoricalHeaders( startHeader, latestHeader *core.Header, w jsonrpc.Conn, id uint64, + rpcVersion version, ) error { var ( err error @@ -557,7 +566,7 @@ func (h *Handler) sendHistoricalHeaders( case <-ctx.Done(): return ctx.Err() default: - if err := h.sendHeader(w, curHeader, id); err != nil { + if err := h.sendHeader(w, curHeader, id, rpcVersion); err != nil { return err } @@ -573,13 +582,13 @@ func (h *Handler) sendHistoricalHeaders( } } -func (h *Handler) processNewHeaders(ctx context.Context, headerSub *feed.Subscription[*core.Header], w jsonrpc.Conn, id uint64) { +func (h *Handler) processNewHeaders(ctx context.Context, headerSub *feed.Subscription[*core.Header], w jsonrpc.Conn, id uint64, rpcVersion version) { for { select { case <-ctx.Done(): return case header := <-headerSub.Recv(): - if err := h.sendHeader(w, header, id); err != nil { + if err := h.sendHeader(w, header, id, rpcVersion); err != nil { h.log.Warnw("Error sending header", "err", err) return } @@ -588,13 +597,13 @@ func (h *Handler) processNewHeaders(ctx context.Context, headerSub *feed.Subscri } // sendHeader creates a request and sends it to the client -func (h *Handler) sendHeader(w jsonrpc.Conn, header *core.Header, id uint64) error { +func (h *Handler) sendHeader(w jsonrpc.Conn, header *core.Header, id uint64, rpcVersion version) error { resp, err := json.Marshal(SubscriptionResponse{ Version: "2.0", Method: "starknet_subscriptionNewHeads", Params: map[string]any{ "subscription_id": id, - "result": adaptBlockHeader(header), + "result": adaptBlockHeader(header, rpcVersion), }, }) if err != nil { From 308530fa924d9b343334a7826208ca6c39f03cea Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 28 Jan 2025 19:49:27 +0300 Subject: [PATCH 4/8] Fix e2e --- rpc/handlers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/handlers.go b/rpc/handlers.go index 2ab8f04fd5..374af7953f 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -432,7 +432,7 @@ func (h *Handler) MethodsV0_7() ([]jsonrpc.Method, string) { //nolint: funlen { Name: "starknet_getBlockWithTxs", Params: []jsonrpc.Parameter{{Name: "block_id"}}, - Handler: h.BlockWithTxs, + Handler: h.BlockWithTxsV0_7, }, { Name: "starknet_getTransactionByHash", From ccdad1b8811050a9640f2ac9fbd1bc7d787e6e2b Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 28 Jan 2025 20:50:21 +0300 Subject: [PATCH 5/8] Fix e2e --- rpc/simulation.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/rpc/simulation.go b/rpc/simulation.go index 92afe4b96a..1638ca93cd 100644 --- a/rpc/simulation.go +++ b/rpc/simulation.go @@ -150,17 +150,29 @@ func (h *Handler) simulateTransactions(id BlockID, transactions []BroadcastedTra } func calculateFeeEstimate(overallFee *felt.Felt, l1DataGas uint64, feeUnit FeeUnit, header *core.Header, rpcVersion version) FeeEstimate { - var l1GasPrice, l2GasPrice, l1DataGasPrice *felt.Felt + var l1GasPrice *felt.Felt + l2GasPrice := &felt.Zero + l1DataGasPrice := &felt.Zero switch feeUnit { case FRI: - l1GasPrice = header.L1GasPriceSTRK - l2GasPrice = header.L2GasPrice.PriceInFri - l1DataGasPrice = header.L1DataGasPrice.PriceInFri + if l1GasPrice = header.L1GasPriceSTRK; l1GasPrice == nil { + l1GasPrice = &felt.Zero + } + if gasPrice := header.L2GasPrice; gasPrice != nil { + l2GasPrice = gasPrice.PriceInFri + } + if gasPrice := header.L1DataGasPrice; gasPrice != nil { + l1DataGasPrice = gasPrice.PriceInFri + } case WEI: l1GasPrice = header.L1GasPriceETH - l2GasPrice = header.L2GasPrice.PriceInWei - l1DataGasPrice = header.L1DataGasPrice.PriceInWei + if gasPrice := header.L2GasPrice; gasPrice != nil { + l2GasPrice = gasPrice.PriceInWei + } + if gasPrice := header.L1DataGasPrice; gasPrice != nil { + l1DataGasPrice = gasPrice.PriceInWei + } } l1DataGasConsumed := new(felt.Felt).SetUint64(l1DataGas) From 43ac42ef3ed14af9995c266145358dc1abec39f7 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 29 Jan 2025 10:22:02 +0300 Subject: [PATCH 6/8] Fix e2e --- rpc/block.go | 79 ++++++++++++++------------------------------ rpc/subscriptions.go | 8 ++--- 2 files changed, 29 insertions(+), 58 deletions(-) diff --git a/rpc/block.go b/rpc/block.go index fcbebab10d..7a6c606e01 100644 --- a/rpc/block.go +++ b/rpc/block.go @@ -107,45 +107,10 @@ type BlockHeader struct { Timestamp uint64 `json:"timestamp"` SequencerAddress *felt.Felt `json:"sequencer_address,omitempty"` L1GasPrice *ResourcePrice `json:"l1_gas_price"` - L2GasPrice *ResourcePrice `json:"l2_gas_price"` + L2GasPrice *ResourcePrice `json:"l2_gas_price,omitempty"` L1DataGasPrice *ResourcePrice `json:"l1_data_gas_price,omitempty"` L1DAMode *L1DAMode `json:"l1_da_mode,omitempty"` StarknetVersion string `json:"starknet_version"` - rpcVersion version -} - -func (h BlockHeader) MarshalJSON() ([]byte, error) { //nolint:gocritic - switch h.rpcVersion { - case V0_7: - return json.Marshal(struct { - Hash *felt.Felt `json:"block_hash,omitempty"` - ParentHash *felt.Felt `json:"parent_hash"` - Number *uint64 `json:"block_number,omitempty"` - NewRoot *felt.Felt `json:"new_root,omitempty"` - Timestamp uint64 `json:"timestamp"` - SequencerAddress *felt.Felt `json:"sequencer_address,omitempty"` - L1GasPrice *ResourcePrice `json:"l1_gas_price"` - L1DataGasPrice *ResourcePrice `json:"l1_data_gas_price,omitempty"` - L1DAMode *L1DAMode `json:"l1_da_mode,omitempty"` - StarknetVersion string `json:"starknet_version"` - }{ - Hash: h.Hash, - ParentHash: h.ParentHash, - Number: h.Number, - NewRoot: h.NewRoot, - Timestamp: h.Timestamp, - SequencerAddress: h.SequencerAddress, - L1GasPrice: h.L1GasPrice, - L1DataGasPrice: h.L1DataGasPrice, - L1DAMode: h.L1DAMode, - StarknetVersion: h.StarknetVersion, - }) - case V0_8: - type alias BlockHeader // avoid infinite recursion - return json.Marshal(alias(h)) - default: - return nil, errors.New("unknown BlockHeader version") - } } // https://github.com/starkware-libs/starknet-specs/blob/a789ccc3432c57777beceaa53a34a7ae2f25fda0/api/starknet_api_openrpc.json#L1131 @@ -206,15 +171,16 @@ func (h *Handler) BlockHashAndNumber() (*BlockHashAndNumber, *jsonrpc.Error) { // // It follows the specification defined here: // https://github.com/starkware-libs/starknet-specs/blob/a789ccc3432c57777beceaa53a34a7ae2f25fda0/api/starknet_api_openrpc.json#L11 -func (h *Handler) BlockWithTxHashes(id BlockID) (*BlockWithTxHashes, *jsonrpc.Error) { - return h.blockWithTxHashes(id, V0_8) -} - func (h *Handler) BlockWithTxHashesV0_7(id BlockID) (*BlockWithTxHashes, *jsonrpc.Error) { - return h.blockWithTxHashes(id, V0_7) + blockWithTxHashes, rpcErr := h.BlockWithTxHashes(id) + if rpcErr != nil { + return nil, rpcErr + } + blockWithTxHashes.L2GasPrice = nil + return blockWithTxHashes, nil } -func (h *Handler) blockWithTxHashes(id BlockID, rpcVersion version) (*BlockWithTxHashes, *jsonrpc.Error) { +func (h *Handler) BlockWithTxHashes(id BlockID) (*BlockWithTxHashes, *jsonrpc.Error) { block, rpcErr := h.blockByID(&id) if rpcErr != nil { return nil, rpcErr @@ -232,7 +198,7 @@ func (h *Handler) blockWithTxHashes(id BlockID, rpcVersion version) (*BlockWithT return &BlockWithTxHashes{ Status: status, - BlockHeader: adaptBlockHeader(block.Header, rpcVersion), + BlockHeader: adaptBlockHeader(block.Header), TxnHashes: txnHashes, }, nil } @@ -251,7 +217,12 @@ func (h *Handler) BlockTransactionCount(id BlockID) (uint64, *jsonrpc.Error) { } func (h *Handler) BlockWithReceiptsV0_7(id BlockID) (*BlockWithReceipts, *jsonrpc.Error) { - return h.blockWithReceipts(id, V0_7) + blockWithReceipts, err := h.blockWithReceipts(id, V0_7) + if err != nil { + return nil, err + } + blockWithReceipts.L2GasPrice = nil + return blockWithReceipts, nil } func (h *Handler) BlockWithReceipts(id BlockID) (*BlockWithReceipts, *jsonrpc.Error) { @@ -289,7 +260,7 @@ func (h *Handler) blockWithReceipts(id BlockID, rpcVersion version) (*BlockWithR return &BlockWithReceipts{ Status: blockStatus, - BlockHeader: adaptBlockHeader(block.Header, rpcVersion), + BlockHeader: adaptBlockHeader(block.Header), Transactions: txsWithReceipts, }, nil } @@ -298,15 +269,16 @@ func (h *Handler) blockWithReceipts(id BlockID, rpcVersion version) (*BlockWithR // // It follows the specification defined here: // https://github.com/starkware-libs/starknet-specs/blob/a789ccc3432c57777beceaa53a34a7ae2f25fda0/api/starknet_api_openrpc.json#L44 -func (h *Handler) BlockWithTxs(id BlockID) (*BlockWithTxs, *jsonrpc.Error) { - return h.blockWithTxs(id, V0_8) -} - func (h *Handler) BlockWithTxsV0_7(id BlockID) (*BlockWithTxs, *jsonrpc.Error) { - return h.blockWithTxs(id, V0_7) + blockWithTxs, rpcErr := h.BlockWithTxs(id) + if rpcErr != nil { + return nil, rpcErr + } + blockWithTxs.L2GasPrice = nil + return blockWithTxs, nil } -func (h *Handler) blockWithTxs(id BlockID, rpcVersion version) (*BlockWithTxs, *jsonrpc.Error) { +func (h *Handler) BlockWithTxs(id BlockID) (*BlockWithTxs, *jsonrpc.Error) { block, rpcErr := h.blockByID(&id) if rpcErr != nil { return nil, rpcErr @@ -324,7 +296,7 @@ func (h *Handler) blockWithTxs(id BlockID, rpcVersion version) (*BlockWithTxs, * return &BlockWithTxs{ Status: status, - BlockHeader: adaptBlockHeader(block.Header, rpcVersion), + BlockHeader: adaptBlockHeader(block.Header), Transactions: txs, }, nil } @@ -345,7 +317,7 @@ func (h *Handler) blockStatus(id BlockID, block *core.Block) (BlockStatus, *json return status, nil } -func adaptBlockHeader(header *core.Header, rpcVersion version) BlockHeader { +func adaptBlockHeader(header *core.Header) BlockHeader { var blockNumber *uint64 // if header.Hash == nil it's a pending block if header.Hash != nil { @@ -406,7 +378,6 @@ func adaptBlockHeader(header *core.Header, rpcVersion version) BlockHeader { L1DataGasPrice: &l1DataGasPrice, L1DAMode: &l1DAMode, StarknetVersion: header.ProtocolVersion, - rpcVersion: rpcVersion, } } diff --git a/rpc/subscriptions.go b/rpc/subscriptions.go index 9cd882a813..33b1cb9782 100644 --- a/rpc/subscriptions.go +++ b/rpc/subscriptions.go @@ -566,7 +566,7 @@ func (h *Handler) sendHistoricalHeaders( case <-ctx.Done(): return ctx.Err() default: - if err := h.sendHeader(w, curHeader, id, rpcVersion); err != nil { + if err := h.sendHeader(w, curHeader, id); err != nil { return err } @@ -588,7 +588,7 @@ func (h *Handler) processNewHeaders(ctx context.Context, headerSub *feed.Subscri case <-ctx.Done(): return case header := <-headerSub.Recv(): - if err := h.sendHeader(w, header, id, rpcVersion); err != nil { + if err := h.sendHeader(w, header, id); err != nil { h.log.Warnw("Error sending header", "err", err) return } @@ -597,13 +597,13 @@ func (h *Handler) processNewHeaders(ctx context.Context, headerSub *feed.Subscri } // sendHeader creates a request and sends it to the client -func (h *Handler) sendHeader(w jsonrpc.Conn, header *core.Header, id uint64, rpcVersion version) error { +func (h *Handler) sendHeader(w jsonrpc.Conn, header *core.Header, id uint64) error { resp, err := json.Marshal(SubscriptionResponse{ Version: "2.0", Method: "starknet_subscriptionNewHeads", Params: map[string]any{ "subscription_id": id, - "result": adaptBlockHeader(header, rpcVersion), + "result": adaptBlockHeader(header), }, }) if err != nil { From 4fd0d3dded69c24151cdadc9238c87fa1fb7c437 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 29 Jan 2025 10:33:28 +0300 Subject: [PATCH 7/8] Fix e2e --- rpc/handlers.go | 2 +- rpc/subscriptions.go | 15 +++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/rpc/handlers.go b/rpc/handlers.go index 374af7953f..e27b76b835 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -564,7 +564,7 @@ func (h *Handler) MethodsV0_7() ([]jsonrpc.Method, string) { //nolint: funlen { Name: "starknet_subscribeNewHeads", Params: []jsonrpc.Parameter{{Name: "block", Optional: true}}, - Handler: h.SubscribeNewHeadsV0_7, + Handler: h.SubscribeNewHeads, }, { Name: "starknet_unsubscribe", diff --git a/rpc/subscriptions.go b/rpc/subscriptions.go index 33b1cb9782..13e2a6f43b 100644 --- a/rpc/subscriptions.go +++ b/rpc/subscriptions.go @@ -331,14 +331,6 @@ func sendEvents(ctx context.Context, w jsonrpc.Conn, events []*blockchain.Filter // SubscribeNewHeads creates a WebSocket stream which will fire events when a new block header is added. func (h *Handler) SubscribeNewHeads(ctx context.Context, blockID *BlockID) (*SubscriptionID, *jsonrpc.Error) { - return h.subscribeNewHeads(ctx, blockID, V0_8) -} - -func (h *Handler) SubscribeNewHeadsV0_7(ctx context.Context, blockID *BlockID) (*SubscriptionID, *jsonrpc.Error) { - return h.subscribeNewHeads(ctx, blockID, V0_7) -} - -func (h *Handler) subscribeNewHeads(ctx context.Context, blockID *BlockID, rpcVersion version) (*SubscriptionID, *jsonrpc.Error) { w, ok := jsonrpc.ConnFromContext(ctx) if !ok { return nil, jsonrpc.Err(jsonrpc.MethodNotFound, nil) @@ -375,7 +367,7 @@ func (h *Handler) subscribeNewHeads(ctx context.Context, blockID *BlockID, rpcVe var wg conc.WaitGroup wg.Go(func() { - if err := h.sendHistoricalHeaders(subscriptionCtx, startHeader, latestHeader, w, id, rpcVersion); err != nil { + if err := h.sendHistoricalHeaders(subscriptionCtx, startHeader, latestHeader, w, id); err != nil { h.log.Errorw("Error sending old headers", "err", err) return } @@ -386,7 +378,7 @@ func (h *Handler) subscribeNewHeads(ctx context.Context, blockID *BlockID, rpcVe }) wg.Go(func() { - h.processNewHeaders(subscriptionCtx, headerSub, w, id, rpcVersion) + h.processNewHeaders(subscriptionCtx, headerSub, w, id) }) wg.Wait() @@ -554,7 +546,6 @@ func (h *Handler) sendHistoricalHeaders( startHeader, latestHeader *core.Header, w jsonrpc.Conn, id uint64, - rpcVersion version, ) error { var ( err error @@ -582,7 +573,7 @@ func (h *Handler) sendHistoricalHeaders( } } -func (h *Handler) processNewHeaders(ctx context.Context, headerSub *feed.Subscription[*core.Header], w jsonrpc.Conn, id uint64, rpcVersion version) { +func (h *Handler) processNewHeaders(ctx context.Context, headerSub *feed.Subscription[*core.Header], w jsonrpc.Conn, id uint64) { for { select { case <-ctx.Done(): From 94cf299e59ce6cfa3d7b8de55cd478622fe86100 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 29 Jan 2025 11:28:28 +0300 Subject: [PATCH 8/8] Fix e2e --- rpc/estimate_fee_pkg_test.go | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 rpc/estimate_fee_pkg_test.go diff --git a/rpc/estimate_fee_pkg_test.go b/rpc/estimate_fee_pkg_test.go new file mode 100644 index 0000000000..5f323c6921 --- /dev/null +++ b/rpc/estimate_fee_pkg_test.go @@ -0,0 +1,55 @@ +package rpc + +import ( + "testing" + + "github.com/NethermindEth/juno/core/felt" + "github.com/NethermindEth/juno/utils" + "github.com/stretchr/testify/require" +) + +func TestEstimateFeeMarshalJson(t *testing.T) { + tests := []struct { + name string + f FeeEstimate + want []byte + }{ + { //nolint:dupl + name: "V0_7", + f: FeeEstimate{ + L1GasConsumed: new(felt.Felt).SetUint64(1), + L1GasPrice: new(felt.Felt).SetUint64(2), + L2GasConsumed: new(felt.Felt).SetUint64(3), + L2GasPrice: new(felt.Felt).SetUint64(4), + L1DataGasConsumed: new(felt.Felt).SetUint64(5), + L1DataGasPrice: new(felt.Felt).SetUint64(6), + OverallFee: new(felt.Felt).SetUint64(7), + Unit: utils.Ptr(WEI), + rpcVersion: V0_7, + }, + want: []byte(`{"gas_consumed":"0x1","gas_price":"0x2","data_gas_consumed":"0x5","data_gas_price":"0x6","overall_fee":"0x7","unit":"WEI"}`), + }, + { //nolint:dupl + name: "V0_8", + f: FeeEstimate{ + L1GasConsumed: new(felt.Felt).SetUint64(8), + L1GasPrice: new(felt.Felt).SetUint64(9), + L2GasConsumed: new(felt.Felt).SetUint64(10), + L2GasPrice: new(felt.Felt).SetUint64(11), + L1DataGasConsumed: new(felt.Felt).SetUint64(12), + L1DataGasPrice: new(felt.Felt).SetUint64(13), + OverallFee: new(felt.Felt).SetUint64(14), + Unit: utils.Ptr(WEI), + rpcVersion: V0_8, + }, + want: []byte(`{"l1_gas_consumed":"0x8","l1_gas_price":"0x9","l2_gas_consumed":"0xa","l2_gas_price":"0xb","l1_data_gas_consumed":"0xc","l1_data_gas_price":"0xd","overall_fee":"0xe","unit":"WEI"}`), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.f.MarshalJSON() + require.NoError(t, err) + require.Equal(t, tt.want, got) + }) + } +}