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

Relayed v3 with multiple transactions #6118

Open
wants to merge 17 commits into
base: feat/relayedv3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
240 changes: 133 additions & 107 deletions api/groups/transactionGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,35 +182,42 @@
return
}

var innerTx *transaction.Transaction
if ftx.InnerTransaction != nil {
if ftx.InnerTransaction.InnerTransaction != nil {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), errors.ErrRecursiveRelayedTxIsNotAllowed.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
}
innerTxs := make([]*transaction.Transaction, 0, len(ftx.InnerTransactions))
if len(ftx.InnerTransactions) != 0 {
for _, innerTx := range ftx.InnerTransactions {
if len(innerTx.InnerTransactions) != 0 {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), errors.ErrRecursiveRelayedTxIsNotAllowed.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
}

innerTx, _, err = tg.createTransaction(ftx.InnerTransaction, nil)
if err != nil {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), err.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
newInnerTx, _, err := tg.createTransaction(innerTx, nil)
if err != nil {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), err.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return

Check warning on line 210 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L200-L210

Added lines #L200 - L210 were not covered by tests
}

innerTxs = append(innerTxs, newInnerTx)

Check warning on line 213 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L213

Added line #L213 was not covered by tests
}
}

tx, txHash, err := tg.createTransaction(&ftx, innerTx)
if len(innerTxs) == 0 {
innerTxs = nil
}
tx, txHash, err := tg.createTransaction(&ftx, innerTxs)
if err != nil {
c.JSON(
http.StatusBadRequest,
Expand Down Expand Up @@ -280,35 +287,42 @@
return
}

var innerTx *transaction.Transaction
if ftx.InnerTransaction != nil {
if ftx.InnerTransaction.InnerTransaction != nil {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), errors.ErrRecursiveRelayedTxIsNotAllowed.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
}
innerTxs := make([]*transaction.Transaction, 0, len(ftx.InnerTransactions))
if len(ftx.InnerTransactions) != 0 {
for _, innerTx := range ftx.InnerTransactions {
if len(innerTx.InnerTransactions) != 0 {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), errors.ErrRecursiveRelayedTxIsNotAllowed.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
}

innerTx, _, err = tg.createTransaction(ftx.InnerTransaction, nil)
if err != nil {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), err.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
newInnerTx, _, err := tg.createTransaction(innerTx, nil)
if err != nil {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), err.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return

Check warning on line 315 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L305-L315

Added lines #L305 - L315 were not covered by tests
}

innerTxs = append(innerTxs, newInnerTx)

Check warning on line 318 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L318

Added line #L318 was not covered by tests
}
}

tx, txHash, err := tg.createTransaction(&ftx, innerTx)
if len(innerTxs) == 0 {
innerTxs = nil
}
tx, txHash, err := tg.createTransaction(&ftx, innerTxs)
if err != nil {
c.JSON(
http.StatusBadRequest,
Expand Down Expand Up @@ -387,23 +401,28 @@
var start time.Time
txsHashes := make(map[int]string)
for idx, receivedTx := range ftxs {
var innerTx *transaction.Transaction
if receivedTx.InnerTransaction != nil {
innerTx, _, err = tg.createTransaction(receivedTx.InnerTransaction, nil)
if err != nil {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), err.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
innerTxs := make([]*transaction.Transaction, 0, len(receivedTx.InnerTransactions))
if len(receivedTx.InnerTransactions) != 0 {
for _, innerTx := range receivedTx.InnerTransactions {
if len(innerTx.InnerTransactions) != 0 {

Check warning on line 407 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L406-L407

Added lines #L406 - L407 were not covered by tests
// if one of the inner txs is invalid, break the loop and move to the next transaction received
break

Check warning on line 409 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L409

Added line #L409 was not covered by tests
}

newInnerTx, _, err := tg.createTransaction(innerTx, nil)
if err != nil {

Check warning on line 413 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L412-L413

Added lines #L412 - L413 were not covered by tests
// if one of the inner txs is invalid, break the loop and move to the next transaction received
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would you send the tx further if the inner tx is wrong? Why not error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, updated

break

Check warning on line 415 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L415

Added line #L415 was not covered by tests
}

innerTxs = append(innerTxs, newInnerTx)

Check warning on line 418 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L418

Added line #L418 was not covered by tests
}
}

tx, txHash, err = tg.createTransaction(&receivedTx, innerTx)
if len(innerTxs) == 0 {
innerTxs = nil
}
tx, txHash, err = tg.createTransaction(&receivedTx, innerTxs)
if err != nil {
continue
}
Expand Down Expand Up @@ -514,35 +533,42 @@
return
}

var innerTx *transaction.Transaction
if ftx.InnerTransaction != nil {
if ftx.InnerTransaction.InnerTransaction != nil {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), errors.ErrRecursiveRelayedTxIsNotAllowed.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
}
innerTxs := make([]*transaction.Transaction, 0, len(ftx.InnerTransactions))
if len(ftx.InnerTransactions) != 0 {
for _, innerTx := range ftx.InnerTransactions {
if len(innerTx.InnerTransactions) != 0 {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), errors.ErrRecursiveRelayedTxIsNotAllowed.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
}

innerTx, _, err = tg.createTransaction(ftx.InnerTransaction, nil)
if err != nil {
c.JSON(
http.StatusInternalServerError,
shared.GenericAPIResponse{
Data: nil,
Error: err.Error(),
Code: shared.ReturnCodeInternalError,
},
)
return
newInnerTx, _, err := tg.createTransaction(innerTx, nil)
if err != nil {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrTxGenerationFailed.Error(), err.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return

Check warning on line 561 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L551-L561

Added lines #L551 - L561 were not covered by tests
}

innerTxs = append(innerTxs, newInnerTx)

Check warning on line 564 in api/groups/transactionGroup.go

View check run for this annotation

Codecov / codecov/patch

api/groups/transactionGroup.go#L564

Added line #L564 was not covered by tests
}
}

tx, _, err := tg.createTransaction(&ftx, innerTx)
if len(innerTxs) == 0 {
innerTxs = nil
}
tx, _, err := tg.createTransaction(&ftx, innerTxs)
if err != nil {
c.JSON(
http.StatusInternalServerError,
Expand Down Expand Up @@ -752,25 +778,25 @@
)
}

func (tg *transactionGroup) createTransaction(receivedTx *transaction.FrontendTransaction, innerTx *transaction.Transaction) (*transaction.Transaction, []byte, error) {
func (tg *transactionGroup) createTransaction(receivedTx *transaction.FrontendTransaction, innerTxs []*transaction.Transaction) (*transaction.Transaction, []byte, error) {
txArgs := &external.ArgsCreateTransaction{
Nonce: receivedTx.Nonce,
Value: receivedTx.Value,
Receiver: receivedTx.Receiver,
ReceiverUsername: receivedTx.ReceiverUsername,
Sender: receivedTx.Sender,
SenderUsername: receivedTx.SenderUsername,
GasPrice: receivedTx.GasPrice,
GasLimit: receivedTx.GasLimit,
DataField: receivedTx.Data,
SignatureHex: receivedTx.Signature,
ChainID: receivedTx.ChainID,
Version: receivedTx.Version,
Options: receivedTx.Options,
Guardian: receivedTx.GuardianAddr,
GuardianSigHex: receivedTx.GuardianSignature,
Relayer: receivedTx.Relayer,
InnerTransaction: innerTx,
Nonce: receivedTx.Nonce,
Value: receivedTx.Value,
Receiver: receivedTx.Receiver,
ReceiverUsername: receivedTx.ReceiverUsername,
Sender: receivedTx.Sender,
SenderUsername: receivedTx.SenderUsername,
GasPrice: receivedTx.GasPrice,
GasLimit: receivedTx.GasLimit,
DataField: receivedTx.Data,
SignatureHex: receivedTx.Signature,
ChainID: receivedTx.ChainID,
Version: receivedTx.Version,
Options: receivedTx.Options,
Guardian: receivedTx.GuardianAddr,
GuardianSigHex: receivedTx.GuardianSignature,
Relayer: receivedTx.Relayer,
InnerTransactions: innerTxs,
}
start := time.Now()
tx, txHash, err := tg.getFacade().CreateTransaction(txArgs)
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 @@ -1155,15 +1155,15 @@ func testRecursiveRelayedV3(url string) func(t *testing.T) {
value,
signature,
)
userTx2 := fmt.Sprintf(`{"nonce": %d, "sender":"%s", "receiver":"%s", "value":"%s", "signature":"%s", "innerTransaction":%s}`,
userTx2 := fmt.Sprintf(`{"nonce": %d, "sender":"%s", "receiver":"%s", "value":"%s", "signature":"%s", "innerTransactions":[%s]}`,
nonce,
sender,
receiver,
value,
signature,
userTx1,
)
tx := fmt.Sprintf(`{"nonce": %d, "sender":"%s", "receiver":"%s", "value":"%s", "signature":"%s", "innerTransaction":%s}`,
tx := fmt.Sprintf(`{"nonce": %d, "sender":"%s", "receiver":"%s", "value":"%s", "signature":"%s", "innerTransactions":[%s]}`,
nonce,
sender,
receiver,
Expand Down
22 changes: 11 additions & 11 deletions dataRetriever/txpool/memorytests/memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,25 @@ func TestShardedTxPool_MemoryFootprint(t *testing.T) {
journals = append(journals, runScenario(t, newScenario(200, 1, core.MegabyteSize, "0"), memoryAssertion{200, 200}, memoryAssertion{0, 1}))
journals = append(journals, runScenario(t, newScenario(10, 1000, 20480, "0"), memoryAssertion{190, 205}, memoryAssertion{1, 4}))
journals = append(journals, runScenario(t, newScenario(10000, 1, 1024, "0"), memoryAssertion{10, 16}, memoryAssertion{4, 10}))
journals = append(journals, runScenario(t, newScenario(1, 60000, 256, "0"), memoryAssertion{30, 38}, memoryAssertion{10, 16}))
journals = append(journals, runScenario(t, newScenario(10, 10000, 100, "0"), memoryAssertion{36, 50}, memoryAssertion{16, 24}))
journals = append(journals, runScenario(t, newScenario(100000, 1, 1024, "0"), memoryAssertion{120, 136}, memoryAssertion{56, 60}))
journals = append(journals, runScenario(t, newScenario(1, 60000, 256, "0"), memoryAssertion{30, 40}, memoryAssertion{10, 16}))
journals = append(journals, runScenario(t, newScenario(10, 10000, 100, "0"), memoryAssertion{36, 52}, memoryAssertion{16, 24}))
journals = append(journals, runScenario(t, newScenario(100000, 1, 1024, "0"), memoryAssertion{120, 138}, memoryAssertion{56, 60}))

// With larger memory footprint

journals = append(journals, runScenario(t, newScenario(100000, 3, 650, "0"), memoryAssertion{290, 330}, memoryAssertion{95, 120}))
journals = append(journals, runScenario(t, newScenario(150000, 2, 650, "0"), memoryAssertion{290, 330}, memoryAssertion{120, 140}))
journals = append(journals, runScenario(t, newScenario(300000, 1, 650, "0"), memoryAssertion{290, 330}, memoryAssertion{170, 190}))
journals = append(journals, runScenario(t, newScenario(30, 10000, 650, "0"), memoryAssertion{290, 330}, memoryAssertion{60, 75}))
journals = append(journals, runScenario(t, newScenario(300, 1000, 650, "0"), memoryAssertion{290, 330}, memoryAssertion{60, 80}))
journals = append(journals, runScenario(t, newScenario(100000, 3, 650, "0"), memoryAssertion{290, 335}, memoryAssertion{95, 120}))
journals = append(journals, runScenario(t, newScenario(150000, 2, 650, "0"), memoryAssertion{290, 335}, memoryAssertion{120, 140}))
journals = append(journals, runScenario(t, newScenario(300000, 1, 650, "0"), memoryAssertion{290, 335}, memoryAssertion{170, 190}))
journals = append(journals, runScenario(t, newScenario(30, 10000, 650, "0"), memoryAssertion{290, 335}, memoryAssertion{60, 75}))
journals = append(journals, runScenario(t, newScenario(300, 1000, 650, "0"), memoryAssertion{290, 335}, memoryAssertion{60, 80}))

// Scenarios where destination == me

journals = append(journals, runScenario(t, newScenario(100, 1, core.MegabyteSize, "1_0"), memoryAssertion{90, 100}, memoryAssertion{0, 1}))
journals = append(journals, runScenario(t, newScenario(10000, 1, 10240, "1_0"), memoryAssertion{96, 128}, memoryAssertion{0, 4}))
journals = append(journals, runScenario(t, newScenario(10, 10000, 1000, "1_0"), memoryAssertion{96, 136}, memoryAssertion{16, 25}))
journals = append(journals, runScenario(t, newScenario(150000, 1, 128, "1_0"), memoryAssertion{50, 75}, memoryAssertion{30, 40}))
journals = append(journals, runScenario(t, newScenario(1, 150000, 128, "1_0"), memoryAssertion{50, 75}, memoryAssertion{30, 40}))
journals = append(journals, runScenario(t, newScenario(10, 10000, 1000, "1_0"), memoryAssertion{96, 140}, memoryAssertion{16, 25}))
journals = append(journals, runScenario(t, newScenario(150000, 1, 128, "1_0"), memoryAssertion{50, 80}, memoryAssertion{30, 40}))
journals = append(journals, runScenario(t, newScenario(1, 150000, 128, "1_0"), memoryAssertion{50, 80}, memoryAssertion{30, 40}))

for _, journal := range journals {
journal.displayFootprintsSummary()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
disabledFactory "github.com/multiversx/mx-chain-go/factory/disabled"
disabledGenesis "github.com/multiversx/mx-chain-go/genesis/process/disabled"
"github.com/multiversx/mx-chain-go/process"
processDisabled "github.com/multiversx/mx-chain-go/process/disabled"
"github.com/multiversx/mx-chain-go/process/factory/interceptorscontainer"
"github.com/multiversx/mx-chain-go/sharding"
"github.com/multiversx/mx-chain-go/storage/cache"
Expand Down Expand Up @@ -108,6 +109,7 @@ func NewEpochStartInterceptorsContainer(args ArgsEpochStartInterceptorContainer)
FullArchivePeerShardMapper: fullArchivePeerShardMapper,
HardforkTrigger: hardforkTrigger,
NodeOperationMode: args.NodeOperationMode,
RelayedTxV3Processor: processDisabled.NewRelayedTxV3Processor(),
}

interceptorsContainerFactory, err := interceptorscontainer.NewMetaInterceptorsContainerFactory(containerFactoryArgs)
Expand Down
3 changes: 3 additions & 0 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,3 +595,6 @@ var ErrInvalidNodeOperationMode = errors.New("invalid node operation mode")

// ErrNilSentSignatureTracker defines the error for setting a nil SentSignatureTracker
var ErrNilSentSignatureTracker = errors.New("nil sent signature tracker")

// ErrNilRelayedTxV3Processor signals that a nil relayed tx v3 processor has been provided
var ErrNilRelayedTxV3Processor = errors.New("nil relayed tx v3 processor")
1 change: 1 addition & 0 deletions factory/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ type ProcessComponentsHolder interface {
AccountsParser() genesis.AccountsParser
ReceiptsRepository() ReceiptsRepository
SentSignaturesTracker() process.SentSignaturesTracker
RelayedTxV3Processor() process.RelayedTxV3Processor
IsInterfaceNil() bool
}

Expand Down
6 changes: 6 additions & 0 deletions factory/mock/processComponentsStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type ProcessComponentsMock struct {
AccountsParserInternal genesis.AccountsParser
ReceiptsRepositoryInternal factory.ReceiptsRepository
SentSignaturesTrackerInternal process.SentSignaturesTracker
RelayedTxV3ProcessorField process.RelayedTxV3Processor
}

// Create -
Expand Down Expand Up @@ -284,6 +285,11 @@ func (pcm *ProcessComponentsMock) SentSignaturesTracker() process.SentSignatures
return pcm.SentSignaturesTrackerInternal
}

// RelayedTxV3Processor -
func (pcm *ProcessComponentsMock) RelayedTxV3Processor() process.RelayedTxV3Processor {
return pcm.RelayedTxV3ProcessorField
}

// IsInterfaceNil -
func (pcm *ProcessComponentsMock) IsInterfaceNil() bool {
return pcm == nil
Expand Down