From dd22b2afcb33d5f700d048a2d368f5a9358df921 Mon Sep 17 00:00:00 2001 From: jholdstock Date: Tue, 7 Nov 2023 12:47:33 +0000 Subject: [PATCH] [release-v1.3] webapi: Wait for unknown outputs to propagate. If broadcasting parent transaction of a ticket fails because it references unknown outputs, there is a good chance that waiting a few seconds will resolve the issue because the ancestor transactions will propagate through the network and reach the mempool of the local dcrd instance. --- internal/webapi/middleware.go | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/internal/webapi/middleware.go b/internal/webapi/middleware.go index 4a3af932..8e2a0435 100644 --- a/internal/webapi/middleware.go +++ b/internal/webapi/middleware.go @@ -275,10 +275,37 @@ func (w *WebAPI) broadcastTicket(c *gin.Context) { w.log.Debugf("%s: Broadcasting parent tx %s (ticketHash=%s)", funcName, parentHash, request.TicketHash) err = dcrdClient.SendRawTransaction(request.ParentHex) if err != nil { - w.log.Errorf("%s: dcrd.SendRawTransaction for parent tx failed (ticketHash=%s): %v", - funcName, request.TicketHash, err) - w.sendError(types.ErrCannotBroadcastTicket, c) - return + // Unknown output errors have special handling because they + // could be resolved by waiting for network propagation. Any + // other errors are returned to client immediately. + if !strings.Contains(err.Error(), rpc.ErrUnknownOutputs) { + w.log.Errorf("%s: dcrd.SendRawTransaction for parent tx failed (ticketHash=%s): %v", + funcName, request.TicketHash, err) + w.sendError(types.ErrCannotBroadcastTicket, c) + return + } + + w.log.Debugf("%s: Parent tx references an unknown output, waiting for it in mempool (ticketHash=%s)", + funcName, request.TicketHash) + + txBroadcast := func() bool { + // Wait for 1 second and try again, max 7 attempts. + for i := 0; i < 7; i++ { + time.Sleep(1 * time.Second) + err := dcrdClient.SendRawTransaction(request.ParentHex) + if err == nil { + return true + } + } + return false + }() + + if !txBroadcast { + w.log.Errorf("%s: Failed to broadcast parent tx, waiting didn't help (ticketHash=%s)", + funcName, request.TicketHash) + w.sendError(types.ErrCannotBroadcastTicket, c) + return + } } } else {