Skip to content

Commit

Permalink
Merge pull request #6039 from multiversx/guardian_in_response_of_tx_p…
Browse files Browse the repository at this point in the history
…ool_request

Added missing fields on the transaction/pool by-sender request
  • Loading branch information
sstanculeanu authored Mar 14, 2024
2 parents 164da49 + 6d6332c commit 1d25207
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 66 deletions.
4 changes: 4 additions & 0 deletions api/groups/transactionGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,10 @@ func validateQuery(sender, fields string, lastNonce, nonceGaps bool) error {
return errors.ErrEmptySenderToGetNonceGaps
}

if fields == "*" {
return nil
}

if fields != "" {
return validateFields(fields)
}
Expand Down
4 changes: 2 additions & 2 deletions api/groups/transactionGroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ func TestTransactionGroup_getTransactionsPool(t *testing.T) {
t.Run("fields + nonce gaps", testTxPoolWithInvalidQuery("?fields=sender,receiver&nonce-gaps=true", apiErrors.ErrFetchingNonceGapsCannotIncludeFields))
t.Run("fields has spaces", testTxPoolWithInvalidQuery("?fields=sender ,receiver", apiErrors.ErrInvalidFields))
t.Run("fields has numbers", testTxPoolWithInvalidQuery("?fields=sender1", apiErrors.ErrInvalidFields))
t.Run("fields + wild card", testTxPoolWithInvalidQuery("?fields=sender,receiver,*", apiErrors.ErrInvalidFields))
t.Run("GetTransactionsPool error should error", func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -816,8 +817,7 @@ func TestTransactionGroup_getTransactionsPool(t *testing.T) {
t.Parallel()

expectedSender := "sender"
providedFields := "sender,receiver"
query := "?by-sender=" + expectedSender + "&fields=" + providedFields
query := "?by-sender=" + expectedSender + "&fields=*"
expectedResp := &common.TransactionsPoolForSenderApiResponse{
Transactions: []common.Transaction{
{
Expand Down
51 changes: 27 additions & 24 deletions node/external/transactionAPI/apiTransactionProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/multiversx/mx-chain-core-go/core"
"github.com/multiversx/mx-chain-core-go/data"
"github.com/multiversx/mx-chain-core-go/data/block"
rewardTxData "github.com/multiversx/mx-chain-core-go/data/rewardTx"
"github.com/multiversx/mx-chain-core-go/data/smartContractResult"
Expand Down Expand Up @@ -308,41 +309,43 @@ func (atp *apiTransactionProcessor) getUnsignedTransactionsFromPool(requestedFie
}

func (atp *apiTransactionProcessor) extractRequestedTxInfo(wrappedTx *txcache.WrappedTransaction, requestedFieldsHandler fieldsHandler) common.Transaction {
fieldGetters := atp.getFieldGettersForTx(wrappedTx)
tx := common.Transaction{
TxFields: make(map[string]interface{}),
}

tx.TxFields[hashField] = hex.EncodeToString(wrappedTx.TxHash)

if requestedFieldsHandler.HasNonce {
tx.TxFields[nonceField] = wrappedTx.Tx.GetNonce()
for field, value := range fieldGetters {
if requestedFieldsHandler.IsFieldSet(field) {
tx.TxFields[field] = value
}
}

if requestedFieldsHandler.HasSender {
tx.TxFields[senderField], _ = atp.addressPubKeyConverter.Encode(wrappedTx.Tx.GetSndAddr())
}
return tx
}

if requestedFieldsHandler.HasReceiver {
tx.TxFields[receiverField], _ = atp.addressPubKeyConverter.Encode(wrappedTx.Tx.GetRcvAddr())
func (atp *apiTransactionProcessor) getFieldGettersForTx(wrappedTx *txcache.WrappedTransaction) map[string]interface{} {
var fieldGetters = map[string]interface{}{
hashField: hex.EncodeToString(wrappedTx.TxHash),
nonceField: wrappedTx.Tx.GetNonce(),
senderField: atp.addressPubKeyConverter.SilentEncode(wrappedTx.Tx.GetSndAddr(), log),
receiverField: atp.addressPubKeyConverter.SilentEncode(wrappedTx.Tx.GetRcvAddr(), log),
gasLimitField: wrappedTx.Tx.GetGasLimit(),
gasPriceField: wrappedTx.Tx.GetGasPrice(),
rcvUsernameField: wrappedTx.Tx.GetRcvUserName(),
dataField: wrappedTx.Tx.GetData(),
valueField: getTxValue(wrappedTx),
senderShardID: wrappedTx.SenderShardID,
receiverShardID: wrappedTx.ReceiverShardID,
}

if requestedFieldsHandler.HasGasLimit {
tx.TxFields[gasLimitField] = wrappedTx.Tx.GetGasLimit()
}
if requestedFieldsHandler.HasGasPrice {
tx.TxFields[gasPriceField] = wrappedTx.Tx.GetGasPrice()
}
if requestedFieldsHandler.HasRcvUsername {
tx.TxFields[rcvUsernameField] = wrappedTx.Tx.GetRcvUserName()
}
if requestedFieldsHandler.HasData {
tx.TxFields[dataField] = wrappedTx.Tx.GetData()
}
if requestedFieldsHandler.HasValue {
tx.TxFields[valueField] = getTxValue(wrappedTx)
guardedTx, isGuardedTx := wrappedTx.Tx.(data.GuardedTransactionHandler)
if isGuardedTx {
fieldGetters[signatureField] = hex.EncodeToString(guardedTx.GetSignature())
fieldGetters[guardianField] = atp.addressPubKeyConverter.SilentEncode(guardedTx.GetGuardianAddr(), log)
fieldGetters[guardianSignatureField] = hex.EncodeToString(guardedTx.GetGuardianSignature())
}

return tx
return fieldGetters
}

func (atp *apiTransactionProcessor) fetchTxsForSender(sender string, senderShard uint32) []*txcache.WrappedTransaction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ func TestApiTransactionProcessor_GetTransactionsPoolForSender(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, atp)

res, err := atp.GetTransactionsPoolForSender(sender, "sender,value")
res, err := atp.GetTransactionsPoolForSender(sender, "*")
require.NoError(t, err)
expectedHashes := []string{hex.EncodeToString(txHash0), hex.EncodeToString(txHash1), hex.EncodeToString(txHash2), hex.EncodeToString(txHash3), hex.EncodeToString(txHash4)}
expectedValues := []string{"100001", "100002", "100003", "100004", "100005"}
Expand Down
75 changes: 48 additions & 27 deletions node/external/transactionAPI/fieldsHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,60 @@ import (
)

const (
hashField = "hash"
nonceField = "nonce"
senderField = "sender"
receiverField = "receiver"
gasLimitField = "gaslimit"
gasPriceField = "gasprice"
rcvUsernameField = "receiverusername"
dataField = "data"
valueField = "value"
hashField = "hash"
nonceField = "nonce"
senderField = "sender"
receiverField = "receiver"
gasLimitField = "gaslimit"
gasPriceField = "gasprice"
rcvUsernameField = "receiverusername"
dataField = "data"
valueField = "value"
signatureField = "signature"
guardianField = "guardian"
guardianSignatureField = "guardiansignature"
senderShardID = "sendershard"
receiverShardID = "receivershard"
wildCard = "*"

separator = ","
)

type fieldsHandler struct {
HasNonce bool
HasSender bool
HasReceiver bool
HasGasLimit bool
HasGasPrice bool
HasRcvUsername bool
HasData bool
HasValue bool
fieldsMap map[string]struct{}
}

func newFieldsHandler(parameters string) fieldsHandler {
if len(parameters) == 0 {
return fieldsHandler{
fieldsMap: map[string]struct{}{
hashField: {}, // hash should always be returned
},
}
}

parameters = strings.ToLower(parameters)
ph := fieldsHandler{
HasNonce: strings.Contains(parameters, nonceField),
HasSender: strings.Contains(parameters, senderField),
HasReceiver: strings.Contains(parameters, receiverField),
HasGasLimit: strings.Contains(parameters, gasLimitField),
HasGasPrice: strings.Contains(parameters, gasPriceField),
HasRcvUsername: strings.Contains(parameters, rcvUsernameField),
HasData: strings.Contains(parameters, dataField),
HasValue: strings.Contains(parameters, valueField),
return fieldsHandler{
fieldsMap: sliceToMap(strings.Split(parameters, separator)),
}
}

// IsFieldSet returns true if the provided field is set
func (handler *fieldsHandler) IsFieldSet(field string) bool {
_, hasWildCard := handler.fieldsMap[wildCard]
if hasWildCard {
return true
}
return ph

_, has := handler.fieldsMap[strings.ToLower(field)]
return has
}

func sliceToMap(providedSlice []string) map[string]struct{} {
result := make(map[string]struct{}, len(providedSlice))
for _, entry := range providedSlice {
result[entry] = struct{}{}
}

return result
}
25 changes: 13 additions & 12 deletions node/external/transactionAPI/fieldsHandler_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package transactionAPI

import (
"fmt"
"strings"
"testing"

"github.com/stretchr/testify/require"
Expand All @@ -10,18 +12,17 @@ func Test_newFieldsHandler(t *testing.T) {
t.Parallel()

fh := newFieldsHandler("")
require.Equal(t, fieldsHandler{}, fh)
require.Equal(t, fieldsHandler{map[string]struct{}{hashField: {}}}, fh)

fh = newFieldsHandler("nOnCe,sender,receiver,gasLimit,GASprice,receiverusername,data,value")
expectedPH := fieldsHandler{
HasNonce: true,
HasSender: true,
HasReceiver: true,
HasGasLimit: true,
HasGasPrice: true,
HasRcvUsername: true,
HasData: true,
HasValue: true,
providedFields := "nOnCe,sender,receiver,gasLimit,GASprice,receiverusername,data,value,signature,guardian,guardiansignature,sendershard,receivershard"
splitFields := strings.Split(providedFields, separator)
fh = newFieldsHandler(providedFields)
for _, field := range splitFields {
require.True(t, fh.IsFieldSet(field), fmt.Sprintf("field %s is not set", field))
}

fh = newFieldsHandler("*")
for _, field := range splitFields {
require.True(t, fh.IsFieldSet(field))
}
require.Equal(t, expectedPH, fh)
}

0 comments on commit 1d25207

Please sign in to comment.