From 0ff2bf2446af65f4e4d11dd9ef6cd5d9d9c7db6c 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 7c9944390..37ed79b67 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)