/
round_vote.go
119 lines (93 loc) · 2.24 KB
/
round_vote.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
package consensus
import (
logging "github.com/inconshreveable/log15"
"boscoin.io/sebak/lib/ballot"
"boscoin.io/sebak/lib/voting"
)
type RoundVoteResult map[ /* Node.Address() */ string]ballot.Ballot
type RoundVote struct {
SIGN RoundVoteResult
ACCEPT RoundVoteResult
}
func NewRoundVote(ballot ballot.Ballot) (rv *RoundVote) {
rv = &RoundVote{
SIGN: RoundVoteResult{},
ACCEPT: RoundVoteResult{},
}
rv.Vote(ballot)
return rv
}
func (rv *RoundVote) IsVoted(ballot ballot.Ballot) bool {
result := rv.GetResult(ballot.State())
_, found := result[ballot.Source()]
return found
}
func (rv *RoundVote) IsVotedByNode(state ballot.State, node string) bool {
result := rv.GetResult(state)
_, found := result[node]
return found
}
func (rv *RoundVote) Vote(b ballot.Ballot) (isNew bool, err error) {
if !b.State().IsValidForVote() {
return
}
result := rv.GetResult(b.State())
_, isNew = result[b.Source()]
result[b.Source()] = b
return
}
func (rv *RoundVote) GetResult(state ballot.State) (result RoundVoteResult) {
if !state.IsValidForVote() {
return
}
switch state {
case ballot.StateSIGN:
result = rv.SIGN
case ballot.StateACCEPT:
result = rv.ACCEPT
}
return result
}
func (rv *RoundVote) CanGetVotingResult(policy voting.ThresholdPolicy, state ballot.State, log logging.Logger) (RoundVoteResult, voting.Hole, bool) {
threshold := policy.Threshold()
if threshold < 1 {
return RoundVoteResult{}, voting.NOTYET, false
}
result := rv.GetResult(state)
var yes, no, expired int
for _, blt := range result {
switch blt.Vote() {
case voting.YES:
yes++
case voting.NO:
no++
case voting.EXP:
expired++
}
}
log.Debug(
"check threshold in isaac",
"threshold", threshold,
"yes", yes,
"no", no,
"expired", expired,
"state", state,
)
if yes >= threshold {
return result, voting.YES, true
} else if no >= threshold {
return result, voting.NO, true
} else {
// do nothing
}
// check draw!
total := policy.Validators()
voted := yes + no + expired
if cannotBeOver(total-voted, threshold, yes, no) { // draw
return result, voting.EXP, true
}
return result, voting.NOTYET, false
}
func cannotBeOver(remain, threshold, yes, no int) bool {
return remain+yes < threshold && remain+no < threshold
}