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