Skip to content

Commit

Permalink
relayed v3 get transaction response improved + support for inner tx
Browse files Browse the repository at this point in the history
  • Loading branch information
sstanculeanu committed Oct 11, 2024
1 parent bff5ae4 commit 5d5e537
Show file tree
Hide file tree
Showing 13 changed files with 332 additions and 22 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion api/groups/baseTransactionGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion api/groups/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 6 additions & 1 deletion api/groups/urlParams.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
6 changes: 3 additions & 3 deletions api/mock/facadeStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 -
Expand Down
2 changes: 1 addition & 1 deletion cmd/proxy/config/swagger/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2042,7 +2042,7 @@
}
}
},
"/transaction/{txHash}?withResults=true": {
"/transaction/{txHash}?withResults=true&withRelayedTxHash={relayedTxHash}": {
"get": {
"tags": [
"transaction"
Expand Down
5 changes: 4 additions & 1 deletion common/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions facade/baseFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion facade/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions facade/mock/transactionProcessorStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions process/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
91 changes: 87 additions & 4 deletions process/transactionProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,16 +359,99 @@ 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
}

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
Expand Down Expand Up @@ -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)
}
Expand Down
Loading

0 comments on commit 5d5e537

Please sign in to comment.