func (s *syncer) AddSnapshot(peerID types.NodeID, snapshot *snapshot) (bool, error) {
	added, err := s.snapshots.Add(peerID, snapshot)
	if err != nil {
		return false, err
	}
	if added {
		s.metrics.TotalSnapshots.Add(1)
		s.logger.Info("Discovered new snapshot", "height", snapshot.Height, "format", snapshot.Format,
			"hash", snapshot.Hash)
	}
	return added, nil
}
AddSnapshot adds a snapshot to the snapshot pool. It returns true if a new, previously unseen
snapshot was accepted and added.
package statesync
import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"time"
	abci "github.com/tendermint/tendermint/abci/types"
	"github.com/tendermint/tendermint/config"
	tmsync "github.com/tendermint/tendermint/internal/libs/sync"
	"github.com/tendermint/tendermint/internal/p2p"
	"github.com/tendermint/tendermint/internal/proxy"
	sm "github.com/tendermint/tendermint/internal/state"
	"github.com/tendermint/tendermint/libs/log"
	"github.com/tendermint/tendermint/light"
	ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync"
	"github.com/tendermint/tendermint/types"
)
const (
	chunkTimeout = 2 * time.Minute
	minimumDiscoveryTime = 5 * time.Second
)
var (
	errAbort = errors.New("state sync aborted")
	errRetrySnapshot = errors.New("retry snapshot")
	errRejectSnapshot = errors.New("snapshot was rejected")
	errRejectFormat = errors.New("snapshot format was rejected")
	errRejectSender = errors.New("snapshot sender was rejected")
	errVerifyFailed = errors.New("verification with app failed")
	errTimeout = errors.New("timed out waiting for chunk")
	errNoSnapshots = errors.New("no suitable snapshots found")
)
type syncer struct {
	logger        log.Logger
	stateProvider StateProvider
	conn          proxy.AppConnSnapshot
	connQuery     proxy.AppConnQuery
	snapshots     *snapshotPool
	snapshotCh    chan<- p2p.Envelope
	chunkCh       chan<- p2p.Envelope
	tempDir       string
	fetchers      int32
	retryTimeout  time.Duration
	mtx     tmsync.RWMutex
	chunks  *chunkQueue
	metrics *Metrics
	avgChunkTime             int64
	lastSyncedSnapshotHeight int64
	processingSnapshot       *snapshot
	closeCh                  <-chan struct{}
}
func newSyncer(
	cfg config.StateSyncConfig,
	logger log.Logger,
	conn proxy.AppConnSnapshot,
	connQuery proxy.AppConnQuery,
	stateProvider StateProvider,
	snapshotCh chan<- p2p.Envelope,
	chunkCh chan<- p2p.Envelope,
	closeCh <-chan struct{},
	tempDir string,
	metrics *Metrics,
) *syncer {
	return &syncer{
		logger:        logger,
		stateProvider: stateProvider,
		conn:          conn,
		connQuery:     connQuery,
		snapshots:     newSnapshotPool(),
		snapshotCh:    snapshotCh,
		chunkCh:       chunkCh,
		tempDir:       tempDir,
		fetchers:      cfg.Fetchers,
		retryTimeout:  cfg.ChunkRequestTimeout,
		metrics:       metrics,
		closeCh:       closeCh,
	}
}
func (s *syncer) AddChunk(chunk *chunk) (bool, error) {
	s.mtx.RLock()
	defer s.mtx.RUnlock()
	if s.chunks == nil {
		return false, errors.New("no state sync in progress")
	}
	added, err := s.chunks.Add(chunk)
	if err != nil {
		return false, err
	}
	if added {
		s.logger.Debug("Added chunk to queue", "height", chunk.Height, "format", chunk.Format,
			"chunk", chunk.Index)
	} else {
		s.logger.Debug("Ignoring duplicate chunk in queue", "height", chunk.Height, "format", chunk.Format,
			"chunk", chunk.Index)
	}
	return added, nil
}