Skip to content

Commit

Permalink
Merge pull request #6335 from multiversx/fix_fee_field
Browse files Browse the repository at this point in the history
Fixed Fee/InitiallyPaidFee fields
  • Loading branch information
sstanculeanu committed Aug 20, 2024
2 parents 2474c88 + 6cec9ed commit a79a79c
Show file tree
Hide file tree
Showing 18 changed files with 473 additions and 80 deletions.
2 changes: 2 additions & 0 deletions factory/api/apiResolverFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ func CreateApiResolver(args *ApiResolverArgs) (facade.ApiResolver, error) {
TxTypeHandler: txTypeHandler,
LogsFacade: logsFacade,
DataFieldParser: dataFieldParser,
TxMarshaller: args.CoreComponents.TxMarshalizer(),
EnableEpochsHandler: args.CoreComponents.EnableEpochsHandler(),
}
apiTransactionProcessor, err := transactionAPI.NewAPITransactionProcessor(argsAPITransactionProc)
if err != nil {
Expand Down
114 changes: 91 additions & 23 deletions integrationTests/chainSimulator/relayedTx/relayedTx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
minGasLimit = 50_000
guardAccountCost = 250_000
extraGasLimitForGuarded = minGasLimit
gasPerDataByte = 1_500
txVersion = 2
mockTxSignature = "sig"
maxNumOfBlocksToGenerateWhenExecutingTx = 10
Expand Down Expand Up @@ -177,16 +178,7 @@ func TestRelayedTransactionInMultiShardEnvironmentWithChainSimulatorScCalls(t *t
require.Nil(t, err)

ownerNonce := uint64(0)
scCode := wasm.GetSCCode("testData/adder.wasm")
params := []string{scCode, wasm.VMTypeHex, wasm.DummyCodeMetadataHex, "00"}
txDataDeploy := strings.Join(params, "@")
deployTx := generateTransaction(owner.Bytes, ownerNonce, make([]byte, 32), big.NewInt(0), txDataDeploy, 100000000)

result, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(deployTx, maxNumOfBlocksToGenerateWhenExecutingTx)
require.NoError(t, err)

scAddress := result.Logs.Events[0].Address
scAddressBytes, _ := pkConv.Decode(scAddress)
scAddressBytes := deployAdder(t, cs, owner, ownerNonce)
scShard := shardC.ComputeId(scAddressBytes)
scShardNodeHandler := cs.GetNodeHandler(scShard)

Expand Down Expand Up @@ -235,7 +227,7 @@ func TestRelayedTransactionInMultiShardEnvironmentWithChainSimulatorScCalls(t *t
relayedTx := generateTransaction(relayer.Bytes, 0, relayer.Bytes, big.NewInt(0), "", relayedTxGasLimit)
relayedTx.InnerTransactions = innerTxs

result, err = cs.SendTxAndGenerateBlockTilTxIsExecuted(relayedTx, maxNumOfBlocksToGenerateWhenExecutingTx)
result, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(relayedTx, maxNumOfBlocksToGenerateWhenExecutingTx)
require.NoError(t, err)

checkSum(t, scShardNodeHandler, scAddressBytes, owner.Bytes, 4)
Expand Down Expand Up @@ -365,8 +357,6 @@ func testFixRelayedMoveBalanceWithChainSimulatorScCall(
cs := startChainSimulator(t, alterConfigsFunc)
defer cs.Close()

pkConv := cs.GetNodeHandler(0).GetCoreComponents().AddressPubKeyConverter()

initialBalance := big.NewInt(0).Mul(oneEGLD, big.NewInt(10))
relayer, err := cs.GenerateAndMintWalletAddress(0, initialBalance)
require.NoError(t, err)
Expand All @@ -379,16 +369,8 @@ func testFixRelayedMoveBalanceWithChainSimulatorScCall(
err = cs.GenerateBlocks(1)
require.NoError(t, err)

scCode := wasm.GetSCCode("testData/adder.wasm")
params := []string{scCode, wasm.VMTypeHex, wasm.DummyCodeMetadataHex, "00"}
txDataDeploy := strings.Join(params, "@")
deployTx := generateTransaction(owner.Bytes, 0, make([]byte, 32), big.NewInt(0), txDataDeploy, 100000000)

result, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(deployTx, maxNumOfBlocksToGenerateWhenExecutingTx)
require.NoError(t, err)

scAddress := result.Logs.Events[0].Address
scAddressBytes, _ := pkConv.Decode(scAddress)
ownerNonce := uint64(0)
scAddressBytes := deployAdder(t, cs, owner, ownerNonce)

// fast-forward until epoch 4
err = cs.GenerateBlocksUntilEpochIsReached(int32(4))
Expand Down Expand Up @@ -651,6 +633,67 @@ func TestRelayedTransactionInMultiShardEnvironmentWithChainSimulatorInnerNotExec
checkBalance(t, cs, receiver, oneEGLD)
}

func TestRelayedTransactionFeeField(t *testing.T) {
if testing.Short() {
t.Skip("this is not a short test")
}

cs := startChainSimulator(t, func(cfg *config.Configs) {
cfg.EpochConfig.EnableEpochs.RelayedTransactionsEnableEpoch = 1
cfg.EpochConfig.EnableEpochs.RelayedTransactionsV2EnableEpoch = 1
cfg.EpochConfig.EnableEpochs.RelayedTransactionsV3EnableEpoch = 1
cfg.EpochConfig.EnableEpochs.FixRelayedBaseCostEnableEpoch = 1
})
defer cs.Close()

initialBalance := big.NewInt(0).Mul(oneEGLD, big.NewInt(10))
relayer, err := cs.GenerateAndMintWalletAddress(0, initialBalance)
require.NoError(t, err)

sender, err := cs.GenerateAndMintWalletAddress(0, initialBalance)
require.NoError(t, err)

receiver, err := cs.GenerateAndMintWalletAddress(0, big.NewInt(0))
require.NoError(t, err)

err = cs.GenerateBlocks(1)
require.Nil(t, err)

t.Run("relayed v1", func(t *testing.T) {
innerTx := generateTransaction(sender.Bytes, 0, receiver.Bytes, oneEGLD, "", minGasLimit)
buff, err := json.Marshal(innerTx)
require.NoError(t, err)

txData := []byte("relayedTx@" + hex.EncodeToString(buff))
gasLimit := minGasLimit + len(txData)*gasPerDataByte + int(innerTx.GasLimit)
relayedTx := generateTransaction(relayer.Bytes, 0, sender.Bytes, big.NewInt(0), string(txData), uint64(gasLimit))

result, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(relayedTx, maxNumOfBlocksToGenerateWhenExecutingTx)
require.NoError(t, err)

expectedFee := core.SafeMul(uint64(gasLimit), minGasPrice)
require.Equal(t, expectedFee.String(), result.Fee)
require.Equal(t, expectedFee.String(), result.InitiallyPaidFee)
require.Equal(t, uint64(gasLimit), result.GasUsed)
})
t.Run("relayed v3", func(t *testing.T) {
innerTx := generateTransaction(sender.Bytes, 1, receiver.Bytes, oneEGLD, "", minGasLimit)
innerTx.RelayerAddr = relayer.Bytes

gasLimit := minGasLimit + int(innerTx.GasLimit)
relayedTx := generateTransaction(relayer.Bytes, 1, relayer.Bytes, big.NewInt(0), "", uint64(gasLimit))
relayedTx.InnerTransactions = []*transaction.Transaction{innerTx}

result, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(relayedTx, maxNumOfBlocksToGenerateWhenExecutingTx)
require.NoError(t, err)

expectedFee := core.SafeMul(uint64(gasLimit), minGasPrice)
require.Equal(t, expectedFee.String(), result.Fee)
require.Equal(t, expectedFee.String(), result.InitiallyPaidFee)
require.Equal(t, uint64(gasLimit), result.GasUsed)
})
}

func startChainSimulator(
t *testing.T,
alterConfigsFunction func(cfg *config.Configs),
Expand Down Expand Up @@ -775,3 +818,28 @@ func checkBalance(
balance := getBalance(t, cs, address)
require.Equal(t, expectedBalance.String(), balance.String())
}

func deployAdder(
t *testing.T,
cs testsChainSimulator.ChainSimulator,
owner dtos.WalletAddress,
ownerNonce uint64,
) []byte {
pkConv := cs.GetNodeHandler(0).GetCoreComponents().AddressPubKeyConverter()

err := cs.GenerateBlocks(1)
require.Nil(t, err)

scCode := wasm.GetSCCode("testData/adder.wasm")
params := []string{scCode, wasm.VMTypeHex, wasm.DummyCodeMetadataHex, "00"}
txDataDeploy := strings.Join(params, "@")
deployTx := generateTransaction(owner.Bytes, ownerNonce, make([]byte, 32), big.NewInt(0), txDataDeploy, 100000000)

result, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(deployTx, maxNumOfBlocksToGenerateWhenExecutingTx)
require.NoError(t, err)

scAddress := result.Logs.Events[0].Address
scAddressBytes, _ := pkConv.Decode(scAddress)

return scAddressBytes
}
3 changes: 3 additions & 0 deletions integrationTests/testProcessorNodeWithTestWebServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/multiversx/mx-chain-go/testscommon"
"github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock"
"github.com/multiversx/mx-chain-go/testscommon/genesisMocks"
"github.com/multiversx/mx-chain-go/testscommon/marshallerMock"
"github.com/multiversx/mx-chain-go/testscommon/state"
"github.com/multiversx/mx-chain-go/vm/systemSmartContracts/defaults"
"github.com/multiversx/mx-chain-vm-common-go/parsers"
Expand Down Expand Up @@ -236,6 +237,8 @@ func createFacadeComponents(tpn *TestProcessorNode) nodeFacade.ApiResolver {
TxTypeHandler: txTypeHandler,
LogsFacade: logsFacade,
DataFieldParser: dataFieldParser,
TxMarshaller: &marshallerMock.MarshalizerMock{},
EnableEpochsHandler: tpn.EnableEpochsHandler,
}
apiTransactionHandler, err := transactionAPI.NewAPITransactionProcessor(argsApiTransactionProc)
log.LogIfError(err)
Expand Down
3 changes: 3 additions & 0 deletions node/external/transactionAPI/apiTransactionArgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/multiversx/mx-chain-core-go/core"
"github.com/multiversx/mx-chain-core-go/data/typeConverters"
"github.com/multiversx/mx-chain-core-go/marshal"
"github.com/multiversx/mx-chain-go/common"
"github.com/multiversx/mx-chain-go/dataRetriever"
"github.com/multiversx/mx-chain-go/dblookupext"
"github.com/multiversx/mx-chain-go/process"
Expand All @@ -27,4 +28,6 @@ type ArgAPITransactionProcessor struct {
TxTypeHandler process.TxTypeHandler
LogsFacade LogsFacade
DataFieldParser DataFieldParser
TxMarshaller marshal.Marshalizer
EnableEpochsHandler common.EnableEpochsHandler
}
18 changes: 17 additions & 1 deletion node/external/transactionAPI/apiTransactionProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/multiversx/mx-chain-go/dataRetriever"
"github.com/multiversx/mx-chain-go/dblookupext"
"github.com/multiversx/mx-chain-go/process"
"github.com/multiversx/mx-chain-go/process/smartContract"
"github.com/multiversx/mx-chain-go/process/txstatus"
"github.com/multiversx/mx-chain-go/sharding"
"github.com/multiversx/mx-chain-go/storage/txcache"
Expand All @@ -44,6 +45,7 @@ type apiTransactionProcessor struct {
transactionResultsProcessor *apiTransactionResultsProcessor
refundDetector *refundDetector
gasUsedAndFeeProcessor *gasUsedAndFeeProcessor
enableEpochsHandler common.EnableEpochsHandler
}

// NewAPITransactionProcessor will create a new instance of apiTransactionProcessor
Expand All @@ -66,7 +68,13 @@ func NewAPITransactionProcessor(args *ArgAPITransactionProcessor) (*apiTransacti
)

refundDetectorInstance := NewRefundDetector()
gasUsedAndFeeProc := newGasUsedAndFeeProcessor(args.FeeComputer, args.AddressPubKeyConverter)
gasUsedAndFeeProc := newGasUsedAndFeeProcessor(
args.FeeComputer,
args.AddressPubKeyConverter,
smartContract.NewArgumentParser(),
args.TxMarshaller,
args.EnableEpochsHandler,
)

return &apiTransactionProcessor{
roundDuration: args.RoundDuration,
Expand All @@ -84,6 +92,7 @@ func NewAPITransactionProcessor(args *ArgAPITransactionProcessor) (*apiTransacti
transactionResultsProcessor: txResultsProc,
refundDetector: refundDetectorInstance,
gasUsedAndFeeProcessor: gasUsedAndFeeProc,
enableEpochsHandler: args.EnableEpochsHandler,
}, nil
}

Expand Down Expand Up @@ -188,6 +197,13 @@ func (atp *apiTransactionProcessor) populateComputedFieldInitiallyPaidFee(tx *tr
fee := atp.feeComputer.ComputeTransactionFee(tx)
// For user-initiated transactions, we can assume the fee is always strictly positive (note: BigInt(0) is stringified as "").
tx.InitiallyPaidFee = fee.String()

isFeeFixActive := atp.enableEpochsHandler.IsFlagEnabledInEpoch(common.FixRelayedBaseCostFlag, tx.Epoch)
isRelayedAfterFix := tx.IsRelayed && isFeeFixActive
if isRelayedAfterFix {
fee, _ = atp.gasUsedAndFeeProcessor.getFeeOfRelayed(tx)
tx.InitiallyPaidFee = fee.String()
}
}

func (atp *apiTransactionProcessor) populateComputedFieldIsRefund(tx *transaction.ApiTransactionResult) {
Expand Down
28 changes: 28 additions & 0 deletions node/external/transactionAPI/apiTransactionProcessor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ import (
"github.com/multiversx/mx-chain-go/testscommon"
dataRetrieverMock "github.com/multiversx/mx-chain-go/testscommon/dataRetriever"
dblookupextMock "github.com/multiversx/mx-chain-go/testscommon/dblookupext"
"github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock"
"github.com/multiversx/mx-chain-go/testscommon/genericMocks"
"github.com/multiversx/mx-chain-go/testscommon/marshallerMock"
storageStubs "github.com/multiversx/mx-chain-go/testscommon/storage"
"github.com/multiversx/mx-chain-go/testscommon/txcachemocks"
datafield "github.com/multiversx/mx-chain-vm-common-go/parsers/dataField"
Expand All @@ -59,6 +61,8 @@ func createMockArgAPITransactionProcessor() *ArgAPITransactionProcessor {
return &datafield.ResponseParseData{}
},
},
TxMarshaller: &marshallerMock.MarshalizerMock{},
EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(),
}
}

Expand Down Expand Up @@ -181,6 +185,24 @@ func TestNewAPITransactionProcessor(t *testing.T) {
_, err := NewAPITransactionProcessor(arguments)
require.Equal(t, ErrNilDataFieldParser, err)
})
t.Run("NilTxMarshaller", func(t *testing.T) {
t.Parallel()

arguments := createMockArgAPITransactionProcessor()
arguments.TxMarshaller = nil

_, err := NewAPITransactionProcessor(arguments)
require.True(t, strings.Contains(err.Error(), process.ErrNilMarshalizer.Error()))
})
t.Run("NilEnableEpochsHandler", func(t *testing.T) {
t.Parallel()

arguments := createMockArgAPITransactionProcessor()
arguments.EnableEpochsHandler = nil

_, err := NewAPITransactionProcessor(arguments)
require.Equal(t, process.ErrNilEnableEpochsHandler, err)
})
}

func TestNode_GetTransactionInvalidHashShouldErr(t *testing.T) {
Expand Down Expand Up @@ -338,6 +360,8 @@ func TestNode_GetSCRs(t *testing.T) {
return &datafield.ResponseParseData{}
},
},
EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(),
TxMarshaller: &mock.MarshalizerFake{},
}
apiTransactionProc, _ := NewAPITransactionProcessor(args)

Expand Down Expand Up @@ -546,6 +570,8 @@ func TestNode_GetTransactionWithResultsFromStorage(t *testing.T) {
return &datafield.ResponseParseData{}
},
},
TxMarshaller: &marshallerMock.MarshalizerMock{},
EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(),
}
apiTransactionProc, _ := NewAPITransactionProcessor(args)

Expand Down Expand Up @@ -1114,6 +1140,8 @@ func createAPITransactionProc(t *testing.T, epoch uint32, withDbLookupExt bool)
TxTypeHandler: &testscommon.TxTypeHandlerMock{},
LogsFacade: &testscommon.LogsFacadeStub{},
DataFieldParser: dataFieldParser,
TxMarshaller: &marshallerMock.MarshalizerMock{},
EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(),
}
apiTransactionProc, err := NewAPITransactionProcessor(args)
require.Nil(t, err)
Expand Down
8 changes: 8 additions & 0 deletions node/external/transactionAPI/check.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package transactionAPI

import (
"fmt"

"github.com/multiversx/mx-chain-core-go/core/check"
"github.com/multiversx/mx-chain-go/process"
)
Expand Down Expand Up @@ -42,6 +44,12 @@ func checkNilArgs(arg *ArgAPITransactionProcessor) error {
if check.IfNilReflect(arg.DataFieldParser) {
return ErrNilDataFieldParser
}
if check.IfNil(arg.TxMarshaller) {
return fmt.Errorf("%w for tx marshaller", process.ErrNilMarshalizer)
}
if check.IfNil(arg.EnableEpochsHandler) {
return process.ErrNilEnableEpochsHandler
}

return nil
}
Loading

0 comments on commit a79a79c

Please sign in to comment.