github.com/decred/dcrd/blockchain@v1.2.1/votebits.go (about)

     1  // Copyright (c) 2017-2018 The Decred developers
     2  // Copyright (c) 2016 The btcsuite developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package blockchain
     7  
     8  import (
     9  	"github.com/decred/dcrd/chaincfg"
    10  )
    11  
    12  // deploymentChecker provides a thresholdConditionChecker which can be used to
    13  // test a specific deployment rule.  This is required for properly detecting
    14  // and activating consensus rule changes.
    15  type deploymentChecker struct {
    16  	deployment *chaincfg.ConsensusDeployment
    17  	chain      *BlockChain
    18  }
    19  
    20  // Ensure the deploymentChecker type implements the thresholdConditionChecker
    21  // interface.
    22  var _ thresholdConditionChecker = deploymentChecker{}
    23  
    24  // BeginTime returns the unix timestamp for the median block time after which
    25  // voting on a rule change starts (at the next window).
    26  //
    27  // This implementation returns the value defined by the specific deployment the
    28  // checker is associated with.
    29  //
    30  // This is part of the thresholdConditionChecker interface implementation.
    31  func (c deploymentChecker) BeginTime() uint64 {
    32  	return c.deployment.StartTime
    33  }
    34  
    35  // EndTime returns the unix timestamp for the median block time after which an
    36  
    37  // attempted rule change fails if it has not already been locked in or
    38  // activated.
    39  //
    40  // This implementation returns the value defined by the specific deployment the
    41  // checker is associated with.
    42  //
    43  // This is part of the thresholdConditionChecker interface implementation.
    44  func (c deploymentChecker) EndTime() uint64 {
    45  	return c.deployment.ExpireTime
    46  }
    47  
    48  // RuleChangeActivationQuorum is the minimum votes required to reach quorum.
    49  //
    50  // This implementation returns the value defined by the chain params the checker
    51  // is associated with.
    52  //
    53  // This is part of the thresholdConditionChecker interface implementation.
    54  func (c deploymentChecker) RuleChangeActivationQuorum() uint32 {
    55  	return c.chain.chainParams.RuleChangeActivationQuorum
    56  }
    57  
    58  // RuleChangeActivationThreshold is the number of votes required to reach the
    59  // threshold as defined by chain params.
    60  //
    61  // This implementation returns the value defined by the chain params the checker
    62  // is associated with.
    63  //
    64  // This is part of the thresholdConditionChecker interface implementation.
    65  func (c deploymentChecker) RuleChangeActivationThreshold(totalVotes uint32) uint32 {
    66  	return totalVotes * c.chain.chainParams.RuleChangeActivationMultiplier /
    67  		c.chain.chainParams.RuleChangeActivationDivisor
    68  }
    69  
    70  // RuleChangeActivationInterval is the number of blocks in each threshold state
    71  // retarget window.
    72  //
    73  // This implementation returns the value defined by the chain params the checker
    74  // is associated with.
    75  //
    76  // This is part of the thresholdConditionChecker interface implementation.
    77  func (c deploymentChecker) RuleChangeActivationInterval() uint32 {
    78  	return c.chain.chainParams.RuleChangeActivationInterval
    79  }
    80  
    81  // StakeValidationHeight is the minimum height required before votes start
    82  // counting.
    83  //
    84  // This implementation returns the value defined by the chain params the checker
    85  // is associated with.
    86  //
    87  // This is part of the thresholdConditionChecker interface implementation.
    88  func (c deploymentChecker) StakeValidationHeight() int64 {
    89  	return c.chain.chainParams.StakeValidationHeight
    90  }
    91  
    92  // Condition returns true when the specific bit defined by the deployment
    93  // associated with the checker is set.
    94  //
    95  // This is part of the thresholdConditionChecker interface implementation.
    96  func (c deploymentChecker) Condition(node *blockNode, version uint32) ([]thresholdConditionTally, error) {
    97  	if c.deployment.Vote.Mask == 0 {
    98  		return []thresholdConditionTally{}, AssertError("invalid mask")
    99  	}
   100  
   101  	// Calculate shift in order to make a zero based index later.
   102  	var shift uint16
   103  	mask := c.deployment.Vote.Mask
   104  	for {
   105  		if mask&0x0001 == 0x0001 {
   106  			break
   107  		}
   108  		shift++
   109  		mask >>= 1
   110  	}
   111  
   112  	// Setup tally array and iterate over Choices to assemble the vote
   113  	// information into the thresholdConditionTally array.
   114  	tally := make([]thresholdConditionTally, len(c.deployment.Vote.Choices))
   115  	for t, choice := range c.deployment.Vote.Choices {
   116  		tally[t].isAbstain = choice.IsAbstain
   117  		tally[t].isNo = choice.IsNo
   118  	}
   119  
   120  	for _, vote := range node.votes {
   121  		if version != vote.Version {
   122  			// Wrong version, ignore.
   123  			continue
   124  		}
   125  		idx := c.deployment.Vote.Mask & vote.Bits >> shift
   126  		if int(idx) > len(c.deployment.Vote.Choices)-1 {
   127  			// Invalid choice.
   128  			continue
   129  		}
   130  		tally[idx].count++
   131  	}
   132  
   133  	return tally, nil
   134  }