From a87fa843495ec57c1d3b478c2ceb3876c3749af5 Mon Sep 17 00:00:00 2001 From: jholdstock Date: Wed, 9 Aug 2023 16:08:59 +0100 Subject: [PATCH] multi: Select managed tickets outside VSP client Move the logic to select managed tickets from the wallet database up into the wallet code. No need for this to be done in the VSP client. --- dcrwallet.go | 6 +++++- internal/rpc/rpcserver/server.go | 7 ++++++- internal/vsp/vsp.go | 36 ++++++++++---------------------- wallet/wallet.go | 30 ++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/dcrwallet.go b/dcrwallet.go index 0a36b9f78..047f10f35 100644 --- a/dcrwallet.go +++ b/dcrwallet.go @@ -433,7 +433,11 @@ func run(ctx context.Context) error { loader.RunAfterLoad(func(w *wallet.Wallet) { if vspClient != nil && cfg.VSPOpts.Sync { - err = vspClient.ProcessManagedTickets(ctx) + tickets, err := w.ProcessedTickets(ctx) + if err != nil { + log.Errorf("Getting VSP tickets failed: %v", err) + } + err = vspClient.ProcessManagedTickets(ctx, tickets) if err != nil { log.Errorf("Adding tickets to VSP client failed: %v", err) } diff --git a/internal/rpc/rpcserver/server.go b/internal/rpc/rpcserver/server.go index 9df9ec805..142cf5940 100644 --- a/internal/rpc/rpcserver/server.go +++ b/internal/rpc/rpcserver/server.go @@ -4203,7 +4203,12 @@ func (s *walletServer) ProcessManagedTickets(ctx context.Context, req *pb.Proces return nil, status.Errorf(codes.Unknown, "VSPClient instance failed to start. Error: %v", err) } - err = vspClient.ProcessManagedTickets(ctx) + tickets, err := s.wallet.ProcessedTickets(ctx) + if err != nil { + return nil, status.Errorf(codes.Unknown, "ProcessedTickets failed. Error: %v", err) + } + + err = vspClient.ProcessManagedTickets(ctx, tickets) if err != nil { return nil, status.Errorf(codes.Unknown, "ProcessManagedTickets failed. Error: %v", err) } diff --git a/internal/vsp/vsp.go b/internal/vsp/vsp.go index f3a45f4fd..b979c7a1f 100644 --- a/internal/vsp/vsp.go +++ b/internal/vsp/vsp.go @@ -139,32 +139,18 @@ func (c *Client) ProcessUnprocessedTickets(ctx context.Context, tickets []*chain wg.Wait() } -// ProcessManagedTickets discovers tickets which were previously registered with -// a VSP and begins syncing them in the background. This is used to recover VSP -// tracking after seed restores, and is only performed on unspent and unexpired -// tickets. -func (c *Client) ProcessManagedTickets(ctx context.Context) error { - err := c.wallet.ForUnspentUnexpiredTickets(ctx, func(hash *chainhash.Hash) error { - // We only want to process tickets that haven't been confirmed yet. - confirmed, err := c.wallet.IsVSPTicketConfirmed(ctx, hash) - if err != nil { - // NotExist error indicates unmanaged tickets. Skip. - if errors.Is(err, errors.NotExist) { - return nil - } - - // Any other errors should propagate upwards. - return err - } - if confirmed { - return nil - } +// ProcessManagedTickets adds the provided tickets to the client and resumes +// their fee payment process. Noop if a given ticket is already added, or if the +// ticket is not registered with the VSP. This is used to recover VSP tracking +// after seed restores. +func (c *Client) ProcessManagedTickets(ctx context.Context, tickets []*chainhash.Hash) error { + for _, hash := range tickets { c.mu.Lock() _, ok := c.jobs[*hash] c.mu.Unlock() if ok { // Already processing this ticket with the VSP. - return nil + continue } // Make ticketstatus api call and only continue if ticket is @@ -175,7 +161,7 @@ func (c *Client) ProcessManagedTickets(ctx context.Context) error { if errors.Is(err, errors.Locked) { return err } - return nil + continue } if status.FeeTxStatus == "confirmed" { @@ -203,9 +189,9 @@ func (c *Client) ProcessManagedTickets(ctx context.Context) error { _ = c.feePayment(ctx, hash, false) } - return nil - }) - return err + } + + return nil } // Process begins processing a VSP fee payment for a ticket. If feeTx contains diff --git a/wallet/wallet.go b/wallet/wallet.go index 3199a85b0..a97823901 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -5958,3 +5958,33 @@ func (w *Wallet) UnprocessedTickets(ctx context.Context) ([]*chainhash.Hash, err return unmanagedTickets, nil } + +// ProcessedTickets returns the hash of every live/immature ticket in the wallet +// database which is currently being processed by a VSP but isnt confirmed yet. +func (w *Wallet) ProcessedTickets(ctx context.Context) ([]*chainhash.Hash, error) { + managedTickets := make([]*chainhash.Hash, 0) + err := w.ForUnspentUnexpiredTickets(ctx, func(hash *chainhash.Hash) error { + // We only want to process tickets that haven't been confirmed yet. + confirmed, err := w.IsVSPTicketConfirmed(ctx, hash) + if err != nil { + // NotExist error indicates unmanaged tickets. Skip. + if errors.Is(err, errors.NotExist) { + return nil + } + + return err + } + if confirmed { + return nil + } + + managedTickets = append(managedTickets, hash) + return nil + }) + + if err != nil { + return nil, err + } + + return managedTickets, nil +}