From eb8b8418502bfe0316a5e3b2149e0ead9b58cf6a Mon Sep 17 00:00:00 2001 From: Svarog Date: Mon, 18 May 2020 10:42:58 +0300 Subject: [PATCH] [NOD-1005] Use sm.isSynced to check whether should request blocks from invs (#721) * [NOD-1005] Moved isSyncedForMining to netsync manager, and renamed to isSynced + removed isCurrent * [NOD-1005] Use sm.isSynced to check whether should request blocks from invs * [NOD-1005] Use private version of isSynced to avoid infinite loop * [NOD-1005] Fix a few typos --- netsync/manager.go | 34 +++++++++++++++++++------ server/rpc/handle_get_block_template.go | 31 +++++----------------- server/rpc/rpcadapters.go | 6 ++--- server/rpc/rpcserver.go | 4 +-- 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/netsync/manager.go b/netsync/manager.go index d10e4e066..fc43d7fbe 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -103,10 +103,10 @@ type processBlockMsg struct { reply chan processBlockResponse } -// isCurrentMsg is a message type to be sent across the message channel for +// isSyncedMsg is a message type to be sent across the message channel for // requesting whether or not the sync manager believes it is synced with the // currently connected peers. -type isCurrentMsg struct { +type isSyncedMsg struct { reply chan bool } @@ -839,7 +839,7 @@ func (sm *SyncManager) sendInvsFromRequestQueue(peer *peerpkg.Peer, state *peerS if err != nil { return err } - if sm.current() { + if sm.syncPeer == nil || sm.isSynced() { err := sm.addInvsToGetDataMessageFromQueue(gdmsg, state, wire.InvTypeBlock, wire.MaxInvPerGetDataMsg) if err != nil { return err @@ -968,8 +968,8 @@ out: err: err, } - case isCurrentMsg: - msg.reply <- sm.current() + case isSyncedMsg: + msg.reply <- sm.isSynced() case pauseMsg: // Wait until the sender unpauses the manager. @@ -1151,14 +1151,32 @@ func (sm *SyncManager) ProcessBlock(block *util.Block, flags blockdag.BehaviorFl return response.isOrphan, response.err } -// IsCurrent returns whether or not the sync manager believes it is synced with +// IsSynced returns whether or not the sync manager believes it is synced with // the connected peers. -func (sm *SyncManager) IsCurrent() bool { +func (sm *SyncManager) IsSynced() bool { reply := make(chan bool) - sm.msgChan <- isCurrentMsg{reply: reply} + sm.msgChan <- isSyncedMsg{reply: reply} return <-reply } +// isSynced checks if the node is synced enough based upon its worldview. +// This is used to determine if the node can support mining and requesting newly-mined blocks. +// To do that, first it checks if the selected tip timestamp is not older than maxTipAge. If that's the case, it means +// the node is synced since blocks' timestamps are not allowed to deviate too much into the future. +// If that's not the case it checks the rate it added new blocks to the DAG recently. If it's faster than +// blockRate * maxSyncRateDeviation it means the node is not synced, since when the node is synced it shouldn't add +// blocks to the DAG faster than the block rate. +func (sm *SyncManager) isSynced() bool { + const maxTipAge = 5 * time.Minute + isCloseToCurrentTime := sm.dag.Now().Sub(sm.dag.SelectedTipHeader().Timestamp) <= maxTipAge + if isCloseToCurrentTime { + return true + } + + const maxSyncRateDeviation = 1.05 + return sm.dag.IsSyncRateBelowThreshold(maxSyncRateDeviation) +} + // Pause pauses the sync manager until the returned channel is closed. // // Note that while paused, all peer and block processing is halted. The diff --git a/server/rpc/handle_get_block_template.go b/server/rpc/handle_get_block_template.go index ac615a596..20385d382 100644 --- a/server/rpc/handle_get_block_template.go +++ b/server/rpc/handle_get_block_template.go @@ -4,6 +4,12 @@ import ( "bytes" "encoding/hex" "fmt" + "math/rand" + "strconv" + "strings" + "sync" + "time" + "github.com/kaspanet/kaspad/blockdag" "github.com/kaspanet/kaspad/config" "github.com/kaspanet/kaspad/mining" @@ -14,11 +20,6 @@ import ( "github.com/kaspanet/kaspad/util/random" "github.com/kaspanet/kaspad/wire" "github.com/pkg/errors" - "math/rand" - "strconv" - "strings" - "sync" - "time" ) const ( @@ -119,24 +120,6 @@ func handleGetBlockTemplate(s *Server, cmd interface{}, closeChan <-chan struct{ } } -// isSyncedForMining checks if the node is synced enough for mining blocks -// on top of its world view. -// To do that, first it checks if the selected tip timestamp is not older than maxTipAge. If that's the case, it means -// the node is synced since blocks' timestamps are not allowed to deviate too much into the future. -// If that's not the case it checks the rate it added new blocks to the DAG recently. If it's faster than -// blockRate * maxSyncRateDeviation it means the node is not synced, since when the node is synced it shouldn't add -// blocks to the DAG faster than the block rate. -func isSyncedForMining(s *Server) bool { - const maxTipAge = 5 * time.Minute - isCloseToCurrentTime := s.cfg.DAG.Now().Sub(s.cfg.DAG.SelectedTipHeader().Timestamp) <= maxTipAge - if isCloseToCurrentTime { - return true - } - - const maxSyncRateDeviation = 1.05 - return s.cfg.DAG.IsSyncRateBelowThreshold(maxSyncRateDeviation) -} - // handleGetBlockTemplateRequest is a helper for handleGetBlockTemplate which // deals with generating and returning block templates to the caller. It // handles both long poll requests as specified by BIP 0022 as well as regular @@ -652,7 +635,7 @@ func (state *gbtWorkState) updateBlockTemplate(s *Server, useCoinbaseValue bool) // This is not a straight-up error because the choice of whether // to mine or not is the responsibility of the miner rather // than the node's. - isSynced := isSyncedForMining(s) + isSynced := s.cfg.SyncMgr.IsSynced() // Update work state to ensure another block template isn't // generated until needed. diff --git a/server/rpc/rpcadapters.go b/server/rpc/rpcadapters.go index 506ccf82b..119e6be6a 100644 --- a/server/rpc/rpcadapters.go +++ b/server/rpc/rpcadapters.go @@ -234,13 +234,13 @@ type rpcSyncMgr struct { // Ensure rpcSyncMgr implements the rpcserverSyncManager interface. var _ rpcserverSyncManager = (*rpcSyncMgr)(nil) -// IsCurrent returns whether or not the sync manager believes the DAG is +// IsSynced returns whether or not the sync manager believes the DAG is // current as compared to the rest of the network. // // This function is safe for concurrent access and is part of the // rpcserverSyncManager interface implementation. -func (b *rpcSyncMgr) IsCurrent() bool { - return b.syncMgr.IsCurrent() +func (b *rpcSyncMgr) IsSynced() bool { + return b.syncMgr.IsSynced() } // SubmitBlock submits the provided block to the network after processing it diff --git a/server/rpc/rpcserver.go b/server/rpc/rpcserver.go index 90cb640a1..fe8920881 100644 --- a/server/rpc/rpcserver.go +++ b/server/rpc/rpcserver.go @@ -723,9 +723,9 @@ type rpcserverConnManager interface { // The interface contract requires that all of these methods are safe for // concurrent access. type rpcserverSyncManager interface { - // IsCurrent returns whether or not the sync manager believes the DAG + // IsSynced returns whether or not the sync manager believes the DAG // is current as compared to the rest of the network. - IsCurrent() bool + IsSynced() bool // SubmitBlock submits the provided block to the network after // processing it locally.