kaspad/server/server.go
Ori Newman 62d14bf2bd [NOD-16] implement initial sync first version (#234)
* [NOD-58] Replace lastBlock with selected tip in version message (#210)

* [NOD-58] Replace lastBlock with selected tip in version message

* [NOD-58] Fix typo in comment

* [NOD-58] Add mutex to SelectedTipHash

* [NOD-58] Remove redundant comment

* [NOD-58] Remove wantStartingHeight from peerStats

* [NOD-58] Remove lock from SelectedTipHash

* Nod 53 change getheaders message to handle new block locator (#213)

* [NOD-53] Change getheaders message to handle the new block locator mechanism

* [NOD-53] Use heap in locateHeaders

* [NOD-53] Create a constructor for each heap direction

* [NOD-57] Check if a node is synced only by timestamps (#214)

* [NOD-60] implement isSyncCandidate (#218)

* [NOD-60] Implement isSyncCandidate

* [NOD-60] Fix typo

* [NOD-65] Fix netsync related tests and remove fields optionality from… (#220)

* [NOD-65] Fix netsync related tests and remove fields optionality from msgversion

* [NOD-65] gofmt rpcserver.go

* [NOD-65] add missing test for verRelayTxFalse

* [NOD-62] Change getblocks message to handle the new block locator mechanism (#219)

* [NOD-62] Change getblocks message to handle the new block locator mechanism

* [NOD-62] Add locateBlockNodes function

* [NOD-68] Adjust orphan parents requesting for a DAG (#222)

* [NOD-68] Adjust orphan parents requesting for a DAG

* [NOD-68] add sendInvsFromRequestedQueue and trigger it when requested blocks slice is empty, or immediatly if we're not in sync mode

* [NOD-68] Prevent duplicates from entering to state.requestQueue and add wrapping locks to addBlocksToRequestQueue

* [NOD-68] Fix Lock -> Unlock in sendInvsFromRequestedQueue

* [NOD-74] Starts syncing again when the current sync peer is done (#225)

* [NOD-74] Starts syncing again when the current sync peer is done

* [NOD-74] Unlock mtx before netsync is restarted

* [NOD-74] Fix name isSyncPeerFree -> isWaitingForBlocks

* [NOD-75] fixing netsync bugs (#227)

* [NOD-74] Starts syncing again when the current sync peer is done

* [NOD-74] Unlock mtx before netsync is restarted

* [NOD-75] Fixing netsync bugs

* [NOD-80] Request block data from block propagation just after you are… (#231)

* [NOD-80] Request block data from block propagation just after you are current

* [NOD-80] Fix adding to both queues in addInvToRequestQueue

* [NOD-81] Start to mine on top of genesis iff all peers selected tip is genesis (#232)

* [NOD-81] Start to mine on top of genesis only if all of your peers' selected tip is genesis

* [NOD-81] Explain forAllPeers/forAllOutboundPeers shouldContinue behaviour in comments

* [NOD-81] Add forAllInboundPeers and add return values for forAllPeers/forAllOutboundPeers/forAllInboundPeers functions

* [NOD-16] Add pushSet to the BlockHeap type

* [NOD-16] Fixed syntax error
2019-03-31 16:47:28 +03:00

148 lines
3.8 KiB
Go

package server
import (
"sync/atomic"
"time"
"github.com/daglabs/btcd/config"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/database"
"github.com/daglabs/btcd/mempool"
"github.com/daglabs/btcd/mining"
"github.com/daglabs/btcd/mining/cpuminer"
"github.com/daglabs/btcd/server/p2p"
"github.com/daglabs/btcd/server/rpc"
"github.com/daglabs/btcd/signal"
)
// Server is a wrapper for p2p server and rpc server
type Server struct {
rpcServer *rpc.Server
p2pServer *p2p.Server
cpuminer *cpuminer.CPUMiner
startupTime int64
started, shutdown int32
}
// Start begins accepting connections from peers.
func (s *Server) Start() {
// Already started?
if atomic.AddInt32(&s.started, 1) != 1 {
return
}
srvrLog.Trace("Starting server")
// Server startup time. Used for the uptime command for uptime calculation.
s.startupTime = time.Now().Unix()
s.p2pServer.Start()
// Start the CPU miner if generation is enabled.
cfg := config.MainConfig()
if cfg.Generate {
s.cpuminer.Start()
}
if !cfg.DisableRPC {
s.rpcServer.Start()
}
}
// Stop gracefully shuts down the server by stopping and disconnecting all
// peers and the main listener.
func (s *Server) Stop() error {
// Make sure this only happens once.
if atomic.AddInt32(&s.shutdown, 1) != 1 {
srvrLog.Infof("Server is already in the process of shutting down")
return nil
}
srvrLog.Warnf("Server shutting down")
// Stop the CPU miner if needed
s.cpuminer.Stop()
s.p2pServer.Stop()
// Shutdown the RPC server if it's not disabled.
if !config.MainConfig().DisableRPC {
s.rpcServer.Stop()
}
return nil
}
// NewServer returns a new btcd server configured to listen on addr for the
// bitcoin network type specified by chainParams. Use start to begin accepting
// connections from peers.
func NewServer(listenAddrs []string, db database.DB, dagParams *dagconfig.Params, interrupt <-chan struct{}) (*Server, error) {
s := &Server{}
var err error
notifyNewTransactions := func(txns []*mempool.TxDesc) {
// Notify both websocket and getblocktemplate long poll clients of all
// newly accepted transactions.
if s.rpcServer != nil {
s.rpcServer.NotifyNewTransactions(txns)
}
}
s.p2pServer, err = p2p.NewServer(listenAddrs, db, dagParams, interrupt, notifyNewTransactions)
if err != nil {
return nil, err
}
cfg := config.MainConfig()
// Create the mining policy and block template generator based on the
// configuration options.
//
// NOTE: The CPU miner relies on the mempool, so the mempool has to be
// created before calling the function to create the CPU miner.
policy := mining.Policy{
BlockMinSize: cfg.BlockMinSize,
BlockMaxSize: cfg.BlockMaxSize,
BlockPrioritySize: cfg.BlockPrioritySize,
TxMinFreeFee: cfg.MinRelayTxFee,
}
blockTemplateGenerator := mining.NewBlkTmplGenerator(&policy,
s.p2pServer.DAGParams, s.p2pServer.TxMemPool, s.p2pServer.DAG, s.p2pServer.TimeSource, s.p2pServer.SigCache)
s.cpuminer = cpuminer.New(&cpuminer.Config{
DAGParams: dagParams,
BlockTemplateGenerator: blockTemplateGenerator,
MiningAddrs: cfg.MiningAddrs,
ProcessBlock: s.p2pServer.SyncManager.ProcessBlock,
ConnectedCount: s.p2pServer.ConnectedCount,
ShouldMineOnGenesis: s.p2pServer.ShouldMineOnGenesis,
IsCurrent: s.p2pServer.SyncManager.IsCurrent,
})
if !cfg.DisableRPC {
s.rpcServer, err = rpc.NewRPCServer(
s.startupTime,
s.p2pServer,
db,
blockTemplateGenerator,
s.cpuminer,
)
if err != nil {
return nil, err
}
// Signal process shutdown when the RPC server requests it.
go func() {
<-s.rpcServer.RequestedProcessShutdown()
signal.ShutdownRequestChannel <- struct{}{}
}()
}
return s, nil
}
// WaitForShutdown blocks until the main listener and peer handlers are stopped.
func (s *Server) WaitForShutdown() {
s.p2pServer.WaitForShutdown()
}