From e183b932d59e48d657813e76ec35adcdb53e0de4 Mon Sep 17 00:00:00 2001 From: gagliardetto Date: Thu, 22 Feb 2024 10:47:30 +0100 Subject: [PATCH] Fix not found tx response (#90) * Fix error response * Add comments * Fix error formatting * If tx not found, return `"result": null` like solana does --- multiepoch-getTransaction.go | 23 ++++++++++++----------- multiepoch.go | 20 +++++++++++++++----- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/multiepoch-getTransaction.go b/multiepoch-getTransaction.go index 0fc1ad8e..34a375a2 100644 --- a/multiepoch-getTransaction.go +++ b/multiepoch-getTransaction.go @@ -56,7 +56,7 @@ func (multi *MultiEpoch) findEpochNumberFromSignature(ctx context.Context, sig s continue } if has, err := bucket.Has(sig); err != nil { - return 0, fmt.Errorf("failed to check if signature exists in bucket: %v", err) + return 0, fmt.Errorf("failed to check if signature exists in bucket: %w", err) } else if has { found = append(found, epochNumber) } @@ -81,7 +81,7 @@ func (multi *MultiEpoch) findEpochNumberFromSignature(ctx context.Context, sig s wg.Spawn(func() (any, error) { epoch, err := multi.GetEpoch(epochNumber) if err != nil { - return nil, fmt.Errorf("failed to get epoch %d: %v", epochNumber, err) + return nil, fmt.Errorf("failed to get epoch %d: %w", epochNumber, err) } if _, err := epoch.FindCidFromSignature(ctx, sig); err == nil { return epochNumber, nil @@ -118,7 +118,7 @@ func (multi *MultiEpoch) handleGetTransaction(ctx context.Context, conn *request return &jsonrpc2.Error{ Code: jsonrpc2.CodeInvalidParams, Message: "Invalid params", - }, fmt.Errorf("failed to parse params: %v", err) + }, fmt.Errorf("failed to parse params: %w", err) } if err := params.Validate(); err != nil { return &jsonrpc2.Error{ @@ -133,15 +133,16 @@ func (multi *MultiEpoch) handleGetTransaction(ctx context.Context, conn *request epochNumber, err := multi.findEpochNumberFromSignature(ctx, sig) if err != nil { if errors.Is(err, ErrNotFound) { + // solana just returns null here in case of transaction not found: {"jsonrpc":"2.0","result":null,"id":1} return &jsonrpc2.Error{ Code: CodeNotFound, - Message: fmt.Sprintf("Epoch %d is not available from this RPC", epochNumber), - }, fmt.Errorf("failed to find epoch number from signature %s: %v", sig, err) + Message: "Transaction not found", + }, fmt.Errorf("failed to find epoch number from signature %s: %w", sig, err) } return &jsonrpc2.Error{ Code: jsonrpc2.CodeInternalError, Message: "Internal error", - }, fmt.Errorf("failed to get epoch for signature %s: %v", sig, err) + }, fmt.Errorf("failed to get epoch for signature %s: %w", sig, err) } klog.V(4).Infof("Found signature %s in epoch %d in %s", sig, epochNumber, time.Since(startedEpochLookupAt)) @@ -156,7 +157,7 @@ func (multi *MultiEpoch) handleGetTransaction(ctx context.Context, conn *request transactionNode, transactionCid, err := epochHandler.GetTransaction(WithSubrapghPrefetch(ctx, true), sig) if err != nil { if errors.Is(err, compactindexsized.ErrNotFound) { - // NOTE: solana just returns null here in case of transaction not found + // NOTE: solana just returns null here in case of transaction not found: {"jsonrpc":"2.0","result":null,"id":1} return &jsonrpc2.Error{ Code: CodeNotFound, Message: "Transaction not found", @@ -165,7 +166,7 @@ func (multi *MultiEpoch) handleGetTransaction(ctx context.Context, conn *request return &jsonrpc2.Error{ Code: jsonrpc2.CodeInternalError, Message: "Internal error", - }, fmt.Errorf("failed to get Transaction: %v", err) + }, fmt.Errorf("failed to get Transaction: %w", err) } { conn.ctx.Response.Header.Set("DAG-Root-CID", transactionCid.String()) @@ -180,7 +181,7 @@ func (multi *MultiEpoch) handleGetTransaction(ctx context.Context, conn *request return &jsonrpc2.Error{ Code: jsonrpc2.CodeInternalError, Message: "Internal error", - }, fmt.Errorf("failed to get block: %v", err) + }, fmt.Errorf("failed to get block: %w", err) } blocktime := uint64(block.Meta.Blocktime) if blocktime != 0 { @@ -198,7 +199,7 @@ func (multi *MultiEpoch) handleGetTransaction(ctx context.Context, conn *request return &jsonrpc2.Error{ Code: jsonrpc2.CodeInternalError, Message: "Internal error", - }, fmt.Errorf("failed to decode transaction: %v", err) + }, fmt.Errorf("failed to decode transaction: %w", err) } response.Signatures = tx.Signatures if tx.Message.IsVersioned() { @@ -213,7 +214,7 @@ func (multi *MultiEpoch) handleGetTransaction(ctx context.Context, conn *request return &jsonrpc2.Error{ Code: jsonrpc2.CodeInternalError, Message: "Internal error", - }, fmt.Errorf("failed to encode transaction: %v", err) + }, fmt.Errorf("failed to encode transaction: %w", err) } response.Transaction = encodedTx } diff --git a/multiepoch.go b/multiepoch.go index 06008e0a..2eb3e13c 100644 --- a/multiepoch.go +++ b/multiepoch.go @@ -2,6 +2,7 @@ package main import ( "context" + "errors" "fmt" "net/http" "sort" @@ -401,11 +402,20 @@ func newMultiEpochHandler(handler *MultiEpoch, lsConf *ListenerConfig) func(ctx metrics_methodToNumProxied.WithLabelValues(sanitizeMethod(method)).Inc() return } else { - rqCtx.ReplyWithError( - reqCtx, - rpcRequest.ID, - errorResp, - ) + if errors.Is(err, ErrNotFound) { + // reply with null result + rqCtx.ReplyRaw( + reqCtx, + rpcRequest.ID, + nil, + ) + } else { + rqCtx.ReplyWithError( + reqCtx, + rpcRequest.ID, + errorResp, + ) + } } return }