Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new core-go #465

Open
wants to merge 3 commits into
base: rc/v1.7.next1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

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

Without the suffix with (since, currently, we use with to dictate whether something has to be included in the response).

- `/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"
Copy link
Contributor

Choose a reason for hiding this comment

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

Without the with prefix. This new parameter is closer (in meaning) to hintEpoch than to withTxs.

)

// 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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
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 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe can be named findSCRByHash().

for _, scr := range allScrs {
if scr.Hash == hash {
return scr
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

currentScr is used for its PrevTxHash only. Thus, an optimization would be to hold a map of [previous hash] to [hash]. This way, the repeated loops can be omitted. However, in practice, the optimization would only be marginal. Thus, all right as it is now, as well 👍


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
Loading