/
vote.go
executable file
·140 lines (121 loc) · 3.25 KB
/
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package types
import (
"errors"
"fmt"
"io"
"github.com/neatlab/neatio/utilities/rlp"
. "github.com/neatlib/common-go"
"github.com/neatlib/crypto-go"
"github.com/neatlib/wire-go"
)
var (
ErrVoteUnexpectedStep = errors.New("Unexpected step")
ErrVoteInvalidValidatorIndex = errors.New("Invalid round vote validator index")
ErrVoteInvalidValidatorAddress = errors.New("Invalid round vote validator address")
ErrVoteInvalidSignature = errors.New("Invalid round vote signature")
ErrVoteInvalidBlockHash = errors.New("Invalid block hash")
)
type ErrVoteConflictingVotes struct {
VoteA *Vote
VoteB *Vote
}
func (err *ErrVoteConflictingVotes) Error() string {
return "Conflicting votes"
}
// Types of votes
// TODO Make a new type "VoteType"
const (
VoteTypePrevote = byte(0x01)
VoteTypePrecommit = byte(0x02)
)
func IsVoteTypeValid(type_ byte) bool {
switch type_ {
case VoteTypePrevote:
return true
case VoteTypePrecommit:
return true
default:
return false
}
}
// Represents a prevote, precommit, or commit vote from validators for consensus.
type Vote struct {
ValidatorAddress []byte `json:"validator_address"`
ValidatorIndex uint64 `json:"validator_index"`
Height uint64 `json:"height"`
Round uint64 `json:"round"`
Type byte `json:"type"`
BlockID BlockID `json:"block_id"` // zero if vote is nil.
Signature crypto.Signature `json:"signature"`
SignBytes []byte `json:"sign_bytes"`
}
func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error) {
wire.WriteJSON(CanonicalJSONOnceVote{
chainID,
CanonicalVote(vote),
}, w, n, err)
}
// EncodeRLP serializes ist into the Ethereum RLP format.
func (vote *Vote) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, []interface{}{
vote.ValidatorAddress,
vote.ValidatorIndex,
vote.Height,
vote.Round,
vote.Type,
vote.BlockID,
vote.Signature.Bytes(),
})
}
// DecodeRLP implements rlp.Decoder, and load the istanbul fields from a RLP stream.
func (vote *Vote) DecodeRLP(s *rlp.Stream) error {
var vt struct {
ValidatorAddress []byte
ValidatorIndex uint64
Height uint64
Round uint64
Type byte
BlockID BlockID
Signature []byte
}
if err := s.Decode(&vt); err != nil {
return err
}
vote.ValidatorAddress = vt.ValidatorAddress
vote.ValidatorIndex = vt.ValidatorIndex
vote.Height = vt.Height
vote.Round = vt.Round
vote.Type = vt.Type
vote.BlockID = vt.BlockID
sig, err := crypto.SignatureFromBytes(vt.Signature)
if err != nil {
return err
}
vote.Signature = sig
if err != nil {
return err
}
return nil
}
func (vote *Vote) Copy() *Vote {
voteCopy := *vote
return &voteCopy
}
func (vote *Vote) String() string {
if vote == nil {
return "nil-Vote"
}
var typeString string
switch vote.Type {
case VoteTypePrevote:
typeString = "Prevote"
case VoteTypePrecommit:
typeString = "Precommit"
default:
PanicSanity("Unknown vote type")
}
return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %v}",
vote.ValidatorIndex, Fingerprint(vote.ValidatorAddress),
vote.Height, vote.Round, vote.Type, typeString,
Fingerprint(vote.BlockID.Hash), vote.Signature)
}