diff --git a/blockmanager.go b/blockmanager.go index 4b15d638..6a96b56d 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -519,7 +519,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { // current returns true if we believe we are synced with our peers, false if we // still have blocks to check func (b *blockManager) current() bool { - if !b.blockChain.IsCurrent() { + if !b.blockChain.IsCurrent(b.server.timeSource) { return false } @@ -591,7 +591,8 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // Process the block to include validation, best chain selection, orphan // handling, etc. - isOrphan, err := b.blockChain.ProcessBlock(bmsg.block, behaviorFlags) + isOrphan, err := b.blockChain.ProcessBlock(bmsg.block, + b.server.timeSource, behaviorFlags) if err != nil { // When the error is a rule error, it means the block was simply // rejected as opposed to something actually going wrong, so log @@ -1065,7 +1066,8 @@ out: case processBlockMsg: isOrphan, err := b.blockChain.ProcessBlock( - msg.block, msg.flags) + msg.block, b.server.timeSource, + msg.flags) if err != nil { msg.reply <- processBlockResponse{ isOrphan: false, diff --git a/peer.go b/peer.go index 5e32bb13..394bba49 100644 --- a/peer.go +++ b/peer.go @@ -444,6 +444,10 @@ func (p *peer) handleVersionMsg(msg *btcwire.MsgVersion) { p.updateAddresses(msg) } + // Add the remote peer time as a sample for creating an offset against + // the local clock to keep the network time in sync. + p.server.timeSource.AddTimeSample(p.addr, msg.Timestamp) + // Signal the block manager this peer is a new sync candidate. p.server.blockManager.NewPeer(p) diff --git a/rpcserver.go b/rpcserver.go index 92a24de5..14032834 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3071,7 +3071,7 @@ func handleSubmitBlock(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) return nil, nil } -func verifyChain(db btcdb.Db, level, depth int32) error { +func verifyChain(db btcdb.Db, level, depth int32, timeSource btcchain.MedianTimeSource) error { _, curHeight64, err := db.NewestSha() if err != nil { rpcsLog.Errorf("Verify is unable to fetch current block "+ @@ -3105,7 +3105,7 @@ func verifyChain(db btcdb.Db, level, depth int32) error { // Level 1 does basic chain sanity checks. if level > 0 { err := btcchain.CheckBlockSanity(block, - activeNetParams.PowLimit) + activeNetParams.PowLimit, timeSource) if err != nil { rpcsLog.Errorf("Verify is unable to "+ "validate block at sha %v height "+ @@ -3140,7 +3140,8 @@ func handleValidateAddress(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struc func handleVerifyChain(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) { c := cmd.(*btcjson.VerifyChainCmd) - err := verifyChain(s.server.db, c.CheckLevel, c.CheckDepth) + err := verifyChain(s.server.db, c.CheckLevel, c.CheckDepth, + s.server.timeSource) return err == nil, nil } diff --git a/server.go b/server.go index 71477b12..87ac6335 100644 --- a/server.go +++ b/server.go @@ -19,6 +19,7 @@ import ( "sync/atomic" "time" + "github.com/conformal/btcchain" "github.com/conformal/btcd/addrmgr" "github.com/conformal/btcdb" "github.com/conformal/btcjson" @@ -90,6 +91,7 @@ type server struct { quit chan struct{} nat NAT db btcdb.Db + timeSource btcchain.MedianTimeSource } type peerState struct { @@ -1229,6 +1231,7 @@ func newServer(listenAddrs []string, db btcdb.Db, netParams *btcnet.Params) (*se modifyRebroadcastInv: make(chan interface{}), nat: nat, db: db, + timeSource: btcchain.NewMedianTime(), } bm, err := newBlockManager(&s) if err != nil {