github.com/palcoin-project/palcd@v1.0.0/blockchain/versionbits.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  	"math"
     9  
    10  	"github.com/palcoin-project/palcd/chaincfg"
    11  )
    12  
    13  const (
    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  
    31  // bitConditionChecker provides a thresholdConditionChecker which can be used to
    32  // test whether or not a specific bit is set when it's not supposed to be
    33  // according to the expected version based on the known deployments and the
    34  // current state of the chain.  This is useful for detecting and warning about
    35  // unknown rule activations.
    36  type bitConditionChecker struct {
    37  	bit   uint32
    38  	chain *BlockChain
    39  }
    40  
    41  // Ensure the bitConditionChecker type implements the thresholdConditionChecker
    42  // interface.
    43  var _ thresholdConditionChecker = bitConditionChecker{}
    44  
    45  // BeginTime returns the unix timestamp for the median block time after which
    46  // voting on a rule change starts (at the next window).
    47  //
    48  // Since this implementation checks for unknown rules, it returns 0 so the rule
    49  // is always treated as active.
    50  //
    51  // This is part of the thresholdConditionChecker interface implementation.
    52  func (c bitConditionChecker) BeginTime() uint64 {
    53  	return 0
    54  }
    55  
    56  // EndTime returns the unix timestamp for the median block time after which an
    57  // attempted rule change fails if it has not already been locked in or
    58  // activated.
    59  //
    60  // Since this implementation checks for unknown rules, it returns the maximum
    61  // possible timestamp so the rule is always treated as active.
    62  //
    63  // This is part of the thresholdConditionChecker interface implementation.
    64  func (c bitConditionChecker) EndTime() uint64 {
    65  	return math.MaxUint64
    66  }
    67  
    68  // RuleChangeActivationThreshold is the number of blocks for which the condition
    69  // must be true in order to lock in a rule change.
    70  //
    71  // This implementation returns the value defined by the chain params the checker
    72  // is associated with.
    73  //
    74  // This is part of the thresholdConditionChecker interface implementation.
    75  func (c bitConditionChecker) RuleChangeActivationThreshold() uint32 {
    76  	return c.chain.chainParams.RuleChangeActivationThreshold
    77  }
    78  
    79  // MinerConfirmationWindow is the number of blocks in each threshold state
    80  // retarget window.
    81  //
    82  // This implementation returns the value defined by the chain params the checker
    83  // is associated with.
    84  //
    85  // This is part of the thresholdConditionChecker interface implementation.
    86  func (c bitConditionChecker) MinerConfirmationWindow() uint32 {
    87  	return c.chain.chainParams.MinerConfirmationWindow
    88  }
    89  
    90  // Condition returns true when the specific bit associated with the checker is
    91  // set and it's not supposed to be according to the expected version based on
    92  // the known deployments and the current state of the chain.
    93  //
    94  // This function MUST be called with the chain state lock held (for writes).
    95  //
    96  // This is part of the thresholdConditionChecker interface implementation.
    97  func (c bitConditionChecker) Condition(node *blockNode) (bool, error) {
    98  	conditionMask := uint32(1) << c.bit
    99  	version := uint32(node.version)
   100  	if version&vbTopMask != vbTopBits {
   101  		return false, nil
   102  	}
   103  	if version&conditionMask == 0 {
   104  		return false, nil
   105  	}
   106  
   107  	expectedVersion, err := c.chain.calcNextBlockVersion(node.parent)
   108  	if err != nil {
   109  		return false, err
   110  	}
   111  	return uint32(expectedVersion)&conditionMask == 0, nil
   112  }
   113  
   114  // deploymentChecker provides a thresholdConditionChecker which can be used to
   115  // test a specific deployment rule.  This is required for properly detecting
   116  // and activating consensus rule changes.
   117  type deploymentChecker struct {
   118  	deployment *chaincfg.ConsensusDeployment
   119  	chain      *BlockChain
   120  }
   121  
   122  // Ensure the deploymentChecker type implements the thresholdConditionChecker
   123  // interface.
   124  var _ thresholdConditionChecker = deploymentChecker{}
   125  
   126  // BeginTime returns the unix timestamp for the median block time after which
   127  // voting on a rule change starts (at the next window).
   128  //
   129  // This implementation returns the value defined by the specific deployment the
   130  // checker is associated with.
   131  //
   132  // This is part of the thresholdConditionChecker interface implementation.
   133  func (c deploymentChecker) BeginTime() uint64 {
   134  	return c.deployment.StartTime
   135  }
   136  
   137  // EndTime returns the unix timestamp for the median block time after which an
   138  // attempted rule change fails if it has not already been locked in or
   139  // activated.
   140  //
   141  // This implementation returns the value defined by the specific deployment the
   142  // checker is associated with.
   143  //
   144  // This is part of the thresholdConditionChecker interface implementation.
   145  func (c deploymentChecker) EndTime() uint64 {
   146  	return c.deployment.ExpireTime
   147  }
   148  
   149  // RuleChangeActivationThreshold is the number of blocks for which the condition
   150  // must be true in order to lock in a rule change.
   151  //
   152  // This implementation returns the value defined by the chain params the checker
   153  // is associated with.
   154  //
   155  // This is part of the thresholdConditionChecker interface implementation.
   156  func (c deploymentChecker) RuleChangeActivationThreshold() uint32 {
   157  	return c.chain.chainParams.RuleChangeActivationThreshold
   158  }
   159  
   160  // MinerConfirmationWindow is the number of blocks in each threshold state
   161  // retarget window.
   162  //
   163  // This implementation returns the value defined by the chain params the checker
   164  // is associated with.
   165  //
   166  // This is part of the thresholdConditionChecker interface implementation.
   167  func (c deploymentChecker) MinerConfirmationWindow() uint32 {
   168  	return c.chain.chainParams.MinerConfirmationWindow
   169  }
   170  
   171  // Condition returns true when the specific bit defined by the deployment
   172  // associated with the checker is set.
   173  //
   174  // This is part of the thresholdConditionChecker interface implementation.
   175  func (c deploymentChecker) Condition(node *blockNode) (bool, error) {
   176  	conditionMask := uint32(1) << c.deployment.BitNumber
   177  	version := uint32(node.version)
   178  	return (version&vbTopMask == vbTopBits) && (version&conditionMask != 0),
   179  		nil
   180  }
   181  
   182  // calcNextBlockVersion calculates the expected version of the block after the
   183  // passed previous block node based on the state of started and locked in
   184  // rule change deployments.
   185  //
   186  // This function differs from the exported CalcNextBlockVersion in that the
   187  // exported version uses the current best chain as the previous block node
   188  // while this function accepts any block node.
   189  //
   190  // This function MUST be called with the chain state lock held (for writes).
   191  func (b *BlockChain) calcNextBlockVersion(prevNode *blockNode) (int32, error) {
   192  	// Set the appropriate bits for each actively defined rule deployment
   193  	// that is either in the process of being voted on, or locked in for the
   194  	// activation at the next threshold window change.
   195  	expectedVersion := uint32(vbTopBits)
   196  	for id := 0; id < len(b.chainParams.Deployments); id++ {
   197  		deployment := &b.chainParams.Deployments[id]
   198  		cache := &b.deploymentCaches[id]
   199  		checker := deploymentChecker{deployment: deployment, chain: b}
   200  		state, err := b.thresholdState(prevNode, checker, cache)
   201  		if err != nil {
   202  			return 0, err
   203  		}
   204  		if state == ThresholdStarted || state == ThresholdLockedIn {
   205  			expectedVersion |= uint32(1) << deployment.BitNumber
   206  		}
   207  	}
   208  	return int32(expectedVersion), nil
   209  }
   210  
   211  // CalcNextBlockVersion calculates the expected version of the block after the
   212  // end of the current best chain based on the state of started and locked in
   213  // rule change deployments.
   214  //
   215  // This function is safe for concurrent access.
   216  func (b *BlockChain) CalcNextBlockVersion() (int32, error) {
   217  	b.chainLock.Lock()
   218  	version, err := b.calcNextBlockVersion(b.bestChain.Tip())
   219  	b.chainLock.Unlock()
   220  	return version, err
   221  }
   222  
   223  // warnUnknownRuleActivations displays a warning when any unknown new rules are
   224  // either about to activate or have been activated.  This will only happen once
   225  // when new rules have been activated and every block for those about to be
   226  // activated.
   227  //
   228  // This function MUST be called with the chain state lock held (for writes)
   229  func (b *BlockChain) warnUnknownRuleActivations(node *blockNode) error {
   230  	// Warn if any unknown new rules are either about to activate or have
   231  	// already been activated.
   232  	for bit := uint32(0); bit < vbNumBits; bit++ {
   233  		checker := bitConditionChecker{bit: bit, chain: b}
   234  		cache := &b.warningCaches[bit]
   235  		state, err := b.thresholdState(node.parent, checker, cache)
   236  		if err != nil {
   237  			return err
   238  		}
   239  
   240  		switch state {
   241  		case ThresholdActive:
   242  			if !b.unknownRulesWarned {
   243  				log.Warnf("Unknown new rules activated (bit %d)",
   244  					bit)
   245  				b.unknownRulesWarned = true
   246  			}
   247  
   248  		case ThresholdLockedIn:
   249  			window := int32(checker.MinerConfirmationWindow())
   250  			activationHeight := window - (node.height % window)
   251  			log.Warnf("Unknown new rules are about to activate in "+
   252  				"%d blocks (bit %d)", activationHeight, bit)
   253  		}
   254  	}
   255  
   256  	return nil
   257  }