1// Copyright (c) 2016-2017 The btcsuite developers 2// Use of this source code is governed by an ISC 3// license that can be found in the LICENSE file. 4 5package blockchain 6 7import ( 8 "math" 9 10 "github.com/btcsuite/btcd/chaincfg" 11) 12 13const ( 14 // vbLegacyBlockVersion is the highest legacy block version before the 15 // version bits scheme became active. 16 vbLegacyBlockVersion = 4 17 18 // vbTopBits defines the bits to set in the version to signal that the 19 // version bits scheme is being used. 20 vbTopBits = 0x20000000 21 22 // vbTopMask is the bitmask to use to determine whether or not the 23 // version bits scheme is in use. 24 vbTopMask = 0xe0000000 25 26 // vbNumBits is the total number of bits available for use with the 27 // version bits scheme. 28 vbNumBits = 29 29 30 // unknownVerNumToCheck is the number of previous blocks to consider 31 // when checking for a threshold of unknown block versions for the 32 // purposes of warning the user. 33 unknownVerNumToCheck = 100 34 35 // unknownVerWarnNum is the threshold of previous blocks that have an 36 // unknown version to use for the purposes of warning the user. 37 unknownVerWarnNum = unknownVerNumToCheck / 2 38) 39 40// bitConditionChecker provides a thresholdConditionChecker which can be used to 41// test whether or not a specific bit is set when it's not supposed to be 42// according to the expected version based on the known deployments and the 43// current state of the chain. This is useful for detecting and warning about 44// unknown rule activations. 45type bitConditionChecker struct { 46 bit uint32 47 chain *BlockChain 48} 49 50// Ensure the bitConditionChecker type implements the thresholdConditionChecker 51// interface. 52var _ thresholdConditionChecker = bitConditionChecker{} 53 54// BeginTime returns the unix timestamp for the median block time after which 55// voting on a rule change starts (at the next window). 56// 57// Since this implementation checks for unknown rules, it returns 0 so the rule 58// is always treated as active. 59// 60// This is part of the thresholdConditionChecker interface implementation. 61func (c bitConditionChecker) BeginTime() uint64 { 62 return 0 63} 64 65// EndTime returns the unix timestamp for the median block time after which an 66// attempted rule change fails if it has not already been locked in or 67// activated. 68// 69// Since this implementation checks for unknown rules, it returns the maximum 70// possible timestamp so the rule is always treated as active. 71// 72// This is part of the thresholdConditionChecker interface implementation. 73func (c bitConditionChecker) EndTime() uint64 { 74 return math.MaxUint64 75} 76 77// RuleChangeActivationThreshold is the number of blocks for which the condition 78// must be true in order to lock in a rule change. 79// 80// This implementation returns the value defined by the chain params the checker 81// is associated with. 82// 83// This is part of the thresholdConditionChecker interface implementation. 84func (c bitConditionChecker) RuleChangeActivationThreshold() uint32 { 85 return c.chain.chainParams.RuleChangeActivationThreshold 86} 87 88// MinerConfirmationWindow is the number of blocks in each threshold state 89// retarget window. 90// 91// This implementation returns the value defined by the chain params the checker 92// is associated with. 93// 94// This is part of the thresholdConditionChecker interface implementation. 95func (c bitConditionChecker) MinerConfirmationWindow() uint32 { 96 return c.chain.chainParams.MinerConfirmationWindow 97} 98 99// Condition returns true when the specific bit associated with the checker is 100// set and it's not supposed to be according to the expected version based on 101// the known deployments and the current state of the chain. 102// 103// This function MUST be called with the chain state lock held (for writes). 104// 105// This is part of the thresholdConditionChecker interface implementation. 106func (c bitConditionChecker) Condition(node *blockNode) (bool, error) { 107 conditionMask := uint32(1) << c.bit 108 version := uint32(node.version) 109 if version&vbTopMask != vbTopBits { 110 return false, nil 111 } 112 if version&conditionMask == 0 { 113 return false, nil 114 } 115 116 expectedVersion, err := c.chain.calcNextBlockVersion(node.parent) 117 if err != nil { 118 return false, err 119 } 120 return uint32(expectedVersion)&conditionMask == 0, nil 121} 122 123// deploymentChecker provides a thresholdConditionChecker which can be used to 124// test a specific deployment rule. This is required for properly detecting 125// and activating consensus rule changes. 126type deploymentChecker struct { 127 deployment *chaincfg.ConsensusDeployment 128 chain *BlockChain 129} 130 131// Ensure the deploymentChecker type implements the thresholdConditionChecker 132// interface. 133var _ thresholdConditionChecker = deploymentChecker{} 134 135// BeginTime returns the unix timestamp for the median block time after which 136// voting on a rule change starts (at the next window). 137// 138// This implementation returns the value defined by the specific deployment the 139// checker is associated with. 140// 141// This is part of the thresholdConditionChecker interface implementation. 142func (c deploymentChecker) BeginTime() uint64 { 143 return c.deployment.StartTime 144} 145 146// EndTime returns the unix timestamp for the median block time after which an 147// attempted rule change fails if it has not already been locked in or 148// activated. 149// 150// This implementation returns the value defined by the specific deployment the 151// checker is associated with. 152// 153// This is part of the thresholdConditionChecker interface implementation. 154func (c deploymentChecker) EndTime() uint64 { 155 return c.deployment.ExpireTime 156} 157 158// RuleChangeActivationThreshold is the number of blocks for which the condition 159// must be true in order to lock in a rule change. 160// 161// This implementation returns the value defined by the chain params the checker 162// is associated with. 163// 164// This is part of the thresholdConditionChecker interface implementation. 165func (c deploymentChecker) RuleChangeActivationThreshold() uint32 { 166 return c.chain.chainParams.RuleChangeActivationThreshold 167} 168 169// MinerConfirmationWindow is the number of blocks in each threshold state 170// retarget window. 171// 172// This implementation returns the value defined by the chain params the checker 173// is associated with. 174// 175// This is part of the thresholdConditionChecker interface implementation. 176func (c deploymentChecker) MinerConfirmationWindow() uint32 { 177 return c.chain.chainParams.MinerConfirmationWindow 178} 179 180// Condition returns true when the specific bit defined by the deployment 181// associated with the checker is set. 182// 183// This is part of the thresholdConditionChecker interface implementation. 184func (c deploymentChecker) Condition(node *blockNode) (bool, error) { 185 conditionMask := uint32(1) << c.deployment.BitNumber 186 version := uint32(node.version) 187 return (version&vbTopMask == vbTopBits) && (version&conditionMask != 0), 188 nil 189} 190 191// calcNextBlockVersion calculates the expected version of the block after the 192// passed previous block node based on the state of started and locked in 193// rule change deployments. 194// 195// This function differs from the exported CalcNextBlockVersion in that the 196// exported version uses the current best chain as the previous block node 197// while this function accepts any block node. 198// 199// This function MUST be called with the chain state lock held (for writes). 200func (b *BlockChain) calcNextBlockVersion(prevNode *blockNode) (int32, error) { 201 // Set the appropriate bits for each actively defined rule deployment 202 // that is either in the process of being voted on, or locked in for the 203 // activation at the next threshold window change. 204 expectedVersion := uint32(vbTopBits) 205 for id := 0; id < len(b.chainParams.Deployments); id++ { 206 deployment := &b.chainParams.Deployments[id] 207 cache := &b.deploymentCaches[id] 208 checker := deploymentChecker{deployment: deployment, chain: b} 209 state, err := b.thresholdState(prevNode, checker, cache) 210 if err != nil { 211 return 0, err 212 } 213 if state == ThresholdStarted || state == ThresholdLockedIn { 214 expectedVersion |= uint32(1) << deployment.BitNumber 215 } 216 } 217 return int32(expectedVersion), nil 218} 219 220// CalcNextBlockVersion calculates the expected version of the block after the 221// end of the current best chain based on the state of started and locked in 222// rule change deployments. 223// 224// This function is safe for concurrent access. 225func (b *BlockChain) CalcNextBlockVersion() (int32, error) { 226 b.chainLock.Lock() 227 version, err := b.calcNextBlockVersion(b.bestChain.Tip()) 228 b.chainLock.Unlock() 229 return version, err 230} 231 232// warnUnknownRuleActivations displays a warning when any unknown new rules are 233// either about to activate or have been activated. This will only happen once 234// when new rules have been activated and every block for those about to be 235// activated. 236// 237// This function MUST be called with the chain state lock held (for writes) 238func (b *BlockChain) warnUnknownRuleActivations(node *blockNode) error { 239 // Warn if any unknown new rules are either about to activate or have 240 // already been activated. 241 for bit := uint32(0); bit < vbNumBits; bit++ { 242 checker := bitConditionChecker{bit: bit, chain: b} 243 cache := &b.warningCaches[bit] 244 state, err := b.thresholdState(node.parent, checker, cache) 245 if err != nil { 246 return err 247 } 248 249 switch state { 250 case ThresholdActive: 251 if !b.unknownRulesWarned { 252 log.Warnf("Unknown new rules activated (bit %d)", 253 bit) 254 b.unknownRulesWarned = true 255 } 256 257 case ThresholdLockedIn: 258 window := int32(checker.MinerConfirmationWindow()) 259 activationHeight := window - (node.height % window) 260 log.Warnf("Unknown new rules are about to activate in "+ 261 "%d blocks (bit %d)", activationHeight, bit) 262 } 263 } 264 265 return nil 266} 267 268// warnUnknownVersions logs a warning if a high enough percentage of the last 269// blocks have unexpected versions. 270// 271// This function MUST be called with the chain state lock held (for writes) 272func (b *BlockChain) warnUnknownVersions(node *blockNode) error { 273 // Nothing to do if already warned. 274 if b.unknownVersionsWarned { 275 return nil 276 } 277 278 // Warn if enough previous blocks have unexpected versions. 279 numUpgraded := uint32(0) 280 for i := uint32(0); i < unknownVerNumToCheck && node != nil; i++ { 281 expectedVersion, err := b.calcNextBlockVersion(node.parent) 282 if err != nil { 283 return err 284 } 285 if expectedVersion > vbLegacyBlockVersion && 286 (node.version & ^expectedVersion) != 0 { 287 288 numUpgraded++ 289 } 290 291 node = node.parent 292 } 293 if numUpgraded > unknownVerWarnNum { 294 log.Warn("Unknown block versions are being mined, so new " + 295 "rules might be in effect. Are you running the " + 296 "latest version of the software?") 297 b.unknownVersionsWarned = true 298 } 299 300 return nil 301} 302