Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix gas used and fee relayed v3 #6541

Open
wants to merge 8 commits into
base: inner_hash_on_scr_prev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions genesis/process/disabled/feeHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ import (
type FeeHandler struct {
}

// ComputeRelayedTxV3GasUnits -
func (fh *FeeHandler) ComputeRelayedTxV3GasUnits(_ data.TransactionWithFeeHandler, _ uint32) uint64 {
return 0
}

// ComputeGasUnitsFromRefundValue -
func (fh *FeeHandler) ComputeGasUnitsFromRefundValue(_ data.TransactionWithFeeHandler, _ *big.Int, _ uint32) uint64 {
return 0
}

// GasPriceModifier returns 1.0
func (fh *FeeHandler) GasPriceModifier() float64 {
return 1.0
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ require (
github.com/klauspost/cpuid/v2 v2.2.5
github.com/mitchellh/mapstructure v1.5.0
github.com/multiversx/mx-chain-communication-go v1.1.0
github.com/multiversx/mx-chain-core-go v1.2.23-0.20241010094929-2bbea4371d73
github.com/multiversx/mx-chain-core-go v1.2.23-0.20241018055916-203f32de05ad
github.com/multiversx/mx-chain-crypto-go v1.2.12
github.com/multiversx/mx-chain-es-indexer-go v1.7.10-0.20241011172845-d1739bada80e
github.com/multiversx/mx-chain-es-indexer-go v1.7.10-0.20241018070419-4c779fec3824
github.com/multiversx/mx-chain-logger-go v1.0.15
github.com/multiversx/mx-chain-scenario-go v1.4.4
github.com/multiversx/mx-chain-storage-go v1.0.16
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,12 @@ github.com/multiversx/concurrent-map v0.1.4 h1:hdnbM8VE4b0KYJaGY5yJS2aNIW9TFFsUY
github.com/multiversx/concurrent-map v0.1.4/go.mod h1:8cWFRJDOrWHOTNSqgYCUvwT7c7eFQ4U2vKMOp4A/9+o=
github.com/multiversx/mx-chain-communication-go v1.1.0 h1:J7bX6HoN3HiHY7cUeEjG8AJWgQDDPcY+OPDOsSUOkRE=
github.com/multiversx/mx-chain-communication-go v1.1.0/go.mod h1:WK6bP4pGEHGDDna/AYRIMtl6G9OA0NByI1Lw8PmOnRM=
github.com/multiversx/mx-chain-core-go v1.2.23-0.20241010094929-2bbea4371d73 h1:+pnMCOuqq3kbGB+vBfzKebPOe1WVOVEHIfyEbgGnNt0=
github.com/multiversx/mx-chain-core-go v1.2.23-0.20241010094929-2bbea4371d73/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE=
github.com/multiversx/mx-chain-core-go v1.2.23-0.20241018055916-203f32de05ad h1:EFWFNts9am6Dp+tJxYiHfsepK4TF0J931mTEZ3Aireo=
github.com/multiversx/mx-chain-core-go v1.2.23-0.20241018055916-203f32de05ad/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE=
github.com/multiversx/mx-chain-crypto-go v1.2.12 h1:zWip7rpUS4CGthJxfKn5MZfMfYPjVjIiCID6uX5BSOk=
github.com/multiversx/mx-chain-crypto-go v1.2.12/go.mod h1:HzcPpCm1zanNct/6h2rIh+MFrlXbjA5C8+uMyXj3LI4=
github.com/multiversx/mx-chain-es-indexer-go v1.7.10-0.20241011172845-d1739bada80e h1:cj4kURXUPtjdSHeXPQolpkfduZV2AmF352Py0rLyEAI=
github.com/multiversx/mx-chain-es-indexer-go v1.7.10-0.20241011172845-d1739bada80e/go.mod h1:oGcRK2E3Syv6vRTszWrrb/TqD8akq0yeoMr1wPPiTO4=
github.com/multiversx/mx-chain-es-indexer-go v1.7.10-0.20241018070419-4c779fec3824 h1:vC8PQ6+w2geSm2z+aA100L6ixMY0dIx7MtaMXUKnByo=
github.com/multiversx/mx-chain-es-indexer-go v1.7.10-0.20241018070419-4c779fec3824/go.mod h1:F1gsY0L3Cth/7ajD8Aw9YIqFAPXBnY+f5gKjLEjsYQE=
github.com/multiversx/mx-chain-logger-go v1.0.15 h1:HlNdK8etyJyL9NQ+6mIXyKPEBo+wRqOwi3n+m2QIHXc=
github.com/multiversx/mx-chain-logger-go v1.0.15/go.mod h1:t3PRKaWB1M+i6gUfD27KXgzLJJC+mAQiN+FLlL1yoGQ=
github.com/multiversx/mx-chain-scenario-go v1.4.4 h1:DVE2V+FPeyD/yWoC+KEfPK3jsFzHeruelESfpTlf460=
Expand Down
5 changes: 5 additions & 0 deletions node/external/timemachine/fee/feeComputer.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ func (computer *feeComputer) ComputeGasLimit(tx *transaction.ApiTransactionResul
return computer.economicsInstance.ComputeGasLimitInEpoch(tx.Tx, tx.Epoch)
}

// ComputeGasUnitForRelayedV3 will compute the gas units for a relayed v3 transaction
func (computer *feeComputer) ComputeGasUnitForRelayedV3(tx *transaction.ApiTransactionResult) uint64 {
return computer.economicsInstance.ComputeRelayedTxV3GasUnits(tx.Tx, tx.Epoch)
}

// ComputeTransactionFee computes a transaction fee, at a given epoch
func (computer *feeComputer) ComputeTransactionFee(tx *transaction.ApiTransactionResult) *big.Int {
return computer.economicsInstance.ComputeTxFeeInEpoch(tx.Tx, tx.Epoch)
Expand Down
26 changes: 25 additions & 1 deletion node/external/transactionAPI/gasUsedAndFeeProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ func (gfp *gasUsedAndFeeProcessor) computeAndAttachGasUsedAndFee(tx *transaction

hasRefundForSender := false
totalRefunds := big.NewInt(0)
for _, scr := range tx.SmartContractResults {
scrs := getSmartContractResultsFromATx(tx)
for _, scr := range scrs {
if !scr.IsRefund || scr.RcvAddr != tx.Sender {
continue
}
Expand All @@ -74,13 +75,36 @@ func (gfp *gasUsedAndFeeProcessor) computeAndAttachGasUsedAndFee(tx *transaction
tx.Fee = fee.String()
}

isRelayedV3AndNoRefund := len(tx.InnerTransactions) > 0 && !hasRefundForSender
if isRelayedV3AndNoRefund {
txFee := gfp.feeComputer.ComputeTransactionFee(tx)
gasUsedRelayed := gfp.feeComputer.ComputeGasUnitForRelayedV3(tx)

tx.GasUsed = gasUsedRelayed
tx.Fee = txFee.String()
tx.InitiallyPaidFee = txFee.String()

return
}

if isRelayedAfterFix {
return
}

gfp.prepareTxWithResultsBasedOnLogs(tx, hasRefundForSender)
}

func getSmartContractResultsFromATx(tx *transaction.ApiTransactionResult) []*transaction.ApiSmartContractResult {
scrs := make([]*transaction.ApiSmartContractResult, 0)
scrs = append(scrs, tx.SmartContractResults...)

for _, innerTx := range tx.InnerTransactions {
scrs = append(scrs, innerTx.SmartContractResults...)
}

return scrs
}

func (gfp *gasUsedAndFeeProcessor) getFeeOfRelayed(tx *transaction.ApiTransactionResult) (*big.Int, bool) {
if !tx.IsRelayed {
return nil, false
Expand Down
115 changes: 115 additions & 0 deletions node/external/transactionAPI/gasUsedAndFeeProcessor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ import (

"github.com/multiversx/mx-chain-core-go/core"
"github.com/multiversx/mx-chain-core-go/core/pubkeyConverter"
"github.com/multiversx/mx-chain-core-go/data"
"github.com/multiversx/mx-chain-core-go/data/transaction"
"github.com/multiversx/mx-chain-core-go/marshal"
"github.com/multiversx/mx-chain-go/common"
"github.com/multiversx/mx-chain-go/node/external/timemachine/fee"
"github.com/multiversx/mx-chain-go/process"
"github.com/multiversx/mx-chain-go/process/economics"
"github.com/multiversx/mx-chain-go/process/mock"
"github.com/multiversx/mx-chain-go/process/smartContract"
"github.com/multiversx/mx-chain-go/testscommon"
"github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock"
"github.com/multiversx/mx-chain-go/testscommon/epochNotifier"
datafield "github.com/multiversx/mx-chain-vm-common-go/parsers/dataField"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

Expand All @@ -28,6 +32,26 @@ func createEconomicsData(enableEpochsHandler common.EnableEpochsHandler) process
EpochNotifier: &epochNotifier.EpochNotifierStub{},
})

dataFieldParser, _ := datafield.NewOperationDataFieldParser(&datafield.ArgsOperationDataFieldParser{
AddressLength: 32,
Marshalizer: &mock.MarshalizerMock{},
})

_ = economicsData.SetTxTypeHandler(&testscommon.TxTypeHandlerMock{
ComputeTransactionTypeCalled: func(tx data.TransactionHandler) (process.TransactionType, process.TransactionType) {
if core.IsSmartContractAddress(tx.GetRcvAddr()) {
return process.SCInvoking, process.SCInvoking
}

res := dataFieldParser.Parse(tx.GetData(), tx.GetSndAddr(), tx.GetRcvAddr(), 3)
if len(res.Tokens) > 0 {
return process.BuiltInFunctionCall, process.BuiltInFunctionCall
}

return process.MoveBalance, process.MoveBalance
},
})

return economicsData
}

Expand Down Expand Up @@ -409,3 +433,94 @@ func TestComputeAndAttachGasUsedAndFeeFailedRelayedV1(t *testing.T) {
require.Equal(t, "1274230000000000", txWithSRefundSCR.Fee)
require.Equal(t, "1274230000000000", txWithSRefundSCR.InitiallyPaidFee)
}

func TestComputeAndAttachGasUsedAndFeeRelayedV3WithAllInnerTxFailed(t *testing.T) {
t.Parallel()

t.Run("all inner txs are failed", testComputeAndAttachGasUsedAndFeeRelayedV3WithInnerTxFailed(
"testData/relayedV3WithAllInnerTxFailed.json",
uint64(60150000),
"2226090000000000",
"2226090000000000",
))
t.Run("one inner tx is failed, other have refunds", testComputeAndAttachGasUsedAndFeeRelayedV3WithInnerTxFailed(
"testData/relayedV3WithOneInnerFailedAndTwoRefunds.json",
uint64(160766000),
"2670920000000000",
"2864760000000000",
))

}

func testComputeAndAttachGasUsedAndFeeRelayedV3WithInnerTxFailed(
inputFile string,
expectedGasUsed uint64,
expectedFee string,
expectedInitiallyPaidFee string,
) func(t *testing.T) {
return func(t *testing.T) {
t.Parallel()

enableEpochsHandler := &enableEpochsHandlerMock.EnableEpochsHandlerStub{
IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool {
return flag == common.GasPriceModifierFlag ||
flag == common.PenalizedTooMuchGasFlag ||
flag == common.RelayedTransactionsV3Flag ||
flag == common.LinkInnerTransactionFlag
},
}
feeComp, _ := fee.NewFeeComputer(createEconomicsData(enableEpochsHandler))
computer := fee.NewTestFeeComputer(feeComp)

gasUsedAndFeeProc := newGasUsedAndFeeProcessor(
computer,
pubKeyConverter,
smartContract.NewArgumentParser(),
&marshal.JsonMarshalizer{},
enableEpochsHandler,
)

txWithFailedInners := &transaction.ApiTransactionResult{}
err := core.LoadJsonFile(txWithFailedInners, inputFile)
require.NoError(t, err)

innerTxs := make([]*transaction.Transaction, 0, len(txWithFailedInners.InnerTransactions))
for _, innerTx := range txWithFailedInners.InnerTransactions {
snd, _ := pubKeyConverter.Decode(innerTx.Sender)
rcv, _ := pubKeyConverter.Decode(innerTx.Receiver)
val, _ := big.NewInt(0).SetString(innerTx.Value, 10)
innerTxs = append(innerTxs, &transaction.Transaction{
Nonce: innerTx.Nonce,
Value: val,
RcvAddr: rcv,
SndAddr: snd,
GasPrice: innerTx.GasPrice,
GasLimit: innerTx.GasLimit,
Data: innerTx.Data,
})
}

snd, _ := pubKeyConverter.Decode(txWithFailedInners.Sender)
rcv, _ := pubKeyConverter.Decode(txWithFailedInners.Receiver)
val, _ := big.NewInt(0).SetString(txWithFailedInners.Value, 10)
txWithFailedInners.Tx = &transaction.Transaction{
Nonce: txWithFailedInners.Nonce,
Value: val,
RcvAddr: rcv,
SndAddr: snd,
GasPrice: txWithFailedInners.GasPrice,
GasLimit: txWithFailedInners.GasLimit,
Data: txWithFailedInners.Data,
InnerTransactions: innerTxs,
}

txWithFailedInners.InitiallyPaidFee = ""
txWithFailedInners.Fee = ""
txWithFailedInners.GasUsed = 0

gasUsedAndFeeProc.computeAndAttachGasUsedAndFee(txWithFailedInners)
assert.Equal(t, expectedGasUsed, txWithFailedInners.GasUsed)
assert.Equal(t, expectedFee, txWithFailedInners.Fee)
assert.Equal(t, expectedInitiallyPaidFee, txWithFailedInners.InitiallyPaidFee)
}
}
1 change: 1 addition & 0 deletions node/external/transactionAPI/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type feeComputer interface {
ComputeGasUsedAndFeeBasedOnRefundValue(tx *transaction.ApiTransactionResult, refundValue *big.Int) (uint64, *big.Int)
ComputeTxFeeBasedOnGasUsed(tx *transaction.ApiTransactionResult, gasUsed uint64) *big.Int
ComputeGasLimit(tx *transaction.ApiTransactionResult) uint64
ComputeGasUnitForRelayedV3(tx *transaction.ApiTransactionResult) uint64
ComputeTransactionFee(tx *transaction.ApiTransactionResult) *big.Int
IsInterfaceNil() bool
}
Expand Down
Loading
Loading