From 80471cb56497b800f5addb981b6dbd2e51dbde42 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 9 Oct 2023 15:23:37 +0300 Subject: [PATCH 01/40] support for relayed v3 --- data/transaction.go | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/data/transaction.go b/data/transaction.go index b2ea4d10..975c6945 100644 --- a/data/transaction.go +++ b/data/transaction.go @@ -11,22 +11,24 @@ import ( // Transaction represents the structure that maps and validates user input for publishing a new transaction type Transaction struct { // This field is used to tag transactions for send-multiple route - Index int `json:"-"` - Nonce uint64 `json:"nonce"` - Value string `json:"value"` - Receiver string `json:"receiver"` - Sender string `json:"sender"` - SenderUsername []byte `json:"senderUsername,omitempty"` - ReceiverUsername []byte `json:"receiverUsername,omitempty"` - GasPrice uint64 `json:"gasPrice"` - GasLimit uint64 `json:"gasLimit"` - Data []byte `json:"data,omitempty"` - Signature string `json:"signature,omitempty"` - ChainID string `json:"chainID"` - Version uint32 `json:"version"` - Options uint32 `json:"options,omitempty"` - GuardianAddr string `json:"guardian,omitempty"` - GuardianSignature string `json:"guardianSignature,omitempty"` + Index int `json:"-"` + Nonce uint64 `json:"nonce"` + Value string `json:"value"` + Receiver string `json:"receiver"` + Sender string `json:"sender"` + SenderUsername []byte `json:"senderUsername,omitempty"` + ReceiverUsername []byte `json:"receiverUsername,omitempty"` + GasPrice uint64 `json:"gasPrice"` + GasLimit uint64 `json:"gasLimit"` + Data []byte `json:"data,omitempty"` + Signature string `json:"signature,omitempty"` + ChainID string `json:"chainID"` + Version uint32 `json:"version"` + Options uint32 `json:"options,omitempty"` + GuardianAddr string `json:"guardian,omitempty"` + GuardianSignature string `json:"guardianSignature,omitempty"` + Relayer string `json:"relayer,omitempty"` + InnerTransactions []*Transaction `json:"innerTransactions,omitempty"` } // GetTransactionResponseData follows the format of the data field of get transaction response From 627293e012eec314292284d935589ad59aba0fc1 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Fri, 27 Oct 2023 14:10:03 +0300 Subject: [PATCH 02/40] single inner tx --- data/transaction.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/data/transaction.go b/data/transaction.go index 975c6945..aa71295b 100644 --- a/data/transaction.go +++ b/data/transaction.go @@ -11,24 +11,24 @@ import ( // Transaction represents the structure that maps and validates user input for publishing a new transaction type Transaction struct { // This field is used to tag transactions for send-multiple route - Index int `json:"-"` - Nonce uint64 `json:"nonce"` - Value string `json:"value"` - Receiver string `json:"receiver"` - Sender string `json:"sender"` - SenderUsername []byte `json:"senderUsername,omitempty"` - ReceiverUsername []byte `json:"receiverUsername,omitempty"` - GasPrice uint64 `json:"gasPrice"` - GasLimit uint64 `json:"gasLimit"` - Data []byte `json:"data,omitempty"` - Signature string `json:"signature,omitempty"` - ChainID string `json:"chainID"` - Version uint32 `json:"version"` - Options uint32 `json:"options,omitempty"` - GuardianAddr string `json:"guardian,omitempty"` - GuardianSignature string `json:"guardianSignature,omitempty"` - Relayer string `json:"relayer,omitempty"` - InnerTransactions []*Transaction `json:"innerTransactions,omitempty"` + Index int `json:"-"` + Nonce uint64 `json:"nonce"` + Value string `json:"value"` + Receiver string `json:"receiver"` + Sender string `json:"sender"` + SenderUsername []byte `json:"senderUsername,omitempty"` + ReceiverUsername []byte `json:"receiverUsername,omitempty"` + GasPrice uint64 `json:"gasPrice"` + GasLimit uint64 `json:"gasLimit"` + Data []byte `json:"data,omitempty"` + Signature string `json:"signature,omitempty"` + ChainID string `json:"chainID"` + Version uint32 `json:"version"` + Options uint32 `json:"options,omitempty"` + GuardianAddr string `json:"guardian,omitempty"` + GuardianSignature string `json:"guardianSignature,omitempty"` + Relayer string `json:"relayer,omitempty"` + InnerTransaction *Transaction `json:"innerTransaction,omitempty"` } // GetTransactionResponseData follows the format of the data field of get transaction response From 990158ee9ea3386d04871555b81ddd70f66cab37 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 11 Mar 2024 20:53:55 +0200 Subject: [PATCH 03/40] added support for wild card in tx pool request by sender --- api/groups/baseTransactionGroup.go | 4 ++++ api/groups/baseTransactionGroup_test.go | 1 + 2 files changed, 5 insertions(+) diff --git a/api/groups/baseTransactionGroup.go b/api/groups/baseTransactionGroup.go index 59a64037..f73c68a4 100644 --- a/api/groups/baseTransactionGroup.go +++ b/api/groups/baseTransactionGroup.go @@ -337,6 +337,10 @@ func validateOptions(options common.TransactionsPoolOptions) error { return errors.ErrEmptySenderToGetNonceGaps } + if options.Fields == "*" { + return nil + } + if options.Fields != "" { return validateFields(options.Fields) } diff --git a/api/groups/baseTransactionGroup_test.go b/api/groups/baseTransactionGroup_test.go index f067abcd..fd4b9c82 100644 --- a/api/groups/baseTransactionGroup_test.go +++ b/api/groups/baseTransactionGroup_test.go @@ -561,6 +561,7 @@ func TestGetTransactionsPool_InvalidOptions(t *testing.T) { t.Run("empty sender when fetching nonce gaps", testInvalidParameters("?nonce-gaps=true", apiErrors.ErrEmptySenderToGetNonceGaps)) t.Run("invalid fields - numeric", testInvalidParameters("?fields=123", apiErrors.ErrInvalidFields)) t.Run("invalid characters on fields", testInvalidParameters("?fields=_/+", apiErrors.ErrInvalidFields)) + t.Run("fields + wild card", testInvalidParameters("?fields=nonce,sender,*", apiErrors.ErrInvalidFields)) } func testInvalidParameters(path string, expectedErr error) func(t *testing.T) { From 826a1ae88780ce7bbe7feae280eb239c1eec6d49 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Fri, 5 Apr 2024 09:56:53 +0300 Subject: [PATCH 04/40] multiple inner txs on relayed v3 --- data/transaction.go | 36 ++++++++++++++++++------------------ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/data/transaction.go b/data/transaction.go index a54572b8..9173a883 100644 --- a/data/transaction.go +++ b/data/transaction.go @@ -11,24 +11,24 @@ import ( // Transaction represents the structure that maps and validates user input for publishing a new transaction type Transaction struct { // This field is used to tag transactions for send-multiple route - Index int `json:"-"` - Nonce uint64 `json:"nonce"` - Value string `json:"value"` - Receiver string `json:"receiver"` - Sender string `json:"sender"` - SenderUsername []byte `json:"senderUsername,omitempty"` - ReceiverUsername []byte `json:"receiverUsername,omitempty"` - GasPrice uint64 `json:"gasPrice"` - GasLimit uint64 `json:"gasLimit"` - Data []byte `json:"data,omitempty"` - Signature string `json:"signature,omitempty"` - ChainID string `json:"chainID"` - Version uint32 `json:"version"` - Options uint32 `json:"options,omitempty"` - GuardianAddr string `json:"guardian,omitempty"` - GuardianSignature string `json:"guardianSignature,omitempty"` - Relayer string `json:"relayer,omitempty"` - InnerTransaction *Transaction `json:"innerTransaction,omitempty"` + Index int `json:"-"` + Nonce uint64 `json:"nonce"` + Value string `json:"value"` + Receiver string `json:"receiver"` + Sender string `json:"sender"` + SenderUsername []byte `json:"senderUsername,omitempty"` + ReceiverUsername []byte `json:"receiverUsername,omitempty"` + GasPrice uint64 `json:"gasPrice"` + GasLimit uint64 `json:"gasLimit"` + Data []byte `json:"data,omitempty"` + Signature string `json:"signature,omitempty"` + ChainID string `json:"chainID"` + Version uint32 `json:"version"` + Options uint32 `json:"options,omitempty"` + GuardianAddr string `json:"guardian,omitempty"` + GuardianSignature string `json:"guardianSignature,omitempty"` + Relayer string `json:"relayer,omitempty"` + InnerTransactions []*Transaction `json:"innerTransactions,omitempty"` } // GetTransactionResponseData follows the format of the data field of get transaction response diff --git a/go.mod b/go.mod index fe449993..ab60d138 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/gin-contrib/pprof v1.4.0 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.9.1 - github.com/multiversx/mx-chain-core-go v1.2.19-0.20231208083458-cdde72601592 + github.com/multiversx/mx-chain-core-go v1.2.20-0.20240404181342-48e2da52259e github.com/multiversx/mx-chain-crypto-go v1.2.9 github.com/multiversx/mx-chain-es-indexer-go v1.4.13 github.com/multiversx/mx-chain-logger-go v1.0.13 diff --git a/go.sum b/go.sum index 06e0a306..83a50dd5 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiversx/mx-chain-core-go v1.2.19-0.20231208083458-cdde72601592 h1:fXpqfN64mLKvJycf5doOhvFRLM06eaMi7Ag3mO1fsbg= -github.com/multiversx/mx-chain-core-go v1.2.19-0.20231208083458-cdde72601592/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-core-go v1.2.20-0.20240404181342-48e2da52259e h1:MseWlrUS8b8RhJ6JUqQBpYeYylmyoWqom+bvn3Cl/U4= +github.com/multiversx/mx-chain-core-go v1.2.20-0.20240404181342-48e2da52259e/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= github.com/multiversx/mx-chain-crypto-go v1.2.9 h1:OEfF2kOQrtzUl273Z3DEcshjlTVUfPpJMd0R0SvTrlU= github.com/multiversx/mx-chain-crypto-go v1.2.9/go.mod h1:fkaWKp1rbQN9wPKya5jeoRyC+c/SyN/NfggreyeBw+8= github.com/multiversx/mx-chain-es-indexer-go v1.4.13 h1:3Ayaw9bSpeNOF+Z3L/11MN1rIJH8Rc6dqtt+o4Wfdno= From 6956918038e87603d616d98b59aca32428795c2b Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 9 May 2024 15:38:19 +0300 Subject: [PATCH 05/40] updated deps after merge --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index fe449993..b875aa32 100644 --- a/go.mod +++ b/go.mod @@ -8,10 +8,10 @@ require ( github.com/gin-contrib/pprof v1.4.0 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.9.1 - github.com/multiversx/mx-chain-core-go v1.2.19-0.20231208083458-cdde72601592 - github.com/multiversx/mx-chain-crypto-go v1.2.9 - github.com/multiversx/mx-chain-es-indexer-go v1.4.13 - github.com/multiversx/mx-chain-logger-go v1.0.13 + github.com/multiversx/mx-chain-core-go v1.2.21-0.20240508071047-fefea5737840 + github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df + github.com/multiversx/mx-chain-es-indexer-go v1.7.1-0.20240509104512-25512675833d + github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 github.com/urfave/cli v1.22.10 diff --git a/go.sum b/go.sum index 06e0a306..e763f63d 100644 --- a/go.sum +++ b/go.sum @@ -131,14 +131,14 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiversx/mx-chain-core-go v1.2.19-0.20231208083458-cdde72601592 h1:fXpqfN64mLKvJycf5doOhvFRLM06eaMi7Ag3mO1fsbg= -github.com/multiversx/mx-chain-core-go v1.2.19-0.20231208083458-cdde72601592/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= -github.com/multiversx/mx-chain-crypto-go v1.2.9 h1:OEfF2kOQrtzUl273Z3DEcshjlTVUfPpJMd0R0SvTrlU= -github.com/multiversx/mx-chain-crypto-go v1.2.9/go.mod h1:fkaWKp1rbQN9wPKya5jeoRyC+c/SyN/NfggreyeBw+8= -github.com/multiversx/mx-chain-es-indexer-go v1.4.13 h1:3Ayaw9bSpeNOF+Z3L/11MN1rIJH8Rc6dqtt+o4Wfdno= -github.com/multiversx/mx-chain-es-indexer-go v1.4.13/go.mod h1:g0REyU8rqJfoBq6mIfqEi6IdpLofECLEvKKGMJO8ZhM= -github.com/multiversx/mx-chain-logger-go v1.0.13 h1:eru/TETo0MkO4ZTnXsQDKf4PBRpAXmqjT02klNT/JnY= -github.com/multiversx/mx-chain-logger-go v1.0.13/go.mod h1:MZJhTAtZTJxT+yK2EHc4ZW3YOHUc1UdjCD0iahRNBZk= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240508071047-fefea5737840 h1:2mCrTUmbbA+Xv4UifZY9xptrGjcJBcJ2wavSb4FwejU= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240508071047-fefea5737840/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df h1:clihfi78bMEOWk/qw6WA4uQbCM2e2NGliqswLAvw19k= +github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df/go.mod h1:gtJYB4rR21KBSqJlazn+2z6f9gFSqQP3KvAgL7Qgxw4= +github.com/multiversx/mx-chain-es-indexer-go v1.7.1-0.20240509104512-25512675833d h1:GD1D8V0bE6hDLjrduSsMwQwwf6PMq2Zww7FYMfJsuiw= +github.com/multiversx/mx-chain-es-indexer-go v1.7.1-0.20240509104512-25512675833d/go.mod h1:UDKRXmxsSyPeAcjLUfGeYkAtYp424PIYkL82kzFYobM= +github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57 h1:g9t410dqjcb7UUptbVd/H6Ua12sEzWU4v7VplyNvRZ0= +github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57/go.mod h1:cY6CIXpndW5g5PTPn4WzPwka/UBEf+mgw+PSY5pHGAU= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= From fbe7165d56b0d70d7cb06479a564e463fe314680 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Tue, 28 May 2024 16:28:11 +0300 Subject: [PATCH 06/40] updated core-go + process-status support for v3 --- go.mod | 2 +- go.sum | 4 ++-- process/transactionProcessor.go | 36 +++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ab60d138..a16300f3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/gin-contrib/pprof v1.4.0 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.9.1 - github.com/multiversx/mx-chain-core-go v1.2.20-0.20240404181342-48e2da52259e + github.com/multiversx/mx-chain-core-go v1.2.21-0.20240528132712-8b6faa711b23 github.com/multiversx/mx-chain-crypto-go v1.2.9 github.com/multiversx/mx-chain-es-indexer-go v1.4.13 github.com/multiversx/mx-chain-logger-go v1.0.13 diff --git a/go.sum b/go.sum index 83a50dd5..fcf85897 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiversx/mx-chain-core-go v1.2.20-0.20240404181342-48e2da52259e h1:MseWlrUS8b8RhJ6JUqQBpYeYylmyoWqom+bvn3Cl/U4= -github.com/multiversx/mx-chain-core-go v1.2.20-0.20240404181342-48e2da52259e/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240528132712-8b6faa711b23 h1:jSP8BjMF9P5I9cO5hY2uN60q4+iPP9uq5WzETtcXWMI= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240528132712-8b6faa711b23/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= github.com/multiversx/mx-chain-crypto-go v1.2.9 h1:OEfF2kOQrtzUl273Z3DEcshjlTVUfPpJMd0R0SvTrlU= github.com/multiversx/mx-chain-crypto-go v1.2.9/go.mod h1:fkaWKp1rbQN9wPKya5jeoRyC+c/SyN/NfggreyeBw+8= github.com/multiversx/mx-chain-es-indexer-go v1.4.13 h1:3Ayaw9bSpeNOF+Z3L/11MN1rIJH8Rc6dqtt+o4Wfdno= diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 05cae2b5..b3ce2860 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -487,6 +487,13 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } + isRelayedV3, status := checkIfRelayedV3Completed(allLogs, tx) + if isRelayedV3 { + return &data.ProcessStatusResponse{ + Status: status, + } + } + if checkIfCompleted(allLogs) { return &data.ProcessStatusResponse{ Status: string(transaction.TxStatusSuccess), @@ -522,6 +529,35 @@ func checkIfCompleted(logs []*transaction.ApiLogs) bool { return found } +func checkIfRelayedV3Completed(logs []*transaction.ApiLogs, tx *transaction.ApiTransactionResult) (bool, string) { + if len(tx.InnerTransactions) == 0 { + return false, string(transaction.TxStatusPending) + } + + if len(logs) == 0 { + return true, string(transaction.TxStatusPending) + } + + completedCnt := 0 + for _, logInstance := range logs { + if logInstance == nil { + continue + } + + completedFound, _ := findIdentifierInSingleLog(logInstance, core.CompletedTxEventIdentifier) + deployFound, _ := findIdentifierInSingleLog(logInstance, core.SCDeployIdentifier) + if completedFound || deployFound { + completedCnt++ + } + } + + status := string(transaction.TxStatusFail) + if completedCnt == len(tx.InnerTransactions) { + status = string(transaction.TxStatusSuccess) + } + return true, status +} + func checkIfMoveBalanceNotarized(tx *transaction.ApiTransactionResult) bool { isNotarized := tx.NotarizedAtSourceInMetaNonce > 0 && tx.NotarizedAtDestinationInMetaNonce > 0 if !isNotarized { From 79e98bc14749890f8a395ea47704ed2db85ae58a Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Tue, 28 May 2024 17:41:45 +0300 Subject: [PATCH 07/40] fixed process-status on relayed v1 with move balance --- ...ishedOkRelayedTxCrossShardMoveBalance.json | 101 +++++++++++++++ process/transactionProcessor.go | 84 +------------ process/transactionProcessor_test.go | 119 ++---------------- 3 files changed, 114 insertions(+), 190 deletions(-) create mode 100644 process/testdata/finishedOkRelayedTxCrossShardMoveBalance.json diff --git a/process/testdata/finishedOkRelayedTxCrossShardMoveBalance.json b/process/testdata/finishedOkRelayedTxCrossShardMoveBalance.json new file mode 100644 index 00000000..0e73e09e --- /dev/null +++ b/process/testdata/finishedOkRelayedTxCrossShardMoveBalance.json @@ -0,0 +1,101 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "RelayedTx", + "processingTypeOnDestination": "RelayedTx", + "hash": "4dd5faec9431b8111e96ac01e592b66be50a1454eb2d008ce941323d49715ca9", + "nonce": 159, + "round": 17813271, + "epoch": 1236, + "value": "0", + "receiver": "erd13mfn9qksaq03c0nltpg23lqca67lhup544a56z0j4vlrhgu90lxq7hpjgw", + "sender": "erd16mpvgjpfgj8fd8h2stw9zxqx2n0prmmqsan02ash93jdrp6m7fqswke499", + "gasPrice": 1000000000, + "gasLimit": 1084000, + "gasUsed": 1084000, + "data": "cmVsYXllZFR4QDdiMjI2ZTZmNmU2MzY1MjIzYTMwMmMyMjc2NjE2Yzc1NjUyMjNhMzMzMzM3MzQzMDMwMzAzMDMwMzAzMDMwMzAzMDMwMzAzMDMwMmMyMjcyNjU2MzY1Njk3NjY1NzIyMjNhMjIzMTczNGM0NTUzNDM2YzQ1NmE3MDYxNjUzNjZmNGM2MzU1NTI2NzQ3NTY0ZTM0NTIzNzMyNDM0ODVhNzY1NjMyNDY3OTc4NmIzMDU5NjQ2MjM4NmI0NTNkMjIyYzIyNzM2NTZlNjQ2NTcyMjIzYTIyNmE3NDRkNzk2Nzc0NDQ2ZjQ4Nzg3NzJiNjYzMTY4NTE3MTUwNzc1OTM3NzIzMzM3Mzg0NDUzNzQ2NTMwMzA0YTM4NzE3MzJiNGYzNjRmNDY2NjM4NzczZDIyMmMyMjY3NjE3MzUwNzI2OTYzNjUyMjNhMzEzMDMwMzAzMDMwMzAzMDMwMzAyYzIyNjc2MTczNGM2OTZkNjk3NDIyM2EzNTMwMzAzMDMwMmMyMjYzNjg2MTY5NmU0OTQ0MjIzYTIyNGQ1MTNkM2QyMjJjMjI3NjY1NzI3MzY5NmY2ZTIyM2EzMTJjMjI3MzY5Njc2ZTYxNzQ3NTcyNjUyMjNhMjI2OTcwNjU2YzY2NWE0ODc1NDE0NTMzMzI2ZTcxMzAyZjU2NDc0ZDZhNjYzNzRhNTQ1NTQ1NTA1NTc3NjQzMjQ4NTA0ZjY1MzU2ZTZhNDMzMDM2MmI0MjcwMzAzMzZiMzAzODZlNTA2YTMxNjMzOTM3NTE1MTQzNzI1OTQ4Nzc1MzQ0NTU1YTZiNDg1MzY1NDk3MTczMmY3YTMyNTE1NTRkNGU2ZTQxNDc0MTQxM2QzZDIyN2Q=", + "signature": "b0a477a7db6820ccd99291e92a7f8f32f3901e54eec99cf143ae7151a51bfbc219853069d4ad515ee5179175937d673efd4549a53ed30f00beb07f3ead68b00c", + "sourceShard": 1, + "destinationShard": 0, + "blockNonce": 17806968, + "blockHash": "52a92fd2b486cf0710e646bc0e91da429d617e47a1f34380c0f890e3f218a072", + "notarizedAtSourceInMetaNonce": 17792304, + "NotarizedAtSourceInMetaHash": "4e82f772d8415d23934693c787a08e75862841a8116682f66c8739f32afb5033", + "notarizedAtDestinationInMetaNonce": 17792308, + "notarizedAtDestinationInMetaHash": "7baa2ddbc7200d0cb20bb445eb9d80f946b5daf7a24a7c6069038d97fd7354e2", + "miniblockType": "TxBlock", + "miniblockHash": "53a543f844b67bea604d5ca90b3c363bb60ae09ec54451fff115ecadcdb946f3", + "hyperblockNonce": 17792308, + "hyperblockHash": "7baa2ddbc7200d0cb20bb445eb9d80f946b5daf7a24a7c6069038d97fd7354e2", + "timestamp": 1702997226, + "smartContractResults": [ + { + "hash": "8cc84367ffe898d922c82d23e7557c4b735c4ef1e93e563a1dfa36839bdfdaa4", + "nonce": 0, + "value": 337400000000000000, + "receiver": "erd16mpvgjpfgj8fd8h2stw9zxqx2n0prmmqsan02ash93jdrp6m7fqswke499", + "sender": "erd13mfn9qksaq03c0nltpg23lqca67lhup544a56z0j4vlrhgu90lxq7hpjgw", + "relayerAddress": "erd16mpvgjpfgj8fd8h2stw9zxqx2n0prmmqsan02ash93jdrp6m7fqswke499", + "relayedValue": 0, + "prevTxHash": "4dd5faec9431b8111e96ac01e592b66be50a1454eb2d008ce941323d49715ca9", + "originalTxHash": "4dd5faec9431b8111e96ac01e592b66be50a1454eb2d008ce941323d49715ca9", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer" + } + ], + "status": "success", + "receivers": [ + "erd16mpvgjpfgj8fd8h2stw9zxqx2n0prmmqsan02ash93jdrp6m7fqswke499" + ], + "receiversShardIDs": [ + 1 + ], + "operation": "transfer", + "initiallyPaidFee": "1034500000000000", + "fee": "1034500000000000", + "isRelayed": true, + "chainID": "1", + "version": 1, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "8cc84367ffe898d922c82d23e7557c4b735c4ef1e93e563a1dfa36839bdfdaa4", + "nonce": 0, + "round": 17813275, + "epoch": 1236, + "value": "337400000000000000", + "receiver": "erd16mpvgjpfgj8fd8h2stw9zxqx2n0prmmqsan02ash93jdrp6m7fqswke499", + "sender": "erd13mfn9qksaq03c0nltpg23lqca67lhup544a56z0j4vlrhgu90lxq7hpjgw", + "gasPrice": 1000000000, + "gasUsed": 50000, + "previousTransactionHash": "4dd5faec9431b8111e96ac01e592b66be50a1454eb2d008ce941323d49715ca9", + "originalTransactionHash": "4dd5faec9431b8111e96ac01e592b66be50a1454eb2d008ce941323d49715ca9", + "sourceShard": 0, + "destinationShard": 1, + "blockNonce": 17800066, + "blockHash": "cdeff6a0d8da1eae1de2a434b4834ee23bea45c64d43e3f303b3b862fdc5028b", + "notarizedAtSourceInMetaNonce": 17792308, + "NotarizedAtSourceInMetaHash": "7baa2ddbc7200d0cb20bb445eb9d80f946b5daf7a24a7c6069038d97fd7354e2", + "notarizedAtDestinationInMetaNonce": 17792312, + "notarizedAtDestinationInMetaHash": "0316c2b4a03ad3172ce3ce975447cace67d30b5002b1e00d40ca44dd43768219", + "miniblockType": "SmartContractResultBlock", + "miniblockHash": "daa45fb36173df935d0786c43afe4085e8a9a20b53aab3b602bd8d8ec3cd1880", + "hyperblockNonce": 17792312, + "hyperblockHash": "0316c2b4a03ad3172ce3ce975447cace67d30b5002b1e00d40ca44dd43768219", + "timestamp": 1702997250, + "status": "success", + "operation": "transfer", + "fee": "0", + "callType": "directCall", + "relayerAddress": "erd16mpvgjpfgj8fd8h2stw9zxqx2n0prmmqsan02ash93jdrp6m7fqswke499", + "relayedValue": "0", + "options": 0 + } + ] +} diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 05cae2b5..40cde1f1 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -5,7 +5,6 @@ import ( "fmt" "math/big" "net/http" - "strings" "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" @@ -552,12 +551,12 @@ func (tp *TransactionProcessor) handleIntraShardRelayedMoveBalanceTransactions( allScrs []*transaction.ApiTransactionResult, ) ([]*transaction.ApiLogs, error) { var newLogs []*transaction.ApiLogs - isIntraShardRelayedV1MoveBalanceTransaction, err := tp.isIntraShardRelayedMoveBalanceTransaction(tx, allScrs) + isRelayedMoveBalanceTransaction, err := tp.isRelayedMoveBalanceTransaction(tx, allScrs) if err != nil { return newLogs, err } - if isIntraShardRelayedV1MoveBalanceTransaction { + if isRelayedMoveBalanceTransaction { newLogs = append(newLogs, &transaction.ApiLogs{ Address: tx.Sender, Events: []*transaction.Events{ @@ -572,7 +571,7 @@ func (tp *TransactionProcessor) handleIntraShardRelayedMoveBalanceTransactions( return newLogs, nil } -func (tp *TransactionProcessor) isIntraShardRelayedMoveBalanceTransaction( +func (tp *TransactionProcessor) isRelayedMoveBalanceTransaction( tx *transaction.ApiTransactionResult, allScrs []*transaction.ApiTransactionResult, ) (bool, error) { @@ -595,83 +594,8 @@ func (tp *TransactionProcessor) isIntraShardRelayedMoveBalanceTransaction( firstScr := allScrs[0] innerIsMoveBalance := firstScr.ProcessingTypeOnSource == moveBalanceDescriptor && firstScr.ProcessingTypeOnDestination == moveBalanceDescriptor - if !innerIsMoveBalance { - return false, nil - } - - senderAddress, err := tp.pubKeyConverter.Decode(tx.Sender) - if err != nil { - return false, err - } - receiverAddress, err := tp.pubKeyConverter.Decode(tx.Receiver) - if err != nil { - return false, err - } - - isSameShardOnRelayed := tp.proc.GetShardCoordinator().SameShard(senderAddress, receiverAddress) - isInnerTxSameShard, err := tp.isSameShardSenderReceiverOfInnerTx(senderAddress, tx) - - return isSameShardOnRelayed && isInnerTxSameShard, err -} - -func (tp *TransactionProcessor) isSameShardSenderReceiverOfInnerTx( - relayedSender []byte, - relayedTx *transaction.ApiTransactionResult, -) (bool, error) { - if relayedTx.ProcessingTypeOnSource == relayedV1TransactionDescriptor { - return tp.isSameShardSenderReceiverOfInnerTxV1(relayedSender, relayedTx) - } - - return tp.isSameShardSenderReceiverOfInnerTxV2(relayedSender, relayedTx) -} - -func (tp *TransactionProcessor) isSameShardSenderReceiverOfInnerTxV1( - relayedSender []byte, - relayedTx *transaction.ApiTransactionResult, -) (bool, error) { - relayedDataField := string(relayedTx.Data) - if strings.Index(relayedDataField, relayedTxV1DataMarker) != 0 { - return false, fmt.Errorf("wrong relayed v1 data marker position") - } - - hexedInnerTxData := relayedDataField[len(relayedTxV1DataMarker):] - innerTxData, err := hex.DecodeString(hexedInnerTxData) - if err != nil { - return false, err - } - - innerTx := &transaction.Transaction{} - err = tp.relayedTxsMarshaller.Unmarshal(innerTx, innerTxData) - if err != nil { - return false, err - } - - isSameShardOnInnerForReceiver := tp.proc.GetShardCoordinator().SameShard(relayedSender, innerTx.RcvAddr) - isSameShardOnInnerForSender := tp.proc.GetShardCoordinator().SameShard(relayedSender, innerTx.SndAddr) - - return isSameShardOnInnerForReceiver && isSameShardOnInnerForSender, nil -} - -func (tp *TransactionProcessor) isSameShardSenderReceiverOfInnerTxV2( - relayedSender []byte, - relayedTx *transaction.ApiTransactionResult, -) (bool, error) { - relayedDataField := string(relayedTx.Data) - if strings.Index(relayedDataField, relayedTxV2DataMarker) != 0 { - return false, fmt.Errorf("wrong relayed v2 data marker position") - } - arguments := strings.Split(relayedDataField, argumentsSeparator) - if len(arguments) < 2 { - return false, fmt.Errorf("wrong relayed v2 formatted data field") - } - - hexedReceiver := arguments[1] - receiver, err := hex.DecodeString(hexedReceiver) - if err != nil { - return false, err - } - return tp.proc.GetShardCoordinator().SameShard(relayedSender, receiver), nil + return innerIsMoveBalance, nil } func findIdentifierInLogs(logs []*transaction.ApiLogs, identifier string) (bool, string) { diff --git a/process/transactionProcessor_test.go b/process/transactionProcessor_test.go index c1329261..0fa9b76f 100644 --- a/process/transactionProcessor_test.go +++ b/process/transactionProcessor_test.go @@ -1961,6 +1961,15 @@ func TestTransactionProcessor_computeTransactionStatus(t *testing.T) { testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedTxWithSCCall.json") tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, string(transaction.TxStatusSuccess), status.Status) + }) + t.Run("tx move balance cross ok", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOkRelayedTxCrossShardMoveBalance.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) require.Equal(t, string(transaction.TxStatusSuccess), status.Status) }) @@ -1983,116 +1992,6 @@ func TestTransactionProcessor_computeTransactionStatus(t *testing.T) { status := tp.ComputeTransactionStatus(testData.Transaction, withResults) require.Equal(t, string(transaction.TxStatusFail), status.Status) }) - t.Run("malformed transactions", func(t *testing.T) { - t.Parallel() - - t.Run("malformed relayed v1 inner transaction - wrong sender", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedTxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - testData.Transaction.Sender = "not a sender" - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - t.Run("malformed relayed v1 inner transaction - wrong receiver", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedTxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - testData.Transaction.Receiver = "not a sender" - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - t.Run("malformed relayed v1 - relayed v1 marker on wrong position", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedTxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - testData.Transaction.Data = append([]byte("A"), testData.Transaction.Data...) - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - t.Run("malformed relayed v2 - missing marker", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedV2TxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - testData.Transaction.Data = []byte("aa") - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - t.Run("malformed relayed v2 - not enough arguments", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedV2TxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - testData.Transaction.Data = []byte(process.RelayedTxV2DataMarker) - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - t.Run("malformed relayed v1 - not a hex character after the marker", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedTxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - testData.Transaction.Data[45] = byte('T') - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - t.Run("malformed relayed v1 - marshaller will fail", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedTxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - testData.Transaction.Data = append(testData.Transaction.Data, []byte("aaaaaa")...) - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - t.Run("malformed relayed v1 - missing scrs", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedTxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - testData.SCRs = nil - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - t.Run("malformed relayed v1 - no scr generated", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/malformedRelayedTxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - t.Run("malformed relayed v2 - no scr generated", func(t *testing.T) { - t.Parallel() - - testData := loadJsonIntoTxAndScrs(t, "./testdata/malformedRelayedV2TxIntraShard.json") - tp := createTestProcessorFromScenarioData(testData) - - status := tp.ComputeTransactionStatus(testData.Transaction, withResults) - require.Equal(t, string(data.TxStatusUnknown), status.Status) - }) - }) } func TestTransactionProcessor_GetProcessedTransactionStatus(t *testing.T) { From 3f9f7fc91fdcd4e1f09fb9a346538024781017bb Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 29 May 2024 20:01:39 +0300 Subject: [PATCH 08/40] merged logs from destination on relayed tx v3 get transaction --- process/transactionProcessor.go | 64 +++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index b3ce2860..399934f5 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -42,6 +42,7 @@ const ( moveBalanceDescriptor = "MoveBalance" relayedV1TransactionDescriptor = "RelayedTx" relayedV2TransactionDescriptor = "RelayedTxV2" + relayedV3TransactionDescriptor = "RelayedTxV3" relayedTxV1DataMarker = "relayedTx@" relayedTxV2DataMarker = "relayedTxV2" argumentsSeparator = "@" @@ -793,8 +794,13 @@ func (tp *TransactionProcessor) getTxFromObservers(txHash string, reqType reques "error", err.Error()) } + if isRelayedTxV3(getTxResponse.Data.Transaction) { + return tp.mergeSCRLogsFromInnerReceivers(&getTxResponse.Data.Transaction, withResults), nil + } + isIntraShard := sndShardID == rcvShardID observerIsInDestShard := rcvShardID == observerShardID + if isIntraShard { return &getTxResponse.Data.Transaction, nil } @@ -820,6 +826,64 @@ func (tp *TransactionProcessor) getTxFromObservers(txHash string, reqType reques return nil, errors.ErrTransactionNotFound } +func isRelayedTxV3(tx transaction.ApiTransactionResult) bool { + return tx.ProcessingTypeOnSource == relayedV3TransactionDescriptor && tx.ProcessingTypeOnDestination == relayedV3TransactionDescriptor +} + +func (tp *TransactionProcessor) mergeSCRLogsFromInnerReceivers(tx *transaction.ApiTransactionResult, withResults bool) *transaction.ApiTransactionResult { + logsOnDestMap := make(map[string]*transaction.ApiLogs, len(tx.SmartContractResults)) + + txsByReceiverShardMap := tp.groupTxsByReceiverShard(tx) + for shardID, scrHashes := range txsByReceiverShardMap { + for _, scrHash := range scrHashes { + observers, err := tp.getNodesInShard(shardID, requestTypeObservers) + if err != nil { + break + } + + for _, observer := range observers { + getTxResponse, ok, _ := tp.getTxFromObserver(observer, scrHash, withResults) + if !ok { + continue + } + + if withResults { + logsOnDestMap[scrHash] = getTxResponse.Data.Transaction.Logs + } + } + } + } + + finalTx := *tx + // if withResults, override the scr logs with the one from the receiver shard + if withResults { + for _, scr := range finalTx.SmartContractResults { + logsOnDest, found := logsOnDestMap[scr.Hash] + if !found { + continue + } + + scr.Logs = logsOnDest + } + } + + return &finalTx +} + +func (tp *TransactionProcessor) groupTxsByReceiverShard(tx *transaction.ApiTransactionResult) map[uint32][]string { + txsByReceiverShardMap := make(map[uint32][]string) + for _, scr := range tx.SmartContractResults { + shardID, err := tp.getShardByAddress(scr.RcvAddr) + if err != nil { + continue + } + + txsByReceiverShardMap[shardID] = append(txsByReceiverShardMap[shardID], scr.Hash) + } + + return txsByReceiverShardMap +} + func (tp *TransactionProcessor) alterTxWithScResultsFromSourceIfNeeded(txHash string, tx *transaction.ApiTransactionResult, withResults bool) *transaction.ApiTransactionResult { if !withResults || len(tx.SmartContractResults) == 0 { return tx From f2a02806edf1318dd08e602b406c1df0c751832a Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 30 May 2024 13:13:30 +0300 Subject: [PATCH 09/40] added unittest for relayed v3 merge of scr events --- process/transactionProcessor_test.go | 125 +++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/process/transactionProcessor_test.go b/process/transactionProcessor_test.go index c1329261..d822e8ea 100644 --- a/process/transactionProcessor_test.go +++ b/process/transactionProcessor_test.go @@ -1312,6 +1312,131 @@ func TestTransactionProcessor_GetTransactionWithEventsFirstFromDstShardAndAfterS assert.Equal(t, 3, len(tx.SmartContractResults)) } +func TestTransactionProcessor_GetTransactionRelayedV3ShouldMergeEvents(t *testing.T) { + t.Parallel() + + relayer := hex.EncodeToString([]byte("relayer")) + sender1 := hex.EncodeToString([]byte("sender1")) + sender2 := hex.EncodeToString([]byte("sender2")) + receiver1 := hex.EncodeToString([]byte("receiver1")) + receiver2 := hex.EncodeToString([]byte("receiver2")) + + addrObs0 := "observer0" + addrObsFailing := "observerFailing" + addrObs1 := "observer1" + + hashRelayed := "hashRelayed" + + scrHash1 := "scrHash1" + providedLogsInnerTx1 := &transaction.ApiLogs{ + Events: []*transaction.Events{ + { + Address: receiver1, + Identifier: "events innertx 1", + }, + }, + } + + scrHash2 := "scrHash2" + providedLogsInnerTx2 := &transaction.ApiLogs{ + Events: []*transaction.Events{ + { + Address: receiver2, + Identifier: "events innertx 2", + }, + }, + } + + tp, _ := process.NewTransactionProcessor( + &mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (uint32, error) { + switch string(addressBuff) { + case "relayer", "sender1", "sender2", "receiver1": + return 0, nil + case "receiver2": + return 1, nil + } + + return 0, nil + }, + GetShardIDsCalled: func() []uint32 { + return []uint32{0, 1} + }, + GetObserversCalled: func(shardId uint32, dataAvailability data.ObserverDataAvailabilityType) ([]*data.NodeData, error) { + if shardId == 0 { + return []*data.NodeData{ + {Address: addrObs0, ShardId: 0}, + }, nil + } + if shardId == 1 { + return []*data.NodeData{ + {Address: addrObsFailing, ShardId: 1}, + {Address: addrObs1, ShardId: 1}, + }, nil + } + + return nil, nil + }, + CallGetRestEndPointCalled: func(address string, path string, value interface{}) (i int, err error) { + if address == addrObsFailing { + return http.StatusBadRequest, errors.New("error for coverage only") + } + + responseGetTx := value.(*data.GetTransactionResponse) + if strings.Contains(path, hashRelayed) { + responseGetTx.Data.Transaction.Hash = hashRelayed + responseGetTx.Data.Transaction.ProcessingTypeOnSource = "RelayedTxV3" + responseGetTx.Data.Transaction.ProcessingTypeOnDestination = "RelayedTxV3" + responseGetTx.Data.Transaction.SmartContractResults = []*transaction.ApiSmartContractResult{ + { + Hash: scrHash1, + RcvAddr: receiver1, + SndAddr: sender1, + RelayerAddr: relayer, + IsRelayed: true, + }, + { + Hash: scrHash2, + RcvAddr: receiver2, + SndAddr: sender2, + RelayerAddr: relayer, + IsRelayed: true, + }, + } + + return http.StatusOK, nil + } + if strings.Contains(path, scrHash1) { + responseGetTx.Data.Transaction.Hash = scrHash1 + responseGetTx.Data.Transaction.Logs = providedLogsInnerTx1 + + return http.StatusOK, nil + } + if strings.Contains(path, scrHash2) { + responseGetTx.Data.Transaction.Hash = scrHash2 + responseGetTx.Data.Transaction.Logs = providedLogsInnerTx2 + + return http.StatusOK, nil + } + + return http.StatusBadRequest, nil + }, + }, + &mock.PubKeyConverterMock{}, + hasher, + marshalizer, + funcNewTxCostHandler, + logsMerger, + true, + ) + + tx, err := tp.GetTransaction(hashRelayed, true) + require.NoError(t, err) + require.Equal(t, 2, len(tx.SmartContractResults)) + require.Equal(t, providedLogsInnerTx1, tx.SmartContractResults[0].Logs) + require.Equal(t, providedLogsInnerTx2, tx.SmartContractResults[1].Logs) +} + func TestTransactionProcessor_GetTransactionPool(t *testing.T) { t.Parallel() From bd24a18aaf86dd6dff5e08ad630694c545a8c58c Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 30 May 2024 19:16:28 +0300 Subject: [PATCH 10/40] fix process status returning failed instead of pending --- process/transactionProcessor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 399934f5..81eb5339 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -552,7 +552,7 @@ func checkIfRelayedV3Completed(logs []*transaction.ApiLogs, tx *transaction.ApiT } } - status := string(transaction.TxStatusFail) + status := string(transaction.TxStatusPending) if completedCnt == len(tx.InnerTransactions) { status = string(transaction.TxStatusSuccess) } From 04c644f8d83316eadd7f375b4c09aff3e6a3ec90 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 3 Jun 2024 18:37:00 +0300 Subject: [PATCH 11/40] added proper return on /process-status for un-executable relayed move balance --- ...iledRelayedTxMoveBalanceReturnMessage.json | 92 +++++++++++++++++++ process/testdata/finishedFailedSCR.json | 30 ++++++ process/transactionProcessor.go | 25 +++++ process/transactionProcessor_test.go | 18 ++++ 4 files changed, 165 insertions(+) create mode 100644 process/testdata/finishedFailedRelayedTxMoveBalanceReturnMessage.json create mode 100644 process/testdata/finishedFailedSCR.json diff --git a/process/testdata/finishedFailedRelayedTxMoveBalanceReturnMessage.json b/process/testdata/finishedFailedRelayedTxMoveBalanceReturnMessage.json new file mode 100644 index 00000000..41236c65 --- /dev/null +++ b/process/testdata/finishedFailedRelayedTxMoveBalanceReturnMessage.json @@ -0,0 +1,92 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "RelayedTx", + "processingTypeOnDestination": "RelayedTx", + "hash": "6c9d9eaf8928257c8019c56d56a9c0273e6428de00b96a584077778a5128be6a", + "nonce": 0, + "round": 66, + "epoch": 3, + "value": "0", + "receiver": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "sender": "erd1u39p5ld7qjg5qz8tnj2zr2ntvqeskzryu3fnh343uux2xlxzk6dsq5zx75", + "gasPrice": 1000000000, + "gasLimit": 1132000, + "gasUsed": 1132000, + "data": "cmVsYXllZFR4QDdiMjI2ZTZmNmU2MzY1MjIzYTMwMmMyMjc2NjE2Yzc1NjUyMjNhMzEzMDMwMzAzMDMwMzAzMDMwMzAzMDMwMzAzMDMwMzAzMDMwMmMyMjcyNjU2MzY1Njk3NjY1NzIyMjNhMjIzNjMzNjc0MTVhNDU0YTdhMmI1MjZjMzU1YTQ4NjY0MjQ4NTkyZjc2NGE0ZjZmNzQ0YTMwNzc2OTMyNzkzNDY0NDM0ODdhNzk0MzRhMzAzOTM0NTE1NTNkMjIyYzIyNzM2NTZlNjQ2NTcyMjIzYTIyNGE1OTQ0NjQ1NjUzNTk3NzUxMzE2NDQxNTQzMjY1Njg0OTQ3NjQ3NjY5NjQ3OTUxNjkyZjJiNTY3YTU2MzM2NDc4NmE3NTRjMmY0Mjc0NzQ0NjY4NGQzZDIyMmMyMjY3NjE3MzUwNzI2OTYzNjUyMjNhMzEzMDMwMzAzMDMwMzAzMDMwMzAyYzIyNjc2MTczNGM2OTZkNjk3NDIyM2EzNTMwMzAzMDMwMmMyMjYzNjg2MTY5NmU0OTQ0MjIzYTIyNjI0NzM5NmE1OTU3Nzc3NDY0NDc1NjdhNjQ0NzM1NmM2NDQxM2QzZDIyMmMyMjc2NjU3MjczNjk2ZjZlMjIzYTMyMmMyMjczNjk2NzZlNjE3NDc1NzI2NTIyM2EyMjcyNDQ1MTRiNTE0ODM0NGU2ZDZkNzQzMjUxNDYzNDcyNGEzMjU3NDYzNTRlNzk3MjYzNjc3NDY1NDM1OTY5NzE2YjRlNTEzMjcwNGM2YTYzNDc3OTc5NTU2NDQ2NTk2ODQ1NDgzMzU4MzE0YTU5NGE3OTQ3NTA1NDRlNDkzMDY2NTU2YTMyNTQ2Mzc0MmY2NzY0NGM2YjYyNDg0NjM3NmE1MDM4MzgzNTQyNDEzZDNkMjI3ZA==", + "signature": "d80e6db348ef8456eb1bf20aa4ba7863deb96366eb45ae0538efc4a43a894615ba72107048fa1b5793743b69e1720e83dac73d5b8cddb747fc8bb88816a5830a", + "sourceShard": 1, + "destinationShard": 1, + "blockNonce": 66, + "blockHash": "84bb2e631eec1c3665839f087e170de19bdaf287a83c6065fa97310f57b94e4c", + "notarizedAtSourceInMetaNonce": 68, + "NotarizedAtSourceInMetaHash": "808f39ce82d978f393d72dc78c3dbb17ab2bfd9fc8812cd982a2fd50fbc89667", + "notarizedAtDestinationInMetaNonce": 68, + "notarizedAtDestinationInMetaHash": "808f39ce82d978f393d72dc78c3dbb17ab2bfd9fc8812cd982a2fd50fbc89667", + "miniblockType": "TxBlock", + "miniblockHash": "fa5a6008a3b30ae7c59960d8d1fb221da0ce38fb38267f2fd40c69fd983581ea", + "hyperblockNonce": 68, + "hyperblockHash": "808f39ce82d978f393d72dc78c3dbb17ab2bfd9fc8812cd982a2fd50fbc89667", + "timestamp": 1717422998, + "smartContractResults": [ + { + "hash": "7cfde9ad5ead518ec768607a3ac992763f5afdcf31e603fdd56418c7ffe19774", + "nonce": 0, + "value": 0, + "receiver": "erd1u39p5ld7qjg5qz8tnj2zr2ntvqeskzryu3fnh343uux2xlxzk6dsq5zx75", + "sender": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "prevTxHash": "6c9d9eaf8928257c8019c56d56a9c0273e6428de00b96a584077778a5128be6a", + "originalTxHash": "6c9d9eaf8928257c8019c56d56a9c0273e6428de00b96a584077778a5128be6a", + "gasLimit": 0, + "gasPrice": 0, + "callType": 0, + "returnMessage": "insufficient funds", + "operation": "transfer" + } + ], + "status": "success", + "receivers": [ + "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r" + ], + "receiversShardIDs": [ + 1 + ], + "operation": "transfer", + "initiallyPaidFee": "1082500000000000", + "fee": "1082500000000000", + "isRelayed": true, + "chainID": "local-testnet", + "version": 2, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "7cfde9ad5ead518ec768607a3ac992763f5afdcf31e603fdd56418c7ffe19774", + "nonce": 0, + "round": 66, + "epoch": 3, + "value": "0", + "receiver": "erd1u39p5ld7qjg5qz8tnj2zr2ntvqeskzryu3fnh343uux2xlxzk6dsq5zx75", + "sender": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "gasUsed": 50000, + "previousTransactionHash": "6c9d9eaf8928257c8019c56d56a9c0273e6428de00b96a584077778a5128be6a", + "originalTransactionHash": "6c9d9eaf8928257c8019c56d56a9c0273e6428de00b96a584077778a5128be6a", + "returnMessage": "insufficient funds", + "sourceShard": 1, + "destinationShard": 1, + "blockNonce": 66, + "blockHash": "84bb2e631eec1c3665839f087e170de19bdaf287a83c6065fa97310f57b94e4c", + "miniblockType": "SmartContractResultBlock", + "miniblockHash": "9627ce0cafb78c5c109ce4fbb9011e8a07ac05057b89488348a05cd9a30d9717", + "timestamp": 1717422998, + "status": "success", + "operation": "transfer", + "fee": "0", + "callType": "directCall", + "options": 0 + } + ] +} diff --git a/process/testdata/finishedFailedSCR.json b/process/testdata/finishedFailedSCR.json new file mode 100644 index 00000000..a41fd6bd --- /dev/null +++ b/process/testdata/finishedFailedSCR.json @@ -0,0 +1,30 @@ +{ + "transaction": { + "type": "unsigned", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "7cfde9ad5ead518ec768607a3ac992763f5afdcf31e603fdd56418c7ffe19774", + "nonce": 0, + "round": 66, + "epoch": 3, + "value": "0", + "receiver": "erd1u39p5ld7qjg5qz8tnj2zr2ntvqeskzryu3fnh343uux2xlxzk6dsq5zx75", + "sender": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "gasUsed": 50000, + "previousTransactionHash": "6c9d9eaf8928257c8019c56d56a9c0273e6428de00b96a584077778a5128be6a", + "originalTransactionHash": "6c9d9eaf8928257c8019c56d56a9c0273e6428de00b96a584077778a5128be6a", + "returnMessage": "insufficient funds", + "sourceShard": 1, + "destinationShard": 1, + "blockNonce": 66, + "blockHash": "84bb2e631eec1c3665839f087e170de19bdaf287a83c6065fa97310f57b94e4c", + "miniblockType": "SmartContractResultBlock", + "miniblockHash": "9627ce0cafb78c5c109ce4fbb9011e8a07ac05057b89488348a05cd9a30d9717", + "timestamp": 1717422998, + "status": "success", + "operation": "transfer", + "fee": "0", + "callType": "directCall", + "options": 0 + } +} diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 40cde1f1..982a471d 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -486,6 +486,12 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } + if checkIfFailedOnReturnMessage(allScrs, tx) { + return &data.ProcessStatusResponse{ + Status: string(transaction.TxStatusFail), + } + } + if checkIfCompleted(allLogs) { return &data.ProcessStatusResponse{ Status: string(transaction.TxStatusSuccess), @@ -497,6 +503,25 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } +func checkIfFailedOnReturnMessage(allScrs []*transaction.ApiTransactionResult, tx *transaction.ApiTransactionResult) bool { + if returnMessageFailure(tx.Value, tx.ReturnMessage) { + return true + } + + for _, scr := range allScrs { + if returnMessageFailure(scr.Value, scr.ReturnMessage) { + return true + } + } + + return false +} + +func returnMessageFailure(value string, returnMessage string) bool { + isZeroValue := value == "0" + return len(returnMessage) > 0 && isZeroValue +} + func checkIfFailed(logs []*transaction.ApiLogs) (bool, string) { found, reason := findIdentifierInLogs(logs, internalVMErrorsEventIdentifier) if found { diff --git a/process/transactionProcessor_test.go b/process/transactionProcessor_test.go index 0fa9b76f..7578f93b 100644 --- a/process/transactionProcessor_test.go +++ b/process/transactionProcessor_test.go @@ -1789,6 +1789,15 @@ func TestTransactionProcessor_computeTransactionStatus(t *testing.T) { status := tp.ComputeTransactionStatus(testData.Transaction, withResults) require.Equal(t, string(transaction.TxStatusSuccess), status.Status) }) + t.Run("failed un-executable move balance scr", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedFailedSCR.json") + tp := createTestProcessorFromScenarioData(testData) + + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, string(transaction.TxStatusFail), status.Status) + }) }) t.Run("SC calls", func(t *testing.T) { t.Run("pending new", func(t *testing.T) { @@ -1898,6 +1907,15 @@ func TestTransactionProcessor_computeTransactionStatus(t *testing.T) { status := tp.ComputeTransactionStatus(testData.Transaction, withResults) require.Equal(t, string(transaction.TxStatusFail), status.Status) }) + t.Run("failed relayed transaction un-executable move balance", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedFailedRelayedTxMoveBalanceReturnMessage.json") + tp := createTestProcessorFromScenarioData(testData) + + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, string(transaction.TxStatusFail), status.Status) + }) t.Run("failed relayed transaction with SC call", func(t *testing.T) { t.Parallel() From 3813d381c349f778c2413beff2f1aac9daa9c0f0 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Tue, 4 Jun 2024 09:54:28 +0300 Subject: [PATCH 12/40] fix after review --- process/transactionProcessor.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 982a471d..55d953b5 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -504,12 +504,12 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } func checkIfFailedOnReturnMessage(allScrs []*transaction.ApiTransactionResult, tx *transaction.ApiTransactionResult) bool { - if returnMessageFailure(tx.Value, tx.ReturnMessage) { + if len(tx.ReturnMessage) > 0 && isZeroValue(tx.Value) { return true } for _, scr := range allScrs { - if returnMessageFailure(scr.Value, scr.ReturnMessage) { + if len(scr.ReturnMessage) > 0 && isZeroValue(scr.Value) { return true } } @@ -517,9 +517,11 @@ func checkIfFailedOnReturnMessage(allScrs []*transaction.ApiTransactionResult, t return false } -func returnMessageFailure(value string, returnMessage string) bool { - isZeroValue := value == "0" - return len(returnMessage) > 0 && isZeroValue +func isZeroValue(value string) bool { + if len(value) == 0 { + return true + } + return value == "0" } func checkIfFailed(logs []*transaction.ApiLogs) (bool, string) { From e60a623e288d3c251ca96e2e5080a2d397c7fb4d Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 5 Jun 2024 18:05:33 +0300 Subject: [PATCH 13/40] go mod tidy after merge --- go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index e763f63d..d50efa14 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240508071047-fefea5737840 h1:2mCrTUmbbA+Xv4UifZY9xptrGjcJBcJ2wavSb4FwejU= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240508071047-fefea5737840/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240528132712-8b6faa711b23 h1:jSP8BjMF9P5I9cO5hY2uN60q4+iPP9uq5WzETtcXWMI= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240528132712-8b6faa711b23/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df h1:clihfi78bMEOWk/qw6WA4uQbCM2e2NGliqswLAvw19k= github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df/go.mod h1:gtJYB4rR21KBSqJlazn+2z6f9gFSqQP3KvAgL7Qgxw4= github.com/multiversx/mx-chain-es-indexer-go v1.7.1-0.20240509104512-25512675833d h1:GD1D8V0bE6hDLjrduSsMwQwwf6PMq2Zww7FYMfJsuiw= From 87b39765fd29daf779698476dbdeda985f6ac3bc Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 5 Jun 2024 18:09:09 +0300 Subject: [PATCH 14/40] fixes after merge --- process/transactionProcessor.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 97d95a5d..2ef984eb 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -5,7 +5,6 @@ import ( "fmt" "math/big" "net/http" - "strings" "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" @@ -43,9 +42,7 @@ const ( relayedV1TransactionDescriptor = "RelayedTx" relayedV2TransactionDescriptor = "RelayedTxV2" relayedV3TransactionDescriptor = "RelayedTxV3" - relayedTxV1DataMarker = "relayedTx@" relayedTxV2DataMarker = "relayedTxV2" - argumentsSeparator = "@" emptyDataStr = "" ) @@ -488,7 +485,7 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } - isRelayedV3, status := checkIfRelayedV3Completed(allLogs, tx) + isRelayedV3, status := checkIfRelayedV3Completed(allScrs, allLogs, tx) if isRelayedV3 { return &data.ProcessStatusResponse{ Status: status, @@ -557,7 +554,7 @@ func checkIfCompleted(logs []*transaction.ApiLogs) bool { return found } -func checkIfRelayedV3Completed(logs []*transaction.ApiLogs, tx *transaction.ApiTransactionResult) (bool, string) { +func checkIfRelayedV3Completed(scrs []*transaction.ApiTransactionResult, logs []*transaction.ApiLogs, tx *transaction.ApiTransactionResult) (bool, string) { if len(tx.InnerTransactions) == 0 { return false, string(transaction.TxStatusPending) } @@ -574,11 +571,16 @@ func checkIfRelayedV3Completed(logs []*transaction.ApiLogs, tx *transaction.ApiT completedFound, _ := findIdentifierInSingleLog(logInstance, core.CompletedTxEventIdentifier) deployFound, _ := findIdentifierInSingleLog(logInstance, core.SCDeployIdentifier) + if completedFound || deployFound { completedCnt++ } } + if checkIfFailedOnReturnMessage(scrs, tx) { + return true, string(transaction.TxStatusFail) + } + status := string(transaction.TxStatusPending) if completedCnt == len(tx.InnerTransactions) { status = string(transaction.TxStatusSuccess) From 935bdb359a0cbdc4012c373a814a444b76451929 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 13 Jun 2024 18:20:57 +0300 Subject: [PATCH 15/40] fixes after review --- process/export_test.go | 3 --- process/transactionProcessor.go | 14 +++++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/process/export_test.go b/process/export_test.go index be16c7f7..e75d3da2 100644 --- a/process/export_test.go +++ b/process/export_test.go @@ -7,9 +7,6 @@ import ( proxyData "github.com/multiversx/mx-chain-proxy-go/data" ) -// RelayedTxV2DataMarker - -const RelayedTxV2DataMarker = relayedTxV2DataMarker - // SetDelayForCheckingNodesSyncState - func (bp *BaseProcessor) SetDelayForCheckingNodesSyncState(delay time.Duration) { bp.delayForCheckingNodesSyncState = delay diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 2ef984eb..40c2b9aa 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -42,7 +42,6 @@ const ( relayedV1TransactionDescriptor = "RelayedTx" relayedV2TransactionDescriptor = "RelayedTxV2" relayedV3TransactionDescriptor = "RelayedTxV3" - relayedTxV2DataMarker = "relayedTxV2" emptyDataStr = "" ) @@ -795,14 +794,15 @@ func (tp *TransactionProcessor) mergeSCRLogsFromInnerReceivers(tx *transaction.A break } - for _, observer := range observers { - getTxResponse, ok, _ := tp.getTxFromObserver(observer, scrHash, withResults) - if !ok { - continue - } + if withResults { + for _, observer := range observers { + getTxResponse, ok, _ := tp.getTxFromObserver(observer, scrHash, withResults) + if !ok { + continue + } - if withResults { logsOnDestMap[scrHash] = getTxResponse.Data.Transaction.Logs + break } } } From 507170f34c61860dcce85d27a43747d44b66f33f Mon Sep 17 00:00:00 2001 From: Daniel Drasovean Date: Mon, 17 Jun 2024 15:04:22 +0300 Subject: [PATCH 16/40] Update actions workflow to support multi-architecture docker image builds --- .github/workflows/deploy-docker.yaml | 45 ++++++++++++++++++---------- docker/Dockerfile | 1 + 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/.github/workflows/deploy-docker.yaml b/.github/workflows/deploy-docker.yaml index da7eeb45..f4479772 100644 --- a/.github/workflows/deploy-docker.yaml +++ b/.github/workflows/deploy-docker.yaml @@ -7,6 +7,7 @@ name: Build Docker image & push on: release: types: [published] + pull_request: jobs: build-docker-image: @@ -17,19 +18,31 @@ jobs: steps: - name: Check out code into the Go module directory - uses: actions/checkout@v3 - - - name: Get the version - id: get_version - run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/} - - - name: Build image - run: | - TAG_VERSION=${{ steps.get_version.outputs.VERSION }} - cd ${GITHUB_WORKSPACE} && docker build -t "${REGISTRY_HOSTNAME}/${IMAGE_NODE}:${TAG_VERSION}" -f ./docker/Dockerfile . - - name: Push image - run: | - docker login --username ${{ secrets.DOCKERHUB_USERNAME }} --password ${{ secrets.DOCKERHUB_TOKEN }} - TAG_VERSION=${{ steps.get_version.outputs.VERSION }} - docker push "${REGISTRY_HOSTNAME}/${IMAGE_NODE}:${TAG_VERSION}" - docker logout + uses: actions/checkout@v4 + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_HOSTNAME }}/${{ env.IMAGE_NODE }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log into Docker Hub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push image to Docker Hub + id: push + uses: docker/build-push-action@v5 + with: + context: . + file: ./docker/Dockerfile + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/docker/Dockerfile b/docker/Dockerfile index 430e211e..f377e9fb 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,5 @@ FROM golang:1.20.7 as builder +LABEL maintainer="multiversx" WORKDIR /mx-chain-proxy-go COPY . . From b28ae65afbe2d0c66ae70f201c210b41c5d8f7a4 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 19 Jun 2024 17:04:03 +0300 Subject: [PATCH 17/40] fix /process-status returning incorrect failed tx with gas refund --- process/transactionProcessor.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 40c2b9aa..78c4c3b9 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -509,11 +509,16 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } func checkIfFailedOnReturnMessage(allScrs []*transaction.ApiTransactionResult, tx *transaction.ApiTransactionResult) bool { - if len(tx.ReturnMessage) > 0 && isZeroValue(tx.Value) { + hasReturnMessageWithZeroValue := len(tx.ReturnMessage) > 0 && isZeroValue(tx.Value) + if hasReturnMessageWithZeroValue && !isRefundScr(tx.ReturnMessage) { return true } for _, scr := range allScrs { + if isRefundScr(scr.ReturnMessage) { + continue + } + if len(scr.ReturnMessage) > 0 && isZeroValue(scr.Value) { return true } @@ -522,6 +527,10 @@ func checkIfFailedOnReturnMessage(allScrs []*transaction.ApiTransactionResult, t return false } +func isRefundScr(returnMessage string) bool { + return returnMessage == core.GasRefundForRelayerMessage +} + func isZeroValue(value string) bool { if len(value) == 0 { return true From ebbe8373830a65b91d07f930bef464ea28fe8737 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Tue, 2 Jul 2024 13:58:31 +0300 Subject: [PATCH 18/40] fix /process-status returning incorrect pending tx for issue which generates more than one completedTxEvent --- process/transactionProcessor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 78c4c3b9..bc140fec 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -590,7 +590,7 @@ func checkIfRelayedV3Completed(scrs []*transaction.ApiTransactionResult, logs [] } status := string(transaction.TxStatusPending) - if completedCnt == len(tx.InnerTransactions) { + if completedCnt >= len(tx.InnerTransactions) { status = string(transaction.TxStatusSuccess) } return true, status From dc3cc55deae90cc3e05c9c5ef1f3f48700ee41fe Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 3 Jul 2024 12:34:54 +0300 Subject: [PATCH 19/40] /process-status now returns success for relayed v3 --- process/transactionProcessor.go | 42 ++++++++------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index bc140fec..9d55ee1a 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -476,18 +476,18 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } - failed, reason = checkIfFailed(allLogs) - if failed { + isRelayedV3, status := checkIfRelayedV3Completed(allLogs, tx) + if isRelayedV3 { return &data.ProcessStatusResponse{ - Status: string(transaction.TxStatusFail), - Reason: reason, + Status: status, } } - isRelayedV3, status := checkIfRelayedV3Completed(allScrs, allLogs, tx) - if isRelayedV3 { + failed, reason = checkIfFailed(allLogs) + if failed { return &data.ProcessStatusResponse{ - Status: status, + Status: string(transaction.TxStatusFail), + Reason: reason, } } @@ -562,38 +562,16 @@ func checkIfCompleted(logs []*transaction.ApiLogs) bool { return found } -func checkIfRelayedV3Completed(scrs []*transaction.ApiTransactionResult, logs []*transaction.ApiLogs, tx *transaction.ApiTransactionResult) (bool, string) { +func checkIfRelayedV3Completed(logs []*transaction.ApiLogs, tx *transaction.ApiTransactionResult) (bool, string) { if len(tx.InnerTransactions) == 0 { return false, string(transaction.TxStatusPending) } - if len(logs) == 0 { + if len(logs) < len(tx.InnerTransactions) { return true, string(transaction.TxStatusPending) } - completedCnt := 0 - for _, logInstance := range logs { - if logInstance == nil { - continue - } - - completedFound, _ := findIdentifierInSingleLog(logInstance, core.CompletedTxEventIdentifier) - deployFound, _ := findIdentifierInSingleLog(logInstance, core.SCDeployIdentifier) - - if completedFound || deployFound { - completedCnt++ - } - } - - if checkIfFailedOnReturnMessage(scrs, tx) { - return true, string(transaction.TxStatusFail) - } - - status := string(transaction.TxStatusPending) - if completedCnt >= len(tx.InnerTransactions) { - status = string(transaction.TxStatusSuccess) - } - return true, status + return true, string(transaction.TxStatusSuccess) } func checkIfMoveBalanceNotarized(tx *transaction.ApiTransactionResult) bool { From 0283601eb7261af04bf8bd8a943a97b3b0690766 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 3 Jul 2024 13:03:44 +0300 Subject: [PATCH 20/40] update deps --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 91972d32..d101ad9a 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,9 @@ require ( github.com/gin-contrib/pprof v1.4.0 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.9.1 - github.com/multiversx/mx-chain-core-go v1.2.21-0.20240528132712-8b6faa711b23 + github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703095353-e5daea901067 github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df - github.com/multiversx/mx-chain-es-indexer-go v1.7.1-0.20240509104512-25512675833d + github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240514103357-929ece92ef86 github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index d50efa14..592e8c9d 100644 --- a/go.sum +++ b/go.sum @@ -131,12 +131,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240528132712-8b6faa711b23 h1:jSP8BjMF9P5I9cO5hY2uN60q4+iPP9uq5WzETtcXWMI= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240528132712-8b6faa711b23/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703095353-e5daea901067 h1:xkWwOJok4GlbMd/BBtJ75wnNRjIVh4o+7RdZL/q/mlQ= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703095353-e5daea901067/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df h1:clihfi78bMEOWk/qw6WA4uQbCM2e2NGliqswLAvw19k= github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df/go.mod h1:gtJYB4rR21KBSqJlazn+2z6f9gFSqQP3KvAgL7Qgxw4= -github.com/multiversx/mx-chain-es-indexer-go v1.7.1-0.20240509104512-25512675833d h1:GD1D8V0bE6hDLjrduSsMwQwwf6PMq2Zww7FYMfJsuiw= -github.com/multiversx/mx-chain-es-indexer-go v1.7.1-0.20240509104512-25512675833d/go.mod h1:UDKRXmxsSyPeAcjLUfGeYkAtYp424PIYkL82kzFYobM= +github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240514103357-929ece92ef86 h1:rw+u7qv0HO+7lRddCzfciqDcAWL9/fl2LQqU8AmVtdU= +github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240514103357-929ece92ef86/go.mod h1:UDKRXmxsSyPeAcjLUfGeYkAtYp424PIYkL82kzFYobM= github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57 h1:g9t410dqjcb7UUptbVd/H6Ua12sEzWU4v7VplyNvRZ0= github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57/go.mod h1:cY6CIXpndW5g5PTPn4WzPwka/UBEf+mgw+PSY5pHGAU= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= From f599657093bc53280fba9778f5d202237fe91a66 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 3 Jul 2024 17:04:41 +0300 Subject: [PATCH 21/40] update deps --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index d101ad9a..0db9fd93 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,9 @@ require ( github.com/gin-contrib/pprof v1.4.0 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.9.1 - github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703095353-e5daea901067 + github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703135649-550eebfbc10b github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df - github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240514103357-929ece92ef86 + github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240619122842-05143459c554 github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index 592e8c9d..c21a856f 100644 --- a/go.sum +++ b/go.sum @@ -131,12 +131,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703095353-e5daea901067 h1:xkWwOJok4GlbMd/BBtJ75wnNRjIVh4o+7RdZL/q/mlQ= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703095353-e5daea901067/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703135649-550eebfbc10b h1:bmN8RtaWC/7lQenavRVVY5NrAPOdh3N9tGyxqVrx2qU= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703135649-550eebfbc10b/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df h1:clihfi78bMEOWk/qw6WA4uQbCM2e2NGliqswLAvw19k= github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df/go.mod h1:gtJYB4rR21KBSqJlazn+2z6f9gFSqQP3KvAgL7Qgxw4= -github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240514103357-929ece92ef86 h1:rw+u7qv0HO+7lRddCzfciqDcAWL9/fl2LQqU8AmVtdU= -github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240514103357-929ece92ef86/go.mod h1:UDKRXmxsSyPeAcjLUfGeYkAtYp424PIYkL82kzFYobM= +github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240619122842-05143459c554 h1:Fv8BfzJSzdovmoh9Jh/by++0uGsOVBlMP3XiN5Svkn4= +github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240619122842-05143459c554/go.mod h1:yMq9q5VdN7jBaErRGQ0T8dkZwbBtfQYmqGbD/Ese1us= github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57 h1:g9t410dqjcb7UUptbVd/H6Ua12sEzWU4v7VplyNvRZ0= github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57/go.mod h1:cY6CIXpndW5g5PTPn4WzPwka/UBEf+mgw+PSY5pHGAU= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= From 6657635d435cd3aaace5e7076235d8aac0d70ddc Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 4 Jul 2024 10:18:49 +0300 Subject: [PATCH 22/40] fix invalid address errors --- api/errors/errors.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/errors/errors.go b/api/errors/errors.go index d3499a73..a31ab72a 100644 --- a/api/errors/errors.go +++ b/api/errors/errors.go @@ -84,16 +84,16 @@ var ErrInvalidSignatureHex = errors.New("invalid signature, could not decode hex var ErrInvalidGuardianSignatureHex = errors.New("invalid guardian signature, could not decode hex value") // ErrInvalidGuardianAddress signals a wrong format for receiver address was provided -var ErrInvalidGuardianAddress = errors.New("invalid hex receiver address provided") +var ErrInvalidGuardianAddress = errors.New("invalid guardian address") // ErrTxGenerationFailed signals an error generating a transaction var ErrTxGenerationFailed = errors.New("transaction generation failed") // ErrInvalidSenderAddress signals a wrong format for sender address was provided -var ErrInvalidSenderAddress = errors.New("invalid hex sender address provided") +var ErrInvalidSenderAddress = errors.New("invalid sender address provided") // ErrInvalidReceiverAddress signals a wrong format for receiver address was provided -var ErrInvalidReceiverAddress = errors.New("invalid hex receiver address provided") +var ErrInvalidReceiverAddress = errors.New("invalid receiver address provided") // ErrTransactionNotFound signals that a transaction was not found var ErrTransactionNotFound = errors.New("transaction not found") From e52d7d1ca84f2b11732041e25c8698cd1690e247 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 4 Jul 2024 10:20:14 +0300 Subject: [PATCH 23/40] remove provided string --- api/errors/errors.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/errors/errors.go b/api/errors/errors.go index a31ab72a..800f7975 100644 --- a/api/errors/errors.go +++ b/api/errors/errors.go @@ -90,10 +90,10 @@ var ErrInvalidGuardianAddress = errors.New("invalid guardian address") var ErrTxGenerationFailed = errors.New("transaction generation failed") // ErrInvalidSenderAddress signals a wrong format for sender address was provided -var ErrInvalidSenderAddress = errors.New("invalid sender address provided") +var ErrInvalidSenderAddress = errors.New("invalid sender address") // ErrInvalidReceiverAddress signals a wrong format for receiver address was provided -var ErrInvalidReceiverAddress = errors.New("invalid receiver address provided") +var ErrInvalidReceiverAddress = errors.New("invalid receiver address") // ErrTransactionNotFound signals that a transaction was not found var ErrTransactionNotFound = errors.New("transaction not found") From 9a6b0bb680364777e2e77194c57c7603b4824851 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 25 Jul 2024 10:45:38 +0300 Subject: [PATCH 24/40] updated deps after merge --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 0db9fd93..2ace1a0a 100644 --- a/go.mod +++ b/go.mod @@ -8,10 +8,10 @@ require ( github.com/gin-contrib/pprof v1.4.0 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.9.1 - github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703135649-550eebfbc10b - github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df - github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240619122842-05143459c554 - github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57 + github.com/multiversx/mx-chain-core-go v1.2.21-0.20240725065431-6e9bfee5a4c6 + github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240725071000-c3212540166f + github.com/multiversx/mx-chain-es-indexer-go v1.7.3-0.20240725073933-b3457c5308ca + github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240725065747-176bd697c775 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 github.com/urfave/cli v1.22.10 diff --git a/go.sum b/go.sum index c21a856f..9b19a00d 100644 --- a/go.sum +++ b/go.sum @@ -131,14 +131,14 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703135649-550eebfbc10b h1:bmN8RtaWC/7lQenavRVVY5NrAPOdh3N9tGyxqVrx2qU= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240703135649-550eebfbc10b/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= -github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df h1:clihfi78bMEOWk/qw6WA4uQbCM2e2NGliqswLAvw19k= -github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240508074452-cc21c1b505df/go.mod h1:gtJYB4rR21KBSqJlazn+2z6f9gFSqQP3KvAgL7Qgxw4= -github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240619122842-05143459c554 h1:Fv8BfzJSzdovmoh9Jh/by++0uGsOVBlMP3XiN5Svkn4= -github.com/multiversx/mx-chain-es-indexer-go v1.7.2-0.20240619122842-05143459c554/go.mod h1:yMq9q5VdN7jBaErRGQ0T8dkZwbBtfQYmqGbD/Ese1us= -github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57 h1:g9t410dqjcb7UUptbVd/H6Ua12sEzWU4v7VplyNvRZ0= -github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240508072523-3f00a726af57/go.mod h1:cY6CIXpndW5g5PTPn4WzPwka/UBEf+mgw+PSY5pHGAU= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240725065431-6e9bfee5a4c6 h1:Q7uUjTYTrt8Mw9oq5JWPv+WHhpxHTv6lhZZlhPuNcoQ= +github.com/multiversx/mx-chain-core-go v1.2.21-0.20240725065431-6e9bfee5a4c6/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240725071000-c3212540166f h1:jydjrmVFvSllBOTppveOAkLITpOYKk0kma5z0bfDImI= +github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240725071000-c3212540166f/go.mod h1:9aSp//uBSvqFdzh4gvYISraoruhr1FCTXgPQalQ687k= +github.com/multiversx/mx-chain-es-indexer-go v1.7.3-0.20240725073933-b3457c5308ca h1:9b2yFAarWDG/jTYePv0UqNWQ9gxeSZy9mGxtd8dFj2Y= +github.com/multiversx/mx-chain-es-indexer-go v1.7.3-0.20240725073933-b3457c5308ca/go.mod h1:bHPP5zerhmbRfVcbfXgpMPUaTKMrK6gGi+rRbw0BpDE= +github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240725065747-176bd697c775 h1:a8LOfz3p4MQfRtbF00rGDAJiebziwtSfVmBHIaHBDdY= +github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240725065747-176bd697c775/go.mod h1:owPYyrK7RcsLx9eOCAZQ22fIyW6BE7ttJr4XIhFIbQw= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= From f6267bacc2966361bdfa955f7e941e3166d2f898 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Fri, 26 Jul 2024 15:13:19 +0300 Subject: [PATCH 25/40] process status fix for adding nil values on logs --- process/testdata/pendingSCROfRelayedV3.json | 101 ++++++++++++++++++++ process/transactionProcessor.go | 15 ++- process/transactionProcessor_test.go | 8 ++ 3 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 process/testdata/pendingSCROfRelayedV3.json diff --git a/process/testdata/pendingSCROfRelayedV3.json b/process/testdata/pendingSCROfRelayedV3.json new file mode 100644 index 00000000..d27da23e --- /dev/null +++ b/process/testdata/pendingSCROfRelayedV3.json @@ -0,0 +1,101 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "RelayedTxV3", + "processingTypeOnDestination": "RelayedTxV3", + "hash": "98f2a122f8bc1c87401d184b4bfa292dee6010033837e7b2927ada345e0e82ca", + "nonce": 0, + "round": 360, + "epoch": 7, + "value": "0", + "receiver": "erd15uchpdmkn90qxd9add6npnst3mckkapkq7zmn5l8rlkwnvk7k0ese9q8z5", + "sender": "erd15uchpdmkn90qxd9add6npnst3mckkapkq7zmn5l8rlkwnvk7k0ese9q8z5", + "gasPrice": 1000000000, + "gasLimit": 55050000, + "gasUsed": 55050000, + "signature": "629d9ed05630e9a9ae637ae920d33f0118e1fb067d4a986ebaee147867a62f12a07e64195113ea513e6c2b51a9881f9deefbcc50269511471d2ba6778a672b01", + "sourceShard": 1, + "destinationShard": 1, + "blockNonce": 360, + "blockHash": "92661989d434e60faee1a8c4f97e82f858e035f58252e9842238b150beb61739", + "miniblockType": "TxBlock", + "miniblockHash": "8ec424450f436c00d20d6fc5fec97a739892e44027587f57ea703457e925ce16", + "timestamp": 1721997247, + "smartContractResults": [ + { + "hash": "208d3b73ebcefba5565f3f7c1f4435040f2a8bd7efbe30498c65afaa40ff4a34", + "nonce": 0, + "value": 5000000000000000000000, + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqplllst77y4l", + "sender": "erd10vn8cuug0wx6anj84g7ukzlm06fullcjadetvmusqzv039x04f3supvc4v", + "relayerAddress": "erd15uchpdmkn90qxd9add6npnst3mckkapkq7zmn5l8rlkwnvk7k0ese9q8z5", + "relayedValue": 0, + "data": "stake@02@d690d1419e7667c59c5f70277bb92764518fc472d9418ae7b1c53ca90959da6abc3a188d9e9fd5ea03ed9d5fbef8fa0cc47d0e632105e1ba2f2abd6685a50be1c4af50d1ec8cfc083d2264714a1a9339f6d1e48cadc556f6efd451bf447b5619@dc49b56485ab67ab8a82659ef43339bbaa35839eb2011bbf79c02204d83127638ebd448d49412863057d4da20b6b0d14@19d2d21b2a5a22d91e6308d79c57dda4dde41c266a0e999c506f1f8b894509b1b5a1cb2e573feda1e771cf88672e2e11ae1c4a79a7dbcb19698984e27bd07b2c93c0919091ec9514fed26e15bb1bfdfe82e922fa6d6b626118a4f56c19d4408b@2b1c53e18ef0b6166b423c87bf0fe8b5800a3174f1b176d80b7633cf6debc96ef2142f35d2b3e93416887101a40df787", + "prevTxHash": "98f2a122f8bc1c87401d184b4bfa292dee6010033837e7b2927ada345e0e82ca", + "originalTxHash": "98f2a122f8bc1c87401d184b4bfa292dee6010033837e7b2927ada345e0e82ca", + "gasLimit": 54068000, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer", + "function": "stake" + } + ], + "status": "success", + "receivers": [ + "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqplllst77y4l" + ], + "receiversShardIDs": [ + 4294967295 + ], + "operation": "transfer", + "initiallyPaidFee": "1522680000000000", + "fee": "1522680000000000", + "isRelayed": true, + "chainID": "chain", + "version": 2, + "options": 0, + "innerTransactions": [ + { + "nonce": 0, + "value": "5000000000000000000000", + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqplllst77y4l", + "sender": "erd10vn8cuug0wx6anj84g7ukzlm06fullcjadetvmusqzv039x04f3supvc4v", + "gasPrice": 1000000000, + "gasLimit": 55000000, + "data": "c3Rha2VAMDJAZDY5MGQxNDE5ZTc2NjdjNTljNWY3MDI3N2JiOTI3NjQ1MThmYzQ3MmQ5NDE4YWU3YjFjNTNjYTkwOTU5ZGE2YWJjM2ExODhkOWU5ZmQ1ZWEwM2VkOWQ1ZmJlZjhmYTBjYzQ3ZDBlNjMyMTA1ZTFiYTJmMmFiZDY2ODVhNTBiZTFjNGFmNTBkMWVjOGNmYzA4M2QyMjY0NzE0YTFhOTMzOWY2ZDFlNDhjYWRjNTU2ZjZlZmQ0NTFiZjQ0N2I1NjE5QGRjNDliNTY0ODVhYjY3YWI4YTgyNjU5ZWY0MzMzOWJiYWEzNTgzOWViMjAxMWJiZjc5YzAyMjA0ZDgzMTI3NjM4ZWJkNDQ4ZDQ5NDEyODYzMDU3ZDRkYTIwYjZiMGQxNEAxOWQyZDIxYjJhNWEyMmQ5MWU2MzA4ZDc5YzU3ZGRhNGRkZTQxYzI2NmEwZTk5OWM1MDZmMWY4Yjg5NDUwOWIxYjVhMWNiMmU1NzNmZWRhMWU3NzFjZjg4NjcyZTJlMTFhZTFjNGE3OWE3ZGJjYjE5Njk4OTg0ZTI3YmQwN2IyYzkzYzA5MTkwOTFlYzk1MTRmZWQyNmUxNWJiMWJmZGZlODJlOTIyZmE2ZDZiNjI2MTE4YTRmNTZjMTlkNDQwOGJAMmIxYzUzZTE4ZWYwYjYxNjZiNDIzYzg3YmYwZmU4YjU4MDBhMzE3NGYxYjE3NmQ4MGI3NjMzY2Y2ZGViYzk2ZWYyMTQyZjM1ZDJiM2U5MzQxNjg4NzEwMWE0MGRmNzg3", + "signature": "4c075c5ee550931e9b64b6db5974a4a1c0c48c9e7f48ac792949bb87e4861addb774310506a313b8d0fc062cadcba010449707bf34b7adeb2f4da67e8b2db602", + "chainID": "chain", + "version": 2, + "relayer": "erd15uchpdmkn90qxd9add6npnst3mckkapkq7zmn5l8rlkwnvk7k0ese9q8z5" + } + ] + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "208d3b73ebcefba5565f3f7c1f4435040f2a8bd7efbe30498c65afaa40ff4a34", + "nonce": 0, + "round": 0, + "epoch": 0, + "value": "5000000000000000000000", + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqplllst77y4l", + "sender": "erd10vn8cuug0wx6anj84g7ukzlm06fullcjadetvmusqzv039x04f3supvc4v", + "gasPrice": 1000000000, + "gasLimit": 54068000, + "gasUsed": 932000, + "data": "c3Rha2VAMDJAZDY5MGQxNDE5ZTc2NjdjNTljNWY3MDI3N2JiOTI3NjQ1MThmYzQ3MmQ5NDE4YWU3YjFjNTNjYTkwOTU5ZGE2YWJjM2ExODhkOWU5ZmQ1ZWEwM2VkOWQ1ZmJlZjhmYTBjYzQ3ZDBlNjMyMTA1ZTFiYTJmMmFiZDY2ODVhNTBiZTFjNGFmNTBkMWVjOGNmYzA4M2QyMjY0NzE0YTFhOTMzOWY2ZDFlNDhjYWRjNTU2ZjZlZmQ0NTFiZjQ0N2I1NjE5QGRjNDliNTY0ODVhYjY3YWI4YTgyNjU5ZWY0MzMzOWJiYWEzNTgzOWViMjAxMWJiZjc5YzAyMjA0ZDgzMTI3NjM4ZWJkNDQ4ZDQ5NDEyODYzMDU3ZDRkYTIwYjZiMGQxNEAxOWQyZDIxYjJhNWEyMmQ5MWU2MzA4ZDc5YzU3ZGRhNGRkZTQxYzI2NmEwZTk5OWM1MDZmMWY4Yjg5NDUwOWIxYjVhMWNiMmU1NzNmZWRhMWU3NzFjZjg4NjcyZTJlMTFhZTFjNGE3OWE3ZGJjYjE5Njk4OTg0ZTI3YmQwN2IyYzkzYzA5MTkwOTFlYzk1MTRmZWQyNmUxNWJiMWJmZGZlODJlOTIyZmE2ZDZiNjI2MTE4YTRmNTZjMTlkNDQwOGJAMmIxYzUzZTE4ZWYwYjYxNjZiNDIzYzg3YmYwZmU4YjU4MDBhMzE3NGYxYjE3NmQ4MGI3NjMzY2Y2ZGViYzk2ZWYyMTQyZjM1ZDJiM2U5MzQxNjg4NzEwMWE0MGRmNzg3", + "previousTransactionHash": "98f2a122f8bc1c87401d184b4bfa292dee6010033837e7b2927ada345e0e82ca", + "originalTransactionHash": "98f2a122f8bc1c87401d184b4bfa292dee6010033837e7b2927ada345e0e82ca", + "sourceShard": 1, + "destinationShard": 4294967295, + "status": "pending", + "fee": "0", + "callType": "directCall", + "relayerAddress": "erd15uchpdmkn90qxd9add6npnst3mckkapkq7zmn5l8rlkwnvk7k0ese9q8z5", + "relayedValue": "0", + "options": 0 + } + ] +} diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 9d55ee1a..14c7a436 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -682,17 +682,28 @@ func findIdentifierInSingleLog(log *transaction.ApiLogs, identifier string) (boo func (tp *TransactionProcessor) gatherAllLogsAndScrs(tx *transaction.ApiTransactionResult) ([]*transaction.ApiLogs, []*transaction.ApiTransactionResult, error) { const withResults = true - allLogs := []*transaction.ApiLogs{tx.Logs} + allLogs := make([]*transaction.ApiLogs, 0) allScrs := make([]*transaction.ApiTransactionResult, 0) + if tx.Logs != nil { + allLogs = append(allLogs, tx.Logs) + } + for _, scrFromTx := range tx.SmartContractResults { scr, err := tp.GetTransaction(scrFromTx.Hash, withResults) if err != nil { return nil, nil, fmt.Errorf("%w for scr hash %s", err, scrFromTx.Hash) } - allLogs = append(allLogs, scr.Logs) + if scr == nil { + continue + } allScrs = append(allScrs, scr) + + if scr.Logs == nil { + continue + } + allLogs = append(allLogs, scr.Logs) } return allLogs, allScrs, nil diff --git a/process/transactionProcessor_test.go b/process/transactionProcessor_test.go index 350f7de6..0457a28b 100644 --- a/process/transactionProcessor_test.go +++ b/process/transactionProcessor_test.go @@ -2116,6 +2116,14 @@ func TestTransactionProcessor_computeTransactionStatus(t *testing.T) { status := tp.ComputeTransactionStatus(testData.Transaction, withResults) require.Equal(t, string(transaction.TxStatusSuccess), status.Status) }) + t.Run("pending scr of relayed v3 should return pending", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/pendingSCROfRelayedV3.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, true) + require.Equal(t, string(transaction.TxStatusPending), status.Status) + }) }) t.Run("reward transaction", func(t *testing.T) { t.Parallel() From dd7d971672af6b70328742c41365cfaadd102f83 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 29 Jul 2024 11:38:27 +0300 Subject: [PATCH 26/40] updated deps --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 2ace1a0a..fbb90512 100644 --- a/go.mod +++ b/go.mod @@ -8,10 +8,10 @@ require ( github.com/gin-contrib/pprof v1.4.0 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.9.1 - github.com/multiversx/mx-chain-core-go v1.2.21-0.20240725065431-6e9bfee5a4c6 - github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240725071000-c3212540166f - github.com/multiversx/mx-chain-es-indexer-go v1.7.3-0.20240725073933-b3457c5308ca - github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240725065747-176bd697c775 + github.com/multiversx/mx-chain-core-go v1.2.21 + github.com/multiversx/mx-chain-crypto-go v1.2.12 + github.com/multiversx/mx-chain-es-indexer-go v1.7.4 + github.com/multiversx/mx-chain-logger-go v1.0.15 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 github.com/urfave/cli v1.22.10 diff --git a/go.sum b/go.sum index 9b19a00d..3ff90b70 100644 --- a/go.sum +++ b/go.sum @@ -131,14 +131,14 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240725065431-6e9bfee5a4c6 h1:Q7uUjTYTrt8Mw9oq5JWPv+WHhpxHTv6lhZZlhPuNcoQ= -github.com/multiversx/mx-chain-core-go v1.2.21-0.20240725065431-6e9bfee5a4c6/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= -github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240725071000-c3212540166f h1:jydjrmVFvSllBOTppveOAkLITpOYKk0kma5z0bfDImI= -github.com/multiversx/mx-chain-crypto-go v1.2.12-0.20240725071000-c3212540166f/go.mod h1:9aSp//uBSvqFdzh4gvYISraoruhr1FCTXgPQalQ687k= -github.com/multiversx/mx-chain-es-indexer-go v1.7.3-0.20240725073933-b3457c5308ca h1:9b2yFAarWDG/jTYePv0UqNWQ9gxeSZy9mGxtd8dFj2Y= -github.com/multiversx/mx-chain-es-indexer-go v1.7.3-0.20240725073933-b3457c5308ca/go.mod h1:bHPP5zerhmbRfVcbfXgpMPUaTKMrK6gGi+rRbw0BpDE= -github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240725065747-176bd697c775 h1:a8LOfz3p4MQfRtbF00rGDAJiebziwtSfVmBHIaHBDdY= -github.com/multiversx/mx-chain-logger-go v1.0.15-0.20240725065747-176bd697c775/go.mod h1:owPYyrK7RcsLx9eOCAZQ22fIyW6BE7ttJr4XIhFIbQw= +github.com/multiversx/mx-chain-core-go v1.2.21 h1:+XVKznPTlUU5EFS1A8chtS8fStW60upRIyF4Pgml19I= +github.com/multiversx/mx-chain-core-go v1.2.21/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.4 h1:SjJk9G9SN8baz0sFIU2jymYCfx3XiikGEB2wW0jwvfw= +github.com/multiversx/mx-chain-es-indexer-go v1.7.4/go.mod h1:oGcRK2E3Syv6vRTszWrrb/TqD8akq0yeoMr1wPPiTO4= +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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= From 2487bb1fc8b7815b347cc5f20b7803dcd0864acb Mon Sep 17 00:00:00 2001 From: danielailie Date: Thu, 1 Aug 2024 15:46:10 +0300 Subject: [PATCH 27/40] Remove code for address/:address/transactions --- .gitignore | 1 + README.md | 1 - api/groups/baseAccountsGroup.go | 22 ---------- api/groups/interface.go | 1 - cmd/proxy/config/apiConfig/v1_0.toml | 1 - cmd/proxy/config/apiConfig/v_next.toml | 1 - cmd/proxy/config/swagger/openapi.json | 44 +++---------------- facade/baseFacade.go | 5 --- facade/interface.go | 1 - facade/mock/accountProccessorStub.go | 5 --- process/accountProcessor.go | 9 ---- process/accountProcessor_test.go | 20 --------- process/database/elasticSearchConnector.go | 10 ----- .../database/elasticSearchConnector_test.go | 14 ------ process/interface.go | 1 - process/mock/elasticSearchConnectorMock.go | 5 --- process/mock/externalStorageConnectorStub.go | 10 ----- 17 files changed, 7 insertions(+), 144 deletions(-) diff --git a/.gitignore b/.gitignore index 44e69658..a4530dd0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ .idea/ vendor/ +cmd/proxy/proxy diff --git a/README.md b/README.md index bef3670e..5967add5 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ For more details, go [here](https://docs.multiversx.com/sdk-and-tools/proxy/). - `/v1.0/address/:address/shard` (GET) --> returns the shard of an :address based on current proxy's configuration. - `/v1.0/address/:address/keys ` (GET) --> returns the key-value pairs of an :address. - `/v1.0/address/:address/storage/:key` (GET) --> returns the value for a given key for an account. -- `/v1.0/address/:address/transactions` (GET) --> returns the transactions stored in indexer for a given :address. - `/v1.0/address/:address/esdt` (GET) --> returns the account's ESDT tokens list for the given :address. - `/v1.0/address/:address/esdt/:tokenIdentifier` (GET) --> returns the token data for a given :address and ESDT token, such as balance and properties. - `/v1.0/address/:address/esdts-with-role/:role` (GET) --> returns the token identifiers for a given :address and the provided role. diff --git a/api/groups/baseAccountsGroup.go b/api/groups/baseAccountsGroup.go index 62ea2592..2daaca58 100644 --- a/api/groups/baseAccountsGroup.go +++ b/api/groups/baseAccountsGroup.go @@ -34,7 +34,6 @@ func NewAccountsGroup(facadeHandler data.FacadeHandler) (*accountsGroup, error) {Path: "/:address/nonce", Handler: ag.getNonce, Method: http.MethodGet}, {Path: "/:address/shard", Handler: ag.getShard, Method: http.MethodGet}, {Path: "/:address/code-hash", Handler: ag.getCodeHash, Method: http.MethodGet}, - {Path: "/:address/transactions", Handler: ag.getTransactions, Method: http.MethodGet}, {Path: "/:address/keys", Handler: ag.getKeyValuePairs, Method: http.MethodGet}, {Path: "/:address/key/:key", Handler: ag.getValueForKey, Method: http.MethodGet}, {Path: "/:address/esdt", Handler: ag.getESDTTokens, Method: http.MethodGet}, @@ -71,16 +70,6 @@ func (group *accountsGroup) respondWithAccount(c *gin.Context, transform func(*d shared.RespondWith(c, http.StatusOK, response, "", data.ReturnCodeSuccess) } -func (group *accountsGroup) getTransactionsFromFacade(c *gin.Context) ([]data.DatabaseTransaction, int, error) { - addr := c.Param("address") - transactions, err := group.facade.GetTransactions(addr) - if err != nil { - return nil, http.StatusInternalServerError, err - } - - return transactions, http.StatusOK, nil -} - // getAccount returns an accountResponse containing information // about the account correlated with provided address func (group *accountsGroup) getAccount(c *gin.Context) { @@ -157,17 +146,6 @@ func (group *accountsGroup) getAccounts(c *gin.Context) { shared.RespondWith(c, http.StatusOK, response, "", data.ReturnCodeSuccess) } -// getTransactions returns the transactions for the address parameter -func (group *accountsGroup) getTransactions(c *gin.Context) { - transactions, status, err := group.getTransactionsFromFacade(c) - if err != nil { - shared.RespondWith(c, status, nil, err.Error(), data.ReturnCodeInternalError) - return - } - - shared.RespondWith(c, http.StatusOK, gin.H{"transactions": transactions}, "", data.ReturnCodeSuccess) -} - // getKeyValuePairs returns the key-value pairs for the address parameter func (group *accountsGroup) getKeyValuePairs(c *gin.Context) { addr := c.Param("address") diff --git a/api/groups/interface.go b/api/groups/interface.go index a4c18868..c97a076b 100644 --- a/api/groups/interface.go +++ b/api/groups/interface.go @@ -13,7 +13,6 @@ import ( type AccountsFacadeHandler interface { GetAccount(address string, options common.AccountQueryOptions) (*data.AccountModel, error) GetCodeHash(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) - GetTransactions(address string) ([]data.DatabaseTransaction, error) GetShardIDForAddress(address string) (uint32, error) GetValueForKey(address string, key string, options common.AccountQueryOptions) (string, error) GetAllESDTTokens(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) diff --git a/cmd/proxy/config/apiConfig/v1_0.toml b/cmd/proxy/config/apiConfig/v1_0.toml index 1f5d2aed..6bfd4d85 100644 --- a/cmd/proxy/config/apiConfig/v1_0.toml +++ b/cmd/proxy/config/apiConfig/v1_0.toml @@ -45,7 +45,6 @@ Routes = [ { Name = "/:address/registered-nfts", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:address/nft/:tokenIdentifier/nonce/:nonce", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:address/shard", Open = true, Secured = false, RateLimit = 0 }, - { Name = "/:address/transactions", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:address/guardian-data", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:address/is-data-trie-migrated", Open = true, Secured = false, RateLimit = 0 } ] diff --git a/cmd/proxy/config/apiConfig/v_next.toml b/cmd/proxy/config/apiConfig/v_next.toml index 1bdf4e85..8fdb4dd1 100644 --- a/cmd/proxy/config/apiConfig/v_next.toml +++ b/cmd/proxy/config/apiConfig/v_next.toml @@ -45,7 +45,6 @@ Routes = [ { Name = "/:address/registered-nfts", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:address/nft/:tokenIdentifier/nonce/:nonce", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:address/shard", Open = true, Secured = false, RateLimit = 0 }, - { Name = "/:address/transactions", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:address/guardian-data", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:address/is-data-trie-migrated", Open = true, Secured = false, RateLimit = 0 } ] diff --git a/cmd/proxy/config/swagger/openapi.json b/cmd/proxy/config/swagger/openapi.json index 05c1e5b9..f27cc0a1 100644 --- a/cmd/proxy/config/swagger/openapi.json +++ b/cmd/proxy/config/swagger/openapi.json @@ -270,38 +270,6 @@ } } }, - "/address/{address}/transactions": { - "get": { - "tags": [ - "address" - ], - "summary": "returns the transactions of the provided address", - "parameters": [ - { - "name": "address", - "in": "path", - "description": "the address in bech32 format", - "required": true, - "schema": { - "type": "string", - "default": null - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddressTransactions" - } - } - } - } - } - } - }, "/address/{address}/key/{key}": { "get": { "tags": [ @@ -2671,7 +2639,7 @@ "name": "fields", "in": "query", "description": "the requested transaction fields, comma sepparated. If none provided, only hash is returned. Possible values are: hash, nonce, sender, receiver, gaslimit, gasprice, receiverusername, data, value", - "schema" : { + "schema": { "type": "string", "default": null } @@ -2680,7 +2648,7 @@ "name": "shard-id", "in": "query", "description": "the shard id to return transactions pool", - "schema" : { + "schema": { "type": "string", "default": null } @@ -2689,7 +2657,7 @@ "name": "by-sender", "in": "query", "description": "the bech32 address of transactions' sender", - "schema" : { + "schema": { "type": "string", "default": null } @@ -2698,7 +2666,7 @@ "name": "last-nonce", "in": "query", "description": "returns the last nonce from pool. This parameter requires by-sender and does not work with fields", - "schema" : { + "schema": { "type": "boolean", "default": false } @@ -2707,7 +2675,7 @@ "name": "nonce-gaps", "in": "query", "description": "returns the nonce gaps from pool. This parameter requires by-sender and does not work with fields", - "schema" : { + "schema": { "type": "boolean", "default": false } @@ -3271,4 +3239,4 @@ } } } -} +} \ No newline at end of file diff --git a/facade/baseFacade.go b/facade/baseFacade.go index 01e04910..525937d7 100644 --- a/facade/baseFacade.go +++ b/facade/baseFacade.go @@ -161,11 +161,6 @@ func (pf *ProxyFacade) GetShardIDForAddress(address string) (uint32, error) { return pf.accountProc.GetShardIDForAddress(address) } -// GetTransactions returns transactions by address -func (pf *ProxyFacade) GetTransactions(address string) ([]data.DatabaseTransaction, error) { - return pf.accountProc.GetTransactions(address) -} - // GetESDTTokenData returns the token data for a given token name func (pf *ProxyFacade) GetESDTTokenData(address string, key string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) { return pf.accountProc.GetESDTTokenData(address, key, options) diff --git a/facade/interface.go b/facade/interface.go index a76d8edc..ac29e844 100644 --- a/facade/interface.go +++ b/facade/interface.go @@ -22,7 +22,6 @@ type AccountProcessor interface { GetAccounts(addresses []string, options common.AccountQueryOptions) (*data.AccountsModel, error) GetShardIDForAddress(address string) (uint32, error) GetValueForKey(address string, key string, options common.AccountQueryOptions) (string, error) - GetTransactions(address string) ([]data.DatabaseTransaction, error) GetAllESDTTokens(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) GetKeyValuePairs(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) GetESDTTokenData(address string, key string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) diff --git a/facade/mock/accountProccessorStub.go b/facade/mock/accountProccessorStub.go index e50e728c..03c6943e 100644 --- a/facade/mock/accountProccessorStub.go +++ b/facade/mock/accountProccessorStub.go @@ -89,11 +89,6 @@ func (aps *AccountProcessorStub) GetShardIDForAddress(address string) (uint32, e return aps.GetShardIDForAddressCalled(address) } -// GetTransactions - -func (aps *AccountProcessorStub) GetTransactions(address string) ([]data.DatabaseTransaction, error) { - return aps.GetTransactionsCalled(address) -} - // GetCodeHash - func (aps *AccountProcessorStub) GetCodeHash(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) { return aps.GetCodeHashCalled(address, options) diff --git a/process/accountProcessor.go b/process/accountProcessor.go index 22465f38..a749a4f0 100644 --- a/process/accountProcessor.go +++ b/process/accountProcessor.go @@ -452,15 +452,6 @@ func (ap *AccountProcessor) GetGuardianData(address string, options common.Accou return nil, WrapObserversError(apiResponse.Error) } -// GetTransactions resolves the request and returns a slice of transaction for the specific address -func (ap *AccountProcessor) GetTransactions(address string) ([]data.DatabaseTransaction, error) { - if _, err := ap.pubKeyConverter.Decode(address); err != nil { - return nil, fmt.Errorf("%w, %v", ErrInvalidAddress, err) - } - - return ap.connector.GetTransactionsByAddress(address) -} - // GetCodeHash returns the code hash for a given address func (ap *AccountProcessor) GetCodeHash(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) { availability := ap.availabilityProvider.AvailabilityForAccountQueryOptions(options) diff --git a/process/accountProcessor_test.go b/process/accountProcessor_test.go index b06959f2..608c0ebf 100644 --- a/process/accountProcessor_test.go +++ b/process/accountProcessor_test.go @@ -286,26 +286,6 @@ func TestAccountProcessor_GetShardIDForAddressShouldError(t *testing.T) { assert.Equal(t, expectedError, err) } -func TestAccountProcessor_GetTransactions(t *testing.T) { - t.Parallel() - - converter, _ := pubkeyConverter.NewBech32PubkeyConverter(32, "erd") - ap, _ := process.NewAccountProcessor( - &mock.ProcessorStub{}, - converter, - &mock.ElasticSearchConnectorMock{}, - ) - - _, err := ap.GetTransactions("invalidAddress") - assert.True(t, errors.Is(err, process.ErrInvalidAddress)) - - _, err = ap.GetTransactions("") - assert.True(t, errors.Is(err, process.ErrInvalidAddress)) - - _, err = ap.GetTransactions("erd1ycega644rvjtgtyd8hfzt6hl5ymaa8ml2nhhs5cv045cz5vxm00q022myr") - assert.Nil(t, err) -} - func TestAccountProcessor_GetESDTsWithRoleGetObserversFails(t *testing.T) { t.Parallel() diff --git a/process/database/elasticSearchConnector.go b/process/database/elasticSearchConnector.go index bc9e1573..0b6cd4c7 100644 --- a/process/database/elasticSearchConnector.go +++ b/process/database/elasticSearchConnector.go @@ -35,16 +35,6 @@ func NewElasticSearchConnector(url, username, password string) (*elasticSearchCo }, nil } -// GetTransactionsByAddress gets transactions TO or FROM the specified address -func (esc *elasticSearchConnector) GetTransactionsByAddress(address string) ([]data.DatabaseTransaction, error) { - decodedBody, err := esc.doSearchRequestTx(address, "transactions", numTopTransactions) - if err != nil { - return nil, err - } - - return convertObjectToTransactions(decodedBody) -} - // GetAtlasBlockByShardIDAndNonce gets from database a block with the specified shardID and nonce func (esc *elasticSearchConnector) GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) { query := blockByNonceAndShardIDQuery(nonce, shardID) diff --git a/process/database/elasticSearchConnector_test.go b/process/database/elasticSearchConnector_test.go index b6d6d991..2b6b1949 100644 --- a/process/database/elasticSearchConnector_test.go +++ b/process/database/elasticSearchConnector_test.go @@ -8,20 +8,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestDatabaseReader(t *testing.T) { - t.Skip("this test queries Elastic Search") - - url := "https://elastic-aws.multiversx.com" - user := "" - password := "" - reader, err := NewElasticSearchConnector(url, user, password) - require.Nil(t, err) - - addr := "erd1ewshdn9yv0wx38xgs5cdhvcq4dz0n7tdlgh8wfj9nxugwmyunnyqpkpzal" - txs, err := reader.GetTransactionsByAddress(addr) - fmt.Println(txs) - require.Nil(t, err) -} func TestDatabaseReader_GetBlockByShardIDAndNonce(t *testing.T) { t.Skip("this test queries Elastic Search") diff --git a/process/interface.go b/process/interface.go index b6762d80..bbfb5932 100644 --- a/process/interface.go +++ b/process/interface.go @@ -31,7 +31,6 @@ type Processor interface { // ExternalStorageConnector defines what a external storage connector should be able to do type ExternalStorageConnector interface { - GetTransactionsByAddress(address string) ([]data.DatabaseTransaction, error) GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) IsInterfaceNil() bool } diff --git a/process/mock/elasticSearchConnectorMock.go b/process/mock/elasticSearchConnectorMock.go index ee174772..b6c97769 100644 --- a/process/mock/elasticSearchConnectorMock.go +++ b/process/mock/elasticSearchConnectorMock.go @@ -5,11 +5,6 @@ import "github.com/multiversx/mx-chain-proxy-go/data" type ElasticSearchConnectorMock struct { } -// GetTransactionsByAddress - -func (escm *ElasticSearchConnectorMock) GetTransactionsByAddress(_ string) ([]data.DatabaseTransaction, error) { - return nil, nil -} - // GetAtlasBlockByShardIDAndNonce - func (escm *ElasticSearchConnectorMock) GetAtlasBlockByShardIDAndNonce(_ uint32, _ uint64) (data.AtlasBlock, error) { return data.AtlasBlock{}, nil diff --git a/process/mock/externalStorageConnectorStub.go b/process/mock/externalStorageConnectorStub.go index 43a5873f..febec410 100644 --- a/process/mock/externalStorageConnectorStub.go +++ b/process/mock/externalStorageConnectorStub.go @@ -3,19 +3,9 @@ package mock import "github.com/multiversx/mx-chain-proxy-go/data" type ExternalStorageConnectorStub struct { - GetTransactionsByAddressCalled func(address string) ([]data.DatabaseTransaction, error) GetAtlasBlockByShardIDAndNonceCalled func(shardID uint32, nonce uint64) (data.AtlasBlock, error) } -// GetTransactionsByAddress - -func (e *ExternalStorageConnectorStub) GetTransactionsByAddress(address string) ([]data.DatabaseTransaction, error) { - if e.GetTransactionsByAddressCalled != nil { - return e.GetTransactionsByAddressCalled(address) - } - - return []data.DatabaseTransaction{{Fee: "0"}}, nil -} - // GetAtlasBlockByShardIDAndNonce - func (e *ExternalStorageConnectorStub) GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) { if e.GetAtlasBlockByShardIDAndNonceCalled != nil { From 39b655cb2d0706a000ce7e38b38355548303ed4d Mon Sep 17 00:00:00 2001 From: danielailie Date: Thu, 1 Aug 2024 15:59:19 +0300 Subject: [PATCH 28/40] Add empty new line at the and of file --- cmd/proxy/config/swagger/openapi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/proxy/config/swagger/openapi.json b/cmd/proxy/config/swagger/openapi.json index f27cc0a1..075ef6bc 100644 --- a/cmd/proxy/config/swagger/openapi.json +++ b/cmd/proxy/config/swagger/openapi.json @@ -3239,4 +3239,4 @@ } } } -} \ No newline at end of file +} From e8a085ae8afdd931476e93bb399ce89bc22fd81e Mon Sep 17 00:00:00 2001 From: ssd04 Date: Thu, 1 Aug 2024 16:54:29 +0300 Subject: [PATCH 29/40] fix swagger esdts roles endpoint --- cmd/proxy/config/swagger/openapi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/proxy/config/swagger/openapi.json b/cmd/proxy/config/swagger/openapi.json index 05c1e5b9..cdcbc189 100644 --- a/cmd/proxy/config/swagger/openapi.json +++ b/cmd/proxy/config/swagger/openapi.json @@ -375,7 +375,7 @@ } } }, - "/address/{address}/esdt/roles": { + "/address/{address}/esdts/roles": { "get": { "tags": [ "address" From d2dea9c81f5591c4664785e6cc4b731cbf85463d Mon Sep 17 00:00:00 2001 From: danielailie Date: Mon, 5 Aug 2024 16:37:39 +0300 Subject: [PATCH 30/40] Remove code that serves endpoint /block-atlas --- README.md | 5 - api/apiHandler.go | 6 - api/groups/baseBlockAtlasGroup.go | 58 ------ api/groups/baseBlockAtlasGroup_test.go | 132 ------------- api/groups/baseBlockGroup_test.go | 6 +- api/groups/interface.go | 5 - api/mock/facadeStub.go | 6 - cmd/proxy/config/apiConfig/v1_0.toml | 5 - cmd/proxy/config/apiConfig/v_next.toml | 5 - cmd/proxy/config/external.toml | 4 - cmd/proxy/config/swagger/openapi.json | 82 +-------- cmd/proxy/main.go | 52 +----- config/config.go | 13 -- data/block.go | 8 - facade/baseFacade.go | 6 - facade/interface.go | 1 - facade/mock/blockProcessorStub.go | 6 - go.mod | 1 - go.sum | 2 - process/accountProcessor.go | 7 +- process/accountProcessor_test.go | 29 +-- process/blockProcessor.go | 13 +- process/blockProcessor_test.go | 115 +++++------- .../disabledElasticSearchConnector.go | 30 --- process/database/elasticSearchConnector.go | 173 ------------------ .../database/elasticSearchConnector_test.go | 24 --- process/interface.go | 6 - process/mock/elasticSearchConnectorMock.go | 16 -- process/mock/externalStorageConnectorStub.go | 21 --- 29 files changed, 62 insertions(+), 775 deletions(-) delete mode 100644 api/groups/baseBlockAtlasGroup.go delete mode 100644 api/groups/baseBlockAtlasGroup_test.go delete mode 100644 cmd/proxy/config/external.toml delete mode 100644 process/database/disabledElasticSearchConnector.go delete mode 100644 process/database/elasticSearchConnector.go delete mode 100644 process/database/elasticSearchConnector_test.go delete mode 100644 process/mock/elasticSearchConnectorMock.go delete mode 100644 process/mock/externalStorageConnectorStub.go diff --git a/README.md b/README.md index 5967add5..9262d6c1 100644 --- a/README.md +++ b/README.md @@ -82,11 +82,6 @@ Please note that `altered-accounts` endpoints will only work if the backing obse - `/v1.0/blocks/by-round/:round` (GET) --> returns all blocks by round -### block-atlas - -- `/v1.0/block-atlas/:shard/:nonce` (GET) --> returns a block by nonce, as required by Block Atlas - - ### hyperblock - `/v1.0/hyperblock/by-nonce/:nonce` (GET) --> returns a hyperblock by nonce, with transactions included diff --git a/api/apiHandler.go b/api/apiHandler.go index 87a275aa..4035f8dc 100644 --- a/api/apiHandler.go +++ b/api/apiHandler.go @@ -49,11 +49,6 @@ func initBaseGroupsWithFacade(facade data.FacadeHandler) (map[string]data.GroupH return nil, err } - blockAtlasGroup, err := groups.NewBlockAtlasGroup(facade) - if err != nil { - return nil, err - } - hyperBlocksGroup, err := groups.NewHyperBlockGroup(facade) if err != nil { return nil, err @@ -110,7 +105,6 @@ func initBaseGroupsWithFacade(facade data.FacadeHandler) (map[string]data.GroupH "/block": blockGroup, "/blocks": blocksGroup, "/internal": internalGroup, - "/block-atlas": blockAtlasGroup, "/hyperblock": hyperBlocksGroup, "/network": networkGroup, "/node": nodeGroup, diff --git a/api/groups/baseBlockAtlasGroup.go b/api/groups/baseBlockAtlasGroup.go deleted file mode 100644 index 6cdd40f0..00000000 --- a/api/groups/baseBlockAtlasGroup.go +++ /dev/null @@ -1,58 +0,0 @@ -package groups - -import ( - "net/http" - - "github.com/gin-gonic/gin" - apiErrors "github.com/multiversx/mx-chain-proxy-go/api/errors" - "github.com/multiversx/mx-chain-proxy-go/api/shared" - "github.com/multiversx/mx-chain-proxy-go/data" -) - -type blockAtlasGroup struct { - facade BlockAtlasFacadeHandler - *baseGroup -} - -// NewBlockAtlasGroup returns a new instance of blockAtlasGroup -func NewBlockAtlasGroup(facadeHandler data.FacadeHandler) (*blockAtlasGroup, error) { - facade, ok := facadeHandler.(BlockAtlasFacadeHandler) - if !ok { - return nil, ErrWrongTypeAssertion - } - - bag := &blockAtlasGroup{ - facade: facade, - baseGroup: &baseGroup{}, - } - - baseRoutesHandlers := []*data.EndpointHandlerData{ - {Path: "/:shard/:nonce", Handler: bag.getBlockByShardIDAndNonceFromElastic, Method: http.MethodGet}, - } - bag.baseGroup.endpoints = baseRoutesHandlers - - return bag, nil -} - -// getBlockByShardIDAndNonceFromElastic returns the block by shardID and nonce -func (group *blockAtlasGroup) getBlockByShardIDAndNonceFromElastic(c *gin.Context) { - shardID, err := shared.FetchShardIDFromRequest(c) - if err != nil { - shared.RespondWith(c, http.StatusBadRequest, nil, apiErrors.ErrCannotParseShardID.Error(), data.ReturnCodeRequestError) - return - } - - nonce, err := shared.FetchNonceFromRequest(c) - if err != nil { - shared.RespondWith(c, http.StatusBadRequest, nil, apiErrors.ErrCannotParseNonce.Error(), data.ReturnCodeRequestError) - return - } - - apiBlock, err := group.facade.GetAtlasBlockByShardIDAndNonce(shardID, nonce) - if err != nil { - shared.RespondWith(c, http.StatusInternalServerError, nil, err.Error(), data.ReturnCodeInternalError) - return - } - - shared.RespondWith(c, http.StatusOK, gin.H{"block": apiBlock}, "", data.ReturnCodeSuccess) -} diff --git a/api/groups/baseBlockAtlasGroup_test.go b/api/groups/baseBlockAtlasGroup_test.go deleted file mode 100644 index efb8c6e9..00000000 --- a/api/groups/baseBlockAtlasGroup_test.go +++ /dev/null @@ -1,132 +0,0 @@ -package groups_test - -import ( - "errors" - "net/http" - "net/http/httptest" - "testing" - - apiErrors "github.com/multiversx/mx-chain-proxy-go/api/errors" - "github.com/multiversx/mx-chain-proxy-go/api/groups" - "github.com/multiversx/mx-chain-proxy-go/api/mock" - "github.com/multiversx/mx-chain-proxy-go/data" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const blockAtlasPath = "/blockatlas" - -type blockResponseData struct { - Block data.AtlasBlock `json:"block"` -} - -type blockResponse struct { - Data blockResponseData `json:"data"` - Error string `json:"error"` - Code string `json:"code"` -} - -func TestNewBlockAtlasGroup_WrongFacadeShouldErr(t *testing.T) { - wrongFacade := &mock.WrongFacade{} - group, err := groups.NewBlockAtlasGroup(wrongFacade) - require.Nil(t, group) - require.Equal(t, groups.ErrWrongTypeAssertion, err) -} - -func TestGetBlockByShardIDAndNonceFromElastic_FailWhenShardParamIsInvalid(t *testing.T) { - t.Parallel() - - facade := &mock.FacadeStub{} - - baseBlockAtlasGroup, err := groups.NewBlockAtlasGroup(facade) - require.NoError(t, err) - ws := startProxyServer(baseBlockAtlasGroup, blockAtlasPath) - - req, _ := http.NewRequest("GET", "/blockatlas/invalid_shard_id/1", nil) - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) - - apiResp := data.GenericAPIResponse{} - loadResponse(resp.Body, &apiResp) - - assert.Equal(t, http.StatusBadRequest, resp.Code) - assert.Empty(t, apiResp.Data) - assert.Equal(t, apiErrors.ErrCannotParseShardID.Error(), apiResp.Error) -} - -func TestGetBlockByShardIDAndNonceFromElastic_FailWhenNonceParamIsInvalid(t *testing.T) { - t.Parallel() - - facade := &mock.FacadeStub{} - baseBlockAtlasGroup, err := groups.NewBlockAtlasGroup(facade) - require.NoError(t, err) - ws := startProxyServer(baseBlockAtlasGroup, blockAtlasPath) - - req, _ := http.NewRequest("GET", "/blockatlas/0/invalid_nonce", nil) - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) - - apiResp := data.GenericAPIResponse{} - loadResponse(resp.Body, &apiResp) - - assert.Equal(t, http.StatusBadRequest, resp.Code) - assert.Empty(t, apiResp.Data) - assert.Equal(t, apiErrors.ErrCannotParseNonce.Error(), apiResp.Error) -} - -func TestGetBlockByShardIDAndNonceFromElastic_FailWhenFacadeGetAccountFails(t *testing.T) { - t.Parallel() - - returnedError := errors.New("i am an error") - facade := &mock.FacadeStub{ - GetBlockByShardIDAndNonceHandler: func(_ uint32, _ uint64) (data.AtlasBlock, error) { - return data.AtlasBlock{}, returnedError - }, - } - baseBlockAtlasGroup, err := groups.NewBlockAtlasGroup(facade) - require.NoError(t, err) - ws := startProxyServer(baseBlockAtlasGroup, blockAtlasPath) - - req, _ := http.NewRequest("GET", "/blockatlas/0/1", nil) - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) - - apiResp := data.GenericAPIResponse{} - loadResponse(resp.Body, &apiResp) - - assert.Equal(t, http.StatusInternalServerError, resp.Code) - assert.Empty(t, apiResp.Data) - assert.Equal(t, returnedError.Error(), apiResp.Error) -} - -func TestGetBlockByShardIDAndNonceFromElastic_ReturnsSuccessfully(t *testing.T) { - t.Parallel() - - nonce := uint64(37) - hash := "hashhh" - facade := &mock.FacadeStub{ - GetBlockByShardIDAndNonceHandler: func(_ uint32, _ uint64) (data.AtlasBlock, error) { - return data.AtlasBlock{ - Nonce: nonce, - Hash: hash, - }, nil - }, - } - - baseBlockAtlasGroup, err := groups.NewBlockAtlasGroup(facade) - require.NoError(t, err) - ws := startProxyServer(baseBlockAtlasGroup, blockAtlasPath) - - req, _ := http.NewRequest("GET", "/blockatlas/0/1", nil) - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) - - apiResp := blockResponse{} - loadResponse(resp.Body, &apiResp) - - assert.Equal(t, http.StatusOK, resp.Code) - assert.Equal(t, apiResp.Data.Block.Nonce, nonce) - assert.Equal(t, apiResp.Data.Block.Hash, hash) - assert.Empty(t, apiResp.Error) - assert.Equal(t, string(data.ReturnCodeSuccess), apiResp.Code) -} diff --git a/api/groups/baseBlockGroup_test.go b/api/groups/baseBlockGroup_test.go index 9e6c17eb..0ab93625 100644 --- a/api/groups/baseBlockGroup_test.go +++ b/api/groups/baseBlockGroup_test.go @@ -18,7 +18,7 @@ import ( "github.com/stretchr/testify/require" ) -const blockPath = "/block" +const blockPath = "/block" func TestNewBlockGroup_WrongFacadeShouldErr(t *testing.T) { wrongFacade := &mock.WrongFacade{} @@ -138,7 +138,7 @@ func TestGetBlockByNonce_ReturnsSuccessfully(t *testing.T) { resp := httptest.NewRecorder() ws.ServeHTTP(resp, req) - apiResp := blockResponse{} + apiResp := data.BlockApiResponse{} loadResponse(resp.Body, &apiResp) assert.Equal(t, http.StatusOK, resp.Code) @@ -258,7 +258,7 @@ func TestGetBlockByHash_ReturnsSuccessfully(t *testing.T) { resp := httptest.NewRecorder() ws.ServeHTTP(resp, req) - apiResp := blockResponse{} + apiResp := data.BlockApiResponse{} loadResponse(resp.Body, &apiResp) assert.Equal(t, http.StatusOK, resp.Code) diff --git a/api/groups/interface.go b/api/groups/interface.go index c97a076b..f5a4e4fd 100644 --- a/api/groups/interface.go +++ b/api/groups/interface.go @@ -49,11 +49,6 @@ type InternalFacadeHandler interface { GetInternalStartOfEpochValidatorsInfo(epoch uint32) (*data.ValidatorsInfoApiResponse, error) } -// BlockAtlasFacadeHandler interface defines methods that can be used from facade context variable -type BlockAtlasFacadeHandler interface { - GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) -} - // HyperBlockFacadeHandler defines the actions needed for fetching the hyperblocks from the nodes type HyperBlockFacadeHandler interface { GetHyperBlockByNonce(nonce uint64, options common.HyperblockQueryOptions) (*data.HyperblockApiResponse, error) diff --git a/api/mock/facadeStub.go b/api/mock/facadeStub.go index 27888b72..66417554 100644 --- a/api/mock/facadeStub.go +++ b/api/mock/facadeStub.go @@ -49,7 +49,6 @@ type FacadeStub struct { GetDirectStakedInfoCalled func() (*data.GenericAPIResponse, error) GetDelegatedInfoCalled func() (*data.GenericAPIResponse, error) GetRatingsConfigCalled func() (*data.GenericAPIResponse, error) - GetBlockByShardIDAndNonceHandler func(shardID uint32, nonce uint64) (data.AtlasBlock, error) GetTransactionByHashAndSenderAddressHandler func(txHash string, sndAddr string, withResults bool) (*transaction.ApiTransactionResult, int, error) GetBlockByHashCalled func(shardID uint32, hash string, options common.BlockQueryOptions) (*data.BlockApiResponse, error) GetBlockByNonceCalled func(shardID uint32, nonce uint64, options common.BlockQueryOptions) (*data.BlockApiResponse, error) @@ -443,11 +442,6 @@ func (f *FacadeStub) GetHeartbeatData() (*data.HeartbeatResponse, error) { return f.GetHeartbeatDataHandler() } -// GetAtlasBlockByShardIDAndNonce - -func (f *FacadeStub) GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) { - return f.GetBlockByShardIDAndNonceHandler(shardID, nonce) -} - // GetBlockByHash - func (f *FacadeStub) GetBlockByHash(shardID uint32, hash string, options common.BlockQueryOptions) (*data.BlockApiResponse, error) { return f.GetBlockByHashCalled(shardID, hash, options) diff --git a/cmd/proxy/config/apiConfig/v1_0.toml b/cmd/proxy/config/apiConfig/v1_0.toml index 6bfd4d85..f90ee4ae 100644 --- a/cmd/proxy/config/apiConfig/v1_0.toml +++ b/cmd/proxy/config/apiConfig/v1_0.toml @@ -115,11 +115,6 @@ Routes = [ { Name = "/by-round/:round", Secured = false, Open = true, RateLimit = 0 }, ] -[APIPackages.block-atlas] -Routes = [ - { Name = "/:shard/:nonce", Secured = false, Open = true, RateLimit = 0 } -] - [APIPackages.proof] Routes = [ { Name = "/root-hash/:roothash/address/:address", Secured = false, Open = false, RateLimit = 0 }, diff --git a/cmd/proxy/config/apiConfig/v_next.toml b/cmd/proxy/config/apiConfig/v_next.toml index 8fdb4dd1..fbb7c733 100644 --- a/cmd/proxy/config/apiConfig/v_next.toml +++ b/cmd/proxy/config/apiConfig/v_next.toml @@ -115,11 +115,6 @@ Routes = [ { Name = "/by-round/:round", Secured = false, Open = true, RateLimit = 0 }, ] -[APIPackages.block-atlas] -Routes = [ - { Name = "/:shard/:nonce", Secured = false, Open = true, RateLimit = 0 } -] - [APIPackages.proof] Routes = [ { Name = "/root-hash/:roothash/address/:address", Secured = false, Open = false, RateLimit = 0 }, diff --git a/cmd/proxy/config/external.toml b/cmd/proxy/config/external.toml deleted file mode 100644 index 9bc54b1a..00000000 --- a/cmd/proxy/config/external.toml +++ /dev/null @@ -1,4 +0,0 @@ -# ElasticSearchConnector defines settings related to ElasticSearch such as login information or URL -[ElasticSearchConnector] - Enabled = false - URL = "" diff --git a/cmd/proxy/config/swagger/openapi.json b/cmd/proxy/config/swagger/openapi.json index 75f33e76..dad65efa 100644 --- a/cmd/proxy/config/swagger/openapi.json +++ b/cmd/proxy/config/swagger/openapi.json @@ -574,86 +574,6 @@ } } }, - "/block-atlas/{shard}/{nonce}": { - "get": { - "tags": [ - "block-atlas" - ], - "summary": "get a block from a specified shard and at a specified nonce", - "parameters": [ - { - "name": "shard", - "in": "path", - "description": "the shard ID to look after", - "required": true, - "schema": { - "type": "integer" - } - }, - { - "name": "nonce", - "in": "path", - "description": "the nonce to look after", - "required": true, - "schema": { - "type": "integer" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenericResponse" - } - } - } - } - } - } - }, - "/block-atlas/{shard}/by-hash/{hash}": { - "get": { - "tags": [ - "block" - ], - "summary": "get a block from a specified shard and with a specified hash", - "parameters": [ - { - "name": "shard", - "in": "path", - "description": "the shard ID to look after", - "required": true, - "schema": { - "type": "integer" - } - }, - { - "name": "hash", - "in": "path", - "description": "the hash to look after", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenericResponse" - } - } - } - } - } - } - }, "/blocks/by-round/{round}": { "get": { "tags": [ @@ -3239,4 +3159,4 @@ } } } -} +} \ No newline at end of file diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index d32470a1..2e1b1af2 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -27,7 +27,6 @@ import ( "github.com/multiversx/mx-chain-proxy-go/observer" "github.com/multiversx/mx-chain-proxy-go/process" "github.com/multiversx/mx-chain-proxy-go/process/cache" - "github.com/multiversx/mx-chain-proxy-go/process/database" processFactory "github.com/multiversx/mx-chain-proxy-go/process/factory" "github.com/multiversx/mx-chain-proxy-go/testing" versionsFactory "github.com/multiversx/mx-chain-proxy-go/versions/factory" @@ -105,13 +104,6 @@ VERSION: Usage: "This represents the path of the walletKey.pem file", Value: "./config/walletKey.pem", } - // externalConfigFile defines a flag for the path to the external toml configuration file - externalConfigFile = cli.StringFlag{ - Name: "config-external", - Usage: "The path for the external configuration file. This TOML file contains" + - " external configurations such as ElasticSearch's URL and login information", - Value: "./config/external.toml", - } // credentialsConfigFile defines a flag for the path to the credentials toml configuration file credentialsConfigFile = cli.StringFlag{ @@ -182,7 +174,6 @@ func main() { app.Usage = "This is the entry point for starting a new Multiversx node proxy" app.Flags = []cli.Flag{ configurationFile, - externalConfigFile, credentialsConfigFile, apiConfigDirectory, profileMode, @@ -271,12 +262,6 @@ func startProxy(ctx *cli.Context) error { } log.Info(fmt.Sprintf("Initialized with main config from: %s", configurationFile)) - externalConfigurationFileName := ctx.GlobalString(externalConfigFile.Name) - externalConfig, err := loadExternalConfig(externalConfigurationFileName) - if err != nil { - return err - } - closableComponents := data.NewClosableComponentsHandler() credentialsConfigurationFileName := ctx.GlobalString(credentialsConfigFile.Name) @@ -288,7 +273,7 @@ func startProxy(ctx *cli.Context) error { statusMetricsProvider := metrics.NewStatusMetrics() shouldStartSwaggerUI := ctx.GlobalBool(startSwaggerUI.Name) - versionsRegistry, err := createVersionsRegistryTestOrProduction(ctx, generalConfig, configurationFileName, externalConfig, statusMetricsProvider, closableComponents) + versionsRegistry, err := createVersionsRegistryTestOrProduction(ctx, generalConfig, configurationFileName, statusMetricsProvider, closableComponents) if err != nil { return err } @@ -318,21 +303,10 @@ func loadMainConfig(filepath string) (*config.Config, error) { return cfg, nil } -func loadExternalConfig(filepath string) (*config.ExternalConfig, error) { - cfg := &config.ExternalConfig{} - err := core.LoadTomlFile(cfg, filepath) - if err != nil { - return nil, err - } - - return cfg, nil -} - func createVersionsRegistryTestOrProduction( ctx *cli.Context, cfg *config.Config, configurationFilePath string, - exCfg *config.ExternalConfig, statusMetricsHandler data.StatusMetricsProvider, closableComponents *data.ClosableComponentsHandler, ) (data.VersionsRegistryHandler, error) { @@ -395,7 +369,6 @@ func createVersionsRegistryTestOrProduction( return createVersionsRegistry( testCfg, configurationFilePath, - exCfg, statusMetricsHandler, ctx.GlobalString(walletKeyPemFile.Name), ctx.GlobalString(apiConfigDirectory.Name), @@ -406,7 +379,6 @@ func createVersionsRegistryTestOrProduction( return createVersionsRegistry( cfg, configurationFilePath, - exCfg, statusMetricsHandler, ctx.GlobalString(walletKeyPemFile.Name), ctx.GlobalString(apiConfigDirectory.Name), @@ -417,7 +389,6 @@ func createVersionsRegistryTestOrProduction( func createVersionsRegistry( cfg *config.Config, configurationFilePath string, - exCfg *config.ExternalConfig, statusMetricsHandler data.StatusMetricsProvider, pemFileLocation string, apiConfigDirectoryPath string, @@ -471,12 +442,7 @@ func createVersionsRegistry( } bp.StartNodesSyncStateChecks() - connector, err := createElasticSearchConnector(exCfg) - if err != nil { - return nil, err - } - - accntProc, err := process.NewAccountProcessor(bp, pubKeyConverter, connector) + accntProc, err := process.NewAccountProcessor(bp, pubKeyConverter) if err != nil { return nil, err } @@ -534,7 +500,7 @@ func createVersionsRegistry( valStatsProc.StartCacheUpdate() nodeStatusProc.StartCacheUpdate() - blockProc, err := process.NewBlockProcessor(connector, bp) + blockProc, err := process.NewBlockProcessor(bp) if err != nil { return nil, err } @@ -590,18 +556,6 @@ func createVersionsRegistry( return versionsFactory.CreateVersionsRegistry(facadeArgs, apiConfigParser) } -func createElasticSearchConnector(exCfg *config.ExternalConfig) (process.ExternalStorageConnector, error) { - if !exCfg.ElasticSearchConnector.Enabled { - return database.NewDisabledElasticSearchConnector(), nil - } - - return database.NewElasticSearchConnector( - exCfg.ElasticSearchConnector.URL, - exCfg.ElasticSearchConnector.Username, - exCfg.ElasticSearchConnector.Password, - ) -} - func getShardCoordinator(cfg *config.Config) (common.Coordinator, error) { maxShardID := uint32(0) for _, obs := range cfg.Observers { diff --git a/config/config.go b/config/config.go index b5d23613..5cd581b4 100644 --- a/config/config.go +++ b/config/config.go @@ -52,16 +52,3 @@ type CredentialsConfig struct { Credentials []data.Credential Hasher TypeConfig } - -// ExternalConfig will hold the configurations for external tools, such as Explorer or Elastic Search -type ExternalConfig struct { - ElasticSearchConnector ElasticSearchConfig -} - -// ElasticSearchConfig will hold the configuration for the elastic search -type ElasticSearchConfig struct { - Enabled bool - URL string - Username string - Password string -} diff --git a/data/block.go b/data/block.go index 1c213a26..ac70eb0c 100644 --- a/data/block.go +++ b/data/block.go @@ -5,14 +5,6 @@ import ( "github.com/multiversx/mx-chain-core-go/data/api" ) -// AtlasBlock is a block, as required by BlockAtlas -// Will be removed when using the "hyperblock" route in BlockAtlas as well. -type AtlasBlock struct { - Nonce uint64 `form:"nonce" json:"nonce"` - Hash string `form:"hash" json:"hash"` - Transactions []DatabaseTransaction `form:"transactions" json:"transactions"` -} - // BlockApiResponse is a response holding a block type BlockApiResponse struct { Data BlockApiResponsePayload `json:"data"` diff --git a/facade/baseFacade.go b/facade/baseFacade.go index 525937d7..3dd96691 100644 --- a/facade/baseFacade.go +++ b/facade/baseFacade.go @@ -17,7 +17,6 @@ var _ groups.ActionsFacadeHandler = (*ProxyFacade)(nil) var _ groups.AccountsFacadeHandler = (*ProxyFacade)(nil) var _ groups.BlockFacadeHandler = (*ProxyFacade)(nil) var _ groups.BlocksFacadeHandler = (*ProxyFacade)(nil) -var _ groups.BlockAtlasFacadeHandler = (*ProxyFacade)(nil) var _ groups.HyperBlockFacadeHandler = (*ProxyFacade)(nil) var _ groups.NetworkFacadeHandler = (*ProxyFacade)(nil) var _ groups.NodeFacadeHandler = (*ProxyFacade)(nil) @@ -416,11 +415,6 @@ func (epf *ProxyFacade) AuctionList() ([]*data.AuctionListValidatorAPIResponse, return auctionList.AuctionListValidators, nil } -// GetAtlasBlockByShardIDAndNonce returns block by shardID and nonce in a BlockAtlas-friendly-format -func (pf *ProxyFacade) GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) { - return pf.blockProc.GetAtlasBlockByShardIDAndNonce(shardID, nonce) -} - // GetAddressConverter returns the address converter func (pf *ProxyFacade) GetAddressConverter() (core.PubkeyConverter, error) { return pf.pubKeyConverter, nil diff --git a/facade/interface.go b/facade/interface.go index ac29e844..9ed6c19c 100644 --- a/facade/interface.go +++ b/facade/interface.go @@ -107,7 +107,6 @@ type BlocksProcessor interface { // BlockProcessor defines what a block processor should do type BlockProcessor interface { - GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) GetBlockByHash(shardID uint32, hash string, options common.BlockQueryOptions) (*data.BlockApiResponse, error) GetBlockByNonce(shardID uint32, nonce uint64, options common.BlockQueryOptions) (*data.BlockApiResponse, error) GetHyperBlockByHash(hash string, options common.HyperblockQueryOptions) (*data.HyperblockApiResponse, error) diff --git a/facade/mock/blockProcessorStub.go b/facade/mock/blockProcessorStub.go index 08b09f2b..87d8702a 100644 --- a/facade/mock/blockProcessorStub.go +++ b/facade/mock/blockProcessorStub.go @@ -7,7 +7,6 @@ import ( // BlockProcessorStub - type BlockProcessorStub struct { - GetBlockByShardIDAndNonceCalled func(shardID uint32, nonce uint64) (data.AtlasBlock, error) GetBlockByHashCalled func(shardID uint32, hash string, options common.BlockQueryOptions) (*data.BlockApiResponse, error) GetBlockByNonceCalled func(shardID uint32, nonce uint64, options common.BlockQueryOptions) (*data.BlockApiResponse, error) GetHyperBlockByHashCalled func(hash string, options common.HyperblockQueryOptions) (*data.HyperblockApiResponse, error) @@ -27,11 +26,6 @@ func (bps *BlockProcessorStub) GetBlockByNonce(shardID uint32, nonce uint64, opt return bps.GetBlockByNonceCalled(shardID, nonce, options) } -// GetAtlasBlockByShardIDAndNonce - -func (bps *BlockProcessorStub) GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) { - return bps.GetBlockByShardIDAndNonceCalled(shardID, nonce) -} - // GetHyperBlockByHash - func (bps *BlockProcessorStub) GetHyperBlockByHash(hash string, options common.HyperblockQueryOptions) (*data.HyperblockApiResponse, error) { if bps.GetHyperBlockByHashCalled != nil { diff --git a/go.mod b/go.mod index fbb90512..1bd7ba8f 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/multiversx/mx-chain-proxy-go go 1.20 require ( - github.com/elastic/go-elasticsearch/v7 v7.12.0 github.com/gin-contrib/cors v1.4.0 github.com/gin-contrib/pprof v1.4.0 github.com/gin-contrib/static v0.0.1 diff --git a/go.sum b/go.sum index 3ff90b70..ea5cead0 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,6 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeC github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ= github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI= -github.com/elastic/go-elasticsearch/v7 v7.12.0 h1:j4tvcMrZJLp39L2NYvBb7f+lHKPqPHSL3nvB8+/DV+s= -github.com/elastic/go-elasticsearch/v7 v7.12.0/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= diff --git a/process/accountProcessor.go b/process/accountProcessor.go index a749a4f0..3846b22e 100644 --- a/process/accountProcessor.go +++ b/process/accountProcessor.go @@ -18,28 +18,23 @@ const addressPath = "/address/" // AccountProcessor is able to process account requests type AccountProcessor struct { - connector ExternalStorageConnector proc Processor pubKeyConverter core.PubkeyConverter availabilityProvider availabilityCommon.AvailabilityProvider } // NewAccountProcessor creates a new instance of AccountProcessor -func NewAccountProcessor(proc Processor, pubKeyConverter core.PubkeyConverter, connector ExternalStorageConnector) (*AccountProcessor, error) { +func NewAccountProcessor(proc Processor, pubKeyConverter core.PubkeyConverter) (*AccountProcessor, error) { if check.IfNil(proc) { return nil, ErrNilCoreProcessor } if check.IfNil(pubKeyConverter) { return nil, ErrNilPubKeyConverter } - if check.IfNil(connector) { - return nil, ErrNilDatabaseConnector - } return &AccountProcessor{ proc: proc, pubKeyConverter: pubKeyConverter, - connector: connector, availabilityProvider: availabilityCommon.AvailabilityProvider{}, }, nil } diff --git a/process/accountProcessor_test.go b/process/accountProcessor_test.go index 608c0ebf..312b2fc2 100644 --- a/process/accountProcessor_test.go +++ b/process/accountProcessor_test.go @@ -12,7 +12,6 @@ import ( "github.com/multiversx/mx-chain-proxy-go/common" "github.com/multiversx/mx-chain-proxy-go/data" "github.com/multiversx/mx-chain-proxy-go/process" - "github.com/multiversx/mx-chain-proxy-go/process/database" "github.com/multiversx/mx-chain-proxy-go/process/mock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -21,7 +20,7 @@ import ( func TestNewAccountProcessor_NilCoreProcessorShouldErr(t *testing.T) { t.Parallel() - ap, err := process.NewAccountProcessor(nil, &mock.PubKeyConverterMock{}, database.NewDisabledElasticSearchConnector()) + ap, err := process.NewAccountProcessor(nil, &mock.PubKeyConverterMock{}) assert.Nil(t, ap) assert.Equal(t, process.ErrNilCoreProcessor, err) @@ -30,7 +29,7 @@ func TestNewAccountProcessor_NilCoreProcessorShouldErr(t *testing.T) { func TestNewAccountProcessor_NilPubKeyConverterShouldErr(t *testing.T) { t.Parallel() - ap, err := process.NewAccountProcessor(&mock.ProcessorStub{}, nil, database.NewDisabledElasticSearchConnector()) + ap, err := process.NewAccountProcessor(&mock.ProcessorStub{}, nil) assert.Nil(t, ap) assert.Equal(t, process.ErrNilPubKeyConverter, err) @@ -39,7 +38,7 @@ func TestNewAccountProcessor_NilPubKeyConverterShouldErr(t *testing.T) { func TestNewAccountProcessor_WithCoreProcessorShouldWork(t *testing.T) { t.Parallel() - ap, err := process.NewAccountProcessor(&mock.ProcessorStub{}, &mock.PubKeyConverterMock{}, database.NewDisabledElasticSearchConnector()) + ap, err := process.NewAccountProcessor(&mock.ProcessorStub{}, &mock.PubKeyConverterMock{}) assert.NotNil(t, ap) assert.Nil(t, err) @@ -50,7 +49,7 @@ func TestNewAccountProcessor_WithCoreProcessorShouldWork(t *testing.T) { func TestAccountProcessor_GetAccountInvalidHexAddressShouldErr(t *testing.T) { t.Parallel() - ap, _ := process.NewAccountProcessor(&mock.ProcessorStub{}, &mock.PubKeyConverterMock{}, database.NewDisabledElasticSearchConnector()) + ap, _ := process.NewAccountProcessor(&mock.ProcessorStub{}, &mock.PubKeyConverterMock{}) accnt, err := ap.GetAccount("invalid hex number", common.AccountQueryOptions{}) assert.Nil(t, accnt) @@ -69,7 +68,6 @@ func TestAccountProcessor_GetAccountComputeShardIdFailsShouldErr(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) address := "DEADBEEF" accnt, err := ap.GetAccount(address, common.AccountQueryOptions{}) @@ -92,7 +90,6 @@ func TestAccountProcessor_GetAccountGetObserversFailsShouldErr(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) address := "DEADBEEF" accnt, err := ap.GetAccount(address, common.AccountQueryOptions{}) @@ -121,7 +118,6 @@ func TestAccountProcessor_GetAccountSendingFailsOnAllObserversShouldErr(t *testi }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) address := "DEADBEEF" accnt, err := ap.GetAccount(address, common.AccountQueryOptions{}) @@ -162,7 +158,6 @@ func TestAccountProcessor_GetAccountSendingFailsOnFirstObserverShouldStillSend(t }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) address := "DEADBEEF" accountModel, err := ap.GetAccount(address, common.AccountQueryOptions{}) @@ -192,7 +187,6 @@ func TestAccountProcessor_GetValueForAKeyShouldWork(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) key := "key" @@ -221,7 +215,6 @@ func TestAccountProcessor_GetValueForAKeyShouldError(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) key := "key" @@ -255,7 +248,6 @@ func TestAccountProcessor_GetShardIForAddressShouldWork(t *testing.T) { }, }, bech32C, - database.NewDisabledElasticSearchConnector(), ) shardID, err := ap.GetShardIDForAddress(addressShard1) @@ -278,7 +270,6 @@ func TestAccountProcessor_GetShardIDForAddressShouldError(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) shardID, err := ap.GetShardIDForAddress("aaaa") @@ -297,7 +288,6 @@ func TestAccountProcessor_GetESDTsWithRoleGetObserversFails(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - &mock.ElasticSearchConnectorMock{}, ) result, err := ap.GetESDTsWithRole("address", "role", common.AccountQueryOptions{}) @@ -325,7 +315,6 @@ func TestAccountProcessor_GetESDTsWithRoleApiCallFails(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - &mock.ElasticSearchConnectorMock{}, ) result, err := ap.GetESDTsWithRole("address", "role", common.AccountQueryOptions{}) @@ -354,7 +343,6 @@ func TestAccountProcessor_GetESDTsWithRoleShouldWork(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) address := "DEADBEEF" response, err := ap.GetESDTsWithRole(address, "role", common.AccountQueryOptions{}) @@ -373,7 +361,6 @@ func TestAccountProcessor_GetESDTsRolesGetObserversFails(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - &mock.ElasticSearchConnectorMock{}, ) result, err := ap.GetESDTsRoles("address", common.AccountQueryOptions{}) @@ -401,7 +388,6 @@ func TestAccountProcessor_GetESDTsRolesApiCallFails(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - &mock.ElasticSearchConnectorMock{}, ) result, err := ap.GetESDTsRoles("address", common.AccountQueryOptions{}) @@ -430,7 +416,6 @@ func TestAccountProcessor_GetESDTsRolesShouldWork(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) address := "DEADBEEF" response, err := ap.GetESDTsRoles(address, common.AccountQueryOptions{}) @@ -458,7 +443,6 @@ func TestAccountProcessor_GetCodeHash(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - database.NewDisabledElasticSearchConnector(), ) address := "DEADBEEF" response, err := ap.GetCodeHash(address, common.AccountQueryOptions{}) @@ -477,7 +461,6 @@ func TestAccountProcessor_IsDataTrieMigrated(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - &mock.ElasticSearchConnectorMock{}, ) result, err := ap.IsDataTrieMigrated("address", common.AccountQueryOptions{}) @@ -505,7 +488,6 @@ func TestAccountProcessor_IsDataTrieMigrated(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - &mock.ElasticSearchConnectorMock{}, ) result, err := ap.IsDataTrieMigrated("DEADBEEF", common.AccountQueryOptions{}) @@ -535,7 +517,6 @@ func TestAccountProcessor_IsDataTrieMigrated(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - &mock.ElasticSearchConnectorMock{}, ) result, err := ap.IsDataTrieMigrated("DEADBEEF", common.AccountQueryOptions{}) @@ -582,7 +563,6 @@ func TestAccountProcessor_GetAccounts(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - &mock.ElasticSearchConnectorMock{}, ) result, err := ap.GetAccounts([]string{"aabb", "bbaa"}, common.AccountQueryOptions{}) @@ -628,7 +608,6 @@ func TestAccountProcessor_GetAccounts(t *testing.T) { }, }, &mock.PubKeyConverterMock{}, - &mock.ElasticSearchConnectorMock{}, ) result, err := ap.GetAccounts([]string{"aabb", "bbaa"}, common.AccountQueryOptions{}) diff --git a/process/blockProcessor.go b/process/blockProcessor.go index 63388e37..63dfaedd 100644 --- a/process/blockProcessor.go +++ b/process/blockProcessor.go @@ -38,29 +38,20 @@ const ( // BlockProcessor handles blocks retrieving type BlockProcessor struct { proc Processor - dbReader ExternalStorageConnector } // NewBlockProcessor will create a new block processor -func NewBlockProcessor(dbReader ExternalStorageConnector, proc Processor) (*BlockProcessor, error) { - if check.IfNil(dbReader) { - return nil, ErrNilDatabaseConnector - } +func NewBlockProcessor(proc Processor) (*BlockProcessor, error) { if check.IfNil(proc) { return nil, ErrNilCoreProcessor } return &BlockProcessor{ - dbReader: dbReader, proc: proc, }, nil } -// GetAtlasBlockByShardIDAndNonce return the block byte shardID and nonce -func (bp *BlockProcessor) GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) { - return bp.dbReader.GetAtlasBlockByShardIDAndNonce(shardID, nonce) -} - + // GetBlockByHash will return the block based on its hash func (bp *BlockProcessor) GetBlockByHash(shardID uint32, hash string, options common.BlockQueryOptions) (*data.BlockApiResponse, error) { observers, err := bp.getObserversOrFullHistoryNodes(shardID) diff --git a/process/blockProcessor_test.go b/process/blockProcessor_test.go index 146deef1..2451f03b 100644 --- a/process/blockProcessor_test.go +++ b/process/blockProcessor_test.go @@ -18,18 +18,10 @@ import ( "github.com/stretchr/testify/require" ) -func TestNewBlockProcessor_NilExternalStorageConnectorShouldErr(t *testing.T) { - t.Parallel() - - bp, err := process.NewBlockProcessor(nil, &mock.ProcessorStub{}) - require.Nil(t, bp) - require.Equal(t, process.ErrNilDatabaseConnector, err) -} - func TestNewBlockProcessor_NilProcessorShouldErr(t *testing.T) { t.Parallel() - bp, err := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, nil) + bp, err := process.NewBlockProcessor(nil) require.Nil(t, bp) require.Equal(t, process.ErrNilCoreProcessor, err) } @@ -37,22 +29,11 @@ func TestNewBlockProcessor_NilProcessorShouldErr(t *testing.T) { func TestNewBlockProcessor_ShouldWork(t *testing.T) { t.Parallel() - bp, err := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, &mock.ProcessorStub{}) + bp, err := process.NewBlockProcessor(&mock.ProcessorStub{}) require.NotNil(t, bp) require.NoError(t, err) } -func TestBlockProcessor_GetAtlasBlockByShardIDAndNonce(t *testing.T) { - t.Parallel() - - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, &mock.ProcessorStub{}) - require.NotNil(t, bp) - - res, err := bp.GetAtlasBlockByShardIDAndNonce(0, 1) - require.NoError(t, err) - require.NotNil(t, res) -} - func TestBlockProcessor_GetBlockByHashShouldGetFullHistoryNodes(t *testing.T) { t.Parallel() @@ -70,7 +51,7 @@ func TestBlockProcessor_GetBlockByHashShouldGetFullHistoryNodes(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetBlockByHash(0, "hash", common.BlockQueryOptions{}) @@ -96,7 +77,7 @@ func TestBlockProcessor_GetBlockByHashShouldGetObservers(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetBlockByHash(0, "hash", common.BlockQueryOptions{}) @@ -118,7 +99,7 @@ func TestBlockProcessor_GetBlockByHashNoFullNodesOrObserversShouldErr(t *testing }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetBlockByHash(0, "hash", common.BlockQueryOptions{}) @@ -139,7 +120,7 @@ func TestBlockProcessor_GetBlockByHashCallGetFailsShouldErr(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetBlockByHash(0, "hash", common.BlockQueryOptions{}) @@ -162,7 +143,7 @@ func TestBlockProcessor_GetBlockByHashShouldWork(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetBlockByHash(0, "hash", common.BlockQueryOptions{}) @@ -190,7 +171,7 @@ func TestBlockProcessor_GetBlockByHashShouldWorkAndIncludeAlsoTxs(t *testing.T) }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetBlockByHash(0, "hash", common.BlockQueryOptions{WithTransactions: true}) @@ -219,7 +200,7 @@ func TestBlockProcessor_GetBlockByNonceShouldGetFullHistoryNodes(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetBlockByNonce(0, 0, common.BlockQueryOptions{}) @@ -245,7 +226,7 @@ func TestBlockProcessor_GetBlockByNonceShouldGetObservers(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetBlockByNonce(0, 1, common.BlockQueryOptions{}) @@ -267,7 +248,7 @@ func TestBlockProcessor_GetBlockByNonceNoFullNodesOrObserversShouldErr(t *testin }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetBlockByNonce(0, 1, common.BlockQueryOptions{}) @@ -288,7 +269,7 @@ func TestBlockProcessor_GetBlockByNonceCallGetFailsShouldErr(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetBlockByNonce(0, 0, common.BlockQueryOptions{}) @@ -311,7 +292,7 @@ func TestBlockProcessor_GetBlockByNonceShouldWork(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetBlockByNonce(0, nonce, common.BlockQueryOptions{}) @@ -339,7 +320,7 @@ func TestBlockProcessor_GetBlockByNonceShouldWorkAndIncludeAlsoTxs(t *testing.T) }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetBlockByNonce(0, 3, common.BlockQueryOptions{WithTransactions: true}) @@ -378,7 +359,7 @@ func TestBlockProcessor_GetHyperBlock(t *testing.T) { }, } - processor, err := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + processor, err := process.NewBlockProcessor(proc) require.Nil(t, err) require.NotNil(t, processor) @@ -410,7 +391,7 @@ func TestBlockProcessor_GetInternalBlockByNonceInvalidOutputFormat_ShouldFail(t }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) blk, err := bp.GetInternalBlockByNonce(0, 0, 2) @@ -435,7 +416,7 @@ func TestBlockProcessor_GetInternalBlockByNonceShouldGetFullHistoryNodes(t *test }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetInternalBlockByNonce(0, 0, common.Internal) @@ -461,7 +442,7 @@ func TestBlockProcessor_GetInternalBlockByNonceShouldGetObservers(t *testing.T) }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetInternalBlockByNonce(0, 1, common.Internal) @@ -483,7 +464,7 @@ func TestBlockProcessor_GetInternalBlockByNonceNoFullNodesOrObserversShouldErr(t }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalBlockByNonce(0, 1, common.Internal) @@ -504,7 +485,7 @@ func TestBlockProcessor_GetInternalBlockByNonceCallGetFailsShouldErr(t *testing. }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalBlockByNonce(0, 0, common.Internal) @@ -533,7 +514,7 @@ func TestBlockProcessor_GetInternalBlockByNonceShouldWork(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalBlockByNonce(0, nonce, common.Internal) @@ -558,7 +539,7 @@ func TestBlockProcessor_GetInternalBlockByHashInvalidOutputFormat_ShouldFail(t * }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) blk, err := bp.GetInternalBlockByHash(0, "aaaa", 2) @@ -583,7 +564,7 @@ func TestBlockProcessor_GetInternalBlockByHashShouldGetFullHistoryNodes(t *testi }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetInternalBlockByHash(0, "aaaa", common.Internal) @@ -609,7 +590,7 @@ func TestBlockProcessor_GetInternalBlockByHashShouldGetObservers(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetInternalBlockByHash(0, "aaaa", common.Internal) @@ -631,7 +612,7 @@ func TestBlockProcessor_GetInternalBlockByHashNoFullNodesOrObserversShouldErr(t }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalBlockByHash(0, "aaaa", common.Internal) @@ -652,7 +633,7 @@ func TestBlockProcessor_GetInternalBlockByHashCallGetFailsShouldErr(t *testing.T }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalBlockByHash(0, "aaaa", common.Internal) @@ -680,7 +661,7 @@ func TestBlockProcessor_GetInternalBlockByHashShouldWork(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalBlockByHash(0, "aaaa", common.Internal) @@ -705,7 +686,7 @@ func TestBlockProcessor_GetInternalMiniBlockByHashInvalidOutputFormat_ShouldFail }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) blk, err := bp.GetInternalMiniBlockByHash(0, "aaaa", 1, 2) @@ -730,7 +711,7 @@ func TestBlockProcessor_GetInternalMiniBlockByHashShouldGetFullHistoryNodes(t *t }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetInternalMiniBlockByHash(0, "aaaa", 1, common.Internal) @@ -756,7 +737,7 @@ func TestBlockProcessor_GetInternalMiniBlockByHashShouldGetObservers(t *testing. }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetInternalMiniBlockByHash(0, "aaaa", 1, common.Internal) @@ -778,7 +759,7 @@ func TestBlockProcessor_GetInternalMiniBlockByHashNoFullNodesOrObserversShouldEr }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalMiniBlockByHash(0, "aaaa", 1, common.Internal) @@ -799,7 +780,7 @@ func TestBlockProcessor_GetInternalMiniBlockByHashCallGetFailsShouldErr(t *testi }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalMiniBlockByHash(0, "aaaa", 1, common.Internal) @@ -827,7 +808,7 @@ func TestBlockProcessor_GetInternalMiniBlockByHashShouldWork(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalMiniBlockByHash(0, "aaaa", 1, common.Internal) @@ -852,7 +833,7 @@ func TestBlockProcessor_GetInternalStartOfEpochMetaBlockInvalidOutputFormat_Shou }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) blk, err := bp.GetInternalStartOfEpochMetaBlock(0, 2) @@ -877,7 +858,7 @@ func TestBlockProcessor_GetInternalStartOfEpochMetaBlockShouldGetFullHistoryNode }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetInternalStartOfEpochMetaBlock(0, common.Internal) @@ -903,7 +884,7 @@ func TestBlockProcessor_GetInternalStartOfEpochMetaBlockShouldGetObservers(t *te }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) _, _ = bp.GetInternalStartOfEpochMetaBlock(0, common.Internal) @@ -925,7 +906,7 @@ func TestBlockProcessor_GetInternalStartOfEpochMetaBlockNoFullNodesOrObserversSh }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalStartOfEpochMetaBlock(0, common.Internal) @@ -947,7 +928,7 @@ func TestBlockProcessor_GetInternalStartOfEpochMetaBlockCallGetFailsShouldErr(t }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalStartOfEpochMetaBlock(0, common.Internal) @@ -975,7 +956,7 @@ func TestBlockProcessor_GetInternalStartOfEpochMetaBlockShouldWork(t *testing.T) }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalStartOfEpochMetaBlock(1, common.Internal) @@ -1005,7 +986,7 @@ func TestBlockProcessor_GetAlteredAccountsByNonce(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) res, err := bp.GetAlteredAccountsByNonce(requestedShardID, 4, common.GetAlteredAccountsForBlockOptions{}) require.Equal(t, expectedErr, err) require.Nil(t, res) @@ -1034,7 +1015,7 @@ func TestBlockProcessor_GetAlteredAccountsByNonce(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) res, err := bp.GetAlteredAccountsByNonce(requestedShardID, 4, common.GetAlteredAccountsForBlockOptions{}) require.Equal(t, 2, callGetEndpointCt) require.True(t, errors.Is(err, process.ErrSendingRequest)) @@ -1063,7 +1044,7 @@ func TestBlockProcessor_GetAlteredAccountsByNonce(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) res, err := bp.GetAlteredAccountsByNonce(requestedShardID, 4, common.GetAlteredAccountsForBlockOptions{}) require.Nil(t, err) require.Equal(t, &data.AlteredAccountsApiResponse{ @@ -1092,7 +1073,7 @@ func TestBlockProcessor_GetAlteredAccountsByHash(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) res, err := bp.GetAlteredAccountsByHash(requestedShardID, "hash", common.GetAlteredAccountsForBlockOptions{}) require.Equal(t, expectedErr, err) require.Nil(t, res) @@ -1121,7 +1102,7 @@ func TestBlockProcessor_GetAlteredAccountsByHash(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) res, err := bp.GetAlteredAccountsByHash(requestedShardID, "hash", common.GetAlteredAccountsForBlockOptions{}) require.Equal(t, 2, callGetEndpointCt) require.True(t, errors.Is(err, process.ErrSendingRequest)) @@ -1150,7 +1131,7 @@ func TestBlockProcessor_GetAlteredAccountsByHash(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) res, err := bp.GetAlteredAccountsByHash(requestedShardID, "hash", common.GetAlteredAccountsForBlockOptions{}) require.Nil(t, err) require.Equal(t, &data.AlteredAccountsApiResponse{ @@ -1245,7 +1226,7 @@ func TestBlockProcessor_GetHyperBlockByNonceWithAlteredAccounts(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) res, err := bp.GetHyperBlockByNonce(4, common.HyperblockQueryOptions{WithAlteredAccounts: true}) require.Nil(t, err) @@ -1362,7 +1343,7 @@ func TestBlockProcessor_GetHyperBlockByHashWithAlteredAccounts(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) res, err := bp.GetHyperBlockByHash("abcdef", common.HyperblockQueryOptions{WithAlteredAccounts: true}) require.Nil(t, err) @@ -1419,7 +1400,7 @@ func TestBlockProcessor_GetInternalStartOfEpochValidatorsInfo(t *testing.T) { }, } - bp, _ := process.NewBlockProcessor(&mock.ExternalStorageConnectorStub{}, proc) + bp, _ := process.NewBlockProcessor(proc) require.NotNil(t, bp) res, err := bp.GetInternalStartOfEpochValidatorsInfo(1) diff --git a/process/database/disabledElasticSearchConnector.go b/process/database/disabledElasticSearchConnector.go deleted file mode 100644 index 3f82d070..00000000 --- a/process/database/disabledElasticSearchConnector.go +++ /dev/null @@ -1,30 +0,0 @@ -package database - -import ( - "errors" - - "github.com/multiversx/mx-chain-proxy-go/data" -) - -var errDatabaseConnectionIsDisabled = errors.New("database connection is disabled") - -type disabledElasticSearchConnector struct{} - -func NewDisabledElasticSearchConnector() *disabledElasticSearchConnector { - return new(disabledElasticSearchConnector) -} - -// GetTransactionsByAddress will return error because database connection is disabled -func (desc *disabledElasticSearchConnector) GetTransactionsByAddress(_ string) ([]data.DatabaseTransaction, error) { - return nil, errDatabaseConnectionIsDisabled -} - -// GetAtlasBlockByShardIDAndNonce will return error because database connection is disabled -func (desc *disabledElasticSearchConnector) GetAtlasBlockByShardIDAndNonce(_ uint32, _ uint64) (data.AtlasBlock, error) { - return data.AtlasBlock{}, errDatabaseConnectionIsDisabled -} - -// IsInterfaceNil - -func (desc *disabledElasticSearchConnector) IsInterfaceNil() bool { - return desc == nil -} diff --git a/process/database/elasticSearchConnector.go b/process/database/elasticSearchConnector.go deleted file mode 100644 index 0b6cd4c7..00000000 --- a/process/database/elasticSearchConnector.go +++ /dev/null @@ -1,173 +0,0 @@ -package database - -import ( - "encoding/json" - "fmt" - - "github.com/elastic/go-elasticsearch/v7" - "github.com/multiversx/mx-chain-proxy-go/data" -) - -const ( - numTopTransactions = 20 - numTransactionFromAMiniblock = 100 -) - -type elasticSearchConnector struct { - client *elasticsearch.Client -} - -// NewElasticSearchConnector create a new elastic search database reader object -func NewElasticSearchConnector(url, username, password string) (*elasticSearchConnector, error) { - cfg := elasticsearch.Config{ - Addresses: []string{url}, - Username: username, - Password: password, - } - - client, err := elasticsearch.NewClient(cfg) - if err != nil { - return nil, fmt.Errorf("cannot create database reader %w", err) - } - - return &elasticSearchConnector{ - client: client, - }, nil -} - -// GetAtlasBlockByShardIDAndNonce gets from database a block with the specified shardID and nonce -func (esc *elasticSearchConnector) GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) { - query := blockByNonceAndShardIDQuery(nonce, shardID) - decodedBody, err := esc.doSearchRequest(query, "blocks", 1) - if err != nil { - return data.AtlasBlock{}, err - } - - metaBlock, metaBlockHash, err := convertObjectToBlock(decodedBody) - if err != nil { - return data.AtlasBlock{}, err - } - - txs, err := esc.getTxsByMiniblockHashes(metaBlock.MiniBlocksHashes) - if err != nil { - return data.AtlasBlock{}, err - } - - transactions, err := esc.getTxsByNotarizedBlockHashes(metaBlock.NotarizedBlocksHashes) - if err != nil { - return data.AtlasBlock{}, err - } - - txs = append(txs, transactions...) - - return data.AtlasBlock{ - Nonce: metaBlock.Nonce, - Hash: metaBlockHash, - Transactions: txs, - }, nil -} - -func (esc *elasticSearchConnector) getTxsByNotarizedBlockHashes(hashes []string) ([]data.DatabaseTransaction, error) { - txs := make([]data.DatabaseTransaction, 0) - for _, hash := range hashes { - query := blockByHashQuery(hash) - decodedBody, err := esc.doSearchRequest(query, "blocks", 1) - if err != nil { - return nil, err - } - - shardBlock, _, err := convertObjectToBlock(decodedBody) - if err != nil { - return nil, err - } - - transactions, err := esc.getTxsByMiniblockHashes(shardBlock.MiniBlocksHashes) - if err != nil { - return nil, err - } - - txs = append(txs, transactions...) - } - return txs, nil -} - -func (esc *elasticSearchConnector) getTxsByMiniblockHashes(hashes []string) ([]data.DatabaseTransaction, error) { - txs := make([]data.DatabaseTransaction, 0) - for _, hash := range hashes { - query := txsByMiniblockHashQuery(hash) - decodedBody, err := esc.doSearchRequest(query, "transactions", numTransactionFromAMiniblock) - if err != nil { - return nil, err - } - - transactions, err := convertObjectToTransactions(decodedBody) - if err != nil { - return nil, err - } - - txs = append(txs, transactions...) - } - return txs, nil -} - -func (esc *elasticSearchConnector) doSearchRequest(query object, index string, size int) (object, error) { - buff, err := encodeQuery(query) - if err != nil { - return nil, err - } - - res, err := esc.client.Search( - esc.client.Search.WithIndex(index), - esc.client.Search.WithSize(size), - esc.client.Search.WithBody(&buff), - ) - if err != nil { - return nil, fmt.Errorf("cannot get data from database: %w", err) - } - - defer func() { - _ = res.Body.Close() - }() - if res.IsError() { - return nil, fmt.Errorf("cannot get data from database: %v", res) - } - - var decodedBody map[string]interface{} - if err := json.NewDecoder(res.Body).Decode(&decodedBody); err != nil { - return nil, err - } - - return decodedBody, nil -} - -func (esc *elasticSearchConnector) doSearchRequestTx(address string, index string, size int) (object, error) { - query := fmt.Sprintf("sender:%s OR receiver:%s", address, address) - res, err := esc.client.Search( - esc.client.Search.WithIndex(index), - esc.client.Search.WithSize(size), - esc.client.Search.WithQuery(query), - esc.client.Search.WithSort("timestamp:desc"), - ) - if err != nil { - return nil, fmt.Errorf("cannot get data from database: %w", err) - } - - defer func() { - _ = res.Body.Close() - }() - if res.IsError() { - return nil, fmt.Errorf("cannot get data from database: %v", res) - } - - var decodedBody map[string]interface{} - if err := json.NewDecoder(res.Body).Decode(&decodedBody); err != nil { - return nil, err - } - - return decodedBody, nil -} - -// IsInterfaceNil returns true if there is no value under the interface -func (esc *elasticSearchConnector) IsInterfaceNil() bool { - return esc == nil -} diff --git a/process/database/elasticSearchConnector_test.go b/process/database/elasticSearchConnector_test.go deleted file mode 100644 index 2b6b1949..00000000 --- a/process/database/elasticSearchConnector_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package database - -import ( - "fmt" - "testing" - - "github.com/multiversx/mx-chain-core-go/core" - "github.com/stretchr/testify/require" -) - - -func TestDatabaseReader_GetBlockByShardIDAndNonce(t *testing.T) { - t.Skip("this test queries Elastic Search") - - url := "https://elastic-aws.multiversx.com" - user := "" - password := "" - reader, err := NewElasticSearchConnector(url, user, password) - require.Nil(t, err) - - block, err := reader.GetAtlasBlockByShardIDAndNonce(core.MetachainShardId, 7720) - fmt.Println(block) - require.Nil(t, err) -} diff --git a/process/interface.go b/process/interface.go index bbfb5932..eb7e558c 100644 --- a/process/interface.go +++ b/process/interface.go @@ -29,12 +29,6 @@ type Processor interface { IsInterfaceNil() bool } -// ExternalStorageConnector defines what a external storage connector should be able to do -type ExternalStorageConnector interface { - GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) - IsInterfaceNil() bool -} - // PrivateKeysLoaderHandler defines what a component which handles loading of the private keys file should do type PrivateKeysLoaderHandler interface { PrivateKeysByShard() (map[uint32][]crypto.PrivateKey, error) diff --git a/process/mock/elasticSearchConnectorMock.go b/process/mock/elasticSearchConnectorMock.go deleted file mode 100644 index b6c97769..00000000 --- a/process/mock/elasticSearchConnectorMock.go +++ /dev/null @@ -1,16 +0,0 @@ -package mock - -import "github.com/multiversx/mx-chain-proxy-go/data" - -type ElasticSearchConnectorMock struct { -} - -// GetAtlasBlockByShardIDAndNonce - -func (escm *ElasticSearchConnectorMock) GetAtlasBlockByShardIDAndNonce(_ uint32, _ uint64) (data.AtlasBlock, error) { - return data.AtlasBlock{}, nil -} - -// IsInterfaceNil - -func (escm *ElasticSearchConnectorMock) IsInterfaceNil() bool { - return escm == nil -} diff --git a/process/mock/externalStorageConnectorStub.go b/process/mock/externalStorageConnectorStub.go deleted file mode 100644 index febec410..00000000 --- a/process/mock/externalStorageConnectorStub.go +++ /dev/null @@ -1,21 +0,0 @@ -package mock - -import "github.com/multiversx/mx-chain-proxy-go/data" - -type ExternalStorageConnectorStub struct { - GetAtlasBlockByShardIDAndNonceCalled func(shardID uint32, nonce uint64) (data.AtlasBlock, error) -} - -// GetAtlasBlockByShardIDAndNonce - -func (e *ExternalStorageConnectorStub) GetAtlasBlockByShardIDAndNonce(shardID uint32, nonce uint64) (data.AtlasBlock, error) { - if e.GetAtlasBlockByShardIDAndNonceCalled != nil { - return e.GetAtlasBlockByShardIDAndNonceCalled(shardID, nonce) - } - - return data.AtlasBlock{Hash: "hash"}, nil -} - -// IsInterfaceNil - -func (e *ExternalStorageConnectorStub) IsInterfaceNil() bool { - return e == nil -} From 980d416d0e211592c1828a7d8c280036a0513b68 Mon Sep 17 00:00:00 2001 From: danielailie Date: Mon, 5 Aug 2024 16:51:21 +0300 Subject: [PATCH 31/40] Remove whitespaces --- api/groups/baseBlockGroup_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/groups/baseBlockGroup_test.go b/api/groups/baseBlockGroup_test.go index 0ab93625..9d0e9b67 100644 --- a/api/groups/baseBlockGroup_test.go +++ b/api/groups/baseBlockGroup_test.go @@ -18,7 +18,7 @@ import ( "github.com/stretchr/testify/require" ) -const blockPath = "/block" +const blockPath = "/block" func TestNewBlockGroup_WrongFacadeShouldErr(t *testing.T) { wrongFacade := &mock.WrongFacade{} From 7865fa548de65ba56025afb52147c3cf1c1de915 Mon Sep 17 00:00:00 2001 From: Daniel Drasovean Date: Fri, 9 Aug 2024 14:12:39 +0300 Subject: [PATCH 32/40] Replaced 'hash' with 'nonce' in get-by-nonce description --- cmd/proxy/config/swagger/openapi.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/proxy/config/swagger/openapi.json b/cmd/proxy/config/swagger/openapi.json index dad65efa..8d3b7497 100644 --- a/cmd/proxy/config/swagger/openapi.json +++ b/cmd/proxy/config/swagger/openapi.json @@ -624,7 +624,7 @@ { "name": "nonce", "in": "path", - "description": "the hash to look after", + "description": "the nonce to look after", "required": true, "schema": { "type": "integer" @@ -655,7 +655,7 @@ { "name": "nonce", "in": "path", - "description": "the hash to look after", + "description": "the nonce to look after", "required": true, "schema": { "type": "integer" @@ -3159,4 +3159,4 @@ } } } -} \ No newline at end of file +} From b06b627f11f70944c1c06f3b151f8dd8cf78332b Mon Sep 17 00:00:00 2001 From: Iuga Mihai <50499646+miiu96@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:58:41 +0300 Subject: [PATCH 33/40] Fix get transaction endpoint (#456) * fix get transaction endpoint * empty scr list * fix rcv address * pending scr check * unit tests * fix * remove folder * fix * fixes after merge * fixes after review --- api/errors/errors.go | 3 + data/transaction.go | 12 ++ process/testdata/transactionWithScrs.json | 206 ++++++++++++++++++++++ process/transactionProcessor.go | 172 ++++++++++++++++-- process/transactionProcessor_test.go | 59 ++++++- 5 files changed, 437 insertions(+), 15 deletions(-) create mode 100644 process/testdata/transactionWithScrs.json diff --git a/api/errors/errors.go b/api/errors/errors.go index d3499a73..5f45ff38 100644 --- a/api/errors/errors.go +++ b/api/errors/errors.go @@ -98,6 +98,9 @@ var ErrInvalidReceiverAddress = errors.New("invalid hex receiver address provide // ErrTransactionNotFound signals that a transaction was not found var ErrTransactionNotFound = errors.New("transaction not found") +// ErrSCRsNoFound signals that smart contract results were not found +var ErrSCRsNoFound = errors.New("smart contract results not found") + // ErrTransactionsNotFoundInPool signals that no transaction was not found in pool var ErrTransactionsNotFoundInPool = errors.New("transactions not found in pool") diff --git a/data/transaction.go b/data/transaction.go index 9173a883..e283e468 100644 --- a/data/transaction.go +++ b/data/transaction.go @@ -43,6 +43,18 @@ type GetTransactionResponse struct { Code string `json:"code"` } +// GetSCRsResponseData follows the format of the data field of get smart contract results response +type GetSCRsResponseData struct { + SCRs []*transaction.ApiSmartContractResult `json:"scrs"` +} + +// GetSCRsResponse defines a response from the node holding the smart contract results +type GetSCRsResponse struct { + Data GetSCRsResponseData `json:"data"` + Error string `json:"error"` + Code string `json:"code"` +} + // transactionWrapper is a wrapper over a normal transaction in order to implement the interface needed in mx-chain-go // for computing gas cost for a transaction type transactionWrapper struct { diff --git a/process/testdata/transactionWithScrs.json b/process/testdata/transactionWithScrs.json new file mode 100644 index 00000000..4551425d --- /dev/null +++ b/process/testdata/transactionWithScrs.json @@ -0,0 +1,206 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "70ddb98dca6fd7cf9abdffdc61d8b7cd5faa76ee090304135a8704996f4aafb7", + "nonce": 1, + "round": 23, + "epoch": 1, + "value": "10000000000000000", + "receiver": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "sender": "erd1l6xt0rqlyzw56a3k8xwwshq2dcjwy3q9cppucvqsmdyw8r98dz3sae0kxl", + "gasPrice": 1000000000, + "gasLimit": 100000000, + "gasUsed": 100000000, + "data": "aXNzdWU=", + "signature": "64756d6d79", + "sourceShard": 1, + "destinationShard": 1, + "blockNonce": 23, + "blockHash": "e0d6fc125d63ce24694bdc6c16ec49f9354eb4298eb2ab02eab86ea16c0b7fef", + "notarizedAtSourceInMetaNonce": 25, + "NotarizedAtSourceInMetaHash": "c48e6170b51619173e2d30d223c9be23c148eca52f55d6a9f4164e76e47b9e65", + "notarizedAtDestinationInMetaNonce": 25, + "notarizedAtDestinationInMetaHash": "c48e6170b51619173e2d30d223c9be23c148eca52f55d6a9f4164e76e47b9e65", + "miniblockType": "TxBlock", + "miniblockHash": "6712ac7ec8504f46a74ca7b346bab4669ae21b68a2c153f772c96bbace614354", + "hyperblockNonce": 25, + "hyperblockHash": "c48e6170b51619173e2d30d223c9be23c148eca52f55d6a9f4164e76e47b9e65", + "timestamp": 1722930888, + "smartContractResults": [ + { + "hash": "7059ea78e7e0fc194f159c848b76276fe50d0673eb8f053113dde9bfb320f354", + "nonce": 0, + "value": 10000000000000000, + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "sender": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "data": "issue@54455354@54455354@@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4d696e74@66616c7365@63616e4275726e@66616c7365@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565@24cc3c6b7d5bcc3733ca038eb5685fb49b86a7079042d8e075265a72c2cb0d50@70ddb98dca6fd7cf9abdffdc61d8b7cd5faa76ee090304135a8704996f4aafb7@4159b0", + "prevTxHash": "70ddb98dca6fd7cf9abdffdc61d8b7cd5faa76ee090304135a8704996f4aafb7", + "originalTxHash": "70ddb98dca6fd7cf9abdffdc61d8b7cd5faa76ee090304135a8704996f4aafb7", + "gasLimit": 98349849, + "gasPrice": 1000000000, + "callType": 1, + "originalSender": "erd1l6xt0rqlyzw56a3k8xwwshq2dcjwy3q9cppucvqsmdyw8r98dz3sae0kxl", + "logs": { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "events": [ + { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "identifier": "signalError", + "topics": [ + "AAAAAAAAAAAFANiFt9JZ6zTaAZPrwKDvH/5/YRzNaKM=", + "Y2FsbFZhbHVlIG5vdCBlcXVhbHMgd2l0aCBiYXNlSXNzdWluZ0Nvc3Q=" + ], + "data": "QDA0QDYzNjE2YzZjNTY2MTZjNzU2NTIwNmU2Zjc0MjA2NTcxNzU2MTZjNzMyMDc3Njk3NDY4MjA2MjYxNzM2NTQ5NzM3Mzc1Njk2ZTY3NDM2ZjczNzRAYWM5NDdlNDM5Mjg5MzI4NDI2MzExMWNhMTk1MzFkZjY0ZWRkMzBhYzdiYWU0MmUyMmU2OTY4N2JjYTE5MzcwNEAyNGNjM2M2YjdkNWJjYzM3MzNjYTAzOGViNTY4NWZiNDliODZhNzA3OTA0MmQ4ZTA3NTI2NWE3MmMyY2IwZDUwQDcwZGRiOThkY2E2ZmQ3Y2Y5YWJkZmZkYzYxZDhiN2NkNWZhYTc2ZWUwOTAzMDQxMzVhODcwNDk5NmY0YWFmYjdAMDA=", + "additionalData": [ + "QDA0QDYzNjE2YzZjNTY2MTZjNzU2NTIwNmU2Zjc0MjA2NTcxNzU2MTZjNzMyMDc3Njk3NDY4MjA2MjYxNzM2NTQ5NzM3Mzc1Njk2ZTY3NDM2ZjczNzRAYWM5NDdlNDM5Mjg5MzI4NDI2MzExMWNhMTk1MzFkZjY0ZWRkMzBhYzdiYWU0MmUyMmU2OTY4N2JjYTE5MzcwNEAyNGNjM2M2YjdkNWJjYzM3MzNjYTAzOGViNTY4NWZiNDliODZhNzA3OTA0MmQ4ZTA3NTI2NWE3MmMyY2IwZDUwQDcwZGRiOThkY2E2ZmQ3Y2Y5YWJkZmZkYzYxZDhiN2NkNWZhYTc2ZWUwOTAzMDQxMzVhODcwNDk5NmY0YWFmYjdAMDA=" + ] + } + ] + }, + "operation": "transfer", + "function": "issue" + }, + { + "hash": "818b468a55536bb3e38afd754da17fb5f1c739726cccc938a8b94077d50f22c5", + "nonce": 1, + "value": 30999900000000, + "receiver": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "sender": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "data": "@6f6b", + "prevTxHash": "280d36aae1061f3d31550872e09afa9485ea1d58cb0def0732369d4631707439", + "originalTxHash": "70ddb98dca6fd7cf9abdffdc61d8b7cd5faa76ee090304135a8704996f4aafb7", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer", + "isRefund": true + }, + { + "hash": "280d36aae1061f3d31550872e09afa9485ea1d58cb0def0732369d4631707439", + "nonce": 0, + "value": 10000000000000000, + "receiver": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "data": "@04@63616c6c56616c7565206e6f7420657175616c732077697468206261736549737375696e67436f7374@ac947e4392893284263111ca19531df64edd30ac7bae42e22e69687bca193704@24cc3c6b7d5bcc3733ca038eb5685fb49b86a7079042d8e075265a72c2cb0d50@70ddb98dca6fd7cf9abdffdc61d8b7cd5faa76ee090304135a8704996f4aafb7@00", + "prevTxHash": "7059ea78e7e0fc194f159c848b76276fe50d0673eb8f053113dde9bfb320f354", + "originalTxHash": "70ddb98dca6fd7cf9abdffdc61d8b7cd5faa76ee090304135a8704996f4aafb7", + "gasLimit": 4282800, + "gasPrice": 1000000000, + "callType": 2, + "returnMessage": "callValue not equals with baseIssuingCost", + "originalSender": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "logs": { + "address": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "events": [ + { + "address": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "identifier": "completedTxEvent", + "topics": [ + "cFnqeOfg/BlPFZyEi3Ynb+UNBnPrjwUxE93pv7Mg81Q=" + ], + "data": null, + "additionalData": null + } + ] + }, + "operation": "transfer" + } + ], + "logs": { + "address": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "events": [ + { + "address": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "identifier": "transferValueOnly", + "topics": [ + "I4byb8EAAA==", + "AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAC//8=" + ], + "data": "QXN5bmNDYWxs", + "additionalData": [ + "QXN5bmNDYWxs", + "aXNzdWU=", + "VEVTVA==", + "VEVTVA==", + "", + "", + "Y2FuRnJlZXpl", + "dHJ1ZQ==", + "Y2FuV2lwZQ==", + "dHJ1ZQ==", + "Y2FuUGF1c2U=", + "dHJ1ZQ==", + "Y2FuTWludA==", + "ZmFsc2U=", + "Y2FuQnVybg==", + "ZmFsc2U=", + "Y2FuQ2hhbmdlT3duZXI=", + "dHJ1ZQ==", + "Y2FuVXBncmFkZQ==", + "dHJ1ZQ==", + "Y2FuQWRkU3BlY2lhbFJvbGVz", + "dHJ1ZQ==" + ] + }, + { + "address": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "identifier": "writeLog", + "topics": [ + "/oy3jB8gnU12Njmc6FwKbiTiRAXAQ8wwENtI44ynaKM=" + ], + "data": "QDZmNmI=", + "additionalData": [ + "QDZmNmI=" + ] + } + ] + }, + "status": "success", + "operation": "transfer", + "function": "issue", + "initiallyPaidFee": "1056925000000000", + "fee": "1056925000000000", + "chainID": "chain", + "version": 2, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "280d36aae1061f3d31550872e09afa9485ea1d58cb0def0732369d4631707439", + "nonce": 0, + "round": 26, + "epoch": 1, + "value": "10000000000000000", + "receiver": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "gasPrice": 1000000000, + "gasLimit": 4282800, + "gasUsed": 476000, + "data": "QDA0QDYzNjE2YzZjNTY2MTZjNzU2NTIwNmU2Zjc0MjA2NTcxNzU2MTZjNzMyMDc3Njk3NDY4MjA2MjYxNzM2NTQ5NzM3Mzc1Njk2ZTY3NDM2ZjczNzRAYWM5NDdlNDM5Mjg5MzI4NDI2MzExMWNhMTk1MzFkZjY0ZWRkMzBhYzdiYWU0MmUyMmU2OTY4N2JjYTE5MzcwNEAyNGNjM2M2YjdkNWJjYzM3MzNjYTAzOGViNTY4NWZiNDliODZhNzA3OTA0MmQ4ZTA3NTI2NWE3MmMyY2IwZDUwQDcwZGRiOThkY2E2ZmQ3Y2Y5YWJkZmZkYzYxZDhiN2NkNWZhYTc2ZWUwOTAzMDQxMzVhODcwNDk5NmY0YWFmYjdAMDA=", + "previousTransactionHash": "7059ea78e7e0fc194f159c848b76276fe50d0673eb8f053113dde9bfb320f354", + "originalTransactionHash": "70ddb98dca6fd7cf9abdffdc61d8b7cd5faa76ee090304135a8704996f4aafb7", + "returnMessage": "callValue not equals with baseIssuingCost", + "originalSender": "erd1qqqqqqqqqqqqqpgqmzzm05jeav6d5qvna0q2pmcllelkz8xddz3syjszx5", + "sourceShard": 4294967295, + "destinationShard": 1, + "blockNonce": 26, + "blockHash": "3d69e4b55225947cfe1b1aeb467868b5ce14e84538f0360761629eb931a19989", + "notarizedAtSourceInMetaNonce": 25, + "NotarizedAtSourceInMetaHash": "c48e6170b51619173e2d30d223c9be23c148eca52f55d6a9f4164e76e47b9e65", + "miniblockType": "SmartContractResultBlock", + "miniblockHash": "20419d6c4e5091a6802f8c954291b24cf94c744d784961361169218831ef565e", + "timestamp": 1722930906, + "status": "pending", + "operation": "transfer", + "fee": "0", + "callType": "asynchronousCallBack", + "options": 0 + } + ] +} + diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 9d55ee1a..1fb7d985 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -30,8 +30,12 @@ const TransactionSimulatePath = "/transaction/simulate" // MultipleTransactionsPath defines the multiple transactions send path of the node const MultipleTransactionsPath = "/transaction/send-multiple" +// SCRsByTxHash defines smart contract results by transaction hash path of the node +const SCRsByTxHash = "/transaction/scrs-by-tx-hash/" + const ( withResultsParam = "?withResults=true" + scrHashParam = "?scrHash=%s" checkSignatureFalse = "?checkSignature=false" bySenderParam = "&by-sender=" fieldsParam = "?fields=" @@ -65,6 +69,11 @@ type erdTransaction struct { Version uint32 `json:"version"` } +type tupleHashWasFetched struct { + hash string + fetched bool +} + // TransactionProcessor is able to process transaction requests type TransactionProcessor struct { proc Processor @@ -451,6 +460,20 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } + allLogs, allScrs, err := tp.gatherAllLogsAndScrs(tx) + if err != nil { + log.Warn("error in TransactionProcessor.computeTransactionStatus", "error", err) + return &data.ProcessStatusResponse{ + Status: string(data.TxStatusUnknown), + } + } + + if hasPendingSCR(allScrs) { + return &data.ProcessStatusResponse{ + Status: string(transaction.TxStatusPending), + } + } + txLogsOnFirstLevel := []*transaction.ApiLogs{tx.Logs} failed, reason := checkIfFailed(txLogsOnFirstLevel) if failed { @@ -460,14 +483,6 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } - allLogs, allScrs, err := tp.gatherAllLogsAndScrs(tx) - if err != nil { - log.Warn("error in TransactionProcessor.computeTransactionStatus", "error", err) - return &data.ProcessStatusResponse{ - Status: string(data.TxStatusUnknown), - } - } - allLogs, err = tp.addMissingLogsOnProcessingExceptions(tx, allLogs, allScrs) if err != nil { log.Warn("error in TransactionProcessor.computeTransactionStatus on addMissingLogsOnProcessingExceptions call", "error", err) @@ -497,7 +512,8 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } - if checkIfCompleted(allLogs) { + isUnsigned := string(transaction.TxTypeUnsigned) == tx.Type + if checkIfCompleted(allLogs) || isUnsigned { return &data.ProcessStatusResponse{ Status: string(transaction.TxStatusSuccess), } @@ -508,6 +524,16 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } +func hasPendingSCR(scrs []*transaction.ApiTransactionResult) bool { + for _, scr := range scrs { + if scr.Status == transaction.TxStatusPending { + return true + } + } + + return false +} + func checkIfFailedOnReturnMessage(allScrs []*transaction.ApiTransactionResult, tx *transaction.ApiTransactionResult) bool { hasReturnMessageWithZeroValue := len(tx.ReturnMessage) > 0 && isZeroValue(tx.Value) if hasReturnMessageWithZeroValue && !isRefundScr(tx.ReturnMessage) { @@ -700,6 +726,7 @@ func (tp *TransactionProcessor) gatherAllLogsAndScrs(tx *transaction.ApiTransact func (tp *TransactionProcessor) getTxFromObservers(txHash string, reqType requestType, withResults bool) (*transaction.ApiTransactionResult, error) { observersShardIDs := tp.proc.GetShardIDs() + shardIDWasFetch := make(map[uint32]*tupleHashWasFetched) for _, observerShardID := range observersShardIDs { nodesInShard, err := tp.getNodesInShard(observerShardID, reqType) if err != nil { @@ -726,6 +753,10 @@ func (tp *TransactionProcessor) getTxFromObservers(txHash string, reqType reques "sender address", getTxResponse.Data.Transaction.Sender, "error", err.Error()) } + shardIDWasFetch[sndShardID] = &tupleHashWasFetched{ + hash: getTxResponse.Data.Transaction.Hash, + fetched: false, + } rcvShardID, err := tp.getShardByAddress(getTxResponse.Data.Transaction.Receiver) if err != nil { @@ -733,6 +764,10 @@ func (tp *TransactionProcessor) getTxFromObservers(txHash string, reqType reques "receiver address", getTxResponse.Data.Transaction.Receiver, "error", err.Error()) } + shardIDWasFetch[rcvShardID] = &tupleHashWasFetched{ + hash: getTxResponse.Data.Transaction.Hash, + fetched: false, + } if isRelayedTxV3(getTxResponse.Data.Transaction) { return tp.mergeSCRLogsFromInnerReceivers(&getTxResponse.Data.Transaction, withResults), nil @@ -742,24 +777,52 @@ func (tp *TransactionProcessor) getTxFromObservers(txHash string, reqType reques observerIsInDestShard := rcvShardID == observerShardID if isIntraShard { - return &getTxResponse.Data.Transaction, nil + shardIDWasFetch[sndShardID].fetched = true + if len(getTxResponse.Data.Transaction.SmartContractResults) == 0 { + return &getTxResponse.Data.Transaction, nil + } + + tp.extraShardFromSCRs(getTxResponse.Data.Transaction.SmartContractResults, shardIDWasFetch) } if observerIsInDestShard { // need to get transaction from source shard and merge scResults // if withEvents is true - return tp.alterTxWithScResultsFromSourceIfNeeded(txHash, &getTxResponse.Data.Transaction, withResults), nil + txFromSource := tp.alterTxWithScResultsFromSourceIfNeeded(txHash, &getTxResponse.Data.Transaction, withResults, shardIDWasFetch) + + tp.extraShardFromSCRs(txFromSource.SmartContractResults, shardIDWasFetch) + + err = tp.fetchSCRSBasedOnShardMap(txFromSource, shardIDWasFetch) + if err != nil { + return nil, err + } + + return txFromSource, nil } // get transaction from observer that is in destination shard txFromDstShard, ok := tp.getTxFromDestShard(txHash, rcvShardID, withResults) if ok { + tp.extraShardFromSCRs(txFromDstShard.SmartContractResults, shardIDWasFetch) + alteredTxFromDest := tp.mergeScResultsFromSourceAndDestIfNeeded(&getTxResponse.Data.Transaction, txFromDstShard, withResults) + + err = tp.fetchSCRSBasedOnShardMap(alteredTxFromDest, shardIDWasFetch) + if err != nil { + return nil, err + } + return alteredTxFromDest, nil } // return transaction from observer from source shard // if did not get ok responses from observers from destination shard + + err = tp.fetchSCRSBasedOnShardMap(&getTxResponse.Data.Transaction, shardIDWasFetch) + if err != nil { + return nil, err + } + return &getTxResponse.Data.Transaction, nil } @@ -825,7 +888,86 @@ func (tp *TransactionProcessor) groupTxsByReceiverShard(tx *transaction.ApiTrans return txsByReceiverShardMap } -func (tp *TransactionProcessor) alterTxWithScResultsFromSourceIfNeeded(txHash string, tx *transaction.ApiTransactionResult, withResults bool) *transaction.ApiTransactionResult { +func (tp *TransactionProcessor) fetchSCRSBasedOnShardMap(tx *transaction.ApiTransactionResult, shardIDWasFetch map[uint32]*tupleHashWasFetched) error { + for shardID, info := range shardIDWasFetch { + scrs, err := tp.fetchSCRs(tx.Hash, info.hash, shardID) + if err != nil { + return err + } + + scResults := append(tx.SmartContractResults, scrs...) + scResultsNew := tp.getScResultsUnion(scResults) + + tx.SmartContractResults = scResultsNew + info.fetched = true + } + + return nil +} + +func (tp *TransactionProcessor) fetchSCRs(txHash, scrHash string, shardID uint32) ([]*transaction.ApiSmartContractResult, error) { + observers, err := tp.getNodesInShard(shardID, requestTypeFullHistoryNodes) + if err != nil { + return nil, err + } + + apiPath := SCRsByTxHash + txHash + fmt.Sprintf(scrHashParam, scrHash) + for _, observer := range observers { + getTxResponseDst := &data.GetSCRsResponse{} + respCode, errG := tp.proc.CallGetRestEndPoint(observer.Address, apiPath, getTxResponseDst) + if errG != nil { + log.Trace("cannot get smart contract results", "address", observer.Address, "error", errG) + continue + } + + if respCode != http.StatusOK { + continue + } + + return getTxResponseDst.Data.SCRs, nil + } + + return []*transaction.ApiSmartContractResult{}, nil + +} + +func (tp *TransactionProcessor) extraShardFromSCRs(scrs []*transaction.ApiSmartContractResult, shardIDWasFetch map[uint32]*tupleHashWasFetched) { + for _, scr := range scrs { + sndShardID, err := tp.getShardByAddress(scr.SndAddr) + if err != nil { + log.Warn("cannot compute shard ID from sender address", + "sender address", scr.SndAddr, + "error", err.Error()) + continue + } + + _, found := shardIDWasFetch[sndShardID] + if !found { + shardIDWasFetch[sndShardID] = &tupleHashWasFetched{ + hash: scr.Hash, + fetched: false, + } + } + + rcvShardID, err := tp.getShardByAddress(scr.RcvAddr) + if err != nil { + log.Warn("cannot compute shard ID from receiver address", + "receiver address", scr.RcvAddr, + "error", err.Error()) + continue + } + + _, found = shardIDWasFetch[rcvShardID] + if !found { + shardIDWasFetch[rcvShardID] = &tupleHashWasFetched{ + hash: scr.Hash, + fetched: false, + } + } + } +} + +func (tp *TransactionProcessor) alterTxWithScResultsFromSourceIfNeeded(txHash string, tx *transaction.ApiTransactionResult, withResults bool, shardIDWasFetch map[uint32]*tupleHashWasFetched) *transaction.ApiTransactionResult { if !withResults || len(tx.SmartContractResults) == 0 { return tx } @@ -842,6 +984,12 @@ func (tp *TransactionProcessor) alterTxWithScResultsFromSourceIfNeeded(txHash st } alteredTxFromDest := tp.mergeScResultsFromSourceAndDestIfNeeded(&getTxResponse.Data.Transaction, tx, withResults) + + shardIDWasFetch[tx.SourceShard] = &tupleHashWasFetched{ + hash: getTxResponse.Data.Transaction.Hash, + fetched: true, + } + return alteredTxFromDest } diff --git a/process/transactionProcessor_test.go b/process/transactionProcessor_test.go index 350f7de6..2e6b5096 100644 --- a/process/transactionProcessor_test.go +++ b/process/transactionProcessor_test.go @@ -650,7 +650,10 @@ func TestTransactionProcessor_GetTransactionStatusCrossShardTransaction(t *testi }, nil }, CallGetRestEndPointCalled: func(address string, path string, value interface{}) (i int, err error) { - responseGetTx := value.(*data.GetTransactionResponse) + responseGetTx, ok := value.(*data.GetTransactionResponse) + if !ok { + return http.StatusOK, nil + } responseGetTx.Data.Transaction = transaction.ApiTransactionResult{ Receiver: sndrShard1, @@ -718,7 +721,10 @@ func TestTransactionProcessor_GetTransactionStatusCrossShardTransactionDestinati return http.StatusBadRequest, nil } - responseGetTx := value.(*data.GetTransactionResponse) + responseGetTx, ok := value.(*data.GetTransactionResponse) + if !ok { + return http.StatusOK, nil + } responseGetTx.Data.Transaction = transaction.ApiTransactionResult{ Receiver: sndrShard1, @@ -1255,7 +1261,11 @@ func TestTransactionProcessor_GetTransactionWithEventsFirstFromDstShardAndAfterS return nil, nil }, CallGetRestEndPointCalled: func(address string, path string, value interface{}) (i int, err error) { - responseGetTx := value.(*data.GetTransactionResponse) + responseGetTx, ok := value.(*data.GetTransactionResponse) + if !ok { + return http.StatusOK, nil + } + if strings.Contains(path, scHash1) { responseGetTx.Data.Transaction.Hash = scHash1 return http.StatusOK, nil @@ -2183,6 +2193,49 @@ func TestTransactionProcessor_GetProcessedTransactionStatus(t *testing.T) { assert.Equal(t, string(transaction.TxStatusPending), status.Status) // not a move balance tx with missing finish markers } +func TestTransactionProcessor_GetProcessedStatusIntraShardTxWithPendingSCR(t *testing.T) { + txWithSCRs := loadJsonIntoTxAndScrs(t, "./testdata/transactionWithScrs.json") + + processorStub := &mock.ProcessorStub{ + GetShardIDsCalled: func() []uint32 { + return []uint32{0} // force everything intra-shard for test setup simplicity + }, + ComputeShardIdCalled: func(addressBuff []byte) (uint32, error) { + return 0, nil + }, + GetObserversCalled: func(shardId uint32, dataAvailability data.ObserverDataAvailabilityType) ([]*data.NodeData, error) { + return []*data.NodeData{ + { + Address: "test", + ShardId: 0, + }, + }, nil + }, + CallGetRestEndPointCalled: func(address string, path string, value interface{}) (int, error) { + valueC, ok := value.(*data.GetTransactionResponse) + if !ok { + return http.StatusOK, nil + } + valueC.Data.Transaction = *txWithSCRs.SCRs[0] + + return http.StatusOK, nil + }, + } + tp, _ := process.NewTransactionProcessor( + processorStub, + testPubkeyConverter, + hasher, + marshalizer, + funcNewTxCostHandler, + logsMerger, + false, + ) + + status := tp.ComputeTransactionStatus(txWithSCRs.Transaction, true) + require.Equal(t, string(transaction.TxStatusPending), status.Status) + +} + func TestCheckIfFailed(t *testing.T) { t.Parallel() From c9cc5f59969b47d17f7d219f7b450f00a1c8719f Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 4 Sep 2024 12:29:26 +0300 Subject: [PATCH 34/40] configurable number of shards --- cmd/proxy/config/config.toml | 3 + cmd/proxy/main.go | 21 +------ config/config.go | 1 + observer/baseNodeProvider.go | 37 +++++++----- observer/baseNodeProvider_test.go | 65 ++++++++++++++++++--- observer/circularQueueNodesProvider.go | 7 ++- observer/circularQueueNodesProvider_test.go | 19 +++--- observer/errors.go | 3 + observer/nodesProviderFactory.go | 20 +++++-- observer/simpleNodesProvider.go | 7 ++- observer/simpleNodesProvider_test.go | 14 ++--- observer/testdata/config.toml | 33 +++++++---- 12 files changed, 157 insertions(+), 73 deletions(-) diff --git a/cmd/proxy/config/config.toml b/cmd/proxy/config/config.toml index 9cf47be2..3072af75 100644 --- a/cmd/proxy/config/config.toml +++ b/cmd/proxy/config/config.toml @@ -39,6 +39,9 @@ # With this flag disabled, /transaction/pool route will return an error AllowEntireTxPoolFetch = false + # NumberOfShards represents the total number of shards from the network (excluding metachain) + NumberOfShards = 3 + [AddressPubkeyConverter] #Length specifies the length in bytes of an address Length = 32 diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 2e1b1af2..a51261dd 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -328,6 +328,7 @@ func createVersionsRegistryTestOrProduction( ValStatsCacheValidityDurationSec: 60, EconomicsMetricsCacheValidityDurationSec: 6, FaucetValue: "10000000000", + NumberOfShards: 2, }, ApiLogging: config.ApiLoggingConfig{ LoggingEnabled: true, @@ -408,7 +409,7 @@ func createVersionsRegistry( return nil, err } - shardCoord, err := getShardCoordinator(cfg) + shardCoord, err := sharding.NewMultiShardCoordinator(uint32(cfg.GeneralSettings.NumberOfShards)+1, 0) if err != nil { return nil, err } @@ -556,24 +557,6 @@ func createVersionsRegistry( return versionsFactory.CreateVersionsRegistry(facadeArgs, apiConfigParser) } -func getShardCoordinator(cfg *config.Config) (common.Coordinator, error) { - maxShardID := uint32(0) - for _, obs := range cfg.Observers { - shardID := obs.ShardId - isMetaChain := shardID == core.MetachainShardId - if maxShardID < shardID && !isMetaChain { - maxShardID = shardID - } - } - - shardCoordinator, err := sharding.NewMultiShardCoordinator(maxShardID+1, 0) - if err != nil { - return nil, err - } - - return shardCoordinator, nil -} - func startWebServer( versionsRegistry data.VersionsRegistryHandler, generalConfig *config.Config, diff --git a/config/config.go b/config/config.go index 5cd581b4..2357dc72 100644 --- a/config/config.go +++ b/config/config.go @@ -16,6 +16,7 @@ type GeneralSettingsConfig struct { BalancedObservers bool BalancedFullHistoryNodes bool AllowEntireTxPoolFetch bool + NumberOfShards uint32 } // Config will hold the whole config file's data diff --git a/observer/baseNodeProvider.go b/observer/baseNodeProvider.go index 8395750f..00210b6a 100644 --- a/observer/baseNodeProvider.go +++ b/observer/baseNodeProvider.go @@ -14,6 +14,7 @@ import ( type baseNodeProvider struct { mutNodes sync.RWMutex shardIds []uint32 + numOfShards uint32 configurationFilePath string regularNodes NodesHolder snapshotlessNodes NodesHolder @@ -28,6 +29,19 @@ func (bnp *baseNodeProvider) initNodes(nodes []*data.NodeData) error { for _, observer := range nodes { shardId := observer.ShardId newNodes[shardId] = append(newNodes[shardId], observer) + isMeta := shardId == core.MetachainShardId + if isMeta { + continue + } + + if shardId > bnp.numOfShards { + return fmt.Errorf("%w for observer %s, provided shard %d, number of shards configured %d", + ErrInvalidShard, + observer.Address, + observer.ShardId, + bnp.numOfShards, + ) + } } err := checkNodesInShards(newNodes) @@ -116,10 +130,6 @@ func splitNodesByDataAvailability(nodes []*data.NodeData) ([]*data.NodeData, []* // ReloadNodes will reload the observers or the full history observers func (bnp *baseNodeProvider) ReloadNodes(nodesType data.NodeType) data.NodesReloadResponse { - bnp.mutNodes.RLock() - numOldShardsCount := len(bnp.shardIds) - bnp.mutNodes.RUnlock() - newConfig, err := loadMainConfig(bnp.configurationFilePath) if err != nil { return data.NodesReloadResponse{ @@ -129,21 +139,22 @@ func (bnp *baseNodeProvider) ReloadNodes(nodesType data.NodeType) data.NodesRelo } } + numOldShards := bnp.numOfShards + numNewShards := newConfig.GeneralSettings.NumberOfShards + if numOldShards != numNewShards { + return data.NodesReloadResponse{ + OkRequest: false, + Description: "not reloaded", + Error: fmt.Sprintf("different number of shards. before: %d, now: %d", numOldShards, numNewShards), + } + } + nodes := newConfig.Observers if nodesType == data.FullHistoryNode { nodes = newConfig.FullHistoryNodes } newNodes := nodesSliceToShardedMap(nodes) - numNewShardsCount := len(newNodes) - - if numOldShardsCount != numNewShardsCount { - return data.NodesReloadResponse{ - OkRequest: false, - Description: "not reloaded", - Error: fmt.Sprintf("different number of shards. before: %d, now: %d", numOldShardsCount, numNewShardsCount), - } - } bnp.mutNodes.Lock() defer bnp.mutNodes.Unlock() diff --git a/observer/baseNodeProvider_test.go b/observer/baseNodeProvider_test.go index 847e3ed8..9ac5cfef 100644 --- a/observer/baseNodeProvider_test.go +++ b/observer/baseNodeProvider_test.go @@ -1,6 +1,8 @@ package observer import ( + "errors" + "strings" "testing" "github.com/multiversx/mx-chain-core-go/core" @@ -40,15 +42,42 @@ func TestBaseNodeProvider_InvalidNodesConfiguration(t *testing.T) { }, } - bnp := baseNodeProvider{} + bnp := baseNodeProvider{ + numOfShards: 1, + } err := bnp.initNodes(nodes) require.Contains(t, err.Error(), "observers for shard 1 must include at least one historical (non-snapshotless) observer") } +func TestBaseNodeProvider_InvalidShardForObserver(t *testing.T) { + t.Parallel() + + nodes := []*data.NodeData{ + { + Address: "addr0", + ShardId: 0, + IsSnapshotless: false, + }, + { + Address: "addr1", + ShardId: 2, + IsSnapshotless: true, + }, + } + + bnp := baseNodeProvider{ + numOfShards: 1, + } + err := bnp.initNodes(nodes) + require.True(t, errors.Is(err, ErrInvalidShard)) + require.True(t, strings.Contains(err.Error(), "addr1")) +} + func TestBaseNodeProvider_ReloadNodesDifferentNumberOfNewShard(t *testing.T) { bnp := &baseNodeProvider{ configurationFilePath: configurationPath, shardIds: []uint32{0, 1}, + numOfShards: 2, } response := bnp.ReloadNodes(data.Observer) @@ -66,14 +95,34 @@ func TestBaseNodeProvider_ReloadNodesConfigurationFileNotFound(t *testing.T) { } func TestBaseNodeProvider_ReloadNodesShouldWork(t *testing.T) { - bnp := &baseNodeProvider{ - configurationFilePath: configurationPath, - shardIds: []uint32{0, 1, core.MetachainShardId}, - } + t.Parallel() - response := bnp.ReloadNodes(data.Observer) - require.True(t, response.OkRequest) - require.Empty(t, response.Error) + t.Run("same number of observer shards provided", func(t *testing.T) { + t.Parallel() + + bnp := &baseNodeProvider{ + configurationFilePath: configurationPath, + shardIds: []uint32{0, 1, core.MetachainShardId}, + numOfShards: 3, + } + + response := bnp.ReloadNodes(data.Observer) + require.True(t, response.OkRequest) + require.Empty(t, response.Error) + }) + t.Run("more observer shards provided", func(t *testing.T) { + t.Parallel() + + bnp := &baseNodeProvider{ + configurationFilePath: configurationPath, + shardIds: []uint32{0, 1, core.MetachainShardId}, // no observer for shard 2, will come after reload + numOfShards: 3, // same as in configurationPath + } + + response := bnp.ReloadNodes(data.Observer) + require.True(t, response.OkRequest) + require.Empty(t, response.Error) + }) } func TestBaseNodeProvider_prepareReloadResponseMessage(t *testing.T) { diff --git a/observer/circularQueueNodesProvider.go b/observer/circularQueueNodesProvider.go index 9236e6c8..124542d3 100644 --- a/observer/circularQueueNodesProvider.go +++ b/observer/circularQueueNodesProvider.go @@ -13,9 +13,14 @@ type circularQueueNodesProvider struct { } // NewCircularQueueNodesProvider returns a new instance of circularQueueNodesProvider -func NewCircularQueueNodesProvider(observers []*data.NodeData, configurationFilePath string) (*circularQueueNodesProvider, error) { +func NewCircularQueueNodesProvider( + observers []*data.NodeData, + configurationFilePath string, + numberOfShards uint32, +) (*circularQueueNodesProvider, error) { bop := &baseNodeProvider{ configurationFilePath: configurationFilePath, + numOfShards: numberOfShards, } err := bop.initNodes(observers) diff --git a/observer/circularQueueNodesProvider_test.go b/observer/circularQueueNodesProvider_test.go index bd195f69..a24aadc8 100644 --- a/observer/circularQueueNodesProvider_test.go +++ b/observer/circularQueueNodesProvider_test.go @@ -23,6 +23,9 @@ func getDummyConfig() config.Config { ShardId: 1, }, }, + GeneralSettings: config.GeneralSettingsConfig{ + NumberOfShards: 2, + }, } } @@ -31,7 +34,7 @@ func TestNewCircularQueueObserverProvider_EmptyObserversListShouldErr(t *testing cfg := getDummyConfig() cfg.Observers = make([]*data.NodeData, 0) - cqop, err := NewCircularQueueNodesProvider(cfg.Observers, "path") + cqop, err := NewCircularQueueNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) assert.Nil(t, cqop) assert.Equal(t, ErrEmptyObserversList, err) } @@ -40,7 +43,7 @@ func TestNewCircularQueueObserverProvider_ShouldWork(t *testing.T) { t.Parallel() cfg := getDummyConfig() - cqop, err := NewCircularQueueNodesProvider(cfg.Observers, "path") + cqop, err := NewCircularQueueNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) assert.Nil(t, err) assert.False(t, check.IfNil(cqop)) } @@ -50,7 +53,7 @@ func TestCircularQueueObserversProvider_GetObserversByShardIdShouldWork(t *testi shardId := uint32(0) cfg := getDummyConfig() - cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path") + cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) res, err := cqop.GetNodesByShardId(shardId, data.AvailabilityAll) assert.Nil(t, err) @@ -77,7 +80,7 @@ func TestCircularQueueObserversProvider_GetObserversByShardIdShouldBalanceObserv }, }, } - cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path") + cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) res1, _ := cqop.GetNodesByShardId(shardId, data.AvailabilityAll) res2, _ := cqop.GetNodesByShardId(shardId, data.AvailabilityAll) @@ -94,7 +97,7 @@ func TestCircularQueueObserversProvider_GetAllObserversShouldWork(t *testing.T) t.Parallel() cfg := getDummyConfig() - cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path") + cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) res, err := cqop.GetAllNodes(data.AvailabilityAll) assert.NoError(t, err) @@ -120,7 +123,7 @@ func TestCircularQueueObserversProvider_GetAllObserversShouldWorkAndBalanceObser }, }, } - cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path") + cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) res1, _ := cqop.GetAllNodes(data.AvailabilityAll) res2, _ := cqop.GetAllNodes(data.AvailabilityAll) @@ -166,7 +169,7 @@ func TestCircularQueueObserversProvider_GetAllObservers_ConcurrentSafe(t *testin expectedNumOfTimesAnObserverIsCalled := (numOfTimesToCallForEachRoutine * numOfGoRoutinesToStart) / len(observers) - cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path") + cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) for i := 0; i < numOfGoRoutinesToStart; i++ { for j := 0; j < numOfTimesToCallForEachRoutine; j++ { @@ -225,7 +228,7 @@ func TestCircularQueueObserversProvider_GetObserversByShardId_ConcurrentSafe(t * expectedNumOfTimesAnObserverIsCalled := 2 * ((numOfTimesToCallForEachRoutine * numOfGoRoutinesToStart) / len(observers)) - cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path") + cqop, _ := NewCircularQueueNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) for i := 0; i < numOfGoRoutinesToStart; i++ { for j := 0; j < numOfTimesToCallForEachRoutine; j++ { diff --git a/observer/errors.go b/observer/errors.go index c4529012..d9af62a4 100644 --- a/observer/errors.go +++ b/observer/errors.go @@ -7,3 +7,6 @@ var ErrEmptyObserversList = errors.New("empty observers list") // ErrShardNotAvailable signals that the specified shard ID cannot be found in internal maps var ErrShardNotAvailable = errors.New("the specified shard ID does not exist in proxy's configuration") + +// ErrInvalidShard signals that an invalid shard has been provided +var ErrInvalidShard = errors.New("invalid shard") diff --git a/observer/nodesProviderFactory.go b/observer/nodesProviderFactory.go index c860ebe6..83153d7c 100644 --- a/observer/nodesProviderFactory.go +++ b/observer/nodesProviderFactory.go @@ -24,16 +24,25 @@ func NewNodesProviderFactory(cfg config.Config, configurationFilePath string) (* // CreateObservers will create and return an object of type NodesProviderHandler based on a flag func (npf *nodesProviderFactory) CreateObservers() (NodesProviderHandler, error) { if npf.cfg.GeneralSettings.BalancedObservers { - return NewCircularQueueNodesProvider(npf.cfg.Observers, npf.configurationFilePath) + return NewCircularQueueNodesProvider( + npf.cfg.Observers, + npf.configurationFilePath, + npf.cfg.GeneralSettings.NumberOfShards) } - return NewSimpleNodesProvider(npf.cfg.Observers, npf.configurationFilePath) + return NewSimpleNodesProvider( + npf.cfg.Observers, + npf.configurationFilePath, + npf.cfg.GeneralSettings.NumberOfShards) } // CreateFullHistoryNodes will create and return an object of type NodesProviderHandler based on a flag func (npf *nodesProviderFactory) CreateFullHistoryNodes() (NodesProviderHandler, error) { if npf.cfg.GeneralSettings.BalancedFullHistoryNodes { - nodesProviderHandler, err := NewCircularQueueNodesProvider(npf.cfg.FullHistoryNodes, npf.configurationFilePath) + nodesProviderHandler, err := NewCircularQueueNodesProvider( + npf.cfg.FullHistoryNodes, + npf.configurationFilePath, + npf.cfg.GeneralSettings.NumberOfShards) if err != nil { return getDisabledFullHistoryNodesProviderIfNeeded(err) } @@ -41,7 +50,10 @@ func (npf *nodesProviderFactory) CreateFullHistoryNodes() (NodesProviderHandler, return nodesProviderHandler, nil } - nodesProviderHandler, err := NewSimpleNodesProvider(npf.cfg.FullHistoryNodes, npf.configurationFilePath) + nodesProviderHandler, err := NewSimpleNodesProvider( + npf.cfg.FullHistoryNodes, + npf.configurationFilePath, + npf.cfg.GeneralSettings.NumberOfShards) if err != nil { return getDisabledFullHistoryNodesProviderIfNeeded(err) } diff --git a/observer/simpleNodesProvider.go b/observer/simpleNodesProvider.go index e3e095a4..d1667ce0 100644 --- a/observer/simpleNodesProvider.go +++ b/observer/simpleNodesProvider.go @@ -11,9 +11,14 @@ type simpleNodesProvider struct { } // NewSimpleNodesProvider will return a new instance of simpleNodesProvider -func NewSimpleNodesProvider(observers []*data.NodeData, configurationFilePath string) (*simpleNodesProvider, error) { +func NewSimpleNodesProvider( + observers []*data.NodeData, + configurationFilePath string, + numberOfShards uint32, +) (*simpleNodesProvider, error) { bop := &baseNodeProvider{ configurationFilePath: configurationFilePath, + numOfShards: numberOfShards, } err := bop.initNodes(observers) diff --git a/observer/simpleNodesProvider_test.go b/observer/simpleNodesProvider_test.go index 633cf373..39b8d6d0 100644 --- a/observer/simpleNodesProvider_test.go +++ b/observer/simpleNodesProvider_test.go @@ -16,7 +16,7 @@ func TestNewSimpleObserversProvider_EmptyObserversListShouldErr(t *testing.T) { cfg := getDummyConfig() cfg.Observers = make([]*data.NodeData, 0) - sop, err := NewSimpleNodesProvider(cfg.Observers, "path") + sop, err := NewSimpleNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) assert.Nil(t, sop) assert.Equal(t, ErrEmptyObserversList, err) } @@ -25,7 +25,7 @@ func TestNewSimpleObserversProvider_ShouldWork(t *testing.T) { t.Parallel() cfg := getDummyConfig() - sop, err := NewSimpleNodesProvider(cfg.Observers, "path") + sop, err := NewSimpleNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) assert.Nil(t, err) assert.False(t, check.IfNil(sop)) } @@ -35,7 +35,7 @@ func TestSimpleObserversProvider_GetObserversByShardIdShouldErrBecauseInvalidSha invalidShardId := uint32(37) cfg := getDummyConfig() - cqop, _ := NewSimpleNodesProvider(cfg.Observers, "path") + cqop, _ := NewSimpleNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) res, err := cqop.GetNodesByShardId(invalidShardId, "") assert.Nil(t, res) @@ -47,7 +47,7 @@ func TestSimpleObserversProvider_GetObserversByShardIdShouldWork(t *testing.T) { shardId := uint32(0) cfg := getDummyConfig() - cqop, _ := NewSimpleNodesProvider(cfg.Observers, "path") + cqop, _ := NewSimpleNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) res, err := cqop.GetNodesByShardId(shardId, "") assert.Nil(t, err) @@ -58,7 +58,7 @@ func TestSimpleObserversProvider_GetAllObserversShouldWork(t *testing.T) { t.Parallel() cfg := getDummyConfig() - cqop, _ := NewSimpleNodesProvider(cfg.Observers, "path") + cqop, _ := NewSimpleNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) res, _ := cqop.GetAllNodes("") assert.Equal(t, 2, len(res)) @@ -105,7 +105,7 @@ func TestSimpleObserversProvider_GetObserversByShardId_ConcurrentSafe(t *testing // will be called expectedNumOfTimesAnObserverIsCalled := numOfTimesToCallForEachRoutine * numOfGoRoutinesToStart - sop, _ := NewSimpleNodesProvider(cfg.Observers, "path") + sop, _ := NewSimpleNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) for i := 0; i < numOfGoRoutinesToStart; i++ { for j := 0; j < numOfTimesToCallForEachRoutine; j++ { @@ -168,7 +168,7 @@ func TestSimpleObserversProvider_GetAllObservers_ConcurrentSafe(t *testing.T) { // will be called expectedNumOfTimesAnObserverIsCalled := numOfTimesToCallForEachRoutine * numOfGoRoutinesToStart - sop, _ := NewSimpleNodesProvider(cfg.Observers, "path") + sop, _ := NewSimpleNodesProvider(cfg.Observers, "path", uint32(len(cfg.Observers))) for i := 0; i < numOfGoRoutinesToStart; i++ { for j := 0; j < numOfTimesToCallForEachRoutine; j++ { diff --git a/observer/testdata/config.toml b/observer/testdata/config.toml index 89ccdd9f..c82a7ee4 100644 --- a/observer/testdata/config.toml +++ b/observer/testdata/config.toml @@ -1,25 +1,34 @@ +# GeneralSettings section of the proxy server +[GeneralSettings] + # NumberOfShards represents the total number of shards from the network (excluding metachain) + NumberOfShards = 3 + # List of Observers. If you want to define a metachain observer (needed for validator statistics route) use # shard id 4294967295 [[Observers]] -ShardId = 0 -Address = "observer-shard-0" + ShardId = 0 + Address = "observer-shard-0" + +[[Observers]] + ShardId = 1 + Address = "observer-shard-1" [[Observers]] -ShardId = 1 -Address = "observer-shard-1" + ShardId = 2 + Address = "observer-shard-2" [[Observers]] -ShardId = 4294967295 -Address = "observer-shard-4294967295" + ShardId = 4294967295 + Address = "observer-shard-4294967295" [[FullHistoryNodes]] -ShardId = 0 -Address = "full-history-observer-shard-0" + ShardId = 0 + Address = "full-history-observer-shard-0" [[FullHistoryNodes]] -ShardId = 1 -Address = "full-history-observer-shard-1" + ShardId = 1 + Address = "full-history-observer-shard-1" [[FullHistoryNodes]] -ShardId = 1 -Address = "full-history-observer-shard-4294967295" + ShardId = 1 + Address = "full-history-observer-shard-4294967295" From 05660f875cadc0a021cb42f5ea3b9fa03559361b Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 4 Sep 2024 13:00:38 +0300 Subject: [PATCH 35/40] fix shard coordinator initialization --- cmd/proxy/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index a51261dd..955c7842 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -409,7 +409,7 @@ func createVersionsRegistry( return nil, err } - shardCoord, err := sharding.NewMultiShardCoordinator(uint32(cfg.GeneralSettings.NumberOfShards)+1, 0) + shardCoord, err := sharding.NewMultiShardCoordinator(cfg.GeneralSettings.NumberOfShards, 0) if err != nil { return nil, err } From fa067f846510e4950da90a3f789aa9af26496f7c Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 4 Sep 2024 14:03:45 +0300 Subject: [PATCH 36/40] fixes after review --- cmd/proxy/main.go | 2 +- observer/baseNodeProvider.go | 2 +- observer/baseNodeProvider_test.go | 4 ++-- observer/testdata/config.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 955c7842..154f7e5c 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -328,7 +328,7 @@ func createVersionsRegistryTestOrProduction( ValStatsCacheValidityDurationSec: 60, EconomicsMetricsCacheValidityDurationSec: 6, FaucetValue: "10000000000", - NumberOfShards: 2, + NumberOfShards: 3, }, ApiLogging: config.ApiLoggingConfig{ LoggingEnabled: true, diff --git a/observer/baseNodeProvider.go b/observer/baseNodeProvider.go index 00210b6a..82ebe82c 100644 --- a/observer/baseNodeProvider.go +++ b/observer/baseNodeProvider.go @@ -34,7 +34,7 @@ func (bnp *baseNodeProvider) initNodes(nodes []*data.NodeData) error { continue } - if shardId > bnp.numOfShards { + if shardId >= bnp.numOfShards { return fmt.Errorf("%w for observer %s, provided shard %d, number of shards configured %d", ErrInvalidShard, observer.Address, diff --git a/observer/baseNodeProvider_test.go b/observer/baseNodeProvider_test.go index 9ac5cfef..34db5660 100644 --- a/observer/baseNodeProvider_test.go +++ b/observer/baseNodeProvider_test.go @@ -43,7 +43,7 @@ func TestBaseNodeProvider_InvalidNodesConfiguration(t *testing.T) { } bnp := baseNodeProvider{ - numOfShards: 1, + numOfShards: 2, } err := bnp.initNodes(nodes) require.Contains(t, err.Error(), "observers for shard 1 must include at least one historical (non-snapshotless) observer") @@ -60,7 +60,7 @@ func TestBaseNodeProvider_InvalidShardForObserver(t *testing.T) { }, { Address: "addr1", - ShardId: 2, + ShardId: 1, IsSnapshotless: true, }, } diff --git a/observer/testdata/config.toml b/observer/testdata/config.toml index c82a7ee4..ec117fd6 100644 --- a/observer/testdata/config.toml +++ b/observer/testdata/config.toml @@ -30,5 +30,5 @@ Address = "full-history-observer-shard-1" [[FullHistoryNodes]] - ShardId = 1 + ShardId = 4294967295 Address = "full-history-observer-shard-4294967295" From e72a68eb4a38c88e81b70d039a5dcdb8796630b4 Mon Sep 17 00:00:00 2001 From: Iuga Mihai <50499646+miiu96@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:16:17 +0300 Subject: [PATCH 37/40] Relayed tx v3 process status fix (#461) * fix * one more fix * fix * cleanup --- process/transactionProcessor.go | 71 +-------------- process/transactionProcessor_test.go | 125 --------------------------- 2 files changed, 2 insertions(+), 194 deletions(-) diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index f96ad95c..d2d85ba8 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -491,7 +491,7 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } - isRelayedV3, status := checkIfRelayedV3Completed(allLogs, tx) + isRelayedV3, status := checkIfRelayedV3Completed(tx) if isRelayedV3 { return &data.ProcessStatusResponse{ Status: status, @@ -588,15 +588,11 @@ func checkIfCompleted(logs []*transaction.ApiLogs) bool { return found } -func checkIfRelayedV3Completed(logs []*transaction.ApiLogs, tx *transaction.ApiTransactionResult) (bool, string) { +func checkIfRelayedV3Completed(tx *transaction.ApiTransactionResult) (bool, string) { if len(tx.InnerTransactions) == 0 { return false, string(transaction.TxStatusPending) } - if len(logs) < len(tx.InnerTransactions) { - return true, string(transaction.TxStatusPending) - } - return true, string(transaction.TxStatusSuccess) } @@ -780,10 +776,6 @@ func (tp *TransactionProcessor) getTxFromObservers(txHash string, reqType reques fetched: false, } - if isRelayedTxV3(getTxResponse.Data.Transaction) { - return tp.mergeSCRLogsFromInnerReceivers(&getTxResponse.Data.Transaction, withResults), nil - } - isIntraShard := sndShardID == rcvShardID observerIsInDestShard := rcvShardID == observerShardID @@ -840,65 +832,6 @@ func (tp *TransactionProcessor) getTxFromObservers(txHash string, reqType reques return nil, errors.ErrTransactionNotFound } -func isRelayedTxV3(tx transaction.ApiTransactionResult) bool { - return tx.ProcessingTypeOnSource == relayedV3TransactionDescriptor && tx.ProcessingTypeOnDestination == relayedV3TransactionDescriptor -} - -func (tp *TransactionProcessor) mergeSCRLogsFromInnerReceivers(tx *transaction.ApiTransactionResult, withResults bool) *transaction.ApiTransactionResult { - logsOnDestMap := make(map[string]*transaction.ApiLogs, len(tx.SmartContractResults)) - - txsByReceiverShardMap := tp.groupTxsByReceiverShard(tx) - for shardID, scrHashes := range txsByReceiverShardMap { - for _, scrHash := range scrHashes { - observers, err := tp.getNodesInShard(shardID, requestTypeObservers) - if err != nil { - break - } - - if withResults { - for _, observer := range observers { - getTxResponse, ok, _ := tp.getTxFromObserver(observer, scrHash, withResults) - if !ok { - continue - } - - logsOnDestMap[scrHash] = getTxResponse.Data.Transaction.Logs - break - } - } - } - } - - finalTx := *tx - // if withResults, override the scr logs with the one from the receiver shard - if withResults { - for _, scr := range finalTx.SmartContractResults { - logsOnDest, found := logsOnDestMap[scr.Hash] - if !found { - continue - } - - scr.Logs = logsOnDest - } - } - - return &finalTx -} - -func (tp *TransactionProcessor) groupTxsByReceiverShard(tx *transaction.ApiTransactionResult) map[uint32][]string { - txsByReceiverShardMap := make(map[uint32][]string) - for _, scr := range tx.SmartContractResults { - shardID, err := tp.getShardByAddress(scr.RcvAddr) - if err != nil { - continue - } - - txsByReceiverShardMap[shardID] = append(txsByReceiverShardMap[shardID], scr.Hash) - } - - return txsByReceiverShardMap -} - func (tp *TransactionProcessor) fetchSCRSBasedOnShardMap(tx *transaction.ApiTransactionResult, shardIDWasFetch map[uint32]*tupleHashWasFetched) error { for shardID, info := range shardIDWasFetch { scrs, err := tp.fetchSCRs(tx.Hash, info.hash, shardID) diff --git a/process/transactionProcessor_test.go b/process/transactionProcessor_test.go index b37765a2..4e551aff 100644 --- a/process/transactionProcessor_test.go +++ b/process/transactionProcessor_test.go @@ -1322,131 +1322,6 @@ func TestTransactionProcessor_GetTransactionWithEventsFirstFromDstShardAndAfterS assert.Equal(t, 3, len(tx.SmartContractResults)) } -func TestTransactionProcessor_GetTransactionRelayedV3ShouldMergeEvents(t *testing.T) { - t.Parallel() - - relayer := hex.EncodeToString([]byte("relayer")) - sender1 := hex.EncodeToString([]byte("sender1")) - sender2 := hex.EncodeToString([]byte("sender2")) - receiver1 := hex.EncodeToString([]byte("receiver1")) - receiver2 := hex.EncodeToString([]byte("receiver2")) - - addrObs0 := "observer0" - addrObsFailing := "observerFailing" - addrObs1 := "observer1" - - hashRelayed := "hashRelayed" - - scrHash1 := "scrHash1" - providedLogsInnerTx1 := &transaction.ApiLogs{ - Events: []*transaction.Events{ - { - Address: receiver1, - Identifier: "events innertx 1", - }, - }, - } - - scrHash2 := "scrHash2" - providedLogsInnerTx2 := &transaction.ApiLogs{ - Events: []*transaction.Events{ - { - Address: receiver2, - Identifier: "events innertx 2", - }, - }, - } - - tp, _ := process.NewTransactionProcessor( - &mock.ProcessorStub{ - ComputeShardIdCalled: func(addressBuff []byte) (uint32, error) { - switch string(addressBuff) { - case "relayer", "sender1", "sender2", "receiver1": - return 0, nil - case "receiver2": - return 1, nil - } - - return 0, nil - }, - GetShardIDsCalled: func() []uint32 { - return []uint32{0, 1} - }, - GetObserversCalled: func(shardId uint32, dataAvailability data.ObserverDataAvailabilityType) ([]*data.NodeData, error) { - if shardId == 0 { - return []*data.NodeData{ - {Address: addrObs0, ShardId: 0}, - }, nil - } - if shardId == 1 { - return []*data.NodeData{ - {Address: addrObsFailing, ShardId: 1}, - {Address: addrObs1, ShardId: 1}, - }, nil - } - - return nil, nil - }, - CallGetRestEndPointCalled: func(address string, path string, value interface{}) (i int, err error) { - if address == addrObsFailing { - return http.StatusBadRequest, errors.New("error for coverage only") - } - - responseGetTx := value.(*data.GetTransactionResponse) - if strings.Contains(path, hashRelayed) { - responseGetTx.Data.Transaction.Hash = hashRelayed - responseGetTx.Data.Transaction.ProcessingTypeOnSource = "RelayedTxV3" - responseGetTx.Data.Transaction.ProcessingTypeOnDestination = "RelayedTxV3" - responseGetTx.Data.Transaction.SmartContractResults = []*transaction.ApiSmartContractResult{ - { - Hash: scrHash1, - RcvAddr: receiver1, - SndAddr: sender1, - RelayerAddr: relayer, - IsRelayed: true, - }, - { - Hash: scrHash2, - RcvAddr: receiver2, - SndAddr: sender2, - RelayerAddr: relayer, - IsRelayed: true, - }, - } - - return http.StatusOK, nil - } - if strings.Contains(path, scrHash1) { - responseGetTx.Data.Transaction.Hash = scrHash1 - responseGetTx.Data.Transaction.Logs = providedLogsInnerTx1 - - return http.StatusOK, nil - } - if strings.Contains(path, scrHash2) { - responseGetTx.Data.Transaction.Hash = scrHash2 - responseGetTx.Data.Transaction.Logs = providedLogsInnerTx2 - - return http.StatusOK, nil - } - - return http.StatusBadRequest, nil - }, - }, - &mock.PubKeyConverterMock{}, - hasher, - marshalizer, - funcNewTxCostHandler, - logsMerger, - true, - ) - - tx, err := tp.GetTransaction(hashRelayed, true) - require.NoError(t, err) - require.Equal(t, 2, len(tx.SmartContractResults)) - require.Equal(t, providedLogsInnerTx1, tx.SmartContractResults[0].Logs) - require.Equal(t, providedLogsInnerTx2, tx.SmartContractResults[1].Logs) -} - func TestTransactionProcessor_GetTransactionPool(t *testing.T) { t.Parallel() From b9b92e5f5fb15cf5c092fd3987101849de35105c Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 9 Sep 2024 11:38:36 +0300 Subject: [PATCH 38/40] updated deps to new tags --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 1bd7ba8f..d578cbd1 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,9 @@ require ( github.com/gin-contrib/pprof v1.4.0 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.9.1 - github.com/multiversx/mx-chain-core-go v1.2.21 + github.com/multiversx/mx-chain-core-go v1.2.22 github.com/multiversx/mx-chain-crypto-go v1.2.12 - github.com/multiversx/mx-chain-es-indexer-go v1.7.4 + github.com/multiversx/mx-chain-es-indexer-go v1.7.8 github.com/multiversx/mx-chain-logger-go v1.0.15 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index ea5cead0..5e15844f 100644 --- a/go.sum +++ b/go.sum @@ -129,12 +129,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiversx/mx-chain-core-go v1.2.21 h1:+XVKznPTlUU5EFS1A8chtS8fStW60upRIyF4Pgml19I= -github.com/multiversx/mx-chain-core-go v1.2.21/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-core-go v1.2.22 h1:yDYrvoQOBbsDerEp7L3+de5AfMy3pTF333gWPpd+FNk= +github.com/multiversx/mx-chain-core-go v1.2.22/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.4 h1:SjJk9G9SN8baz0sFIU2jymYCfx3XiikGEB2wW0jwvfw= -github.com/multiversx/mx-chain-es-indexer-go v1.7.4/go.mod h1:oGcRK2E3Syv6vRTszWrrb/TqD8akq0yeoMr1wPPiTO4= +github.com/multiversx/mx-chain-es-indexer-go v1.7.8 h1:ZDKTXkQhQ7lLi6huVrBTUssVEqCvaCxGH4Y52GapboQ= +github.com/multiversx/mx-chain-es-indexer-go v1.7.8/go.mod h1:oGcRK2E3Syv6vRTszWrrb/TqD8akq0yeoMr1wPPiTO4= 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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= From 1763fd14aec3abda9c5afaeddc15ff59dbcff5d3 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 30 Sep 2024 15:50:45 +0300 Subject: [PATCH 39/40] get number of shards from observers --- cmd/proxy/config/config.toml | 15 +- cmd/proxy/main.go | 30 +++- config/config.go | 3 +- observer/baseNodeProvider.go | 10 -- observer/baseNodeProvider_test.go | 12 -- observer/circularQueueNodesProvider_test.go | 3 - observer/nodesProviderFactory.go | 12 +- observer/nodesProviderFactory_test.go | 6 +- process/errors.go | 9 +- process/interface.go | 7 + process/mock/httpClientMock.go | 16 ++ process/numShardsProcessor.go | 147 ++++++++++++++++ process/numShardsProcessor_test.go | 176 ++++++++++++++++++++ 13 files changed, 397 insertions(+), 49 deletions(-) create mode 100644 process/mock/httpClientMock.go create mode 100644 process/numShardsProcessor.go create mode 100644 process/numShardsProcessor_test.go diff --git a/cmd/proxy/config/config.toml b/cmd/proxy/config/config.toml index 3072af75..03ef65fc 100644 --- a/cmd/proxy/config/config.toml +++ b/cmd/proxy/config/config.toml @@ -39,15 +39,18 @@ # With this flag disabled, /transaction/pool route will return an error AllowEntireTxPoolFetch = false - # NumberOfShards represents the total number of shards from the network (excluding metachain) - NumberOfShards = 3 + # NumShardsTimeoutInSec represents the maximum number of seconds to wait for at least one observer online until throwing an error + NumShardsTimeoutInSec = 90 + + # TimeBetweenNodesRequestsInSec represents time to wait before retry to get the number of shards from observers + TimeBetweenNodesRequestsInSec = 2 [AddressPubkeyConverter] - #Length specifies the length in bytes of an address - Length = 32 + #Length specifies the length in bytes of an address + Length = 32 - # Type specifies the type of public keys: hex or bech32 - Type = "bech32" + # Type specifies the type of public keys: hex or bech32 + Type = "bech32" [Marshalizer] Type = "gogo protobuf" diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 154f7e5c..21b66cb7 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -328,7 +328,6 @@ func createVersionsRegistryTestOrProduction( ValStatsCacheValidityDurationSec: 60, EconomicsMetricsCacheValidityDurationSec: 6, FaucetValue: "10000000000", - NumberOfShards: 3, }, ApiLogging: config.ApiLoggingConfig{ LoggingEnabled: true, @@ -409,12 +408,32 @@ func createVersionsRegistry( return nil, err } - shardCoord, err := sharding.NewMultiShardCoordinator(cfg.GeneralSettings.NumberOfShards, 0) + httpClient := &http.Client{} + httpClient.Timeout = time.Duration(cfg.GeneralSettings.RequestTimeoutSec) * time.Second + observersList := make([]string, 0, len(cfg.Observers)) + for _, node := range cfg.Observers { + observersList = append(observersList, node.Address) + } + argsNumShardsProcessor := process.ArgNumShardsProcessor{ + HttpClient: httpClient, + Observers: observersList, + TimeBetweenNodesRequestsInSec: cfg.GeneralSettings.TimeBetweenNodesRequestsInSec, + NumShardsTimeoutInSec: cfg.GeneralSettings.NumShardsTimeoutInSec, + RequestTimeoutInSec: cfg.GeneralSettings.RequestTimeoutSec, + } + numShardsProcessor, err := process.NewNumShardsProcessor(argsNumShardsProcessor) + if err != nil { + return nil, err + } + + ctx, cancel := context.WithCancel(context.Background()) + numShards, err := numShardsProcessor.GetNetworkNumShards(ctx) + cancel() if err != nil { return nil, err } - nodesProviderFactory, err := observer.NewNodesProviderFactory(*cfg, configurationFilePath) + nodesProviderFactory, err := observer.NewNodesProviderFactory(*cfg, configurationFilePath, numShards) if err != nil { return nil, err } @@ -431,6 +450,11 @@ func createVersionsRegistry( } } + shardCoord, err := sharding.NewMultiShardCoordinator(numShards, 0) + if err != nil { + return nil, err + } + bp, err := process.NewBaseProcessor( cfg.GeneralSettings.RequestTimeoutSec, shardCoord, diff --git a/config/config.go b/config/config.go index 2357dc72..90317616 100644 --- a/config/config.go +++ b/config/config.go @@ -16,7 +16,8 @@ type GeneralSettingsConfig struct { BalancedObservers bool BalancedFullHistoryNodes bool AllowEntireTxPoolFetch bool - NumberOfShards uint32 + NumShardsTimeoutInSec int + TimeBetweenNodesRequestsInSec int } // Config will hold the whole config file's data diff --git a/observer/baseNodeProvider.go b/observer/baseNodeProvider.go index 82ebe82c..49b964ec 100644 --- a/observer/baseNodeProvider.go +++ b/observer/baseNodeProvider.go @@ -139,16 +139,6 @@ func (bnp *baseNodeProvider) ReloadNodes(nodesType data.NodeType) data.NodesRelo } } - numOldShards := bnp.numOfShards - numNewShards := newConfig.GeneralSettings.NumberOfShards - if numOldShards != numNewShards { - return data.NodesReloadResponse{ - OkRequest: false, - Description: "not reloaded", - Error: fmt.Sprintf("different number of shards. before: %d, now: %d", numOldShards, numNewShards), - } - } - nodes := newConfig.Observers if nodesType == data.FullHistoryNode { nodes = newConfig.FullHistoryNodes diff --git a/observer/baseNodeProvider_test.go b/observer/baseNodeProvider_test.go index 34db5660..f5c09c92 100644 --- a/observer/baseNodeProvider_test.go +++ b/observer/baseNodeProvider_test.go @@ -73,18 +73,6 @@ func TestBaseNodeProvider_InvalidShardForObserver(t *testing.T) { require.True(t, strings.Contains(err.Error(), "addr1")) } -func TestBaseNodeProvider_ReloadNodesDifferentNumberOfNewShard(t *testing.T) { - bnp := &baseNodeProvider{ - configurationFilePath: configurationPath, - shardIds: []uint32{0, 1}, - numOfShards: 2, - } - - response := bnp.ReloadNodes(data.Observer) - require.False(t, response.OkRequest) - require.Contains(t, response.Error, "different number of shards") -} - func TestBaseNodeProvider_ReloadNodesConfigurationFileNotFound(t *testing.T) { bnp := &baseNodeProvider{ configurationFilePath: "wrong config path", diff --git a/observer/circularQueueNodesProvider_test.go b/observer/circularQueueNodesProvider_test.go index a24aadc8..f94f2bed 100644 --- a/observer/circularQueueNodesProvider_test.go +++ b/observer/circularQueueNodesProvider_test.go @@ -23,9 +23,6 @@ func getDummyConfig() config.Config { ShardId: 1, }, }, - GeneralSettings: config.GeneralSettingsConfig{ - NumberOfShards: 2, - }, } } diff --git a/observer/nodesProviderFactory.go b/observer/nodesProviderFactory.go index 83153d7c..ea18322e 100644 --- a/observer/nodesProviderFactory.go +++ b/observer/nodesProviderFactory.go @@ -11,13 +11,15 @@ var log = logger.GetOrCreate("observer") type nodesProviderFactory struct { cfg config.Config configurationFilePath string + numberOfShards uint32 } // NewNodesProviderFactory returns a new instance of nodesProviderFactory -func NewNodesProviderFactory(cfg config.Config, configurationFilePath string) (*nodesProviderFactory, error) { +func NewNodesProviderFactory(cfg config.Config, configurationFilePath string, numberOfShards uint32) (*nodesProviderFactory, error) { return &nodesProviderFactory{ cfg: cfg, configurationFilePath: configurationFilePath, + numberOfShards: numberOfShards, }, nil } @@ -27,13 +29,13 @@ func (npf *nodesProviderFactory) CreateObservers() (NodesProviderHandler, error) return NewCircularQueueNodesProvider( npf.cfg.Observers, npf.configurationFilePath, - npf.cfg.GeneralSettings.NumberOfShards) + npf.numberOfShards) } return NewSimpleNodesProvider( npf.cfg.Observers, npf.configurationFilePath, - npf.cfg.GeneralSettings.NumberOfShards) + npf.numberOfShards) } // CreateFullHistoryNodes will create and return an object of type NodesProviderHandler based on a flag @@ -42,7 +44,7 @@ func (npf *nodesProviderFactory) CreateFullHistoryNodes() (NodesProviderHandler, nodesProviderHandler, err := NewCircularQueueNodesProvider( npf.cfg.FullHistoryNodes, npf.configurationFilePath, - npf.cfg.GeneralSettings.NumberOfShards) + npf.numberOfShards) if err != nil { return getDisabledFullHistoryNodesProviderIfNeeded(err) } @@ -53,7 +55,7 @@ func (npf *nodesProviderFactory) CreateFullHistoryNodes() (NodesProviderHandler, nodesProviderHandler, err := NewSimpleNodesProvider( npf.cfg.FullHistoryNodes, npf.configurationFilePath, - npf.cfg.GeneralSettings.NumberOfShards) + npf.numberOfShards) if err != nil { return getDisabledFullHistoryNodesProviderIfNeeded(err) } diff --git a/observer/nodesProviderFactory_test.go b/observer/nodesProviderFactory_test.go index ee095e42..9e9a26c8 100644 --- a/observer/nodesProviderFactory_test.go +++ b/observer/nodesProviderFactory_test.go @@ -10,7 +10,7 @@ import ( func TestNewObserversProviderFactory_ShouldWork(t *testing.T) { t.Parallel() - opf, err := NewNodesProviderFactory(config.Config{}, "path") + opf, err := NewNodesProviderFactory(config.Config{}, "path", 2) assert.Nil(t, err) assert.NotNil(t, opf) } @@ -21,7 +21,7 @@ func TestObserversProviderFactory_CreateShouldReturnSimple(t *testing.T) { cfg := getDummyConfig() cfg.GeneralSettings.BalancedObservers = false - opf, _ := NewNodesProviderFactory(cfg, "path") + opf, _ := NewNodesProviderFactory(cfg, "path", 2) op, err := opf.CreateObservers() assert.Nil(t, err) _, ok := op.(*simpleNodesProvider) @@ -34,7 +34,7 @@ func TestObserversProviderFactory_CreateShouldReturnCircularQueue(t *testing.T) cfg := getDummyConfig() cfg.GeneralSettings.BalancedObservers = true - opf, _ := NewNodesProviderFactory(cfg, "path") + opf, _ := NewNodesProviderFactory(cfg, "path", 2) op, err := opf.CreateObservers() assert.Nil(t, err) _, ok := op.(*circularQueueNodesProvider) diff --git a/process/errors.go b/process/errors.go index 134e7bf9..8060b7b4 100644 --- a/process/errors.go +++ b/process/errors.go @@ -56,18 +56,12 @@ var ErrNoFaucetAccountForGivenShard = errors.New("no faucet account found for th // ErrNilNodesProvider signals that a nil observers provider has been provided var ErrNilNodesProvider = errors.New("nil nodes provider") -// ErrInvalidShardId signals that a invalid shard id has been provided -var ErrInvalidShardId = errors.New("invalid shard id") - // ErrNilPubKeyConverter signals that a nil pub key converter has been provided var ErrNilPubKeyConverter = errors.New("nil pub key converter provided") // ErrNoValidTransactionToSend signals that no valid transaction were received var ErrNoValidTransactionToSend = errors.New("no valid transaction to send") -// ErrNilDatabaseConnector signals that a nil database connector was provided -var ErrNilDatabaseConnector = errors.New("not valid database connector") - // ErrCannotParseNodeStatusMetrics signals that the node status metrics cannot be parsed var ErrCannotParseNodeStatusMetrics = errors.New("cannot parse node status metrics") @@ -115,3 +109,6 @@ var ErrEmptyCommitString = errors.New("empty commit id string") // ErrEmptyPubKey signals that an empty public key has been provided var ErrEmptyPubKey = errors.New("public key is empty") + +// ErrNilHttpClient signals that a nil http client has been provided +var ErrNilHttpClient = errors.New("nil http client") diff --git a/process/interface.go b/process/interface.go index eb7e558c..f424bdfc 100644 --- a/process/interface.go +++ b/process/interface.go @@ -1,6 +1,8 @@ package process import ( + "net/http" + "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-core-go/data/vm" @@ -78,3 +80,8 @@ type StatusMetricsProvider interface { GetMetricsForPrometheus() string IsInterfaceNil() bool } + +// HttpClient defines an interface for the http client +type HttpClient interface { + Do(req *http.Request) (*http.Response, error) +} diff --git a/process/mock/httpClientMock.go b/process/mock/httpClientMock.go new file mode 100644 index 00000000..9e09fb2a --- /dev/null +++ b/process/mock/httpClientMock.go @@ -0,0 +1,16 @@ +package mock + +import "net/http" + +// HttpClientMock - +type HttpClientMock struct { + DoCalled func(req *http.Request) (*http.Response, error) +} + +// Do - +func (mock *HttpClientMock) Do(req *http.Request) (*http.Response, error) { + if mock.DoCalled != nil { + return mock.DoCalled(req) + } + return &http.Response{}, nil +} diff --git a/process/numShardsProcessor.go b/process/numShardsProcessor.go new file mode 100644 index 00000000..8a9d907c --- /dev/null +++ b/process/numShardsProcessor.go @@ -0,0 +1,147 @@ +package process + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "time" + + "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-core-go/core/check" +) + +var errTimeIsOut = errors.New("time is out") + +const ( + networkConfigPath = "/network/config" +) + +type networkConfigResponseData struct { + Config struct { + NumShards uint32 `json:"erd_num_shards_without_meta"` + } `json:"config"` +} + +type networkConfigResponse struct { + Data networkConfigResponseData `json:"data"` + Error string `json:"error"` + Code string `json:"code"` +} + +// ArgNumShardsProcessor is the DTO used to create a new instance of numShardsProcessor +type ArgNumShardsProcessor struct { + HttpClient HttpClient + Observers []string + TimeBetweenNodesRequestsInSec int + NumShardsTimeoutInSec int + RequestTimeoutInSec int +} + +type numShardsProcessor struct { + observers []string + httpClient HttpClient + timeBetweenNodesRequests time.Duration + numShardsTimeout time.Duration + requestTimeout time.Duration +} + +// NewNumShardsProcessor returns a new instance of numShardsProcessor +func NewNumShardsProcessor(args ArgNumShardsProcessor) (*numShardsProcessor, error) { + err := checkArgs(args) + if err != nil { + return nil, err + } + + return &numShardsProcessor{ + observers: args.Observers, + httpClient: args.HttpClient, + timeBetweenNodesRequests: time.Second * time.Duration(args.TimeBetweenNodesRequestsInSec), + numShardsTimeout: time.Second * time.Duration(args.NumShardsTimeoutInSec), + requestTimeout: time.Second * time.Duration(args.RequestTimeoutInSec), + }, nil +} + +func checkArgs(args ArgNumShardsProcessor) error { + if check.IfNilReflect(args.HttpClient) { + return ErrNilHttpClient + } + if len(args.Observers) == 0 { + return fmt.Errorf("%w for Observers, empty list provided", core.ErrInvalidValue) + } + if args.TimeBetweenNodesRequestsInSec == 0 { + return fmt.Errorf("%w for TimeBetweenNodesRequestsInSec, %d provided", core.ErrInvalidValue, args.TimeBetweenNodesRequestsInSec) + } + if args.NumShardsTimeoutInSec == 0 { + return fmt.Errorf("%w for NumShardsTimeoutInSec, %d provided", core.ErrInvalidValue, args.NumShardsTimeoutInSec) + } + if args.RequestTimeoutInSec == 0 { + return fmt.Errorf("%w for RequestTimeoutInSec, %d provided", core.ErrInvalidValue, args.RequestTimeoutInSec) + } + + return nil +} + +// GetNetworkNumShards tries to get the number of shards from the network +func (processor *numShardsProcessor) GetNetworkNumShards(ctx context.Context) (uint32, error) { + log.Info("getting the number of shards from observers...") + + waitNodeTicker := time.NewTicker(processor.timeBetweenNodesRequests) + for { + select { + case <-waitNodeTicker.C: + for _, observerAddress := range processor.observers { + numShards, httpStatus := processor.tryGetnumShardsFromObserver(observerAddress) + if httpStatus == http.StatusOK { + log.Info("fetched the number of shards", "shards", numShards) + return numShards, nil + } + } + case <-time.After(processor.numShardsTimeout): + return 0, fmt.Errorf("%w, no observer online", errTimeIsOut) + case <-ctx.Done(): + log.Debug("closing the getNetworkNumShards loop due to context done...") + return 0, errTimeIsOut + } + } +} + +func (processor *numShardsProcessor) tryGetnumShardsFromObserver(observerAddress string) (uint32, int) { + ctx, cancel := context.WithTimeout(context.Background(), processor.requestTimeout) + defer cancel() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, observerAddress+networkConfigPath, nil) + if err != nil { + return 0, http.StatusNotFound + } + + resp, err := processor.httpClient.Do(req) + if err != nil { + return 0, http.StatusNotFound + } + + defer func() { + if resp != nil && resp.Body != nil { + log.LogIfError(resp.Body.Close()) + } + }() + + if resp.StatusCode != http.StatusOK { + return 0, resp.StatusCode + } + + responseBodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + return 0, http.StatusInternalServerError + } + + var response networkConfigResponse + err = json.Unmarshal(responseBodyBytes, &response) + if err != nil { + return 0, http.StatusInternalServerError + } + + return response.Data.Config.NumShards, resp.StatusCode +} diff --git a/process/numShardsProcessor_test.go b/process/numShardsProcessor_test.go new file mode 100644 index 00000000..2111c784 --- /dev/null +++ b/process/numShardsProcessor_test.go @@ -0,0 +1,176 @@ +package process + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "io" + "net/http" + "strings" + "testing" + "time" + + "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-proxy-go/process/mock" + "github.com/stretchr/testify/require" +) + +func createMockArgNumShardsProcessor() ArgNumShardsProcessor { + return ArgNumShardsProcessor{ + HttpClient: &mock.HttpClientMock{}, + Observers: []string{"obs1, obs2"}, + TimeBetweenNodesRequestsInSec: 2, + NumShardsTimeoutInSec: 10, + RequestTimeoutInSec: 5, + } +} + +func TestNewNumShardsProcessor(t *testing.T) { + t.Parallel() + + t.Run("nil HttpClient should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgNumShardsProcessor() + args.HttpClient = nil + + proc, err := NewNumShardsProcessor(args) + require.Equal(t, ErrNilHttpClient, err) + require.Nil(t, proc) + }) + t.Run("empty observers list should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgNumShardsProcessor() + args.Observers = []string{} + + proc, err := NewNumShardsProcessor(args) + require.True(t, errors.Is(err, core.ErrInvalidValue)) + require.True(t, strings.Contains(err.Error(), "Observers")) + require.Nil(t, proc) + }) + t.Run("invalid TimeBetweenNodesRequestsInSec should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgNumShardsProcessor() + args.TimeBetweenNodesRequestsInSec = 0 + + proc, err := NewNumShardsProcessor(args) + require.True(t, errors.Is(err, core.ErrInvalidValue)) + require.True(t, strings.Contains(err.Error(), "TimeBetweenNodesRequestsInSec")) + require.Nil(t, proc) + }) + t.Run("invalid NumShardsTimeoutInSec should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgNumShardsProcessor() + args.NumShardsTimeoutInSec = 0 + + proc, err := NewNumShardsProcessor(args) + require.True(t, errors.Is(err, core.ErrInvalidValue)) + require.True(t, strings.Contains(err.Error(), "NumShardsTimeoutInSec")) + require.Nil(t, proc) + }) + t.Run("invalid RequestTimeoutInSec should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgNumShardsProcessor() + args.RequestTimeoutInSec = 0 + + proc, err := NewNumShardsProcessor(args) + require.True(t, errors.Is(err, core.ErrInvalidValue)) + require.True(t, strings.Contains(err.Error(), "RequestTimeoutInSec")) + require.Nil(t, proc) + }) + t.Run("should work", func(t *testing.T) { + t.Parallel() + + proc, err := NewNumShardsProcessor(createMockArgNumShardsProcessor()) + require.NoError(t, err) + require.NotNil(t, proc) + }) +} + +func TestNumShardsProcessor_GetNetworkNumShards(t *testing.T) { + t.Parallel() + + t.Run("context done should exit with timeout", func(t *testing.T) { + t.Parallel() + + args := createMockArgNumShardsProcessor() + args.TimeBetweenNodesRequestsInSec = 30 + args.NumShardsTimeoutInSec = 30 + + proc, err := NewNumShardsProcessor(args) + require.NoError(t, err) + + ctx, cancel := context.WithCancel(context.Background()) + go func() { + time.Sleep(time.Millisecond * 200) + cancel() + }() + numShards, err := proc.GetNetworkNumShards(ctx) + require.Equal(t, errTimeIsOut, err) + require.Zero(t, numShards) + }) + t.Run("timeout should exit with timeout", func(t *testing.T) { + t.Parallel() + + args := createMockArgNumShardsProcessor() + args.TimeBetweenNodesRequestsInSec = 30 + args.NumShardsTimeoutInSec = 1 + + proc, err := NewNumShardsProcessor(args) + require.NoError(t, err) + numShards, err := proc.GetNetworkNumShards(context.Background()) + require.True(t, errors.Is(err, errTimeIsOut)) + require.Zero(t, numShards) + }) + t.Run("should work on 4th observer", func(t *testing.T) { + t.Parallel() + + providedBody := &networkConfigResponse{ + Data: networkConfigResponseData{ + Config: struct { + NumShards uint32 `json:"erd_num_shards_without_meta"` + }(struct{ NumShards uint32 }{NumShards: 2}), + }, + } + providedBodyBuff, _ := json.Marshal(providedBody) + + args := createMockArgNumShardsProcessor() + args.TimeBetweenNodesRequestsInSec = 1 + args.NumShardsTimeoutInSec = 15 + cnt := 0 + args.HttpClient = &mock.HttpClientMock{ + DoCalled: func(req *http.Request) (*http.Response, error) { + cnt++ + switch cnt { + case 1: // error on Do + return nil, errors.New("observer offline") + case 2: // status code not 200 + return &http.Response{ + StatusCode: http.StatusBadRequest, + }, nil + case 3: // status code ok, but invalid response + return &http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(strings.NewReader("not the expected response")), + }, nil + default: // response ok + return &http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(bytes.NewReader(providedBodyBuff)), + }, nil + } + }, + } + + proc, err := NewNumShardsProcessor(args) + require.NoError(t, err) + numShards, err := proc.GetNetworkNumShards(context.Background()) + require.NoError(t, err) + require.Equal(t, uint32(2), numShards) + }) +} From 2e35868d64c61a233eea9d2d7a36cefc0267b135 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Tue, 1 Oct 2024 11:56:36 +0300 Subject: [PATCH 40/40] fixes after review --- cmd/proxy/main.go | 48 ++++++++++++++++++++--------------- process/numShardsProcessor.go | 6 +---- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 21b66cb7..05295c1f 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -408,27 +408,7 @@ func createVersionsRegistry( return nil, err } - httpClient := &http.Client{} - httpClient.Timeout = time.Duration(cfg.GeneralSettings.RequestTimeoutSec) * time.Second - observersList := make([]string, 0, len(cfg.Observers)) - for _, node := range cfg.Observers { - observersList = append(observersList, node.Address) - } - argsNumShardsProcessor := process.ArgNumShardsProcessor{ - HttpClient: httpClient, - Observers: observersList, - TimeBetweenNodesRequestsInSec: cfg.GeneralSettings.TimeBetweenNodesRequestsInSec, - NumShardsTimeoutInSec: cfg.GeneralSettings.NumShardsTimeoutInSec, - RequestTimeoutInSec: cfg.GeneralSettings.RequestTimeoutSec, - } - numShardsProcessor, err := process.NewNumShardsProcessor(argsNumShardsProcessor) - if err != nil { - return nil, err - } - - ctx, cancel := context.WithCancel(context.Background()) - numShards, err := numShardsProcessor.GetNetworkNumShards(ctx) - cancel() + numShards, err := getNumOfShards(cfg) if err != nil { return nil, err } @@ -636,6 +616,32 @@ func waitForServerShutdown(httpServer *http.Server, closableComponents *data.Clo _ = httpServer.Close() } +// getNumOfShards will delay the start of proxy until it successfully gets the number of shards +func getNumOfShards(cfg *config.Config) (uint32, error) { + httpClient := &http.Client{} + httpClient.Timeout = time.Duration(cfg.GeneralSettings.RequestTimeoutSec) * time.Second + observersList := make([]string, 0, len(cfg.Observers)) + for _, node := range cfg.Observers { + observersList = append(observersList, node.Address) + } + argsNumShardsProcessor := process.ArgNumShardsProcessor{ + HttpClient: httpClient, + Observers: observersList, + TimeBetweenNodesRequestsInSec: cfg.GeneralSettings.TimeBetweenNodesRequestsInSec, + NumShardsTimeoutInSec: cfg.GeneralSettings.NumShardsTimeoutInSec, + RequestTimeoutInSec: cfg.GeneralSettings.RequestTimeoutSec, + } + numShardsProcessor, err := process.NewNumShardsProcessor(argsNumShardsProcessor) + if err != nil { + return 0, err + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + return numShardsProcessor.GetNetworkNumShards(ctx) +} + func removeLogColors() { err := logger.RemoveLogObserver(os.Stdout) if err != nil { diff --git a/process/numShardsProcessor.go b/process/numShardsProcessor.go index 8a9d907c..3062e361 100644 --- a/process/numShardsProcessor.go +++ b/process/numShardsProcessor.go @@ -15,10 +15,6 @@ import ( var errTimeIsOut = errors.New("time is out") -const ( - networkConfigPath = "/network/config" -) - type networkConfigResponseData struct { Config struct { NumShards uint32 `json:"erd_num_shards_without_meta"` @@ -112,7 +108,7 @@ func (processor *numShardsProcessor) tryGetnumShardsFromObserver(observerAddress ctx, cancel := context.WithTimeout(context.Background(), processor.requestTimeout) defer cancel() - req, err := http.NewRequestWithContext(ctx, http.MethodGet, observerAddress+networkConfigPath, nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, observerAddress+NetworkConfigPath, nil) if err != nil { return 0, http.StatusNotFound }