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.
10 "github.com/btcsuite/btcd/chaincfg"
14 // vbLegacyBlockVersion is the highest legacy block version before the
15 // version bits scheme became active.
16 vbLegacyBlockVersion = 4
18 // vbTopBits defines the bits to set in the version to signal that the
19 // version bits scheme is being used.
20 vbTopBits = 0x20000000
22 // vbTopMask is the bitmask to use to determine whether or not the
23 // version bits scheme is in use.
24 vbTopMask = 0xe0000000
26 // vbNumBits is the total number of bits available for use with the
27 // version bits scheme.
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
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
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.
45 type bitConditionChecker struct {
50 // Ensure the bitConditionChecker type implements the thresholdConditionChecker
52 var _ thresholdConditionChecker = bitConditionChecker{}
54 // BeginTime returns the unix timestamp for the median block time after which
55 // voting on a rule change starts (at the next window).
57 // Since this implementation checks for unknown rules, it returns 0 so the rule
58 // is always treated as active.
60 // This is part of the thresholdConditionChecker interface implementation.
61 func (c bitConditionChecker) BeginTime() uint64 {
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
69 // Since this implementation checks for unknown rules, it returns the maximum
70 // possible timestamp so the rule is always treated as active.
72 // This is part of the thresholdConditionChecker interface implementation.
73 func (c bitConditionChecker) EndTime() uint64 {
77 // RuleChangeActivationThreshold is the number of blocks for which the condition
78 // must be true in order to lock in a rule change.
80 // This implementation returns the value defined by the chain params the checker
81 // is associated with.
83 // This is part of the thresholdConditionChecker interface implementation.
84 func (c bitConditionChecker) RuleChangeActivationThreshold() uint32 {
85 return c.chain.chainParams.RuleChangeActivationThreshold
88 // MinerConfirmationWindow is the number of blocks in each threshold state
91 // This implementation returns the value defined by the chain params the checker
92 // is associated with.
94 // This is part of the thresholdConditionChecker interface implementation.
95 func (c bitConditionChecker) MinerConfirmationWindow() uint32 {
96 return c.chain.chainParams.MinerConfirmationWindow
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.
103 // This function MUST be called with the chain state lock held (for writes).
105 // This is part of the thresholdConditionChecker interface implementation.
106 func (c bitConditionChecker) Condition(node *blockNode) (bool, error) {
107 conditionMask := uint32(1) << c.bit
108 version := uint32(node.version)
109 if version&vbTopMask != vbTopBits {
112 if version&conditionMask == 0 {
116 expectedVersion, err := c.chain.calcNextBlockVersion(node.parent)
120 return uint32(expectedVersion)&conditionMask == 0, nil
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.
126 type deploymentChecker struct {
127 deployment *chaincfg.ConsensusDeployment
131 // Ensure the deploymentChecker type implements the thresholdConditionChecker
133 var _ thresholdConditionChecker = deploymentChecker{}
135 // BeginTime returns the unix timestamp for the median block time after which
136 // voting on a rule change starts (at the next window).
138 // This implementation returns the value defined by the specific deployment the
139 // checker is associated with.
141 // This is part of the thresholdConditionChecker interface implementation.
142 func (c deploymentChecker) BeginTime() uint64 {
143 return c.deployment.StartTime
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
150 // This implementation returns the value defined by the specific deployment the
151 // checker is associated with.
153 // This is part of the thresholdConditionChecker interface implementation.
154 func (c deploymentChecker) EndTime() uint64 {
155 return c.deployment.ExpireTime
158 // RuleChangeActivationThreshold is the number of blocks for which the condition
159 // must be true in order to lock in a rule change.
161 // This implementation returns the value defined by the chain params the checker
162 // is associated with.
164 // This is part of the thresholdConditionChecker interface implementation.
165 func (c deploymentChecker) RuleChangeActivationThreshold() uint32 {
166 return c.chain.chainParams.RuleChangeActivationThreshold
169 // MinerConfirmationWindow is the number of blocks in each threshold state
172 // This implementation returns the value defined by the chain params the checker
173 // is associated with.
175 // This is part of the thresholdConditionChecker interface implementation.
176 func (c deploymentChecker) MinerConfirmationWindow() uint32 {
177 return c.chain.chainParams.MinerConfirmationWindow
180 // Condition returns true when the specific bit defined by the deployment
181 // associated with the checker is set.
183 // This is part of the thresholdConditionChecker interface implementation.
184 func (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),
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.
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.
199 // This function MUST be called with the chain state lock held (for writes).
200 func (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)
213 if state == ThresholdStarted || state == ThresholdLockedIn {
214 expectedVersion |= uint32(1) << deployment.BitNumber
217 return int32(expectedVersion), nil
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.
224 // This function is safe for concurrent access.
225 func (b *BlockChain) CalcNextBlockVersion() (int32, error) {
227 version, err := b.calcNextBlockVersion(b.bestChain.Tip())
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
237 // This function MUST be called with the chain state lock held (for writes)
238 func (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)
250 case ThresholdActive:
251 if !b.unknownRulesWarned {
252 log.Warnf("Unknown new rules activated (bit %d)",
254 b.unknownRulesWarned = true
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)
268 // warnUnknownVersions logs a warning if a high enough percentage of the last
269 // blocks have unexpected versions.
271 // This function MUST be called with the chain state lock held (for writes)
272 func (b *BlockChain) warnUnknownVersions(node *blockNode) error {
273 // Nothing to do if already warned.
274 if b.unknownVersionsWarned {
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)
285 if expectedVersion > vbLegacyBlockVersion &&
286 (node.version & ^expectedVersion) != 0 {
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