func (s *Syncer) peerConnected(remotesCount int, addr string) {
	if s.notifications != nil && s.notifications.PeerConnected != nil {
		s.notifications.PeerConnected(int32(remotesCount), addr)
	}
}
peerConnected updates the notification for peer count, if set.
package spv
import (
	"context"
	"runtime"
	"sync"
	"sync/atomic"
	"time"
	"decred.org/dcrwallet/v2/errors"
	"decred.org/dcrwallet/v2/lru"
	"decred.org/dcrwallet/v2/p2p"
	"decred.org/dcrwallet/v2/validate"
	"decred.org/dcrwallet/v2/wallet"
	"github.com/decred/dcrd/addrmgr/v2"
	"github.com/decred/dcrd/blockchain/stake/v4"
	"github.com/decred/dcrd/chaincfg/chainhash"
	"github.com/decred/dcrd/gcs/v3/blockcf2"
	"github.com/decred/dcrd/wire"
	"golang.org/x/sync/errgroup"
)
const reqSvcs = wire.SFNodeNetwork
type Syncer struct {
	atomicCatchUpTryLock uint32  
	atomicWalletSynced   uint32  
	wallet *wallet.Wallet
	lp     *p2p.LocalPeer
	discoverAccounts bool
	loadedFilters    bool
	persistentPeers []string
	connectingRemotes map[string]struct{}
	remotes           map[string]*p2p.RemotePeer
	remotesMu         sync.Mutex
	rescanFilter *wallet.RescanFilter
	filterData   blockcf2.Entries
	filterMu     sync.Mutex
	seenTxs lru.Cache
	sidechains  wallet.SidechainForest
	sidechainMu sync.Mutex
	currentLocators   []*chainhash.Hash
	locatorGeneration uint
	locatorMu         sync.Mutex
	notifications *Notifications
	mempool     sync.Map  
	mempoolAdds chan *chainhash.Hash
}
type Notifications struct {
	Synced                       func(sync bool)
	PeerConnected                func(peerCount int32, addr string)
	PeerDisconnected             func(peerCount int32, addr string)
	FetchMissingCFiltersStarted  func()
	FetchMissingCFiltersProgress func(startCFiltersHeight, endCFiltersHeight int32)
	FetchMissingCFiltersFinished func()
	FetchHeadersStarted          func()
	FetchHeadersProgress         func(lastHeaderHeight int32, lastHeaderTime int64)
	FetchHeadersFinished         func()
	DiscoverAddressesStarted     func()
	DiscoverAddressesFinished    func()
	RescanStarted                func()
	RescanProgress               func(rescannedThrough int32)
	RescanFinished               func()
	MempoolTxs func(txs []*wire.MsgTx)
	TipChanged func(tip *wire.BlockHeader, reorgDepth int32, txs []*wire.MsgTx)
}
func NewSyncer(w *wallet.Wallet, lp *p2p.LocalPeer) *Syncer {
	return &Syncer{
		wallet:            w,
		discoverAccounts:  !w.Locked(),
		connectingRemotes: make(map[string]struct{}),
		remotes:           make(map[string]*p2p.RemotePeer),
		rescanFilter:      wallet.NewRescanFilter(nil, nil),
		seenTxs:           lru.NewCache(2000),
		lp:                lp,
		mempoolAdds:       make(chan *chainhash.Hash),
	}
}
func (s *Syncer) SetPersistentPeers(peers []string) {
	s.persistentPeers = peers
}
func (s *Syncer) SetNotifications(ntfns *Notifications) {
	s.notifications = ntfns
}
func (s *Syncer) DisableDiscoverAccounts() {
	s.discoverAccounts = false
}
func (s *Syncer) synced() {
	if atomic.CompareAndSwapUint32(&s.atomicWalletSynced, 0, 1) &&
		s.notifications != nil &&
		s.notifications.Synced != nil {
		s.notifications.Synced(true)
	}
}
func (s *Syncer) Synced() bool {
	return atomic.LoadUint32(&s.atomicWalletSynced) == 1
}
func (s *Syncer) EstimateMainChainTip() int32 {
	_, chainTip := s.wallet.MainChainTip(context.Background())
	s.forRemotes(func(rp *p2p.RemotePeer) error {
		if rp.InitialHeight() > chainTip {
			chainTip = rp.InitialHeight()
		}
		return nil
	})
	return chainTip
}
func (s *Syncer) GetRemotePeers() map[string]*p2p.RemotePeer {
	s.remotesMu.Lock()
	defer s.remotesMu.Unlock()
	remotes := make(map[string]*p2p.RemotePeer, len(s.remotes))
	for k, rp := range s.remotes {
		remotes[k] = rp
	}
	return remotes
}
func (s *Syncer) unsynced() {
	if atomic.CompareAndSwapUint32(&s.atomicWalletSynced, 1, 0) &&
		s.notifications != nil &&
		s.notifications.Synced != nil {
		s.notifications.Synced(false)
	}
}