Skip to content

Commit

Permalink
Merge branch 'feat/polaris-fixes' into remove-numNodes-trie-functiona…
Browse files Browse the repository at this point in the history
…lity
  • Loading branch information
gabi-vuls authored Feb 24, 2023
2 parents b21bdc6 + c69e883 commit 1f8be7b
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 12 deletions.
7 changes: 5 additions & 2 deletions node/external/transactionAPI/apiTransactionProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func NewAPITransactionProcessor(args *ArgAPITransactionProcessor) (*apiTransacti
)

refundDetector := newRefundDetector()
gasUsedAndFeeProc := newGasUsedAndFeeProcessor(args.FeeComputer)
gasUsedAndFeeProc := newGasUsedAndFeeProcessor(args.FeeComputer, args.AddressPubKeyConverter)

return &apiTransactionProcessor{
roundDuration: args.RoundDuration,
Expand Down Expand Up @@ -100,7 +100,10 @@ func (atp *apiTransactionProcessor) GetTransaction(txHash string, withResults bo

tx.Hash = txHash
atp.PopulateComputedFields(tx)
atp.gasUsedAndFeeProcessor.computeAndAttachGasUsedAndFee(tx)

if withResults {
atp.gasUsedAndFeeProcessor.computeAndAttachGasUsedAndFee(tx)
}

return tx, nil
}
Expand Down
40 changes: 36 additions & 4 deletions node/external/transactionAPI/gasUsedAndFeeProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import (
)

type gasUsedAndFeeProcessor struct {
feeComputer feeComputer
feeComputer feeComputer
pubKeyConverter core.PubkeyConverter
}

func newGasUsedAndFeeProcessor(txFeeCalculator feeComputer) *gasUsedAndFeeProcessor {
func newGasUsedAndFeeProcessor(txFeeCalculator feeComputer, pubKeyConverter core.PubkeyConverter) *gasUsedAndFeeProcessor {
return &gasUsedAndFeeProcessor{
feeComputer: txFeeCalculator,
feeComputer: txFeeCalculator,
pubKeyConverter: pubKeyConverter,
}
}

Expand All @@ -24,7 +26,7 @@ func (gfp *gasUsedAndFeeProcessor) computeAndAttachGasUsedAndFee(tx *transaction
tx.GasUsed = gasUsed
tx.Fee = fee.String()

if tx.IsRelayed {
if tx.IsRelayed || gfp.isESDTOperationWithSCCall(tx) {
tx.GasUsed = tx.GasLimit
tx.Fee = tx.InitiallyPaidFee
}
Expand Down Expand Up @@ -74,3 +76,33 @@ func (gfp *gasUsedAndFeeProcessor) setGasUsedAndFeeBaseOnRefundValue(tx *transac
tx.GasUsed = gasUsed
tx.Fee = fee.String()
}

func (gfp *gasUsedAndFeeProcessor) isESDTOperationWithSCCall(tx *transaction.ApiTransactionResult) bool {
isESDTTransferOperation := tx.Operation == core.BuiltInFunctionESDTTransfer ||
tx.Operation == core.BuiltInFunctionESDTNFTTransfer || tx.Operation == core.BuiltInFunctionMultiESDTNFTTransfer

isReceiverSC := core.IsSmartContractAddress(tx.Tx.GetRcvAddr())
hasFunction := tx.Function != ""
if !hasFunction {
return false
}

if tx.Sender != tx.Receiver {
return isESDTTransferOperation && isReceiverSC && hasFunction
}

if len(tx.Receivers) == 0 {
return false
}

receiver := tx.Receivers[0]
decodedReceiver, err := gfp.pubKeyConverter.Decode(receiver)
if err != nil {
log.Warn("gasUsedAndFeeProcessor.isESDTOperationWithSCCall cannot decode receiver address", "error", err.Error())
return false
}

isReceiverSC = core.IsSmartContractAddress(decodedReceiver)

return isESDTTransferOperation && isReceiverSC && hasFunction
}
41 changes: 37 additions & 4 deletions node/external/transactionAPI/gasUsedAndFeeProcessor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestComputeTransactionGasUsedAndFeeMoveBalance(t *testing.T) {
})
computer := fee.NewTestFeeComputer(feeComp)

gasUsedAndFeeProc := newGasUsedAndFeeProcessor(computer)
gasUsedAndFeeProc := newGasUsedAndFeeProcessor(computer, pubKeyConverter)

sender := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"
receiver := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"
Expand Down Expand Up @@ -53,7 +53,7 @@ func TestComputeTransactionGasUsedAndFeeLogWithError(t *testing.T) {
})
computer := fee.NewTestFeeComputer(feeComp)

gasUsedAndFeeProc := newGasUsedAndFeeProcessor(computer)
gasUsedAndFeeProc := newGasUsedAndFeeProcessor(computer, pubKeyConverter)

sender := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"
receiver := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"
Expand Down Expand Up @@ -95,7 +95,7 @@ func TestComputeTransactionGasUsedAndFeeRelayedTxWithWriteLog(t *testing.T) {
})
computer := fee.NewTestFeeComputer(feeComp)

gasUsedAndFeeProc := newGasUsedAndFeeProcessor(computer)
gasUsedAndFeeProc := newGasUsedAndFeeProcessor(computer, pubKeyConverter)

sender := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"
receiver := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"
Expand Down Expand Up @@ -132,7 +132,7 @@ func TestComputeTransactionGasUsedAndFeeTransactionWithScrWithRefund(t *testing.
})
computer := fee.NewTestFeeComputer(feeComp)

gasUsedAndFeeProc := newGasUsedAndFeeProcessor(computer)
gasUsedAndFeeProc := newGasUsedAndFeeProcessor(computer, pubKeyConverter)

sender := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"
receiver := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"
Expand Down Expand Up @@ -166,3 +166,36 @@ func TestComputeTransactionGasUsedAndFeeTransactionWithScrWithRefund(t *testing.
require.Equal(uint64(3_365_000), txWithSRefundSCR.GasUsed)
require.Equal("98000000000000", txWithSRefundSCR.Fee)
}

func TestNFTTransferWithScCall(t *testing.T) {
require := require.New(t)
feeComp, _ := fee.NewFeeComputer(fee.ArgsNewFeeComputer{
BuiltInFunctionsCostHandler: &testscommon.BuiltInCostHandlerStub{},
EconomicsConfig: testscommon.GetEconomicsConfig(),
})
computer := fee.NewTestFeeComputer(feeComp)

gasUsedAndFeeProc := newGasUsedAndFeeProcessor(computer, pubKeyConverter)

sender := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"
receiver := "erd1wc3uh22g2aved3qeehkz9kzgrjwxhg9mkkxp2ee7jj7ph34p2csq0n2y5x"

tx := &transaction.ApiTransactionResult{
Tx: &transaction.Transaction{
GasLimit: 55_000_000,
GasPrice: 1000000000,
SndAddr: silentDecodeAddress(sender),
RcvAddr: silentDecodeAddress(receiver),
Data: []byte("ESDTNFTTransfer@434f572d636434363364@080c@01@00000000000000000500d3b28828d62052124f07dcd50ed31b0825f60eee1526@616363657074476c6f62616c4f66666572@c3e5q"),
},
GasLimit: 55_000_000,
Receivers: []string{"erd1qqqqqqqqqqqqqpgq6wegs2xkypfpync8mn2sa5cmpqjlvrhwz5nqgepyg8"},
Function: "acceptGlobalOffer",
Operation: "ESDTNFTTransfer",
}
tx.InitiallyPaidFee = feeComp.ComputeTransactionFee(tx).String()

gasUsedAndFeeProc.computeAndAttachGasUsedAndFee(tx)
require.Equal(uint64(55_000_000), tx.GasUsed)
require.Equal("822250000000000", tx.Fee)
}
2 changes: 1 addition & 1 deletion outport/process/factory/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
func createArgOutportDataProviderFactory() ArgOutportDataProviderFactory {
return ArgOutportDataProviderFactory{
HasDrivers: false,
AddressConverter: &testscommon.PubkeyConverterMock{},
AddressConverter: testscommon.NewPubkeyConverterMock(32),
AccountsDB: &state.AccountsStub{},
Marshaller: &testscommon.MarshalizerMock{},
EsdtDataStorageHandler: &testscommon.EsdtStorageHandlerStub{},
Expand Down
1 change: 1 addition & 0 deletions outport/process/factory/outportDataProviderFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func CreateOutportDataProvider(arg ArgOutportDataProviderFactory) (outport.DataP
TransactionsStorer: arg.TransactionsStorer,
ShardCoordinator: arg.ShardCoordinator,
TxFeeCalculator: arg.EconomicsData,
PubKeyConverter: arg.AddressConverter,
})
if err != nil {
return nil, err
Expand Down
5 changes: 5 additions & 0 deletions outport/process/transactionsfee/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/multiversx/mx-chain-core-go/data"
"github.com/multiversx/mx-chain-core-go/data/transaction"
datafield "github.com/multiversx/mx-chain-vm-common-go/parsers/dataField"
)

// FeesProcessorHandler defines the interface for the transaction fees processor
Expand All @@ -18,3 +19,7 @@ type FeesProcessorHandler interface {
type transactionGetter interface {
GetTxByHash(txHash []byte) (*transaction.Transaction, error)
}

type dataFieldParser interface {
Parse(dataField []byte, sender, receiver []byte, numOfShards uint32) *datafield.ResponseParseData
}
25 changes: 25 additions & 0 deletions outport/process/transactionsfee/transactionChecker.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,31 @@ import (
vmcommon "github.com/multiversx/mx-chain-vm-common-go"
)

func (tep *transactionsFeeProcessor) isESDTOperationWithSCCall(tx data.TransactionHandlerWithGasUsedAndFee) bool {
res := tep.dataFieldParser.Parse(tx.GetData(), tx.GetSndAddr(), tx.GetRcvAddr(), tep.shardCoordinator.NumberOfShards())

isESDTTransferOperation := res.Operation == core.BuiltInFunctionESDTTransfer ||
res.Operation == core.BuiltInFunctionESDTNFTTransfer || res.Operation == core.BuiltInFunctionMultiESDTNFTTransfer

isReceiverSC := core.IsSmartContractAddress(tx.GetRcvAddr())
hasFunction := res.Function != ""
if !hasFunction {
return false
}

if !bytes.Equal(tx.GetSndAddr(), tx.GetRcvAddr()) {
return isESDTTransferOperation && isReceiverSC && hasFunction
}

if len(res.Receivers) == 0 {
return false
}

isReceiverSC = core.IsSmartContractAddress(res.Receivers[0])

return isESDTTransferOperation && isReceiverSC && hasFunction
}

func isSCRForSenderWithRefund(scr *smartContractResult.SmartContractResult, txHash []byte, tx data.TransactionHandlerWithGasUsedAndFee) bool {
isForSender := bytes.Equal(scr.RcvAddr, tx.GetSndAddr())
isRightNonce := scr.Nonce == tx.GetNonce()+1
Expand Down
20 changes: 19 additions & 1 deletion outport/process/transactionsfee/transactionsFeeProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,26 @@ import (
"github.com/multiversx/mx-chain-core-go/marshal"
"github.com/multiversx/mx-chain-go/sharding"
"github.com/multiversx/mx-chain-go/storage"
logger "github.com/multiversx/mx-chain-logger-go"
datafield "github.com/multiversx/mx-chain-vm-common-go/parsers/dataField"
)

var log = logger.GetOrCreate("outport/process/transactionsfee")

// ArgTransactionsFeeProcessor holds the arguments needed for creating a new instance of transactionsFeeProcessor
type ArgTransactionsFeeProcessor struct {
Marshaller marshal.Marshalizer
TransactionsStorer storage.Storer
ShardCoordinator sharding.Coordinator
TxFeeCalculator FeesProcessorHandler
PubKeyConverter core.PubkeyConverter
}

type transactionsFeeProcessor struct {
txGetter transactionGetter
txFeeCalculator FeesProcessorHandler
shardCoordinator sharding.Coordinator
dataFieldParser dataFieldParser
}

// NewTransactionsFeeProcessor will create a new instance of transactionsFeeProcessor
Expand All @@ -33,10 +39,19 @@ func NewTransactionsFeeProcessor(arg ArgTransactionsFeeProcessor) (*transactions
return nil, err
}

parser, err := datafield.NewOperationDataFieldParser(&datafield.ArgsOperationDataFieldParser{
AddressLength: arg.PubKeyConverter.Len(),
Marshalizer: arg.Marshaller,
})
if err != nil {
return nil, err
}

return &transactionsFeeProcessor{
txFeeCalculator: arg.TxFeeCalculator,
shardCoordinator: arg.ShardCoordinator,
txGetter: newTxGetter(arg.TransactionsStorer, arg.Marshaller),
dataFieldParser: parser,
}, nil
}

Expand All @@ -53,6 +68,9 @@ func checkArg(arg ArgTransactionsFeeProcessor) error {
if check.IfNil(arg.Marshaller) {
return ErrNilMarshaller
}
if check.IfNil(arg.PubKeyConverter) {
return core.ErrNilPubkeyConverter
}

return nil
}
Expand Down Expand Up @@ -86,7 +104,7 @@ func (tep *transactionsFeeProcessor) prepareNormalTxs(transactionsAndScrs *trans
txWithResult.SetFee(fee)
txWithResult.SetInitialPaidFee(initialPaidFee)

if isRelayedTx(txWithResult) {
if isRelayedTx(txWithResult) || tep.isESDTOperationWithSCCall(txWithResult) {
txWithResult.SetGasUsed(txWithResult.GetGasLimit())
txWithResult.SetFee(initialPaidFee)
}
Expand Down
41 changes: 41 additions & 0 deletions outport/process/transactionsfee/transactionsFeeProcessor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/multiversx/mx-chain-core-go/core"
"github.com/multiversx/mx-chain-core-go/core/pubkeyConverter"
coreData "github.com/multiversx/mx-chain-core-go/data"
outportcore "github.com/multiversx/mx-chain-core-go/data/outport"
"github.com/multiversx/mx-chain-core-go/data/smartContractResult"
Expand All @@ -15,12 +16,15 @@ import (
"github.com/stretchr/testify/require"
)

var pubKeyConverter, _ = pubkeyConverter.NewBech32PubkeyConverter(32, log)

func prepareMockArg() ArgTransactionsFeeProcessor {
return ArgTransactionsFeeProcessor{
Marshaller: testscommon.MarshalizerMock{},
TransactionsStorer: genericMocks.NewStorerMock(),
ShardCoordinator: &testscommon.ShardsCoordinatorMock{},
TxFeeCalculator: &mock.EconomicsHandlerMock{},
PubKeyConverter: pubKeyConverter,
}
}

Expand Down Expand Up @@ -298,3 +302,40 @@ func TestPutFeeAndGasUsedWrongRelayedTx(t *testing.T) {
require.Equal(t, uint64(550000000), initialTx.GetGasUsed())
require.Equal(t, "6103405000000000", initialTx.GetInitialPaidFee().String())
}

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

txHash := []byte("tx")
tx := outportcore.NewTransactionHandlerWithGasAndFee(&transaction.Transaction{
Nonce: 1011,
SndAddr: silentDecodeAddress("erd1dglncxk6sl9a3xumj78n6z2xux4ghp5c92cstv5zsn56tjgtdwpsk46qrs"),
RcvAddr: silentDecodeAddress("erd1dglncxk6sl9a3xumj78n6z2xux4ghp5c92cstv5zsn56tjgtdwpsk46qrs"),
GasLimit: 55_000_000,
GasPrice: 1000000000,
Data: []byte("ESDTNFTTransfer@434f572d636434363364@080c@01@00000000000000000500d3b28828d62052124f07dcd50ed31b0825f60eee1526@616363657074476c6f62616c4f66666572@c3e5"),
Value: big.NewInt(0),
}, 0, big.NewInt(0))

pool := &outportcore.Pool{
Txs: map[string]coreData.TransactionHandlerWithGasUsedAndFee{
string(txHash): tx,
},
}

arg := prepareMockArg()
txsFeeProc, err := NewTransactionsFeeProcessor(arg)
require.NotNil(t, txsFeeProc)
require.Nil(t, err)

err = txsFeeProc.PutFeeAndGasUsed(pool)
require.Nil(t, err)
require.Equal(t, big.NewInt(820765000000000), tx.GetFee())
require.Equal(t, uint64(55_000_000), tx.GetGasUsed())
require.Equal(t, "820765000000000", tx.GetInitialPaidFee().String())
}

func silentDecodeAddress(address string) []byte {
decoded, _ := pubKeyConverter.Decode(address)
return decoded
}

0 comments on commit 1f8be7b

Please sign in to comment.