From 5663fed0c94221fcbe0275d428cbe5b19e9ad039 Mon Sep 17 00:00:00 2001 From: agodnic Date: Tue, 27 Jun 2023 10:12:32 -0300 Subject: [PATCH] Fix transaction hash search for Aptos (#461) ### Description Tracking issue: https://github.com/wormhole-foundation/wormhole-explorer/issues/430 In `GET /api/v1/vaas?txHash={hash}`, searching for Aptos VAAs by transaction hash was not working correctly. This pull request fixes the issue. --- api/handlers/vaa/repository.go | 49 ++++++++++++++++++++++------------ api/handlers/vaa/service.go | 15 +++++++---- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/api/handlers/vaa/repository.go b/api/handlers/vaa/repository.go index 6eb6cae9..e112b63b 100644 --- a/api/handlers/vaa/repository.go +++ b/api/handlers/vaa/repository.go @@ -47,22 +47,32 @@ func NewRepository(db *mongo.Database, logger *zap.Logger) *Repository { } } -// FindVaasBySolanaTxHash searches the database for VAAs that match a given Solana transaction hash. -func (r *Repository) FindVaasBySolanaTxHash( +// FindVaasByTxHashWorkaround searches the database for VAAs that match a given transaction hash. +// +// This function exists to work around the issue that for Aptos and Solana, the real transaction +// hashes are stored in a different collection from other chains. +// +// When the `q.txHash` field is set, this function will look up transaction hashes in the `globalTransactions` collection. +// Then, if the transaction hash is not found, it will fall back to searching in the `vaas` collection. +func (r *Repository) FindVaasByTxHashWorkaround( ctx context.Context, - txHash string, - includeParsedPayload bool, + query *VaaQuery, ) ([]*VaaDoc, error) { - // Find globalTransactions that match the given Solana TxHash + // Find globalTransactions that match the given TxHash cur, err := r.collections.globalTransactions.Find( ctx, - bson.D{bson.E{"originTx.nativeTxHash", txHash}}, + bson.D{ + {"$or", bson.A{ + bson.D{{"originTx.nativeTxHash", bson.M{"$eq": query.txHash}}}, + bson.D{{"originTx.nativeTxHash", bson.M{"$eq": "0x" + query.txHash}}}, + }}, + }, nil, ) if err != nil { requestID := fmt.Sprintf("%v", ctx.Value("requestid")) - r.logger.Error("failed to find globalTransactions by Solana TxHash", + r.logger.Error("failed to find globalTransactions by TxHash", zap.Error(err), zap.String("requestID", requestID), ) @@ -80,24 +90,29 @@ func (r *Repository) FindVaasBySolanaTxHash( ) return nil, errors.WithStack(err) } - - // If no results were found, return an empty slice instead of nil. - if len(globalTxs) == 0 { - result := make([]*VaaDoc, 0) - return result, nil - } if len(globalTxs) > 1 { return nil, fmt.Errorf("expected at most one transaction, but found %d", len(globalTxs)) } + // If no documents were found, look up the transaction hash in the `vaas` collection instead. + if len(globalTxs) == 0 { + return r.FindVaas(ctx, query) + } + // Find VAAs that match the given VAA ID - q := Query(). - SetID(globalTxs[0].ID). - IncludeParsedPayload(includeParsedPayload) - return r.FindVaas(ctx, q) + q := *query // making a copy to avoid modifying the struct passed by the caller + q.SetID(globalTxs[0].ID) + // Disable txHash filter, but keep all the other filters. + // We have to do this because the transaction hashes in the `globalTransactions` collection + // may be different that the transaction hash in the `vaas` collection. This is the case + // for Aptos and Solana VAAs. + q.txHash = "" + return r.FindVaas(ctx, &q) } // FindVaas searches the database for VAAs matching the given filters. +// +// When the `q.txHash` field is set, this function will look up transaction hashes in the `vaas` collection. func (r *Repository) FindVaas( ctx context.Context, q *VaaQuery, diff --git a/api/handlers/vaa/service.go b/api/handlers/vaa/service.go index 569931af..2b26e05c 100644 --- a/api/handlers/vaa/service.go +++ b/api/handlers/vaa/service.go @@ -48,7 +48,7 @@ func (s *Service) FindAll( params *FindAllParams, ) (*response.Response[[]*VaaDoc], error) { - // set up query parameters + // Populate query parameters query := Query(). IncludeParsedPayload(params.IncludeParsedPayload) if params.Pagination != nil { @@ -61,11 +61,16 @@ func (s *Service) FindAll( query.SetAppId(params.AppId) } - // execute the database query + // Execute the database query + // + // Unfortunately, for Aptos and Solana, the real transaction hashes are stored + // in a different collection from other chains. + // + // This block of code has additional logic to handle that case. var err error var vaas []*VaaDoc - if params.TxHash != nil && params.TxHash.IsSolanaTxHash() { - vaas, err = s.repo.FindVaasBySolanaTxHash(ctx, params.TxHash.String(), params.IncludeParsedPayload) + if query.txHash != "" { + vaas, err = s.repo.FindVaasByTxHashWorkaround(ctx, query) } else { vaas, err = s.repo.FindVaas(ctx, query) } @@ -73,7 +78,7 @@ func (s *Service) FindAll( return nil, err } - // return the matching documents + // Eeturn the matching documents res := response.Response[[]*VaaDoc]{Data: vaas} return &res, nil }