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.
This commit is contained in:
agodnic 2023-06-27 10:12:32 -03:00 committed by GitHub
parent 471a6dad4d
commit 5663fed0c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 22 deletions

View File

@ -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,

View File

@ -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
}