[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
This commit is contained in:
Svarog 2020-05-18 10:42:58 +03:00 committed by GitHub
parent 28681affda
commit eb8b841850
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 37 deletions

View File

@ -103,10 +103,10 @@ type processBlockMsg struct {
reply chan processBlockResponse 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 // requesting whether or not the sync manager believes it is synced with the
// currently connected peers. // currently connected peers.
type isCurrentMsg struct { type isSyncedMsg struct {
reply chan bool reply chan bool
} }
@ -839,7 +839,7 @@ func (sm *SyncManager) sendInvsFromRequestQueue(peer *peerpkg.Peer, state *peerS
if err != nil { if err != nil {
return err return err
} }
if sm.current() { if sm.syncPeer == nil || sm.isSynced() {
err := sm.addInvsToGetDataMessageFromQueue(gdmsg, state, wire.InvTypeBlock, wire.MaxInvPerGetDataMsg) err := sm.addInvsToGetDataMessageFromQueue(gdmsg, state, wire.InvTypeBlock, wire.MaxInvPerGetDataMsg)
if err != nil { if err != nil {
return err return err
@ -968,8 +968,8 @@ out:
err: err, err: err,
} }
case isCurrentMsg: case isSyncedMsg:
msg.reply <- sm.current() msg.reply <- sm.isSynced()
case pauseMsg: case pauseMsg:
// Wait until the sender unpauses the manager. // 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 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. // the connected peers.
func (sm *SyncManager) IsCurrent() bool { func (sm *SyncManager) IsSynced() bool {
reply := make(chan bool) reply := make(chan bool)
sm.msgChan <- isCurrentMsg{reply: reply} sm.msgChan <- isSyncedMsg{reply: reply}
return <-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. // Pause pauses the sync manager until the returned channel is closed.
// //
// Note that while paused, all peer and block processing is halted. The // Note that while paused, all peer and block processing is halted. The

View File

@ -4,6 +4,12 @@ import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"math/rand"
"strconv"
"strings"
"sync"
"time"
"github.com/kaspanet/kaspad/blockdag" "github.com/kaspanet/kaspad/blockdag"
"github.com/kaspanet/kaspad/config" "github.com/kaspanet/kaspad/config"
"github.com/kaspanet/kaspad/mining" "github.com/kaspanet/kaspad/mining"
@ -14,11 +20,6 @@ import (
"github.com/kaspanet/kaspad/util/random" "github.com/kaspanet/kaspad/util/random"
"github.com/kaspanet/kaspad/wire" "github.com/kaspanet/kaspad/wire"
"github.com/pkg/errors" "github.com/pkg/errors"
"math/rand"
"strconv"
"strings"
"sync"
"time"
) )
const ( 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 // handleGetBlockTemplateRequest is a helper for handleGetBlockTemplate which
// deals with generating and returning block templates to the caller. It // 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 // 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 // This is not a straight-up error because the choice of whether
// to mine or not is the responsibility of the miner rather // to mine or not is the responsibility of the miner rather
// than the node's. // than the node's.
isSynced := isSyncedForMining(s) isSynced := s.cfg.SyncMgr.IsSynced()
// Update work state to ensure another block template isn't // Update work state to ensure another block template isn't
// generated until needed. // generated until needed.

View File

@ -234,13 +234,13 @@ type rpcSyncMgr struct {
// Ensure rpcSyncMgr implements the rpcserverSyncManager interface. // Ensure rpcSyncMgr implements the rpcserverSyncManager interface.
var _ rpcserverSyncManager = (*rpcSyncMgr)(nil) 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. // current as compared to the rest of the network.
// //
// This function is safe for concurrent access and is part of the // This function is safe for concurrent access and is part of the
// rpcserverSyncManager interface implementation. // rpcserverSyncManager interface implementation.
func (b *rpcSyncMgr) IsCurrent() bool { func (b *rpcSyncMgr) IsSynced() bool {
return b.syncMgr.IsCurrent() return b.syncMgr.IsSynced()
} }
// SubmitBlock submits the provided block to the network after processing it // SubmitBlock submits the provided block to the network after processing it

View File

@ -723,9 +723,9 @@ type rpcserverConnManager interface {
// The interface contract requires that all of these methods are safe for // The interface contract requires that all of these methods are safe for
// concurrent access. // concurrent access.
type rpcserverSyncManager interface { 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. // is current as compared to the rest of the network.
IsCurrent() bool IsSynced() bool
// SubmitBlock submits the provided block to the network after // SubmitBlock submits the provided block to the network after
// processing it locally. // processing it locally.