diff --git a/adapters/core2p2p/block.go b/adapters/core2p2p/block.go index fa3c5b446d..5dd6c49a44 100644 --- a/adapters/core2p2p/block.go +++ b/adapters/core2p2p/block.go @@ -47,13 +47,13 @@ func AdaptHeader(header *core.Header, commitments *core.BlockCommitments, }, Receipts: AdaptHash(commitments.ReceiptCommitment), ProtocolVersion: header.ProtocolVersion, - GasPriceFri: AdaptUint128(header.GasPriceSTRK), + GasPriceFri: AdaptUint128(header.L1GasPriceSTRK), Signatures: utils.Map(header.Signatures, AdaptSignature), StateDiffCommitment: &spec.StateDiffCommitment{ StateDiffLength: stateDiffLength, Root: AdaptHash(stateDiffCommitment), }, - GasPriceWei: AdaptUint128(header.GasPrice), + GasPriceWei: AdaptUint128(header.L1GasPriceETH), DataGasPriceFri: AdaptUint128(header.L1DataGasPrice.PriceInFri), DataGasPriceWei: AdaptUint128(header.L1DataGasPrice.PriceInWei), L1DataAvailabilityMode: adaptL1DA(header.L1DAMode), diff --git a/adapters/p2p2core/block.go b/adapters/p2p2core/block.go index e593a3d6c8..74e334ce9e 100644 --- a/adapters/p2p2core/block.go +++ b/adapters/p2p2core/block.go @@ -34,14 +34,16 @@ func AdaptBlockHeader(h *spec.SignedBlockHeader, eventsBloom *bloom.BloomFilter) Timestamp: h.Time, ProtocolVersion: h.ProtocolVersion, EventsBloom: eventsBloom, + L1GasPriceETH: AdaptUint128(h.GasPriceWei), + L2GasPriceETH: nil, // TODO: Fix when we have l2 gas price Signatures: utils.Map(h.Signatures, adaptSignature), + L1GasPriceSTRK: AdaptUint128(h.GasPriceFri), + L2GasPriceSTRK: nil, // TODO: Fix when we have l2 gas price L1DAMode: adaptDA(h.L1DataAvailabilityMode), L1DataGasPrice: &core.GasPrice{ PriceInWei: AdaptUint128(h.DataGasPriceWei), PriceInFri: AdaptUint128(h.DataGasPriceFri), }, - GasPrice: AdaptUint128(h.GasPriceWei), - GasPriceSTRK: AdaptUint128(h.GasPriceFri), } } diff --git a/adapters/sn2core/sn2core.go b/adapters/sn2core/sn2core.go index ead1605a64..4b5174dd70 100644 --- a/adapters/sn2core/sn2core.go +++ b/adapters/sn2core/sn2core.go @@ -50,8 +50,10 @@ func AdaptBlock(response *starknet.Block, sig *starknet.Signature) (*core.Block, TransactionCount: uint64(len(response.Transactions)), EventCount: eventCount, EventsBloom: core.EventsBloom(receipts), - GasPrice: response.GasPriceETH(), - GasPriceSTRK: response.GasPriceSTRK(), + L1GasPriceETH: response.L1GasPriceETH(), + L2GasPriceETH: response.L2GasPriceETH(), + L1GasPriceSTRK: response.L1GasPriceSTRK(), + L2GasPriceSTRK: response.L2GasPriceSTRK(), L1DAMode: core.L1DAMode(response.L1DAMode), L1DataGasPrice: (*core.GasPrice)(response.L1DataGasPrice), Signatures: sigs, diff --git a/adapters/sn2core/sn2core_test.go b/adapters/sn2core/sn2core_test.go index c9d7b618aa..36c2dce608 100644 --- a/adapters/sn2core/sn2core_test.go +++ b/adapters/sn2core/sn2core_test.go @@ -120,8 +120,10 @@ func TestAdaptBlock(t *testing.T) { assert.Empty(t, block.Signatures) } - assert.Equal(t, test.gasPriceSTRK, block.GasPriceSTRK) - assert.Equal(t, test.gasPriceWEI, block.GasPrice) + assert.Equal(t, test.gasPriceSTRK, block.L1GasPriceSTRK) + assert.Equal(t, test.gasPriceWEI, block.L1GasPriceETH) + assert.Nil(t, block.L2GasPriceSTRK) + assert.Nil(t, block.L2GasPriceETH) if test.l1DAGasPriceFRI != nil { assert.Equal(t, test.l1DAGasPriceFRI, block.L1DataGasPrice.PriceInFri) } diff --git a/clients/feeder/feeder_test.go b/clients/feeder/feeder_test.go index a22590a943..85fe79ecb6 100644 --- a/clients/feeder/feeder_test.go +++ b/clients/feeder/feeder_test.go @@ -273,7 +273,7 @@ func TestBlockWithoutSequencerAddressUnmarshal(t *testing.T) { assert.Equal(t, uint64(11817), block.Number) assert.Equal(t, "0x3df24be7b5fed6b41de08d38686b6142944119ca2a345c38793590d6804bba4", block.StateRoot.String()) assert.Equal(t, "ACCEPTED_ON_L2", block.Status) - assert.Equal(t, "0x27ad16775", block.GasPriceETH().String()) + assert.Equal(t, "0x27ad16775", block.L1GasPriceETH().String()) assert.Equal(t, 52, len(block.Transactions)) assert.Equal(t, 52, len(block.Receipts)) assert.Equal(t, uint64(1669465009), block.Timestamp) @@ -291,7 +291,7 @@ func TestBlockWithSequencerAddressUnmarshal(t *testing.T) { assert.Equal(t, uint64(19199), block.Number) assert.Equal(t, "0x541b796ea02703d02ff31459815f65f410ceefe80a4e3499f7ef9ccc36d26ee", block.StateRoot.String()) assert.Equal(t, "ACCEPTED_ON_L2", block.Status) - assert.Equal(t, "0x31c4e2d75", block.GasPriceETH().String()) + assert.Equal(t, "0x31c4e2d75", block.L1GasPriceETH().String()) assert.Equal(t, 324, len(block.Transactions)) assert.Equal(t, 324, len(block.Receipts)) assert.Equal(t, uint64(1674728186), block.Timestamp) @@ -309,8 +309,8 @@ func TestBlockHeaderV013Unmarshal(t *testing.T) { require.Equal(t, uint64(319132), block.Number) require.Equal(t, utils.HexToFelt(t, "0x2a6b9a8b60e1de80dc50e6b704b415a38e8fd03d82244cec92cbff0821a8975"), block.StateRoot) require.Equal(t, "ACCEPTED_ON_L2", block.Status) - require.Equal(t, utils.HexToFelt(t, "0x3b9aca08"), block.GasPriceETH()) - require.Equal(t, utils.HexToFelt(t, "0x2540be400"), block.GasPriceSTRK()) + require.Equal(t, utils.HexToFelt(t, "0x3b9aca08"), block.L1GasPriceETH()) + require.Equal(t, utils.HexToFelt(t, "0x2540be400"), block.L1GasPriceSTRK()) require.Equal(t, uint64(1700075354), block.Timestamp) require.Equal(t, utils.HexToFelt(t, "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8"), block.SequencerAddress) require.Equal(t, "0.13.0", block.Version) @@ -324,8 +324,8 @@ func TestBlockHeaderV0131Unmarshal(t *testing.T) { require.Equal(t, utils.HexToFelt(t, "0x8ab8117e952f95efd96de0bc66dc6f13fe68dfda14b95fe1972759dee283a8"), block.Hash) require.Equal(t, utils.HexToFelt(t, "0x13367121d0b7e34a9b10c8a5a1c269811cd9afc3ce680c88888f1a22d2f017a"), block.TransactionCommitment) require.Equal(t, utils.HexToFelt(t, "0x1090dd2ab2aa22bd5fc5a59d3b1394d54461bb2a80156c4b2c2622d2c474ca2"), block.EventCommitment) - require.Equal(t, utils.HexToFelt(t, "0x3b9aca0a"), block.GasPriceETH()) - require.Equal(t, utils.HexToFelt(t, "0x2b6fdb70"), block.GasPriceSTRK()) + require.Equal(t, utils.HexToFelt(t, "0x3b9aca0a"), block.L1GasPriceETH()) + require.Equal(t, utils.HexToFelt(t, "0x2b6fdb70"), block.L1GasPriceSTRK()) require.Equal(t, utils.HexToFelt(t, "0x5265a14ef"), block.L1DataGasPrice.PriceInWei) require.Equal(t, utils.HexToFelt(t, "0x3c0c00c87"), block.L1DataGasPrice.PriceInFri) require.Equal(t, starknet.Blob, block.L1DAMode) diff --git a/core/block.go b/core/block.go index d9fa02e2fd..9a13d27f53 100644 --- a/core/block.go +++ b/core/block.go @@ -35,12 +35,16 @@ type Header struct { ProtocolVersion string // Bloom filter on the events emitted this block EventsBloom *bloom.BloomFilter - // Amount of WEI charged per Gas spent - GasPrice *felt.Felt + // Amount of WEI charged per Gas spent on L1 + L1GasPriceETH *felt.Felt + // Amount of STRK charged per Gas spent on L2 + L2GasPriceETH *felt.Felt // Sequencer signatures Signatures [][]*felt.Felt - // Amount of STRK charged per Gas spent - GasPriceSTRK *felt.Felt + // Amount of STRK charged per Gas spent on L1 + L1GasPriceSTRK *felt.Felt + // Amount of STRK charged per Gas spent on L2 + L2GasPriceSTRK *felt.Felt // The mode of the L1 data availability L1DAMode L1DAMode // The gas price for L1 data availability @@ -215,11 +219,11 @@ func Post0132Hash(b *Block, stateDiff *StateDiff) (*felt.Felt, *BlockCommitments new(felt.Felt).SetUint64(b.Timestamp), // block timestamp concatCounts, sdCommitment, - txCommitment, // transaction commitment - eCommitment, // event commitment - rCommitment, // receipt commitment - b.GasPrice, // gas price in wei - b.GasPriceSTRK, // gas price in fri + txCommitment, // transaction commitment + eCommitment, // event commitment + rCommitment, // receipt commitment + b.L1GasPriceETH, // gas price in wei + b.L1GasPriceSTRK, // gas price in fri b.L1DataGasPrice.PriceInWei, b.L1DataGasPrice.PriceInFri, new(felt.Felt).SetBytes([]byte(b.ProtocolVersion)), diff --git a/rpc/block.go b/rpc/block.go index 302ccdac42..6b78336465 100644 --- a/rpc/block.go +++ b/rpc/block.go @@ -107,6 +107,7 @@ 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"` L1DataGasPrice *ResourcePrice `json:"l1_data_gas_price,omitempty"` L1DAMode *L1DAMode `json:"l1_da_mode,omitempty"` StarknetVersion string `json:"starknet_version"` @@ -326,8 +327,12 @@ func adaptBlockHeader(header *core.Header) BlockHeader { Timestamp: header.Timestamp, SequencerAddress: sequencerAddress, L1GasPrice: &ResourcePrice{ - InWei: header.GasPrice, - InFri: nilToZero(header.GasPriceSTRK), // Old block headers will be nil. + InWei: header.L1GasPriceETH, + InFri: nilToZero(header.L1GasPriceSTRK), + }, + L2GasPrice: &ResourcePrice{ + InWei: header.L2GasPriceETH, + InFri: header.L2GasPriceSTRK, }, L1DataGasPrice: &l1DataGasPrice, L1DAMode: &l1DAMode, diff --git a/rpc/block_test.go b/rpc/block_test.go index 61f1aa8d52..6ab052f3ad 100644 --- a/rpc/block_test.go +++ b/rpc/block_test.go @@ -534,6 +534,10 @@ func TestBlockWithTxHashesV013(t *testing.T) { InFri: utils.HexToFelt(t, "0x17882b6aa74"), InWei: utils.HexToFelt(t, "0x3b9aca10"), }, + L2GasPrice: &rpc.ResourcePrice{ + InFri: nil, + InWei: nil, + }, L1DataGasPrice: &rpc.ResourcePrice{ InFri: utils.HexToFelt(t, "0x2cc6d7f596e1"), InWei: utils.HexToFelt(t, "0x716a8f6dd"), @@ -643,6 +647,7 @@ func TestBlockWithReceipts(t *testing.T) { Timestamp: header.Timestamp, SequencerAddress: header.SequencerAddress, L1GasPrice: header.L1GasPrice, + L2GasPrice: header.L2GasPrice, L1DataGasPrice: header.L1DataGasPrice, L1DAMode: header.L1DAMode, StarknetVersion: header.StarknetVersion, @@ -689,6 +694,7 @@ func TestBlockWithReceipts(t *testing.T) { SequencerAddress: header.SequencerAddress, L1DAMode: header.L1DAMode, L1GasPrice: header.L1GasPrice, + L2GasPrice: header.L2GasPrice, L1DataGasPrice: header.L1DataGasPrice, StarknetVersion: header.StarknetVersion, }, diff --git a/rpc/estimate_fee.go b/rpc/estimate_fee.go index 3af789c4f3..5923703dd8 100644 --- a/rpc/estimate_fee.go +++ b/rpc/estimate_fee.go @@ -28,7 +28,7 @@ func (u FeeUnit) MarshalText() ([]byte, error) { } } -type FeeEstimate struct { +type FeeEstimateV0_7 struct { GasConsumed *felt.Felt `json:"gas_consumed"` GasPrice *felt.Felt `json:"gas_price"` DataGasConsumed *felt.Felt `json:"data_gas_consumed"` @@ -37,10 +37,45 @@ type FeeEstimate struct { Unit *FeeUnit `json:"unit,omitempty"` } +type FeeEstimate struct { + L1GasConsumed *felt.Felt `json:"l1_gas_consumed,omitempty"` + L1GasPrice *felt.Felt `json:"l1_gas_price,omitempty"` + L2GasConsumed *felt.Felt `json:"l2_gas_consumed,omitempty"` + L2GasPrice *felt.Felt `json:"l2_gas_price,omitempty"` + L1DataGasConsumed *felt.Felt `json:"l1_data_gas_consumed,omitempty"` + L1DataGasPrice *felt.Felt `json:"l1_data_gas_price,omitempty"` + OverallFee *felt.Felt `json:"overall_fee"` + Unit *FeeUnit `json:"unit,omitempty"` +} + /**************************************************** 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) + if err != nil { + return nil, httpHeader, err + } + + return utils.Map(result, func(tx SimulatedTransaction) FeeEstimateV0_7 { + return feeEstimateToV0_7(tx.FeeEstimation) + }), httpHeader, nil +} + func (h *Handler) EstimateFee(broadcastedTxns []BroadcastedTransaction, simulationFlags []SimulationFlag, id BlockID, ) ([]FeeEstimate, http.Header, *jsonrpc.Error) { @@ -54,8 +89,19 @@ func (h *Handler) EstimateFee(broadcastedTxns []BroadcastedTransaction, }), httpHeader, nil } -func (h *Handler) EstimateMessageFee(msg MsgFromL1, id BlockID) (*FeeEstimate, http.Header, *jsonrpc.Error) { //nolint:gocritic - return h.estimateMessageFee(msg, id, h.EstimateFee) +//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 +} + +//nolint:gocritic +func (h *Handler) EstimateMessageFee(msg MsgFromL1, id BlockID) (*FeeEstimate, http.Header, *jsonrpc.Error) { + return estimateMessageFee(msg, id, h.EstimateFee) } type estimateFeeHandler func(broadcastedTxns []BroadcastedTransaction, @@ -63,9 +109,7 @@ type estimateFeeHandler func(broadcastedTxns []BroadcastedTransaction, ) ([]FeeEstimate, http.Header, *jsonrpc.Error) //nolint:gocritic -func (h *Handler) estimateMessageFee(msg MsgFromL1, id BlockID, f estimateFeeHandler) (*FeeEstimate, - http.Header, *jsonrpc.Error, -) { +func estimateMessageFee(msg MsgFromL1, id BlockID, f estimateFeeHandler) (*FeeEstimate, http.Header, *jsonrpc.Error) { calldata := make([]*felt.Felt, 0, len(msg.Payload)+1) // The order of the calldata parameters matters. msg.From must be prepended. calldata = append(calldata, new(felt.Felt).SetBytes(msg.From.Bytes())) diff --git a/rpc/estimate_fee_pkg_test.go b/rpc/estimate_fee_pkg_test.go new file mode 100644 index 0000000000..43530e545a --- /dev/null +++ b/rpc/estimate_fee_pkg_test.go @@ -0,0 +1,43 @@ +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/estimate_fee_test.go b/rpc/estimate_fee_test.go index 7612572073..c1ade1b8cf 100644 --- a/rpc/estimate_fee_test.go +++ b/rpc/estimate_fee_test.go @@ -36,20 +36,30 @@ func TestEstimateFee(t *testing.T) { blockInfo := vm.BlockInfo{Header: &core.Header{}} t.Run("ok with zero values", func(t *testing.T) { mockVM.EXPECT().Execute([]core.Transaction{}, nil, []*felt.Felt{}, &blockInfo, mockState, n, true, false, true). - Return([]*felt.Felt{}, []core.GasConsumed{}, []vm.TransactionTrace{}, uint64(123), nil) + Return([]*felt.Felt{}, []core.GasConsumed{}, []vm.TransactionTrace{}, uint64(123), nil).Times(2) _, httpHeader, err := handler.EstimateFee([]rpc.BroadcastedTransaction{}, []rpc.SimulationFlag{}, rpc.BlockID{Latest: true}) require.Nil(t, err) assert.Equal(t, httpHeader.Get(rpc.ExecutionStepsHeader), "123") + + // TODO: Remove this when v0.7 is removed + _, httpHeader, err = handler.EstimateFeeV0_7([]rpc.BroadcastedTransaction{}, []rpc.SimulationFlag{}, rpc.BlockID{Latest: true}) + require.Nil(t, err) + assert.Equal(t, httpHeader.Get(rpc.ExecutionStepsHeader), "123") }) t.Run("ok with zero values, skip validate", func(t *testing.T) { mockVM.EXPECT().Execute([]core.Transaction{}, nil, []*felt.Felt{}, &blockInfo, mockState, n, true, true, true). - Return([]*felt.Felt{}, []core.GasConsumed{}, []vm.TransactionTrace{}, uint64(123), nil) + Return([]*felt.Felt{}, []core.GasConsumed{}, []vm.TransactionTrace{}, uint64(123), nil).Times(2) _, httpHeader, err := handler.EstimateFee([]rpc.BroadcastedTransaction{}, []rpc.SimulationFlag{rpc.SkipValidateFlag}, rpc.BlockID{Latest: true}) require.Nil(t, err) assert.Equal(t, httpHeader.Get(rpc.ExecutionStepsHeader), "123") + + // TODO: Remove this when v0.7 is removed + _, httpHeader, err = handler.EstimateFeeV0_7([]rpc.BroadcastedTransaction{}, []rpc.SimulationFlag{rpc.SkipValidateFlag}, rpc.BlockID{Latest: true}) + require.Nil(t, err) + assert.Equal(t, httpHeader.Get(rpc.ExecutionStepsHeader), "123") }) t.Run("transaction execution error", func(t *testing.T) { @@ -57,7 +67,7 @@ func TestEstimateFee(t *testing.T) { Return(nil, nil, nil, uint64(0), vm.TransactionExecutionError{ Index: 44, Cause: errors.New("oops"), - }) + }).Times(2) _, httpHeader, err := handler.EstimateFee([]rpc.BroadcastedTransaction{}, []rpc.SimulationFlag{rpc.SkipValidateFlag}, rpc.BlockID{Latest: true}) require.Equal(t, rpc.ErrTransactionExecutionError.CloneWithData(rpc.TransactionExecutionErrorData{ @@ -65,6 +75,14 @@ func TestEstimateFee(t *testing.T) { ExecutionError: "oops", }), err) require.Equal(t, httpHeader.Get(rpc.ExecutionStepsHeader), "0") + + // TODO: Remove this when v0.7 is removed + _, httpHeader, err = handler.EstimateFeeV0_7([]rpc.BroadcastedTransaction{}, []rpc.SimulationFlag{rpc.SkipValidateFlag}, rpc.BlockID{Latest: true}) + require.Equal(t, rpc.ErrTransactionExecutionError.CloneWithData(rpc.TransactionExecutionErrorData{ + TransactionIndex: 44, + ExecutionError: "oops", + }), err) + require.Equal(t, httpHeader.Get(rpc.ExecutionStepsHeader), "0") }) t.Run("transaction with invalid contract class", func(t *testing.T) { diff --git a/rpc/handlers.go b/rpc/handlers.go index 83795b666f..bc0091e62a 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -501,12 +501,12 @@ func (h *Handler) MethodsV0_7() ([]jsonrpc.Method, string) { //nolint: funlen { Name: "starknet_estimateFee", Params: []jsonrpc.Parameter{{Name: "request"}, {Name: "simulation_flags"}, {Name: "block_id"}}, - Handler: h.EstimateFee, + Handler: h.EstimateFeeV0_7, }, { Name: "starknet_estimateMessageFee", Params: []jsonrpc.Parameter{{Name: "message"}, {Name: "block_id"}}, - Handler: h.EstimateMessageFee, + Handler: h.EstimateMessageFeeV0_7, }, { Name: "starknet_traceTransaction", diff --git a/rpc/handlers_test.go b/rpc/handlers_test.go index 8e86da7085..433845f7c1 100644 --- a/rpc/handlers_test.go +++ b/rpc/handlers_test.go @@ -72,7 +72,7 @@ func TestThrottledVMError(t *testing.T) { // hash is not set because it's pending block ParentHash: utils.HexToFelt(t, "0x0C3"), Number: 0, - GasPrice: utils.HexToFelt(t, "0x777"), + L1GasPriceETH: utils.HexToFelt(t, "0x777"), ProtocolVersion: "99.12.3", } l1Tx := &core.L1HandlerTransaction{ diff --git a/rpc/helpers.go b/rpc/helpers.go index ef708dccfc..10f8770274 100644 --- a/rpc/helpers.go +++ b/rpc/helpers.go @@ -113,12 +113,16 @@ func adaptExecutionResources(resources *core.ExecutionResources) *ExecutionResou DataAvailability: &DataAvailability{}, } if resources.DataAvailability != nil { + res.L1Gas = resources.DataAvailability.L1Gas + res.L1DataGas = resources.DataAvailability.L1DataGas res.DataAvailability = &DataAvailability{ L1Gas: resources.DataAvailability.L1Gas, L1DataGas: resources.DataAvailability.L1DataGas, } } + res.L2Gas = 0 // TODO: Use L2Gas when available + return res } diff --git a/rpc/simulation.go b/rpc/simulation.go index 3dda777ed9..11f45e90a7 100644 --- a/rpc/simulation.go +++ b/rpc/simulation.go @@ -56,7 +56,6 @@ func (h *Handler) SimulateTransactions(id BlockID, transactions []BroadcastedTra return h.simulateTransactions(id, transactions, simulationFlags, false) } -//nolint:funlen,gocyclo func (h *Handler) simulateTransactions(id BlockID, transactions []BroadcastedTransaction, simulationFlags []SimulationFlag, errOnRevert bool, ) ([]SimulatedTransaction, http.Header, *jsonrpc.Error) { @@ -125,37 +124,7 @@ func (h *Handler) simulateTransactions(id BlockID, transactions []BroadcastedTra for i, overallFee := range overallFees { feeUnit := feeUnit(txns[i]) - gasPrice := header.GasPrice - if feeUnit == FRI { - if gasPrice = header.GasPriceSTRK; gasPrice == nil { - gasPrice = &felt.Zero - } - } - - dataGasPrice := &felt.Zero - if header.L1DataGasPrice != nil { - switch feeUnit { - case FRI: - dataGasPrice = header.L1DataGasPrice.PriceInFri - case WEI: - dataGasPrice = header.L1DataGasPrice.PriceInWei - } - } - - var gasConsumed *felt.Felt - daGasL1DataGas := new(felt.Felt).SetUint64(daGas[i].L1DataGas) - dataGasFee := new(felt.Felt).Mul(daGasL1DataGas, dataGasPrice) - gasConsumed = new(felt.Felt).Sub(overallFee, dataGasFee) - gasConsumed = gasConsumed.Div(gasConsumed, gasPrice) // division by zero felt is zero felt - - estimate := FeeEstimate{ - GasConsumed: gasConsumed, - GasPrice: gasPrice, - DataGasConsumed: daGasL1DataGas, - DataGasPrice: dataGasPrice, - OverallFee: overallFee, - Unit: utils.Ptr(feeUnit), - } + estimate := calculateFeeEstimate(overallFee, daGas[i].L1DataGas, feeUnit, header) trace := traces[i] executionResources := trace.TotalExecutionResources() @@ -174,6 +143,37 @@ 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 { + var l1GasPrice, l2GasPrice, l1DataGasPrice *felt.Felt + + switch feeUnit { + case FRI: + l1GasPrice = header.L1GasPriceSTRK + l2GasPrice = header.L2GasPriceSTRK + l1DataGasPrice = header.L1DataGasPrice.PriceInFri + case WEI: + l1GasPrice = header.L1GasPriceETH + l2GasPrice = header.L2GasPriceETH + l1DataGasPrice = header.L1DataGasPrice.PriceInWei + } + + l1DataGasConsumed := new(felt.Felt).SetUint64(l1DataGas) + dataGasFee := new(felt.Felt).Mul(l1DataGasConsumed, l1DataGasPrice) + l1GasConsumed := new(felt.Felt).Sub(overallFee, dataGasFee) + l1GasConsumed = l1GasConsumed.Div(l1GasConsumed, l1GasPrice) + + return FeeEstimate{ + L1GasConsumed: l1GasConsumed, + L2GasConsumed: nil, // TODO: Fix when we have l2 gas price + L1GasPrice: l1GasPrice, + L2GasPrice: l2GasPrice, + L1DataGasConsumed: l1DataGasConsumed, + L1DataGasPrice: l1DataGasPrice, + OverallFee: overallFee, + Unit: utils.Ptr(feeUnit), + } +} + type TransactionExecutionErrorData struct { TransactionIndex uint64 `json:"transaction_index"` ExecutionError string `json:"execution_error"` diff --git a/rpc/simulation_pkg_test.go b/rpc/simulation_pkg_test.go new file mode 100644 index 0000000000..907b8a354f --- /dev/null +++ b/rpc/simulation_pkg_test.go @@ -0,0 +1,39 @@ +package rpc + +import ( + "testing" + + "github.com/NethermindEth/juno/core" + "github.com/NethermindEth/juno/core/felt" + "github.com/stretchr/testify/assert" +) + +func TestCalculateFeeEstimate(t *testing.T) { + l1GasPriceETH := new(felt.Felt).SetUint64(200) + l2GasPriceETH := new(felt.Felt).SetUint64(70) + l1GasPriceSTRK := new(felt.Felt).SetUint64(100) + l2GasPriceSTRK := new(felt.Felt).SetUint64(50) + l1DataGasPrice := &core.GasPrice{ + PriceInWei: new(felt.Felt).SetUint64(10), + PriceInFri: new(felt.Felt).SetUint64(5), + } + header := &core.Header{ + L1GasPriceETH: l1GasPriceETH, + L2GasPriceETH: l2GasPriceETH, + L1GasPriceSTRK: l1GasPriceSTRK, + L2GasPriceSTRK: l2GasPriceSTRK, + L1DataGasPrice: l1DataGasPrice, + } + l1DataGas := uint64(500) + overallFee := new(felt.Felt).SetUint64(6000) + + feeEstimate := calculateFeeEstimate(overallFee, l1DataGas, FRI, header) + + assert.Equal(t, l1GasPriceSTRK, feeEstimate.L1GasPrice) + assert.Equal(t, l2GasPriceSTRK, feeEstimate.L2GasPrice) + assert.Equal(t, l1DataGasPrice.PriceInFri, feeEstimate.L1DataGasPrice) + assert.Equal(t, overallFee, feeEstimate.OverallFee) + assert.Equal(t, FRI, *feeEstimate.Unit) + assert.Equal(t, new(felt.Felt).SetUint64(35), feeEstimate.L1GasConsumed) + assert.Nil(t, feeEstimate.L2GasConsumed) +} diff --git a/rpc/subscriptions_test.go b/rpc/subscriptions_test.go index 4757ab73d8..8bd448bd4c 100644 --- a/rpc/subscriptions_test.go +++ b/rpc/subscriptions_test.go @@ -496,7 +496,7 @@ func TestSubscribeNewHeadsHistorical(t *testing.T) { require.Equal(t, subResp(id), got) // Check block 0 content - want := `{"jsonrpc":"2.0","method":"starknet_subscriptionNewHeads","params":{"result":{"block_hash":"0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943","parent_hash":"0x0","block_number":0,"new_root":"0x21870ba80540e7831fb21c591ee93481f5ae1bb71ff85a86ddd465be4eddee6","timestamp":1637069048,"sequencer_address":"0x0","l1_gas_price":{"price_in_fri":"0x0","price_in_wei":"0x0"},"l1_data_gas_price":{"price_in_fri":"0x0","price_in_wei":"0x0"},"l1_da_mode":"CALLDATA","starknet_version":""},"subscription_id":%d}}` + want := `{"jsonrpc":"2.0","method":"starknet_subscriptionNewHeads","params":{"result":{"block_hash":"0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943","parent_hash":"0x0","block_number":0,"new_root":"0x21870ba80540e7831fb21c591ee93481f5ae1bb71ff85a86ddd465be4eddee6","timestamp":1637069048,"sequencer_address":"0x0","l1_gas_price":{"price_in_fri":"0x0","price_in_wei":"0x0"},"l2_gas_price":{"price_in_fri":null,"price_in_wei":null},"l1_data_gas_price":{"price_in_fri":"0x0","price_in_wei":"0x0"},"l1_da_mode":"CALLDATA","starknet_version":""},"subscription_id":%d}}` want = fmt.Sprintf(want, id) _, block0Got, err := conn.Read(ctx) require.NoError(t, err) @@ -813,8 +813,8 @@ func testHeader(t *testing.T) *core.Header { PriceInFri: utils.HexToFelt(t, "0x0"), PriceInWei: utils.HexToFelt(t, "0x0"), }, - GasPrice: utils.HexToFelt(t, "0x0"), - GasPriceSTRK: utils.HexToFelt(t, "0x0"), + L1GasPriceETH: utils.HexToFelt(t, "0x0"), + L1GasPriceSTRK: utils.HexToFelt(t, "0x0"), L1DAMode: core.Calldata, ProtocolVersion: "", } @@ -822,7 +822,7 @@ func testHeader(t *testing.T) *core.Header { } func newHeadsResponse(id uint64) string { - return fmt.Sprintf(`{"jsonrpc":"2.0","method":"starknet_subscriptionNewHeads","params":{"result":{"block_hash":"0x4e1f77f39545afe866ac151ac908bd1a347a2a8a7d58bef1276db4f06fdf2f6","parent_hash":"0x2a70fb03fe363a2d6be843343a1d81ce6abeda1e9bd5cc6ad8fa9f45e30fdeb","block_number":2,"new_root":"0x3ceee867d50b5926bb88c0ec7e0b9c20ae6b537e74aac44b8fcf6bb6da138d9","timestamp":1637084470,"sequencer_address":"0x0","l1_gas_price":{"price_in_fri":"0x0","price_in_wei":"0x0"},"l1_data_gas_price":{"price_in_fri":"0x0","price_in_wei":"0x0"},"l1_da_mode":"CALLDATA","starknet_version":""},"subscription_id":%d}}`, id) + return fmt.Sprintf(`{"jsonrpc":"2.0","method":"starknet_subscriptionNewHeads","params":{"result":{"block_hash":"0x4e1f77f39545afe866ac151ac908bd1a347a2a8a7d58bef1276db4f06fdf2f6","parent_hash":"0x2a70fb03fe363a2d6be843343a1d81ce6abeda1e9bd5cc6ad8fa9f45e30fdeb","block_number":2,"new_root":"0x3ceee867d50b5926bb88c0ec7e0b9c20ae6b537e74aac44b8fcf6bb6da138d9","timestamp":1637084470,"sequencer_address":"0x0","l1_gas_price":{"price_in_fri":"0x0","price_in_wei":"0x0"},"l2_gas_price":{"price_in_fri":null,"price_in_wei":null},"l1_data_gas_price":{"price_in_fri":"0x0","price_in_wei":"0x0"},"l1_da_mode":"CALLDATA","starknet_version":""},"subscription_id":%d}}`, id) } // setupRPC creates a RPC handler that runs in a goroutine and a JSONRPC server that can be used to test subscriptions diff --git a/rpc/trace_test.go b/rpc/trace_test.go index d46cbf40d6..aeabf14188 100644 --- a/rpc/trace_test.go +++ b/rpc/trace_test.go @@ -107,7 +107,7 @@ func TestTraceTransaction(t *testing.T) { Hash: utils.HexToFelt(t, "0xCAFEBABE"), ParentHash: utils.HexToFelt(t, "0x0"), SequencerAddress: utils.HexToFelt(t, "0X111"), - GasPrice: utils.HexToFelt(t, "0x1"), + L1GasPriceETH: utils.HexToFelt(t, "0x1"), ProtocolVersion: "99.12.3", L1DAMode: core.Calldata, } @@ -196,7 +196,7 @@ func TestTraceTransaction(t *testing.T) { SequencerAddress: utils.HexToFelt(t, "0X111"), ProtocolVersion: "99.12.3", L1DAMode: core.Calldata, - GasPrice: utils.HexToFelt(t, "0x1"), + L1GasPriceETH: utils.HexToFelt(t, "0x1"), } require.Nil(t, header.Hash, "hash must be nil for pending block") @@ -323,7 +323,7 @@ func TestTraceBlockTransactions(t *testing.T) { // hash is not set because it's pending block ParentHash: utils.HexToFelt(t, "0x0C3"), Number: 0, - GasPrice: utils.HexToFelt(t, "0x777"), + L1GasPriceETH: utils.HexToFelt(t, "0x777"), ProtocolVersion: "99.12.3", } l1Tx := &core.L1HandlerTransaction{ @@ -406,7 +406,7 @@ func TestTraceBlockTransactions(t *testing.T) { ParentHash: utils.HexToFelt(t, "0x0"), Number: 0, SequencerAddress: utils.HexToFelt(t, "0X111"), - GasPrice: utils.HexToFelt(t, "0x777"), + L1GasPriceETH: utils.HexToFelt(t, "0x777"), ProtocolVersion: "99.12.3", } block := &core.Block{ diff --git a/rpc/transaction.go b/rpc/transaction.go index 0610671299..58741e98f2 100644 --- a/rpc/transaction.go +++ b/rpc/transaction.go @@ -265,6 +265,11 @@ type DataAvailability struct { } type ExecutionResources struct { + L1Gas uint64 `json:"l1_gas"` + L1DataGas uint64 `json:"l1_data_gas"` + L2Gas uint64 `json:"l2_gas"` + + // TODO: Remove this field once the API is updated. ComputationResources DataAvailability *DataAvailability `json:"data_availability,omitempty"` } diff --git a/rpc/transaction_test.go b/rpc/transaction_test.go index a25d47912a..0c63058ed8 100644 --- a/rpc/transaction_test.go +++ b/rpc/transaction_test.go @@ -551,6 +551,9 @@ func TestTransactionReceiptByHash(t *testing.T) { "events": [], "contract_address": "0x20cfa74ee3564b4cd5435cdace0f9c4d43b939620e4a0bb5076105df0a626c6", "execution_resources": { + "l1_data_gas": 0, + "l1_gas": 0, + "l2_gas": 0, "data_availability": { "l1_data_gas": 0, "l1_gas": 0 @@ -581,6 +584,9 @@ func TestTransactionReceiptByHash(t *testing.T) { ], "events": [], "execution_resources": { + "l1_data_gas": 0, + "l1_gas": 0, + "l2_gas": 0, "data_availability": { "l1_data_gas": 0, "l1_gas": 0 @@ -621,6 +627,9 @@ func TestTransactionReceiptByHash(t *testing.T) { ], "events": [], "execution_resources": { + "l1_data_gas": 0, + "l1_gas": 0, + "l2_gas": 0, "data_availability": { "l1_data_gas": 0, "l1_gas": 0 @@ -658,6 +667,9 @@ func TestTransactionReceiptByHash(t *testing.T) { ], "events": [], "execution_resources": { + "l1_data_gas": 0, + "l1_gas": 0, + "l2_gas": 0, "data_availability": { "l1_data_gas": 0, "l1_gas": 0 @@ -690,6 +702,9 @@ func TestTransactionReceiptByHash(t *testing.T) { "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, "data_availability": { "l1_data_gas": 0, "l1_gas": 0 @@ -754,6 +769,9 @@ func TestTransactionReceiptByHash(t *testing.T) { "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 @@ -816,6 +834,9 @@ func TestTransactionReceiptByHash(t *testing.T) { "pedersen_builtin_applications": 16, "poseidon_builtin_applications": 4, "range_check_builtin_applications": 157, + "l1_data_gas": 192, + "l1_gas": 0, + "l2_gas": 0, "data_availability": { "l1_gas": 0, "l1_data_gas": 192 diff --git a/starknet/block.go b/starknet/block.go index c7f65394ce..f9219a684a 100644 --- a/starknet/block.go +++ b/starknet/block.go @@ -24,6 +24,7 @@ type Block struct { Receipts []*TransactionReceipt `json:"transaction_receipts"` SequencerAddress *felt.Felt `json:"sequencer_address"` L1GasPrice *GasPrice `json:"l1_gas_price"` + L2GasPrice *GasPrice `json:"l2_gas_price"` L1DAMode L1DAMode `json:"l1_da_mode"` L1DataGasPrice *GasPrice `json:"l1_data_gas_price"` @@ -36,7 +37,7 @@ type Block struct { GasPriceFRI *felt.Felt `json:"strk_l1_gas_price"` } -func (b *Block) GasPriceETH() *felt.Felt { +func (b *Block) L1GasPriceETH() *felt.Felt { if b.L1GasPrice != nil { return b.L1GasPrice.PriceInWei } else if b.GasPriceWEI != nil { @@ -45,13 +46,29 @@ func (b *Block) GasPriceETH() *felt.Felt { return b.GasPriceLegacy } -func (b *Block) GasPriceSTRK() *felt.Felt { +func (b *Block) L1GasPriceSTRK() *felt.Felt { if b.L1GasPrice != nil { return b.L1GasPrice.PriceInFri } return b.GasPriceFRI } +// TODO: Fix when we have l2 gas price +func (b *Block) L2GasPriceETH() *felt.Felt { + if b.L2GasPrice != nil { + return b.L2GasPrice.PriceInWei + } + return nil +} + +// TODO: Fix when we have l2 gas price +func (b *Block) L2GasPriceSTRK() *felt.Felt { + if b.L2GasPrice != nil { + return b.L2GasPrice.PriceInFri + } + return nil +} + type L1DAMode uint const ( diff --git a/starknet/block_test.go b/starknet/block_test.go new file mode 100644 index 0000000000..8ee062b5db --- /dev/null +++ b/starknet/block_test.go @@ -0,0 +1,30 @@ +package starknet_test + +import ( + "testing" + + "github.com/NethermindEth/juno/core/felt" + "github.com/NethermindEth/juno/starknet" + "github.com/stretchr/testify/assert" +) + +func TestL2GasPrice(t *testing.T) { + t.Run("L2GasPrice is not set", func(t *testing.T) { + block := starknet.Block{} + assert.Nil(t, block.L2GasPriceETH()) + assert.Nil(t, block.L2GasPriceSTRK()) + }) + + t.Run("L2GasPrice is set", func(t *testing.T) { + gasPriceWei := new(felt.Felt).SetUint64(100) + gasPriceFri := new(felt.Felt).SetUint64(50) + block := starknet.Block{ + L2GasPrice: &starknet.GasPrice{ + PriceInWei: gasPriceWei, + PriceInFri: gasPriceFri, + }, + } + assert.Equal(t, gasPriceWei, block.L2GasPriceETH()) + assert.Equal(t, gasPriceFri, block.L2GasPriceSTRK()) + }) +} diff --git a/vm/vm.go b/vm/vm.go index e3b0bdd90e..25b282cc1c 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -206,8 +206,8 @@ func makeCBlockInfo(blockInfo *BlockInfo) C.BlockInfo { cBlockInfo.block_number = C.ulonglong(blockInfo.Header.Number) cBlockInfo.block_timestamp = C.ulonglong(blockInfo.Header.Timestamp) copyFeltIntoCArray(blockInfo.Header.SequencerAddress, &cBlockInfo.sequencer_address[0]) - copyFeltIntoCArray(blockInfo.Header.GasPrice, &cBlockInfo.gas_price_wei[0]) - copyFeltIntoCArray(blockInfo.Header.GasPriceSTRK, &cBlockInfo.gas_price_fri[0]) + copyFeltIntoCArray(blockInfo.Header.L1GasPriceETH, &cBlockInfo.gas_price_wei[0]) + copyFeltIntoCArray(blockInfo.Header.L1GasPriceSTRK, &cBlockInfo.gas_price_fri[0]) cBlockInfo.version = cstring([]byte(blockInfo.Header.ProtocolVersion)) copyFeltIntoCArray(blockInfo.BlockHashToBeRevealed, &cBlockInfo.block_hash_to_be_revealed[0]) if blockInfo.Header.L1DAMode == core.Blob { diff --git a/vm/vm_test.go b/vm/vm_test.go index 00832b6063..aa68dcaf2d 100644 --- a/vm/vm_test.go +++ b/vm/vm_test.go @@ -207,8 +207,8 @@ func TestExecute(t *testing.T) { Header: &core.Header{ Timestamp: 1666877926, SequencerAddress: utils.HexToFelt(t, "0x46a89ae102987331d369645031b49c27738ed096f2789c24449966da4c6de6b"), - GasPrice: &felt.Zero, - GasPriceSTRK: &felt.Zero, + L1GasPriceETH: &felt.Zero, + L1GasPriceSTRK: &felt.Zero, }, }, state, &network, false, false, false) @@ -218,8 +218,8 @@ func TestExecute(t *testing.T) { _, _, _, _, err := New(false, nil).Execute(nil, nil, []*felt.Felt{}, &BlockInfo{ Header: &core.Header{ SequencerAddress: &felt.Zero, - GasPrice: &felt.Zero, - GasPriceSTRK: &felt.Zero, + L1GasPriceETH: &felt.Zero, + L1GasPriceSTRK: &felt.Zero, }, }, state, &network, false, false, false) require.NoError(t, err)