func (sp *serverPeer) newestBlock() (*chainhash.Hash, int32, error) {
	best := sp.server.chain.BestSnapshot()
	dagState := sp.server.chain.DAGSnapshot()
	return &best.Hash, dagState.MaxHeight, nil
}
newestBlock returns the current best block hash and height using the format
required by the configuration for the peer package.
package main
import (
	"bytes"
	"crypto/rand"
	"crypto/tls"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/soteria-dag/soterd/mining/cuckoo"
	"math"
	"net"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"github.com/soteria-dag/soterd/addrmgr"
	"github.com/soteria-dag/soterd/blockdag"
	"github.com/soteria-dag/soterd/blockdag/indexers"
	"github.com/soteria-dag/soterd/chaincfg"
	"github.com/soteria-dag/soterd/chaincfg/chainhash"
	"github.com/soteria-dag/soterd/connmgr"
	"github.com/soteria-dag/soterd/database"
	"github.com/soteria-dag/soterd/mempool"
	"github.com/soteria-dag/soterd/metrics"
	"github.com/soteria-dag/soterd/mining/cpuminer"
	"github.com/soteria-dag/soterd/miningdag"
	"github.com/soteria-dag/soterd/netsync"
	"github.com/soteria-dag/soterd/peer"
	"github.com/soteria-dag/soterd/soterutil"
	"github.com/soteria-dag/soterd/soterutil/bloom"
	"github.com/soteria-dag/soterd/txscript"
	"github.com/soteria-dag/soterd/wire"
)
const (
	defaultServices = wire.SFNodeNetwork | wire.SFNodeBloom |
		wire.SFNodeWitness | wire.SFNodeCF
	defaultRequiredServices = wire.SFNodeNetwork
	defaultTargetOutbound = 8
	connectionRetryInterval = time.Second * 5
)
var (
	userAgentName = "soterd"
	userAgentVersion = version
)
var zeroHash chainhash.Hash
type onionAddr struct {
	addr string
}
func (oa *onionAddr) String() string {
	return oa.addr
}
func (oa *onionAddr) Network() string {
	return "onion"
}
var _ net.Addr = (*onionAddr)(nil)
type simpleAddr struct {
	net, addr string
}
func (a simpleAddr) String() string {
	return a.addr
}
func (a simpleAddr) Network() string {
	return a.net
}
var _ net.Addr = simpleAddr{}
type broadcastMsg struct {
	message      wire.Message
	excludePeers []*serverPeer
}
type broadcastInventoryAdd relayMsg
type broadcastInventoryDel *wire.InvVect
type relayMsg struct {
	invVect *wire.InvVect
	data    interface{}
}
type updatePeerHeightsMsg struct {
	newHash    *chainhash.Hash
	newHeight  int32
	originPeer *peer.Peer
}
type peerState struct {
	inboundPeers    map[int32]*serverPeer
	outboundPeers   map[int32]*serverPeer
	persistentPeers map[int32]*serverPeer
	banned          map[string]time.Time
	outboundGroups  map[string]int
}
func (ps *peerState) Count() int {
	return len(ps.inboundPeers) + len(ps.outboundPeers) +
		len(ps.persistentPeers)
}
func (ps *peerState) forAllOutboundPeers(closure func(sp *serverPeer)) {
	for _, e := range ps.outboundPeers {
		closure(e)
	}
	for _, e := range ps.persistentPeers {
		closure(e)
	}
}
func (ps *peerState) forAllPeers(closure func(sp *serverPeer)) {
	for _, e := range ps.inboundPeers {
		closure(e)
	}
	ps.forAllOutboundPeers(closure)
}
type cfHeaderKV struct {
	blockHash    chainhash.Hash
	filterHeader chainhash.Hash
}
type server struct {
	bytesReceived uint64  
	bytesSent     uint64  
	started       int32
	shutdown      int32
	shutdownSched int32
	startupTime   int64
	chainParams          *chaincfg.Params
	addrManager          *addrmgr.AddrManager
	connManager          *connmgr.ConnManager
	sigCache             *txscript.SigCache
	hashCache            *txscript.HashCache
	rpcServer            *rpcServer
	metricsManager       *metrics.MetricsManager
	syncManager          *netsync.SyncManager
	chain                *blockdag.BlockDAG
	txMemPool            *mempool.TxPool
	cpuMiner             *cpuminer.CPUMiner
	modifyRebroadcastInv chan interface{}
	newPeers             chan *serverPeer
	donePeers            chan *serverPeer
	banPeers             chan *serverPeer
	query                chan interface{}
	relayInv             chan relayMsg
	broadcast            chan broadcastMsg
	peerHeightsUpdate    chan updatePeerHeightsMsg
	wg                   sync.WaitGroup
	quit                 chan struct{}
	nat                  NAT
	db                   database.DB
	timeSource           blockdag.MedianTimeSource
	services             wire.ServiceFlag
	txIndex   *dagindexers.TxIndex
	addrIndex *dagindexers.AddrIndex
	cfIndex   *dagindexers.CfIndex
	feeEstimator *mempool.FeeEstimator
	cfCheckptCaches    map[wire.FilterType][]cfHeaderKV
	cfCheckptCachesMtx sync.RWMutex
}
type serverPeer struct {
	feeFilter int64
	*peer.Peer
	connReq        *connmgr.ConnReq
	server         *server
	persistent     bool
	continueHash   *chainhash.Hash
	relayMtx       sync.Mutex
	disableRelayTx bool
	sentAddrs      bool
	isWhitelisted  bool
	filter         *bloom.Filter
	knownAddresses map[string]struct{}
	addressMtx     sync.RWMutex
	banScore       connmgr.DynamicBanScore
	quit           chan struct{}
	txProcessed    chan struct{}
	blockProcessed chan struct{}
}
func newServerPeer(s *server, isPersistent bool) *serverPeer {
	return &serverPeer{
		server:         s,
		persistent:     isPersistent,
		filter:         bloom.LoadFilter(nil),
		knownAddresses: make(map[string]struct{}),
		quit:           make(chan struct{}),
		txProcessed:    make(chan struct{}, 1),
		blockProcessed: make(chan struct{}, 1),
	}
}