func (b *blockManager) startSync(peers *list.List) {
	if b.syncPeer != nil {
		return
	}
	best := b.chain.BestSnapshot()
	var bestPeer *serverPeer
	var enext *list.Element
	for e := peers.Front(); e != nil; e = enext {
		enext = e.Next()
		sp := e.Value.(*serverPeer)
		if sp.LastBlock() < best.Height {
			peers.Remove(e)
			continue
		}
		bestPeer = sp
	}
	if bestPeer != nil {
		b.requestedBlocks = make(map[chainhash.Hash]struct{})
		locator, err := b.chain.LatestBlockLocator()
		if err != nil {
			bmgrLog.Errorf("Failed to get block locator for the "+
				"latest block: %v", err)
			return
		}
		bmgrLog.Infof("Syncing to block height %d from peer %v",
			bestPeer.LastBlock(), bestPeer.Addr())
		bestPeer.PushGetBlocksMsg(locator, &zeroHash)
		b.syncPeer = bestPeer
	} else {
		bmgrLog.Warnf("No sync peer candidates available")
	}
}
startSync will choose the best peer among the available candidate peers to
download/sync the blockchain from.  When syncing is already running, it
simply returns.  It also examines the candidates for any which are no longer
candidates and removes them as needed.
package main
import (
	"container/list"
	"net"
	"os"
	"path/filepath"
	"sort"
	"sync"
	"sync/atomic"
	"github.com/bitgo/prova/blockchain"
	"github.com/bitgo/prova/chaincfg"
	"github.com/bitgo/prova/chaincfg/chainhash"
	"github.com/bitgo/prova/database"
	"github.com/bitgo/prova/mempool"
	"github.com/bitgo/prova/provautil"
	"github.com/bitgo/prova/wire"
)
const (
	blockDbNamePrefix = "blocks"
	maxRejectedTxns = 1000
	maxRequestedBlocks = wire.MaxInvPerMsg
	maxRequestedTxns = wire.MaxInvPerMsg
)
var zeroHash chainhash.Hash
type newPeerMsg struct {
	peer *serverPeer
}
type blockMsg struct {
	block *provautil.Block
	peer  *serverPeer
}
type invMsg struct {
	inv  *wire.MsgInv
	peer *serverPeer
}
type donePeerMsg struct {
	peer *serverPeer
}
type txMsg struct {
	tx   *provautil.Tx
	peer *serverPeer
}
type getSyncPeerMsg struct {
	reply chan *serverPeer
}
type processBlockResponse struct {
	isOrphan bool
	err      error
}
type processBlockMsg struct {
	block *provautil.Block
	flags blockchain.BehaviorFlags
	reply chan processBlockResponse
}
type isCurrentMsg struct {
	reply chan bool
}
type pauseMsg struct {
	unpause <-chan struct{}
}
type blockManager struct {
	server          *server
	started         int32
	shutdown        int32
	chain           *blockchain.BlockChain
	rejectedTxns    map[chainhash.Hash]struct{}
	requestedTxns   map[chainhash.Hash]struct{}
	requestedBlocks map[chainhash.Hash]struct{}
	progressLogger  *blockProgressLogger
	syncPeer        *serverPeer
	msgChan         chan interface{}
	wg              sync.WaitGroup
	quit            chan struct{}
}