github.com/btcsuite/btcd@v0.24.0/blockchain/thresholdstate.go (about) 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 5 package blockchain 6 7 import ( 8 "fmt" 9 "time" 10 11 "github.com/btcsuite/btcd/chaincfg/chainhash" 12 "github.com/btcsuite/btcd/wire" 13 ) 14 15 // ThresholdState define the various threshold states used when voting on 16 // consensus changes. 17 type ThresholdState byte 18 19 // These constants are used to identify specific threshold states. 20 const ( 21 // ThresholdDefined is the first state for each deployment and is the 22 // state for the genesis block has by definition for all deployments. 23 ThresholdDefined ThresholdState = iota 24 25 // ThresholdStarted is the state for a deployment once its start time 26 // has been reached. 27 ThresholdStarted 28 29 // ThresholdLockedIn is the state for a deployment during the retarget 30 // period which is after the ThresholdStarted state period and the 31 // number of blocks that have voted for the deployment equal or exceed 32 // the required number of votes for the deployment. 33 ThresholdLockedIn 34 35 // ThresholdActive is the state for a deployment for all blocks after a 36 // retarget period in which the deployment was in the ThresholdLockedIn 37 // state. 38 ThresholdActive 39 40 // ThresholdFailed is the state for a deployment once its expiration 41 // time has been reached and it did not reach the ThresholdLockedIn 42 // state. 43 ThresholdFailed 44 45 // numThresholdsStates is the maximum number of threshold states used in 46 // tests. 47 numThresholdsStates 48 ) 49 50 // thresholdStateStrings is a map of ThresholdState values back to their 51 // constant names for pretty printing. 52 var thresholdStateStrings = map[ThresholdState]string{ 53 ThresholdDefined: "ThresholdDefined", 54 ThresholdStarted: "ThresholdStarted", 55 ThresholdLockedIn: "ThresholdLockedIn", 56 ThresholdActive: "ThresholdActive", 57 ThresholdFailed: "ThresholdFailed", 58 } 59 60 // String returns the ThresholdState as a human-readable name. 61 func (t ThresholdState) String() string { 62 if s := thresholdStateStrings[t]; s != "" { 63 return s 64 } 65 return fmt.Sprintf("Unknown ThresholdState (%d)", int(t)) 66 } 67 68 // thresholdConditionChecker provides a generic interface that is invoked to 69 // determine when a consensus rule change threshold should be changed. 70 type thresholdConditionChecker interface { 71 // HasStarted returns true if based on the passed block blockNode the 72 // consensus is eligible for deployment. 73 HasStarted(*blockNode) bool 74 75 // HasEnded returns true if the target consensus rule change has 76 // expired or timed out. 77 HasEnded(*blockNode) bool 78 79 // RuleChangeActivationThreshold is the number of blocks for which the 80 // condition must be true in order to lock in a rule change. 81 RuleChangeActivationThreshold() uint32 82 83 // MinerConfirmationWindow is the number of blocks in each threshold 84 // state retarget window. 85 MinerConfirmationWindow() uint32 86 87 // EligibleToActivate returns true if a custom deployment can 88 // transition from the LockedIn to the Active state. For normal 89 // deployments, this always returns true. However, some deployments add 90 // extra rules like a minimum activation height, which can be 91 // abstracted into a generic arbitrary check at the final state via 92 // this method. 93 EligibleToActivate(*blockNode) bool 94 95 // IsSpeedy returns true if this is to be a "speedy" deployment. A 96 // speedy deployment differs from a regular one in that only after a 97 // miner block confirmation window can the deployment expire. 98 IsSpeedy() bool 99 100 // Condition returns whether or not the rule change activation 101 // condition has been met. This typically involves checking whether or 102 // not the bit associated with the condition is set, but can be more 103 // complex as needed. 104 Condition(*blockNode) (bool, error) 105 } 106 107 // thresholdStateCache provides a type to cache the threshold states of each 108 // threshold window for a set of IDs. 109 type thresholdStateCache struct { 110 entries map[chainhash.Hash]ThresholdState 111 } 112 113 // Lookup returns the threshold state associated with the given hash along with 114 // a boolean that indicates whether or not it is valid. 115 func (c *thresholdStateCache) Lookup(hash *chainhash.Hash) (ThresholdState, bool) { 116 state, ok := c.entries[*hash] 117 return state, ok 118 } 119 120 // Update updates the cache to contain the provided hash to threshold state 121 // mapping. 122 func (c *thresholdStateCache) Update(hash *chainhash.Hash, state ThresholdState) { 123 c.entries[*hash] = state 124 } 125 126 // newThresholdCaches returns a new array of caches to be used when calculating 127 // threshold states. 128 func newThresholdCaches(numCaches uint32) []thresholdStateCache { 129 caches := make([]thresholdStateCache, numCaches) 130 for i := 0; i < len(caches); i++ { 131 caches[i] = thresholdStateCache{ 132 entries: make(map[chainhash.Hash]ThresholdState), 133 } 134 } 135 return caches 136 } 137 138 // PastMedianTime returns the past median time from the PoV of the passed block 139 // header. The past median time is the median time of the 11 blocks prior to 140 // the passed block header. 141 // 142 // NOTE: This is part of the chainfg.BlockClock interface 143 func (b *BlockChain) PastMedianTime(blockHeader *wire.BlockHeader) (time.Time, error) { 144 prevHash := blockHeader.PrevBlock 145 prevNode := b.index.LookupNode(&prevHash) 146 147 // If we can't find the previous node, then we can't compute the block 148 // time since it requires us to walk backwards from this node. 149 if prevNode == nil { 150 return time.Time{}, fmt.Errorf("blockHeader(%v) has no "+ 151 "previous node", blockHeader.BlockHash()) 152 } 153 154 blockNode := newBlockNode(blockHeader, prevNode) 155 156 return CalcPastMedianTime(blockNode), nil 157 } 158 159 // thresholdStateTransition given a state, a previous node, and a toeholds 160 // checker, this function transitions to the next state as defined by BIP 009. 161 // This state transition function is also aware of the "speedy trial" 162 // modifications made to BIP 0009 as part of the taproot softfork activation. 163 func thresholdStateTransition(state ThresholdState, prevNode *blockNode, 164 checker thresholdConditionChecker, 165 confirmationWindow int32) (ThresholdState, error) { 166 167 switch state { 168 case ThresholdDefined: 169 // The deployment of the rule change fails if it 170 // expires before it is accepted and locked in. However 171 // speed deployments can only transition to failed 172 // after a confirmation window. 173 if !checker.IsSpeedy() && checker.HasEnded(prevNode) { 174 log.Debugf("Moving from state=%v, to state=%v", state, 175 ThresholdFailed) 176 177 state = ThresholdFailed 178 break 179 } 180 181 // The state for the rule moves to the started state 182 // once its start time has been reached (and it hasn't 183 // already expired per the above). 184 if checker.HasStarted(prevNode) { 185 log.Debugf("Moving from state=%v, to state=%v", state, 186 ThresholdStarted) 187 188 state = ThresholdStarted 189 } 190 191 case ThresholdStarted: 192 // The deployment of the rule change fails if it 193 // expires before it is accepted and locked in, but 194 // only if this deployment isn't speedy. 195 if !checker.IsSpeedy() && checker.HasEnded(prevNode) { 196 log.Debugf("Moving from state=%v, to state=%v", state, 197 ThresholdFailed) 198 199 state = ThresholdFailed 200 break 201 } 202 203 // At this point, the rule change is still being voted 204 // on by the miners, so iterate backwards through the 205 // confirmation window to count all of the votes in it. 206 var count uint32 207 countNode := prevNode 208 for i := int32(0); i < confirmationWindow; i++ { 209 condition, err := checker.Condition(countNode) 210 if err != nil { 211 return ThresholdFailed, err 212 } 213 if condition { 214 count++ 215 } 216 217 // Get the previous block node. 218 countNode = countNode.parent 219 } 220 221 switch { 222 // The state is locked in if the number of blocks in the 223 // period that voted for the rule change meets the 224 // activation threshold. 225 case count >= checker.RuleChangeActivationThreshold(): 226 log.Debugf("Moving from state=%v, to state=%v", state, 227 ThresholdLockedIn) 228 229 state = ThresholdLockedIn 230 231 // If this is a speedy deployment, we didn't meet the 232 // threshold above, and the deployment has expired, then 233 // we transition to failed. 234 case checker.IsSpeedy() && checker.HasEnded(prevNode): 235 log.Debugf("Moving from state=%v, to state=%v", state, 236 ThresholdFailed) 237 238 state = ThresholdFailed 239 240 default: 241 log.Tracef("Still at state=%v, threshold=%v", state, 242 float64(count)/float64(checker.RuleChangeActivationThreshold())) 243 } 244 245 case ThresholdLockedIn: 246 // At this point, we'll consult the deployment see if a 247 // custom deployment has any other arbitrary conditions 248 // that need to pass before execution. This might be a 249 // minimum activation height or another policy. 250 // 251 // If we aren't eligible to active yet, then we'll just 252 // stay in the locked in position. 253 if !checker.EligibleToActivate(prevNode) { 254 log.Debugf("Moving from state=%v, to state=%v", state, 255 ThresholdLockedIn) 256 257 state = ThresholdLockedIn 258 } else { 259 log.Debugf("Moving from state=%v, to state=%v", state, 260 ThresholdActive) 261 262 // The new rule becomes active when its 263 // previous state was locked in assuming it's 264 // now eligible to activate. 265 state = ThresholdActive 266 } 267 268 // Nothing to do if the previous state is active or failed since 269 // they are both terminal states. 270 case ThresholdActive: 271 case ThresholdFailed: 272 } 273 274 return state, nil 275 } 276 277 // thresholdState returns the current rule change threshold state for the block 278 // AFTER the given node and deployment ID. The cache is used to ensure the 279 // threshold states for previous windows are only calculated once. 280 // 281 // This function MUST be called with the chain state lock held (for writes). 282 func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdConditionChecker, cache *thresholdStateCache) (ThresholdState, error) { 283 // The threshold state for the window that contains the genesis block is 284 // defined by definition. 285 confirmationWindow := int32(checker.MinerConfirmationWindow()) 286 if prevNode == nil || (prevNode.height+1) < confirmationWindow { 287 return ThresholdDefined, nil 288 } 289 290 // Get the ancestor that is the last block of the previous confirmation 291 // window in order to get its threshold state. This can be done because 292 // the state is the same for all blocks within a given window. 293 prevNode = prevNode.Ancestor(prevNode.height - 294 (prevNode.height+1)%confirmationWindow) 295 296 // Iterate backwards through each of the previous confirmation windows 297 // to find the most recently cached threshold state. 298 var neededStates []*blockNode 299 for prevNode != nil { 300 // Nothing more to do if the state of the block is already 301 // cached. 302 if _, ok := cache.Lookup(&prevNode.hash); ok { 303 break 304 } 305 306 // The state is simply defined if the start time hasn't been 307 // been reached yet. 308 if !checker.HasStarted(prevNode) { 309 cache.Update(&prevNode.hash, ThresholdDefined) 310 break 311 } 312 313 // Add this node to the list of nodes that need the state 314 // calculated and cached. 315 neededStates = append(neededStates, prevNode) 316 317 // Get the ancestor that is the last block of the previous 318 // confirmation window. 319 prevNode = prevNode.RelativeAncestor(confirmationWindow) 320 } 321 322 // Start with the threshold state for the most recent confirmation 323 // window that has a cached state. 324 state := ThresholdDefined 325 if prevNode != nil { 326 var ok bool 327 state, ok = cache.Lookup(&prevNode.hash) 328 if !ok { 329 return ThresholdFailed, AssertError(fmt.Sprintf( 330 "thresholdState: cache lookup failed for %v", 331 prevNode.hash)) 332 } 333 } 334 335 // Since each threshold state depends on the state of the previous 336 // window, iterate starting from the oldest unknown window. 337 var err error 338 for neededNum := len(neededStates) - 1; neededNum >= 0; neededNum-- { 339 prevNode := neededStates[neededNum] 340 341 // Based on the current state, the previous node, and the 342 // condition checker, transition to the next threshold state. 343 state, err = thresholdStateTransition( 344 state, prevNode, checker, confirmationWindow, 345 ) 346 if err != nil { 347 return state, err 348 } 349 350 // Update the cache to avoid recalculating the state in the 351 // future. 352 cache.Update(&prevNode.hash, state) 353 } 354 355 return state, nil 356 } 357 358 // ThresholdState returns the current rule change threshold state of the given 359 // deployment ID for the block AFTER the end of the current best chain. 360 // 361 // This function is safe for concurrent access. 362 func (b *BlockChain) ThresholdState(deploymentID uint32) (ThresholdState, error) { 363 b.chainLock.Lock() 364 state, err := b.deploymentState(b.bestChain.Tip(), deploymentID) 365 b.chainLock.Unlock() 366 367 return state, err 368 } 369 370 // IsDeploymentActive returns true if the target deploymentID is active, and 371 // false otherwise. 372 // 373 // This function is safe for concurrent access. 374 func (b *BlockChain) IsDeploymentActive(deploymentID uint32) (bool, error) { 375 b.chainLock.Lock() 376 state, err := b.deploymentState(b.bestChain.Tip(), deploymentID) 377 b.chainLock.Unlock() 378 if err != nil { 379 return false, err 380 } 381 382 return state == ThresholdActive, nil 383 } 384 385 // deploymentState returns the current rule change threshold for a given 386 // deploymentID. The threshold is evaluated from the point of view of the block 387 // node passed in as the first argument to this method. 388 // 389 // It is important to note that, as the variable name indicates, this function 390 // expects the block node prior to the block for which the deployment state is 391 // desired. In other words, the returned deployment state is for the block 392 // AFTER the passed node. 393 // 394 // This function MUST be called with the chain state lock held (for writes). 395 func (b *BlockChain) deploymentState(prevNode *blockNode, deploymentID uint32) (ThresholdState, error) { 396 if deploymentID > uint32(len(b.chainParams.Deployments)) { 397 return ThresholdFailed, DeploymentError(deploymentID) 398 } 399 400 deployment := &b.chainParams.Deployments[deploymentID] 401 checker := deploymentChecker{deployment: deployment, chain: b} 402 cache := &b.deploymentCaches[deploymentID] 403 404 return b.thresholdState(prevNode, checker, cache) 405 } 406 407 // initThresholdCaches initializes the threshold state caches for each warning 408 // bit and defined deployment and provides warnings if the chain is current per 409 // the warnUnknownRuleActivations function. 410 func (b *BlockChain) initThresholdCaches() error { 411 // Initialize the warning and deployment caches by calculating the 412 // threshold state for each of them. This will ensure the caches are 413 // populated and any states that needed to be recalculated due to 414 // definition changes is done now. 415 prevNode := b.bestChain.Tip().parent 416 for bit := uint32(0); bit < vbNumBits; bit++ { 417 checker := bitConditionChecker{bit: bit, chain: b} 418 cache := &b.warningCaches[bit] 419 _, err := b.thresholdState(prevNode, checker, cache) 420 if err != nil { 421 return err 422 } 423 } 424 for id := 0; id < len(b.chainParams.Deployments); id++ { 425 deployment := &b.chainParams.Deployments[id] 426 cache := &b.deploymentCaches[id] 427 checker := deploymentChecker{deployment: deployment, chain: b} 428 _, err := b.thresholdState(prevNode, checker, cache) 429 if err != nil { 430 return err 431 } 432 } 433 434 // No warnings about unknown rules until the chain is current. 435 if b.isCurrent() { 436 bestNode := b.bestChain.Tip() 437 438 // Warn if any unknown new rules are either about to activate or 439 // have already been activated. 440 if err := b.warnUnknownRuleActivations(bestNode); err != nil { 441 return err 442 } 443 } 444 445 return nil 446 }