You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
5.7 KiB

  1. package consensus
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "sync"
  8. . "github.com/tendermint/tendermint/binary"
  9. . "github.com/tendermint/tendermint/blocks"
  10. "github.com/tendermint/tendermint/config"
  11. )
  12. const (
  13. VoteTypeBare = byte(0x00)
  14. VoteTypePrecommit = byte(0x01)
  15. VoteTypeCommit = byte(0x02)
  16. )
  17. var (
  18. ErrVoteUnexpectedPhase = errors.New("Unexpected phase")
  19. ErrVoteInvalidAccount = errors.New("Invalid round vote account")
  20. ErrVoteInvalidSignature = errors.New("Invalid round vote signature")
  21. ErrVoteInvalidHash = errors.New("Invalid hash")
  22. ErrVoteConflictingSignature = errors.New("Conflicting round vote signature")
  23. )
  24. // Represents a bare, precommit, or commit vote for proposals.
  25. type Vote struct {
  26. Height uint32
  27. Round uint16
  28. Type byte
  29. Hash []byte // empty if vote is nil.
  30. Signature
  31. }
  32. func ReadVote(r io.Reader) *Vote {
  33. return &Vote{
  34. Height: uint32(ReadUInt32(r)),
  35. Round: uint16(ReadUInt16(r)),
  36. Type: byte(ReadByte(r)),
  37. Hash: ReadByteSlice(r),
  38. Signature: ReadSignature(r),
  39. }
  40. }
  41. func (v *Vote) WriteTo(w io.Writer) (n int64, err error) {
  42. n, err = WriteTo(UInt32(v.Height), w, n, err)
  43. n, err = WriteTo(UInt16(v.Round), w, n, err)
  44. n, err = WriteTo(Byte(v.Type), w, n, err)
  45. n, err = WriteTo(ByteSlice(v.Hash), w, n, err)
  46. n, err = WriteTo(v.Signature, w, n, err)
  47. return
  48. }
  49. // This is the byteslice that validators should sign to signify a vote
  50. // for the given proposal at given height & round.
  51. // If hash is nil, the vote is a nil vote.
  52. func (v *Vote) GetDocument() []byte {
  53. switch v.Type {
  54. case VoteTypeBare:
  55. if len(v.Hash) == 0 {
  56. doc := fmt.Sprintf("%v://consensus/%v/%v/b\nnil",
  57. config.Config.Network, v.Height, v.Round)
  58. return []byte(doc)
  59. } else {
  60. doc := fmt.Sprintf("%v://consensus/%v/%v/b\n%v",
  61. config.Config.Network, v.Height, v.Round,
  62. CalcBlockURI(v.Height, v.Hash))
  63. return []byte(doc)
  64. }
  65. case VoteTypePrecommit:
  66. if len(v.Hash) == 0 {
  67. doc := fmt.Sprintf("%v://consensus/%v/%v/p\nnil",
  68. config.Config.Network, v.Height, v.Round)
  69. return []byte(doc)
  70. } else {
  71. doc := fmt.Sprintf("%v://consensus/%v/%v/p\n%v",
  72. config.Config.Network, v.Height, v.Round,
  73. CalcBlockURI(v.Height, v.Hash))
  74. return []byte(doc)
  75. }
  76. case VoteTypeCommit:
  77. if len(v.Hash) == 0 {
  78. panic("Commit hash cannot be nil")
  79. } else {
  80. doc := fmt.Sprintf("%v://consensus/%v/c\n%v",
  81. config.Config.Network, v.Height, // omit round info
  82. CalcBlockURI(v.Height, v.Hash))
  83. return []byte(doc)
  84. }
  85. default:
  86. panic("Unknown vote type")
  87. }
  88. }
  89. //-----------------------------------------------------------------------------
  90. // VoteSet helps collect signatures from validators at each height+round
  91. // for a predefined vote type.
  92. type VoteSet struct {
  93. mtx sync.Mutex
  94. height uint32
  95. round uint16
  96. type_ byte
  97. validators map[uint64]*Validator
  98. votes map[uint64]*Vote
  99. votesByHash map[string]uint64
  100. totalVotes uint64
  101. totalVotingPower uint64
  102. }
  103. // Constructs a new VoteSet struct used to accumulate votes for each round.
  104. func NewVoteSet(height uint32, round uint16, type_ byte, validators map[uint64]*Validator) *VoteSet {
  105. totalVotingPower := uint64(0)
  106. for _, val := range validators {
  107. totalVotingPower += uint64(val.VotingPower)
  108. }
  109. return &VoteSet{
  110. height: height,
  111. round: round,
  112. type_: type_,
  113. validators: validators,
  114. votes: make(map[uint64]*Vote, len(validators)),
  115. votesByHash: make(map[string]uint64),
  116. totalVotes: 0,
  117. totalVotingPower: totalVotingPower,
  118. }
  119. }
  120. // True if added, false if not.
  121. // Returns ErrVote[UnexpectedPhase|InvalidAccount|InvalidSignature|InvalidHash|ConflictingSignature]
  122. func (vs *VoteSet) AddVote(vote *Vote) (bool, error) {
  123. vs.mtx.Lock()
  124. defer vs.mtx.Unlock()
  125. // Make sure the phase matches.
  126. if vote.Height != vs.height || vote.Round != vs.round || vote.Type != vs.type_ {
  127. return false, ErrVoteUnexpectedPhase
  128. }
  129. val := vs.validators[uint64(vote.SignerId)]
  130. // Ensure that signer is a validator.
  131. if val == nil {
  132. return false, ErrVoteInvalidAccount
  133. }
  134. // Check signature.
  135. if !val.Verify(vote.GetDocument(), vote.Signature.Bytes) {
  136. // Bad signature.
  137. return false, ErrVoteInvalidSignature
  138. }
  139. // If vote already exists, return false.
  140. if existingVote, ok := vs.votes[uint64(vote.SignerId)]; ok {
  141. if bytes.Equal(existingVote.Hash, vote.Hash) {
  142. return false, nil
  143. } else {
  144. return false, ErrVoteConflictingSignature
  145. }
  146. }
  147. vs.votes[uint64(vote.SignerId)] = vote
  148. vs.votesByHash[string(vote.Hash)] += uint64(val.VotingPower)
  149. vs.totalVotes += uint64(val.VotingPower)
  150. return true, nil
  151. }
  152. // Returns either a blockhash (or nil) that received +2/3 majority.
  153. // If there exists no such majority, returns (nil, false).
  154. func (vs *VoteSet) TwoThirdsMajority() (hash []byte, ok bool) {
  155. vs.mtx.Lock()
  156. defer vs.mtx.Unlock()
  157. twoThirdsMajority := (vs.totalVotingPower*uint64(2) + uint64(2)) / uint64(3)
  158. if vs.totalVotes < twoThirdsMajority {
  159. return nil, false
  160. }
  161. for hash, votes := range vs.votesByHash {
  162. if votes >= twoThirdsMajority {
  163. if hash == "" {
  164. return nil, true
  165. } else {
  166. return []byte(hash), true
  167. }
  168. }
  169. }
  170. return nil, false
  171. }
  172. // Returns blockhashes (or nil) that received a +1/3 majority.
  173. // If there exists no such majority, returns nil.
  174. func (vs *VoteSet) OneThirdMajority() (hashes []interface{}) {
  175. vs.mtx.Lock()
  176. defer vs.mtx.Unlock()
  177. oneThirdMajority := (vs.totalVotingPower + uint64(2)) / uint64(3)
  178. if vs.totalVotes < oneThirdMajority {
  179. return nil
  180. }
  181. for hash, votes := range vs.votesByHash {
  182. if votes >= oneThirdMajority {
  183. if hash == "" {
  184. hashes = append(hashes, nil)
  185. } else {
  186. hashes = append(hashes, []byte(hash))
  187. }
  188. }
  189. }
  190. return hashes
  191. }