From 43f951871fd9443e0c36ddaef3e318c0afb4bae7 Mon Sep 17 00:00:00 2001 From: Matheus Degiovani Date: Tue, 24 Oct 2023 07:17:43 -0300 Subject: [PATCH] spv: Ask for sendheaders after initial sync This makes the remote peers configure to send block announcements via sendheaders only after the initial sync is completed. This ensures the initial sync process can fetch all the needed headers from any and all peers before they are configured to send header annoucements. --- spv/sync.go | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/spv/sync.go b/spv/sync.go index 17bc09b49..bd69aa326 100644 --- a/spv/sync.go +++ b/spv/sync.go @@ -6,6 +6,7 @@ package spv import ( "context" + "fmt" "runtime" "sync" "sync/atomic" @@ -444,8 +445,18 @@ func (s *Syncer) Run(ctx context.Context) error { } s.rescanFinished() + log.Infof("Initial sync completed. Switching to header announcements sync.") s.synced() + // Perform peer startup (publish txs, sendheaders, etc) on + // every connected peer. + err = s.forRemotes(func(rp *p2p.RemotePeer) error { + return s.startupPeerSync(ctx, rp) + }) + if err != nil { + return err + } + // Rescan done. return nil }) @@ -547,16 +558,19 @@ func (s *Syncer) connectAndRunPeer(ctx context.Context, raddr string) { s.peerDisconnected(n, raddr) }() - // Perform peer startup. - err = s.startupSync(ctx, rp) - if err != nil { - if !errors.Is(err, context.Canceled) { - log.Warnf("Unable to complete startup sync with peer %v: %v", raddr, err) - } else { - log.Infof("Lost peer %v", raddr) + // Perform peer sync if the initial sync process has completed. This + // configures the peer to send new headers. + if s.Synced() { + err = s.startupPeerSync(ctx, rp) + if err != nil { + if !errors.Is(err, context.Canceled) { + log.Warnf("Unable to complete startup sync with peer %v: %v", raddr, err) + } else { + log.Infof("Lost peer %v", raddr) + } + rp.Disconnect(err) + return } - rp.Disconnect(err) - return } // Finally, block until the peer disconnects. @@ -1548,7 +1562,9 @@ nextbatch: } } -func (s *Syncer) startupSync(ctx context.Context, rp *p2p.RemotePeer) error { +// startupPeerSync performs peer startup procedures after connection. This should +// only be called after the wallet has had its initial sync complete. +func (s *Syncer) startupPeerSync(ctx context.Context, rp *p2p.RemotePeer) error { var err error if rp.Pver() >= wire.InitStateVersion { @@ -1558,6 +1574,11 @@ func (s *Syncer) startupSync(ctx context.Context, rp *p2p.RemotePeer) error { } } + err = rp.SendHeaders(ctx) + if err != nil { + return fmt.Errorf("unable ask for sendheaders from peer: %w", err) + } + unminedTxs, err := s.wallet.UnminedTransactions(ctx) if err != nil { log.Errorf("Cannot load unmined transactions for resending: %v", err)