From bff5ae4b37e63f1e27a5f87640343ff6214db19f Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 10 Oct 2024 12:52:00 +0300 Subject: [PATCH 1/3] new core-go --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d578cbd1..2d057cf9 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,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.22 + github.com/multiversx/mx-chain-core-go v1.2.23-0.20241010094929-2bbea4371d73 github.com/multiversx/mx-chain-crypto-go v1.2.12 github.com/multiversx/mx-chain-es-indexer-go v1.7.8 github.com/multiversx/mx-chain-logger-go v1.0.15 diff --git a/go.sum b/go.sum index 5e15844f..3f4bda86 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,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.22 h1:yDYrvoQOBbsDerEp7L3+de5AfMy3pTF333gWPpd+FNk= -github.com/multiversx/mx-chain-core-go v1.2.22/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-core-go v1.2.23-0.20241010094929-2bbea4371d73 h1:+pnMCOuqq3kbGB+vBfzKebPOe1WVOVEHIfyEbgGnNt0= +github.com/multiversx/mx-chain-core-go v1.2.23-0.20241010094929-2bbea4371d73/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.8 h1:ZDKTXkQhQ7lLi6huVrBTUssVEqCvaCxGH4Y52GapboQ= From 5d5e537d2ca06a3dfa74704bba640bb94f50b02d Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Fri, 11 Oct 2024 20:26:18 +0300 Subject: [PATCH 2/3] relayed v3 get transaction response improved + support for inner tx --- README.md | 1 + api/groups/baseTransactionGroup.go | 2 +- api/groups/interface.go | 2 +- api/groups/urlParams.go | 7 +- api/mock/facadeStub.go | 6 +- cmd/proxy/config/swagger/openapi.json | 2 +- common/options.go | 5 +- facade/baseFacade.go | 4 +- facade/interface.go | 2 +- facade/mock/transactionProcessorStub.go | 6 +- process/errors.go | 3 + process/transactionProcessor.go | 91 +++++++++- process/transactionProcessor_test.go | 223 +++++++++++++++++++++++- 13 files changed, 332 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 9262d6c1..47b70dc7 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ For more details, go [here](https://docs.multiversx.com/sdk-and-tools/proxy/). - `/v1.0/transaction/cost` (POST) --> receives a single transaction in JSON format and returns it's cost - `/v1.0/transaction/:txHash` (GET) --> returns the transaction which corresponds to the hash - `/v1.0/transaction/:txHash?withResults=true` (GET) --> returns the transaction and results which correspond to the hash +- `/v1.0/transaction/:txHash?withResults=true&withRelayedTxHash=:relayedTxHash` (GET) --> returns the inner transaction which corresponds to the hash and was part of the relayedTxHash - `/v1.0/transaction/:txHash?sender=senderAddress` (GET) --> returns the transaction which corresponds to the hash (faster because will ask for transaction from the observer which is in the shard in which the address is part). - `/v1.0/transaction/:txHash?sender=senderAddress&withResults=true` (GET) --> returns the transaction and results which correspond to the hash (faster because will ask for transaction from observer which is in the shard in which the address is part) - `/v1.0/transaction/:txHash/status` (GET) --> returns the status of the transaction which corresponds to the hash diff --git a/api/groups/baseTransactionGroup.go b/api/groups/baseTransactionGroup.go index fc33e52c..d7d56597 100644 --- a/api/groups/baseTransactionGroup.go +++ b/api/groups/baseTransactionGroup.go @@ -239,7 +239,7 @@ func (group *transactionGroup) getTransaction(c *gin.Context) { return } - tx, err := group.facade.GetTransaction(txHash, options.WithResults) + tx, err := group.facade.GetTransaction(txHash, options.WithResults, options.WithRelayedTxHash) if err != nil { shared.RespondWith(c, http.StatusInternalServerError, nil, err.Error(), data.ReturnCodeInternalError) return diff --git a/api/groups/interface.go b/api/groups/interface.go index f5a4e4fd..b88226bd 100644 --- a/api/groups/interface.go +++ b/api/groups/interface.go @@ -95,7 +95,7 @@ type TransactionFacadeHandler interface { TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error) GetTransactionStatus(txHash string, sender string) (string, error) GetProcessedTransactionStatus(txHash string) (*data.ProcessStatusResponse, error) - GetTransaction(txHash string, withResults bool) (*transaction.ApiTransactionResult, error) + GetTransaction(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) GetTransactionsPool(fields string) (*data.TransactionsPool, error) GetTransactionsPoolForShard(shardID uint32, fields string) (*data.TransactionsPool, error) diff --git a/api/groups/urlParams.go b/api/groups/urlParams.go index 1aa3c140..f12149bd 100644 --- a/api/groups/urlParams.go +++ b/api/groups/urlParams.go @@ -124,7 +124,12 @@ func parseTransactionQueryOptions(c *gin.Context) (common.TransactionQueryOption return common.TransactionQueryOptions{}, err } - options := common.TransactionQueryOptions{WithResults: withResults} + withRelayedTxHash := parseStringUrlParam(c, common.UrlParameterWithRelayedTxHash) + + options := common.TransactionQueryOptions{ + WithResults: withResults, + WithRelayedTxHash: withRelayedTxHash, + } return options, nil } diff --git a/api/mock/facadeStub.go b/api/mock/facadeStub.go index 66417554..a8cac506 100644 --- a/api/mock/facadeStub.go +++ b/api/mock/facadeStub.go @@ -24,7 +24,7 @@ type FacadeStub struct { GetNFTTokenIDsRegisteredByAddressCalled func(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) GetAllESDTTokensCalled func(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) GetTransactionsHandler func(address string) ([]data.DatabaseTransaction, error) - GetTransactionHandler func(txHash string, withResults bool) (*transaction.ApiTransactionResult, error) + GetTransactionHandler func(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) GetTransactionsPoolHandler func(fields string) (*data.TransactionsPool, error) GetTransactionsPoolForShardHandler func(shardID uint32, fields string) (*data.TransactionsPool, error) GetTransactionsPoolForSenderHandler func(sender, fields string) (*data.TransactionsPoolForSender, error) @@ -343,8 +343,8 @@ func (f *FacadeStub) GetTransactionByHashAndSenderAddress(txHash string, sndAddr } // GetTransaction - -func (f *FacadeStub) GetTransaction(txHash string, withResults bool) (*transaction.ApiTransactionResult, error) { - return f.GetTransactionHandler(txHash, withResults) +func (f *FacadeStub) GetTransaction(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) { + return f.GetTransactionHandler(txHash, withResults, withRelayedTxHash) } // GetTransactionsPool - diff --git a/cmd/proxy/config/swagger/openapi.json b/cmd/proxy/config/swagger/openapi.json index 8d3b7497..2571b156 100644 --- a/cmd/proxy/config/swagger/openapi.json +++ b/cmd/proxy/config/swagger/openapi.json @@ -2042,7 +2042,7 @@ } } }, - "/transaction/{txHash}?withResults=true": { + "/transaction/{txHash}?withResults=true&withRelayedTxHash={relayedTxHash}": { "get": { "tags": [ "transaction" diff --git a/common/options.go b/common/options.go index b39df0f6..37723d63 100644 --- a/common/options.go +++ b/common/options.go @@ -49,6 +49,8 @@ const ( UrlParameterWithAlteredAccounts = "withAlteredAccounts" // UrlParameterWithKeys represents the name of an URL parameter UrlParameterWithKeys = "withKeys" + // UrlParameterWithRelayedTxHash represents the name of an URL parameter + UrlParameterWithRelayedTxHash = "withRelayedTxHash" ) // BlockQueryOptions holds options for block queries @@ -67,7 +69,8 @@ type HyperblockQueryOptions struct { // TransactionQueryOptions holds options for transaction queries type TransactionQueryOptions struct { - WithResults bool + WithResults bool + WithRelayedTxHash string } // TransactionSimulationOptions holds options for transaction simulation requests diff --git a/facade/baseFacade.go b/facade/baseFacade.go index 3dd96691..6625cd1e 100644 --- a/facade/baseFacade.go +++ b/facade/baseFacade.go @@ -221,8 +221,8 @@ func (pf *ProxyFacade) GetProcessedTransactionStatus(txHash string) (*data.Proce } // GetTransaction should return a transaction by hash -func (pf *ProxyFacade) GetTransaction(txHash string, withResults bool) (*transaction.ApiTransactionResult, error) { - return pf.txProc.GetTransaction(txHash, withResults) +func (pf *ProxyFacade) GetTransaction(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) { + return pf.txProc.GetTransaction(txHash, withResults, withRelayedTxHash) } // ReloadObservers will try to reload the observers diff --git a/facade/interface.go b/facade/interface.go index 9ed6c19c..b1df6fdf 100644 --- a/facade/interface.go +++ b/facade/interface.go @@ -41,7 +41,7 @@ type TransactionProcessor interface { SimulateTransaction(tx *data.Transaction, checkSignature bool) (*data.GenericAPIResponse, error) TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error) GetTransactionStatus(txHash string, sender string) (string, error) - GetTransaction(txHash string, withEvents bool) (*transaction.ApiTransactionResult, error) + GetTransaction(txHash string, withEvents bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) GetProcessedTransactionStatus(txHash string) (*data.ProcessStatusResponse, error) GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) ComputeTransactionHash(tx *data.Transaction) (string, error) diff --git a/facade/mock/transactionProcessorStub.go b/facade/mock/transactionProcessorStub.go index 599cb80d..c3603683 100644 --- a/facade/mock/transactionProcessorStub.go +++ b/facade/mock/transactionProcessorStub.go @@ -19,7 +19,7 @@ type TransactionProcessorStub struct { TransactionCostRequestCalled func(tx *data.Transaction) (*data.TxCostResponseData, error) GetTransactionStatusCalled func(txHash string, sender string) (string, error) GetProcessedTransactionStatusCalled func(txHash string) (*data.ProcessStatusResponse, error) - GetTransactionCalled func(txHash string, withEvents bool) (*transaction.ApiTransactionResult, error) + GetTransactionCalled func(txHash string, withEvents bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) GetTransactionByHashAndSenderAddressCalled func(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) ComputeTransactionHashCalled func(tx *data.Transaction) (string, error) GetTransactionsPoolCalled func(fields string) (*data.TransactionsPool, error) @@ -93,9 +93,9 @@ func (tps *TransactionProcessorStub) GetProcessedTransactionStatus(txHash string } // GetTransaction - -func (tps *TransactionProcessorStub) GetTransaction(txHash string, withEvents bool) (*transaction.ApiTransactionResult, error) { +func (tps *TransactionProcessorStub) GetTransaction(txHash string, withEvents bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) { if tps.GetTransactionCalled != nil { - return tps.GetTransactionCalled(txHash, withEvents) + return tps.GetTransactionCalled(txHash, withEvents, withRelayedTxHash) } return nil, errNotImplemented diff --git a/process/errors.go b/process/errors.go index 8060b7b4..d699e183 100644 --- a/process/errors.go +++ b/process/errors.go @@ -112,3 +112,6 @@ 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") + +// ErrInvalidHash signals that an invalid hash has been provided +var ErrInvalidHash = errors.New("invalid hash") diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index d2d85ba8..ec0a127a 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -359,8 +359,16 @@ func (tp *TransactionProcessor) TransactionCostRequest(tx *data.Transaction) (*d } // GetTransaction should return a transaction from observer -func (tp *TransactionProcessor) GetTransaction(txHash string, withResults bool) (*transaction.ApiTransactionResult, error) { - tx, err := tp.getTxFromObservers(txHash, requestTypeFullHistoryNodes, withResults) +func (tp *TransactionProcessor) GetTransaction(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) { + txHashToGetFromObservers := txHash + + // if the relayed tx hash was provided, this one should be requested from observers + innerTxRequested := len(withRelayedTxHash) == len(txHash) + if innerTxRequested { + txHashToGetFromObservers = withRelayedTxHash + } + + tx, err := tp.getTxFromObservers(txHashToGetFromObservers, requestTypeFullHistoryNodes, withResults) if err != nil { return nil, err } @@ -368,7 +376,82 @@ func (tp *TransactionProcessor) GetTransaction(txHash string, withResults bool) tx.HyperblockNonce = tx.NotarizedAtDestinationInMetaNonce tx.HyperblockHash = tx.NotarizedAtDestinationInMetaHash - return tx, nil + if len(tx.InnerTransactions) == 0 { + if innerTxRequested { + return nil, fmt.Errorf("%w, requested hash %s with relayedTxHash %s, but the relayedTxHash has no inner transaction", + ErrInvalidHash, txHash, withRelayedTxHash) + } + + return tx, nil + } + + convertRelayedTxV3ToNetworkTx(tx) + + // requested a relayed transaction, returning it after scrs were moved + if !innerTxRequested { + return tx, nil + } + + for _, innerTx := range tx.InnerTransactions { + if innerTx.Hash == txHash { + return innerTx, nil + } + } + + return nil, fmt.Errorf("%w, but the relayedTx %s has no inner transaction with hash %s", + ErrInvalidHash, withRelayedTxHash, txHash) +} + +func convertRelayedTxV3ToNetworkTx(tx *transaction.ApiTransactionResult) { + movedSCRs := make(map[string]struct{}, 0) + for _, innerTx := range tx.InnerTransactions { + for _, scr := range tx.SmartContractResults { + if isResultOfInnerTx(tx.SmartContractResults, scr, innerTx.Hash) { + innerTx.SmartContractResults = append(innerTx.SmartContractResults, scr) + movedSCRs[scr.Hash] = struct{}{} + } + } + } + + if len(movedSCRs) == len(tx.SmartContractResults) { + // all scrs were generated by inner txs + tx.SmartContractResults = make([]*transaction.ApiSmartContractResult, 0) + return + } + + numSCRsLeftForRelayer := len(tx.SmartContractResults) - len(movedSCRs) + scrsForRelayer := make([]*transaction.ApiSmartContractResult, 0, numSCRsLeftForRelayer) + for _, scr := range tx.SmartContractResults { + _, wasMoved := movedSCRs[scr.Hash] + if !wasMoved { + scrsForRelayer = append(scrsForRelayer, scr) + } + } + + tx.SmartContractResults = scrsForRelayer +} + +func isResultOfInnerTx(allScrs []*transaction.ApiSmartContractResult, currentScr *transaction.ApiSmartContractResult, innerTxHash string) bool { + if currentScr.PrevTxHash == innerTxHash { + return true + } + + parentScr := getParentSCR(allScrs, currentScr.PrevTxHash) + if check.IfNilReflect(parentScr) { + return false + } + + return isResultOfInnerTx(allScrs, parentScr, innerTxHash) +} + +func getParentSCR(allScrs []*transaction.ApiSmartContractResult, hash string) *transaction.ApiSmartContractResult { + for _, scr := range allScrs { + if scr.Hash == hash { + return scr + } + } + + return nil } // GetTransactionByHashAndSenderAddress returns a transaction @@ -712,7 +795,7 @@ func (tp *TransactionProcessor) gatherAllLogsAndScrs(tx *transaction.ApiTransact } for _, scrFromTx := range tx.SmartContractResults { - scr, err := tp.GetTransaction(scrFromTx.Hash, withResults) + scr, err := tp.GetTransaction(scrFromTx.Hash, withResults, "") if err != nil { return nil, nil, fmt.Errorf("%w for scr hash %s", err, scrFromTx.Hash) } diff --git a/process/transactionProcessor_test.go b/process/transactionProcessor_test.go index 4e551aff..a2f18248 100644 --- a/process/transactionProcessor_test.go +++ b/process/transactionProcessor_test.go @@ -1107,11 +1107,226 @@ func TestTransactionProcessor_GetTransactionShouldWork(t *testing.T) { true, ) - tx, err := tp.GetTransaction(string(hash0), false) + tx, err := tp.GetTransaction(string(hash0), false, "") assert.NoError(t, err) assert.Equal(t, expectedNonce, tx.Nonce) } +func TestTransactionProcessor_GetTransactionShouldWorkForRelayedV3(t *testing.T) { + t.Parallel() + + t.Run("for relayed tx", func(t *testing.T) { + t.Parallel() + + providedRelayedNonce := uint64(37) + providedInnerNonce := uint64(38) + + sndrShard0 := hex.EncodeToString([]byte("bbbbbb")) + sndrShard1 := hex.EncodeToString([]byte("cccccc")) + + addrObs0 := "observer0" + addrObs1 := "observer1" + + hashRelayed := []byte("hashRelayed") + hashInner := []byte("hashInner") + hashInnerScr := []byte("hashInnerScr") + hashRelayedScr := []byte("hashRelayedScr") + providedInnerTx := &transaction.ApiTransactionResult{ + Hash: string(hashInner), + Nonce: providedInnerNonce, + } + providedInnerScr := &transaction.ApiSmartContractResult{ + Hash: string(hashInnerScr), + PrevTxHash: string(hashInner), + OriginalTxHash: string(hashRelayed), + } + providedRelayedScr := &transaction.ApiSmartContractResult{ + Hash: string(hashRelayedScr), + PrevTxHash: string(hashRelayed), + OriginalTxHash: string(hashRelayed), + } + providedTx := transaction.ApiTransactionResult{ + Hash: string(hashRelayed), + Nonce: providedRelayedNonce, + InnerTransactions: []*transaction.ApiTransactionResult{providedInnerTx}, + SmartContractResults: []*transaction.ApiSmartContractResult{ + providedInnerScr, + providedRelayedScr, + }, + } + tp, _ := process.NewTransactionProcessor( + &mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (uint32, error) { + sndrHex := hex.EncodeToString(addressBuff) + if sndrHex == sndrShard0 { + return uint32(0), nil + } + if sndrHex == sndrShard1 { + return uint32(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: addrObs1, ShardId: 1}, + }, nil + } + return nil, nil + }, + CallGetRestEndPointCalled: func(address string, path string, value interface{}) (i int, err error) { + if address == addrObs0 { + if strings.Contains(path, "scr") { + return http.StatusOK, nil + } + + responseGetTx := value.(*data.GetTransactionResponse) + + responseGetTx.Data.Transaction = providedTx + return http.StatusOK, nil + } + + return http.StatusBadGateway, nil + }, + }, + &mock.PubKeyConverterMock{}, + hasher, + marshalizer, + funcNewTxCostHandler, + logsMerger, + true, + ) + + tx, err := tp.GetTransaction(string(hashRelayedScr), false, "") + assert.NoError(t, err) + + expectedInnerTx := *providedInnerTx + expectedInnerTx.SmartContractResults = []*transaction.ApiSmartContractResult{providedInnerScr} + expectedTx := &transaction.ApiTransactionResult{ + Hash: string(hashRelayed), + Nonce: providedRelayedNonce, + SmartContractResults: []*transaction.ApiSmartContractResult{providedRelayedScr}, + InnerTransactions: []*transaction.ApiTransactionResult{&expectedInnerTx}, + } + require.Equal(t, expectedTx, tx) + }) + t.Run("for inner tx", func(t *testing.T) { + t.Parallel() + + providedRelayedNonce := uint64(37) + providedInnerNonce := uint64(38) + + sndrShard0 := hex.EncodeToString([]byte("bbbbbb")) + sndrShard1 := hex.EncodeToString([]byte("cccccc")) + + addrObs0 := "observer0" + addrObs1 := "observer1" + + hashRelayed := []byte("hashRelayed") + hashInner := []byte("hashInnerrr") // same length with hashRelayed + hashInnerScr := []byte("hashInnerScr") + hashInnerScrLayerTwo := []byte("hashInnerScrLayerTwo") + hashRelayedScr := []byte("hashRelayedScr") + providedInnerTx := &transaction.ApiTransactionResult{ + Hash: string(hashInner), + Nonce: providedInnerNonce, + } + providedInnerScr := &transaction.ApiSmartContractResult{ + Hash: string(hashInnerScr), + PrevTxHash: string(hashInner), + OriginalTxHash: string(hashRelayed), + } + providedInnerScrLayerTwo := &transaction.ApiSmartContractResult{ + Hash: string(hashInnerScrLayerTwo), + PrevTxHash: string(hashInnerScr), + OriginalTxHash: string(hashRelayed), + } + providedRelayedScr := &transaction.ApiSmartContractResult{ + Hash: string(hashRelayedScr), + PrevTxHash: string(hashRelayed), + OriginalTxHash: string(hashRelayed), + } + providedTx := transaction.ApiTransactionResult{ + Hash: string(hashRelayed), + Nonce: providedRelayedNonce, + InnerTransactions: []*transaction.ApiTransactionResult{providedInnerTx}, + SmartContractResults: []*transaction.ApiSmartContractResult{ + providedInnerScr, + providedRelayedScr, + providedInnerScrLayerTwo, + }, + } + tp, _ := process.NewTransactionProcessor( + &mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (uint32, error) { + sndrHex := hex.EncodeToString(addressBuff) + if sndrHex == sndrShard0 { + return uint32(0), nil + } + if sndrHex == sndrShard1 { + return uint32(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: addrObs1, ShardId: 1}, + }, nil + } + return nil, nil + }, + CallGetRestEndPointCalled: func(address string, path string, value interface{}) (i int, err error) { + if address == addrObs0 { + if strings.Contains(path, "scr") { + return http.StatusOK, nil + } + + responseGetTx := value.(*data.GetTransactionResponse) + + responseGetTx.Data.Transaction = providedTx + return http.StatusOK, nil + } + + return http.StatusBadGateway, nil + }, + }, + &mock.PubKeyConverterMock{}, + hasher, + marshalizer, + funcNewTxCostHandler, + logsMerger, + true, + ) + + tx, err := tp.GetTransaction(string(hashInner), false, string(hashRelayed)) + assert.NoError(t, err) + + expectedInnerTx := *providedInnerTx + expectedInnerTx.SmartContractResults = []*transaction.ApiSmartContractResult{providedInnerScr, providedInnerScrLayerTwo} + if tx.SmartContractResults[0].Hash == providedInnerScrLayerTwo.Hash { // match the order of scrs to avoid random failing + expectedInnerTx.SmartContractResults = []*transaction.ApiSmartContractResult{providedInnerScrLayerTwo, providedInnerScr} + } + require.Equal(t, &expectedInnerTx, tx) + }) +} + func TestTransactionProcessor_GetTransactionShouldCallOtherObserverInShardIfHttpError(t *testing.T) { t.Parallel() @@ -1157,7 +1372,7 @@ func TestTransactionProcessor_GetTransactionShouldCallOtherObserverInShardIfHttp true, ) - _, _ = tp.GetTransaction(string(hash0), false) + _, _ = tp.GetTransaction(string(hash0), false, "") assert.True(t, secondObserverWasCalled) } @@ -1203,7 +1418,7 @@ func TestTransactionProcessor_GetTransactionShouldNotCallOtherObserverInShardIfN true, ) - _, _ = tp.GetTransaction(string(hash0), false) + _, _ = tp.GetTransaction(string(hash0), false, "") } func TestTransactionProcessor_GetTransactionWithEventsFirstFromDstShardAndAfterSource(t *testing.T) { @@ -1316,7 +1531,7 @@ func TestTransactionProcessor_GetTransactionWithEventsFirstFromDstShardAndAfterS true, ) - tx, err := tp.GetTransaction(string(hash0), true) + tx, err := tp.GetTransaction(string(hash0), true, "") assert.NoError(t, err) assert.Equal(t, expectedNonce, tx.Nonce) assert.Equal(t, 3, len(tx.SmartContractResults)) From 2f4f269bb7e9397eb6f3804f2d566277e7b25a49 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 14 Oct 2024 09:44:04 +0300 Subject: [PATCH 3/3] fixes after review --- README.md | 2 +- api/groups/baseTransactionGroup.go | 2 +- api/groups/interface.go | 2 +- api/groups/urlParams.go | 6 +++--- api/mock/facadeStub.go | 6 +++--- cmd/proxy/config/swagger/openapi.json | 2 +- common/options.go | 8 ++++---- facade/baseFacade.go | 4 ++-- facade/interface.go | 2 +- facade/mock/transactionProcessorStub.go | 6 +++--- process/transactionProcessor.go | 14 +++++++------- 11 files changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 47b70dc7..d6548f2f 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ For more details, go [here](https://docs.multiversx.com/sdk-and-tools/proxy/). - `/v1.0/transaction/cost` (POST) --> receives a single transaction in JSON format and returns it's cost - `/v1.0/transaction/:txHash` (GET) --> returns the transaction which corresponds to the hash - `/v1.0/transaction/:txHash?withResults=true` (GET) --> returns the transaction and results which correspond to the hash -- `/v1.0/transaction/:txHash?withResults=true&withRelayedTxHash=:relayedTxHash` (GET) --> returns the inner transaction which corresponds to the hash and was part of the relayedTxHash +- `/v1.0/transaction/:txHash?withResults=true&relayedTxHash=:relayedTxHash` (GET) --> returns the inner transaction which corresponds to the hash and was part of the relayedTxHash - `/v1.0/transaction/:txHash?sender=senderAddress` (GET) --> returns the transaction which corresponds to the hash (faster because will ask for transaction from the observer which is in the shard in which the address is part). - `/v1.0/transaction/:txHash?sender=senderAddress&withResults=true` (GET) --> returns the transaction and results which correspond to the hash (faster because will ask for transaction from observer which is in the shard in which the address is part) - `/v1.0/transaction/:txHash/status` (GET) --> returns the status of the transaction which corresponds to the hash diff --git a/api/groups/baseTransactionGroup.go b/api/groups/baseTransactionGroup.go index d7d56597..372771a4 100644 --- a/api/groups/baseTransactionGroup.go +++ b/api/groups/baseTransactionGroup.go @@ -239,7 +239,7 @@ func (group *transactionGroup) getTransaction(c *gin.Context) { return } - tx, err := group.facade.GetTransaction(txHash, options.WithResults, options.WithRelayedTxHash) + tx, err := group.facade.GetTransaction(txHash, options.WithResults, options.RelayedTxHash) if err != nil { shared.RespondWith(c, http.StatusInternalServerError, nil, err.Error(), data.ReturnCodeInternalError) return diff --git a/api/groups/interface.go b/api/groups/interface.go index b88226bd..ef95bc14 100644 --- a/api/groups/interface.go +++ b/api/groups/interface.go @@ -95,7 +95,7 @@ type TransactionFacadeHandler interface { TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error) GetTransactionStatus(txHash string, sender string) (string, error) GetProcessedTransactionStatus(txHash string) (*data.ProcessStatusResponse, error) - GetTransaction(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) + GetTransaction(txHash string, withResults bool, relayedTxHash string) (*transaction.ApiTransactionResult, error) GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) GetTransactionsPool(fields string) (*data.TransactionsPool, error) GetTransactionsPoolForShard(shardID uint32, fields string) (*data.TransactionsPool, error) diff --git a/api/groups/urlParams.go b/api/groups/urlParams.go index f12149bd..a10d2e75 100644 --- a/api/groups/urlParams.go +++ b/api/groups/urlParams.go @@ -124,11 +124,11 @@ func parseTransactionQueryOptions(c *gin.Context) (common.TransactionQueryOption return common.TransactionQueryOptions{}, err } - withRelayedTxHash := parseStringUrlParam(c, common.UrlParameterWithRelayedTxHash) + relayedTxHash := parseStringUrlParam(c, common.UrlParameterRelayedTxHash) options := common.TransactionQueryOptions{ - WithResults: withResults, - WithRelayedTxHash: withRelayedTxHash, + WithResults: withResults, + RelayedTxHash: relayedTxHash, } return options, nil } diff --git a/api/mock/facadeStub.go b/api/mock/facadeStub.go index a8cac506..8d039897 100644 --- a/api/mock/facadeStub.go +++ b/api/mock/facadeStub.go @@ -24,7 +24,7 @@ type FacadeStub struct { GetNFTTokenIDsRegisteredByAddressCalled func(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) GetAllESDTTokensCalled func(address string, options common.AccountQueryOptions) (*data.GenericAPIResponse, error) GetTransactionsHandler func(address string) ([]data.DatabaseTransaction, error) - GetTransactionHandler func(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) + GetTransactionHandler func(txHash string, withResults bool, relayedTxHash string) (*transaction.ApiTransactionResult, error) GetTransactionsPoolHandler func(fields string) (*data.TransactionsPool, error) GetTransactionsPoolForShardHandler func(shardID uint32, fields string) (*data.TransactionsPool, error) GetTransactionsPoolForSenderHandler func(sender, fields string) (*data.TransactionsPoolForSender, error) @@ -343,8 +343,8 @@ func (f *FacadeStub) GetTransactionByHashAndSenderAddress(txHash string, sndAddr } // GetTransaction - -func (f *FacadeStub) GetTransaction(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) { - return f.GetTransactionHandler(txHash, withResults, withRelayedTxHash) +func (f *FacadeStub) GetTransaction(txHash string, withResults bool, relayedTxHash string) (*transaction.ApiTransactionResult, error) { + return f.GetTransactionHandler(txHash, withResults, relayedTxHash) } // GetTransactionsPool - diff --git a/cmd/proxy/config/swagger/openapi.json b/cmd/proxy/config/swagger/openapi.json index 2571b156..fef088d4 100644 --- a/cmd/proxy/config/swagger/openapi.json +++ b/cmd/proxy/config/swagger/openapi.json @@ -2042,7 +2042,7 @@ } } }, - "/transaction/{txHash}?withResults=true&withRelayedTxHash={relayedTxHash}": { + "/transaction/{txHash}?withResults=true&relayedTxHash={relayedTxHash}": { "get": { "tags": [ "transaction" diff --git a/common/options.go b/common/options.go index 37723d63..fc9a356b 100644 --- a/common/options.go +++ b/common/options.go @@ -49,8 +49,8 @@ const ( UrlParameterWithAlteredAccounts = "withAlteredAccounts" // UrlParameterWithKeys represents the name of an URL parameter UrlParameterWithKeys = "withKeys" - // UrlParameterWithRelayedTxHash represents the name of an URL parameter - UrlParameterWithRelayedTxHash = "withRelayedTxHash" + // UrlParameterRelayedTxHash represents the name of an URL parameter + UrlParameterRelayedTxHash = "relayedTxHash" ) // BlockQueryOptions holds options for block queries @@ -69,8 +69,8 @@ type HyperblockQueryOptions struct { // TransactionQueryOptions holds options for transaction queries type TransactionQueryOptions struct { - WithResults bool - WithRelayedTxHash string + WithResults bool + RelayedTxHash string } // TransactionSimulationOptions holds options for transaction simulation requests diff --git a/facade/baseFacade.go b/facade/baseFacade.go index 6625cd1e..0e6fcb5a 100644 --- a/facade/baseFacade.go +++ b/facade/baseFacade.go @@ -221,8 +221,8 @@ func (pf *ProxyFacade) GetProcessedTransactionStatus(txHash string) (*data.Proce } // GetTransaction should return a transaction by hash -func (pf *ProxyFacade) GetTransaction(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) { - return pf.txProc.GetTransaction(txHash, withResults, withRelayedTxHash) +func (pf *ProxyFacade) GetTransaction(txHash string, withResults bool, relayedTxHash string) (*transaction.ApiTransactionResult, error) { + return pf.txProc.GetTransaction(txHash, withResults, relayedTxHash) } // ReloadObservers will try to reload the observers diff --git a/facade/interface.go b/facade/interface.go index b1df6fdf..9bb5361d 100644 --- a/facade/interface.go +++ b/facade/interface.go @@ -41,7 +41,7 @@ type TransactionProcessor interface { SimulateTransaction(tx *data.Transaction, checkSignature bool) (*data.GenericAPIResponse, error) TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error) GetTransactionStatus(txHash string, sender string) (string, error) - GetTransaction(txHash string, withEvents bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) + GetTransaction(txHash string, withEvents bool, relayedTxHash string) (*transaction.ApiTransactionResult, error) GetProcessedTransactionStatus(txHash string) (*data.ProcessStatusResponse, error) GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) ComputeTransactionHash(tx *data.Transaction) (string, error) diff --git a/facade/mock/transactionProcessorStub.go b/facade/mock/transactionProcessorStub.go index c3603683..30a2b7fd 100644 --- a/facade/mock/transactionProcessorStub.go +++ b/facade/mock/transactionProcessorStub.go @@ -19,7 +19,7 @@ type TransactionProcessorStub struct { TransactionCostRequestCalled func(tx *data.Transaction) (*data.TxCostResponseData, error) GetTransactionStatusCalled func(txHash string, sender string) (string, error) GetProcessedTransactionStatusCalled func(txHash string) (*data.ProcessStatusResponse, error) - GetTransactionCalled func(txHash string, withEvents bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) + GetTransactionCalled func(txHash string, withEvents bool, relayedTxHash string) (*transaction.ApiTransactionResult, error) GetTransactionByHashAndSenderAddressCalled func(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) ComputeTransactionHashCalled func(tx *data.Transaction) (string, error) GetTransactionsPoolCalled func(fields string) (*data.TransactionsPool, error) @@ -93,9 +93,9 @@ func (tps *TransactionProcessorStub) GetProcessedTransactionStatus(txHash string } // GetTransaction - -func (tps *TransactionProcessorStub) GetTransaction(txHash string, withEvents bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) { +func (tps *TransactionProcessorStub) GetTransaction(txHash string, withEvents bool, relayedTxHash string) (*transaction.ApiTransactionResult, error) { if tps.GetTransactionCalled != nil { - return tps.GetTransactionCalled(txHash, withEvents, withRelayedTxHash) + return tps.GetTransactionCalled(txHash, withEvents, relayedTxHash) } return nil, errNotImplemented diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index ec0a127a..db27c190 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -359,13 +359,13 @@ func (tp *TransactionProcessor) TransactionCostRequest(tx *data.Transaction) (*d } // GetTransaction should return a transaction from observer -func (tp *TransactionProcessor) GetTransaction(txHash string, withResults bool, withRelayedTxHash string) (*transaction.ApiTransactionResult, error) { +func (tp *TransactionProcessor) GetTransaction(txHash string, withResults bool, relayedTxHash string) (*transaction.ApiTransactionResult, error) { txHashToGetFromObservers := txHash // if the relayed tx hash was provided, this one should be requested from observers - innerTxRequested := len(withRelayedTxHash) == len(txHash) + innerTxRequested := len(relayedTxHash) == len(txHash) if innerTxRequested { - txHashToGetFromObservers = withRelayedTxHash + txHashToGetFromObservers = relayedTxHash } tx, err := tp.getTxFromObservers(txHashToGetFromObservers, requestTypeFullHistoryNodes, withResults) @@ -379,7 +379,7 @@ func (tp *TransactionProcessor) GetTransaction(txHash string, withResults bool, if len(tx.InnerTransactions) == 0 { if innerTxRequested { return nil, fmt.Errorf("%w, requested hash %s with relayedTxHash %s, but the relayedTxHash has no inner transaction", - ErrInvalidHash, txHash, withRelayedTxHash) + ErrInvalidHash, txHash, relayedTxHash) } return tx, nil @@ -399,7 +399,7 @@ func (tp *TransactionProcessor) GetTransaction(txHash string, withResults bool, } return nil, fmt.Errorf("%w, but the relayedTx %s has no inner transaction with hash %s", - ErrInvalidHash, withRelayedTxHash, txHash) + ErrInvalidHash, relayedTxHash, txHash) } func convertRelayedTxV3ToNetworkTx(tx *transaction.ApiTransactionResult) { @@ -436,7 +436,7 @@ func isResultOfInnerTx(allScrs []*transaction.ApiSmartContractResult, currentScr return true } - parentScr := getParentSCR(allScrs, currentScr.PrevTxHash) + parentScr := findSCRByHash(allScrs, currentScr.PrevTxHash) if check.IfNilReflect(parentScr) { return false } @@ -444,7 +444,7 @@ func isResultOfInnerTx(allScrs []*transaction.ApiSmartContractResult, currentScr return isResultOfInnerTx(allScrs, parentScr, innerTxHash) } -func getParentSCR(allScrs []*transaction.ApiSmartContractResult, hash string) *transaction.ApiSmartContractResult { +func findSCRByHash(allScrs []*transaction.ApiSmartContractResult, hash string) *transaction.ApiSmartContractResult { for _, scr := range allScrs { if scr.Hash == hash { return scr