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.

603 lines
17 KiB

  1. package types
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strings"
  6. "sync"
  7. "github.com/pkg/errors"
  8. cmn "github.com/tendermint/tmlibs/common"
  9. )
  10. // UNSTABLE
  11. // XXX: duplicate of p2p.ID to avoid dependence between packages.
  12. // Perhaps we can have a minimal types package containing this (and other things?)
  13. // that both `types` and `p2p` import ?
  14. type P2PID string
  15. /*
  16. VoteSet helps collect signatures from validators at each height+round for a
  17. predefined vote type.
  18. We need VoteSet to be able to keep track of conflicting votes when validators
  19. double-sign. Yet, we can't keep track of *all* the votes seen, as that could
  20. be a DoS attack vector.
  21. There are two storage areas for votes.
  22. 1. voteSet.votes
  23. 2. voteSet.votesByBlock
  24. `.votes` is the "canonical" list of votes. It always has at least one vote,
  25. if a vote from a validator had been seen at all. Usually it keeps track of
  26. the first vote seen, but when a 2/3 majority is found, votes for that get
  27. priority and are copied over from `.votesByBlock`.
  28. `.votesByBlock` keeps track of a list of votes for a particular block. There
  29. are two ways a &blockVotes{} gets created in `.votesByBlock`.
  30. 1. the first vote seen by a validator was for the particular block.
  31. 2. a peer claims to have seen 2/3 majority for the particular block.
  32. Since the first vote from a validator will always get added in `.votesByBlock`
  33. , all votes in `.votes` will have a corresponding entry in `.votesByBlock`.
  34. When a &blockVotes{} in `.votesByBlock` reaches a 2/3 majority quorum, its
  35. votes are copied into `.votes`.
  36. All this is memory bounded because conflicting votes only get added if a peer
  37. told us to track that block, each peer only gets to tell us 1 such block, and,
  38. there's only a limited number of peers.
  39. NOTE: Assumes that the sum total of voting power does not exceed MaxUInt64.
  40. */
  41. type VoteSet struct {
  42. chainID string
  43. height int64
  44. round int
  45. type_ byte
  46. valSet *ValidatorSet
  47. mtx sync.Mutex
  48. votesBitArray *cmn.BitArray
  49. votes []*Vote // Primary votes to share
  50. sum int64 // Sum of voting power for seen votes, discounting conflicts
  51. maj23 *BlockID // First 2/3 majority seen
  52. votesByBlock map[string]*blockVotes // string(blockHash|blockParts) -> blockVotes
  53. peerMaj23s map[P2PID]BlockID // Maj23 for each peer
  54. }
  55. // Constructs a new VoteSet struct used to accumulate votes for given height/round.
  56. func NewVoteSet(chainID string, height int64, round int, type_ byte, valSet *ValidatorSet) *VoteSet {
  57. if height == 0 {
  58. cmn.PanicSanity("Cannot make VoteSet for height == 0, doesn't make sense.")
  59. }
  60. return &VoteSet{
  61. chainID: chainID,
  62. height: height,
  63. round: round,
  64. type_: type_,
  65. valSet: valSet,
  66. votesBitArray: cmn.NewBitArray(valSet.Size()),
  67. votes: make([]*Vote, valSet.Size()),
  68. sum: 0,
  69. maj23: nil,
  70. votesByBlock: make(map[string]*blockVotes, valSet.Size()),
  71. peerMaj23s: make(map[P2PID]BlockID),
  72. }
  73. }
  74. func (voteSet *VoteSet) ChainID() string {
  75. return voteSet.chainID
  76. }
  77. func (voteSet *VoteSet) Height() int64 {
  78. if voteSet == nil {
  79. return 0
  80. }
  81. return voteSet.height
  82. }
  83. func (voteSet *VoteSet) Round() int {
  84. if voteSet == nil {
  85. return -1
  86. }
  87. return voteSet.round
  88. }
  89. func (voteSet *VoteSet) Type() byte {
  90. if voteSet == nil {
  91. return 0x00
  92. }
  93. return voteSet.type_
  94. }
  95. func (voteSet *VoteSet) Size() int {
  96. if voteSet == nil {
  97. return 0
  98. }
  99. return voteSet.valSet.Size()
  100. }
  101. // Returns added=true if vote is valid and new.
  102. // Otherwise returns err=ErrVote[
  103. // UnexpectedStep | InvalidIndex | InvalidAddress |
  104. // InvalidSignature | InvalidBlockHash | ConflictingVotes ]
  105. // Duplicate votes return added=false, err=nil.
  106. // Conflicting votes return added=*, err=ErrVoteConflictingVotes.
  107. // NOTE: vote should not be mutated after adding.
  108. // NOTE: VoteSet must not be nil
  109. // NOTE: Vote must not be nil
  110. func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error) {
  111. if voteSet == nil {
  112. cmn.PanicSanity("AddVote() on nil VoteSet")
  113. }
  114. voteSet.mtx.Lock()
  115. defer voteSet.mtx.Unlock()
  116. return voteSet.addVote(vote)
  117. }
  118. // NOTE: Validates as much as possible before attempting to verify the signature.
  119. func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
  120. if vote == nil {
  121. return false, ErrVoteNil
  122. }
  123. valIndex := vote.ValidatorIndex
  124. valAddr := vote.ValidatorAddress
  125. blockKey := vote.BlockID.Key()
  126. // Ensure that validator index was set
  127. if valIndex < 0 {
  128. return false, errors.Wrap(ErrVoteInvalidValidatorIndex, "Index < 0")
  129. } else if len(valAddr) == 0 {
  130. return false, errors.Wrap(ErrVoteInvalidValidatorAddress, "Empty address")
  131. }
  132. // Make sure the step matches.
  133. if (vote.Height != voteSet.height) ||
  134. (vote.Round != voteSet.round) ||
  135. (vote.Type != voteSet.type_) {
  136. return false, errors.Wrapf(ErrVoteUnexpectedStep, "Got %d/%d/%d, expected %d/%d/%d",
  137. voteSet.height, voteSet.round, voteSet.type_,
  138. vote.Height, vote.Round, vote.Type)
  139. }
  140. // Ensure that signer is a validator.
  141. lookupAddr, val := voteSet.valSet.GetByIndex(valIndex)
  142. if val == nil {
  143. return false, errors.Wrapf(ErrVoteInvalidValidatorIndex,
  144. "Cannot find validator %d in valSet of size %d", valIndex, voteSet.valSet.Size())
  145. }
  146. // Ensure that the signer has the right address
  147. if !bytes.Equal(valAddr, lookupAddr) {
  148. return false, errors.Wrapf(ErrVoteInvalidValidatorAddress,
  149. "vote.ValidatorAddress (%X) does not match address (%X) for vote.ValidatorIndex (%d)\nEnsure the genesis file is correct across all validators.",
  150. valAddr, lookupAddr, valIndex)
  151. }
  152. // If we already know of this vote, return false.
  153. if existing, ok := voteSet.getVote(valIndex, blockKey); ok {
  154. if existing.Signature.Equals(vote.Signature) {
  155. return false, nil // duplicate
  156. }
  157. return false, errors.Wrapf(ErrVoteNonDeterministicSignature, "Existing vote: %v; New vote: %v", existing, vote)
  158. }
  159. // Check signature.
  160. if err := vote.Verify(voteSet.chainID, val.PubKey); err != nil {
  161. return false, errors.Wrapf(err, "Failed to verify vote with ChainID %s and PubKey %s", voteSet.chainID, val.PubKey)
  162. }
  163. // Add vote and get conflicting vote if any
  164. added, conflicting := voteSet.addVerifiedVote(vote, blockKey, val.VotingPower)
  165. if conflicting != nil {
  166. return added, NewConflictingVoteError(val, conflicting, vote)
  167. }
  168. if !added {
  169. cmn.PanicSanity("Expected to add non-conflicting vote")
  170. }
  171. return added, nil
  172. }
  173. // Returns (vote, true) if vote exists for valIndex and blockKey
  174. func (voteSet *VoteSet) getVote(valIndex int, blockKey string) (vote *Vote, ok bool) {
  175. if existing := voteSet.votes[valIndex]; existing != nil && existing.BlockID.Key() == blockKey {
  176. return existing, true
  177. }
  178. if existing := voteSet.votesByBlock[blockKey].getByIndex(valIndex); existing != nil {
  179. return existing, true
  180. }
  181. return nil, false
  182. }
  183. // Assumes signature is valid.
  184. // If conflicting vote exists, returns it.
  185. func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower int64) (added bool, conflicting *Vote) {
  186. valIndex := vote.ValidatorIndex
  187. // Already exists in voteSet.votes?
  188. if existing := voteSet.votes[valIndex]; existing != nil {
  189. if existing.BlockID.Equals(vote.BlockID) {
  190. cmn.PanicSanity("addVerifiedVote does not expect duplicate votes")
  191. } else {
  192. conflicting = existing
  193. }
  194. // Replace vote if blockKey matches voteSet.maj23.
  195. if voteSet.maj23 != nil && voteSet.maj23.Key() == blockKey {
  196. voteSet.votes[valIndex] = vote
  197. voteSet.votesBitArray.SetIndex(valIndex, true)
  198. }
  199. // Otherwise don't add it to voteSet.votes
  200. } else {
  201. // Add to voteSet.votes and incr .sum
  202. voteSet.votes[valIndex] = vote
  203. voteSet.votesBitArray.SetIndex(valIndex, true)
  204. voteSet.sum += votingPower
  205. }
  206. votesByBlock, ok := voteSet.votesByBlock[blockKey]
  207. if ok {
  208. if conflicting != nil && !votesByBlock.peerMaj23 {
  209. // There's a conflict and no peer claims that this block is special.
  210. return false, conflicting
  211. }
  212. // We'll add the vote in a bit.
  213. } else {
  214. // .votesByBlock doesn't exist...
  215. if conflicting != nil {
  216. // ... and there's a conflicting vote.
  217. // We're not even tracking this blockKey, so just forget it.
  218. return false, conflicting
  219. }
  220. // ... and there's no conflicting vote.
  221. // Start tracking this blockKey
  222. votesByBlock = newBlockVotes(false, voteSet.valSet.Size())
  223. voteSet.votesByBlock[blockKey] = votesByBlock
  224. // We'll add the vote in a bit.
  225. }
  226. // Before adding to votesByBlock, see if we'll exceed quorum
  227. origSum := votesByBlock.sum
  228. quorum := voteSet.valSet.TotalVotingPower()*2/3 + 1
  229. // Add vote to votesByBlock
  230. votesByBlock.addVerifiedVote(vote, votingPower)
  231. // If we just crossed the quorum threshold and have 2/3 majority...
  232. if origSum < quorum && quorum <= votesByBlock.sum {
  233. // Only consider the first quorum reached
  234. if voteSet.maj23 == nil {
  235. maj23BlockID := vote.BlockID
  236. voteSet.maj23 = &maj23BlockID
  237. // And also copy votes over to voteSet.votes
  238. for i, vote := range votesByBlock.votes {
  239. if vote != nil {
  240. voteSet.votes[i] = vote
  241. }
  242. }
  243. }
  244. }
  245. return true, conflicting
  246. }
  247. // If a peer claims that it has 2/3 majority for given blockKey, call this.
  248. // NOTE: if there are too many peers, or too much peer churn,
  249. // this can cause memory issues.
  250. // TODO: implement ability to remove peers too
  251. // NOTE: VoteSet must not be nil
  252. func (voteSet *VoteSet) SetPeerMaj23(peerID P2PID, blockID BlockID) error {
  253. if voteSet == nil {
  254. cmn.PanicSanity("SetPeerMaj23() on nil VoteSet")
  255. }
  256. voteSet.mtx.Lock()
  257. defer voteSet.mtx.Unlock()
  258. blockKey := blockID.Key()
  259. // Make sure peer hasn't already told us something.
  260. if existing, ok := voteSet.peerMaj23s[peerID]; ok {
  261. if existing.Equals(blockID) {
  262. return nil // Nothing to do
  263. }
  264. return fmt.Errorf("SetPeerMaj23: Received conflicting blockID from peer %v. Got %v, expected %v",
  265. peerID, blockID, existing)
  266. }
  267. voteSet.peerMaj23s[peerID] = blockID
  268. // Create .votesByBlock entry if needed.
  269. votesByBlock, ok := voteSet.votesByBlock[blockKey]
  270. if ok {
  271. if votesByBlock.peerMaj23 {
  272. return nil // Nothing to do
  273. }
  274. votesByBlock.peerMaj23 = true
  275. // No need to copy votes, already there.
  276. } else {
  277. votesByBlock = newBlockVotes(true, voteSet.valSet.Size())
  278. voteSet.votesByBlock[blockKey] = votesByBlock
  279. // No need to copy votes, no votes to copy over.
  280. }
  281. return nil
  282. }
  283. func (voteSet *VoteSet) BitArray() *cmn.BitArray {
  284. if voteSet == nil {
  285. return nil
  286. }
  287. voteSet.mtx.Lock()
  288. defer voteSet.mtx.Unlock()
  289. return voteSet.votesBitArray.Copy()
  290. }
  291. func (voteSet *VoteSet) BitArrayByBlockID(blockID BlockID) *cmn.BitArray {
  292. if voteSet == nil {
  293. return nil
  294. }
  295. voteSet.mtx.Lock()
  296. defer voteSet.mtx.Unlock()
  297. votesByBlock, ok := voteSet.votesByBlock[blockID.Key()]
  298. if ok {
  299. return votesByBlock.bitArray.Copy()
  300. }
  301. return nil
  302. }
  303. // NOTE: if validator has conflicting votes, returns "canonical" vote
  304. func (voteSet *VoteSet) GetByIndex(valIndex int) *Vote {
  305. if voteSet == nil {
  306. return nil
  307. }
  308. voteSet.mtx.Lock()
  309. defer voteSet.mtx.Unlock()
  310. return voteSet.votes[valIndex]
  311. }
  312. func (voteSet *VoteSet) GetByAddress(address []byte) *Vote {
  313. if voteSet == nil {
  314. return nil
  315. }
  316. voteSet.mtx.Lock()
  317. defer voteSet.mtx.Unlock()
  318. valIndex, val := voteSet.valSet.GetByAddress(address)
  319. if val == nil {
  320. cmn.PanicSanity("GetByAddress(address) returned nil")
  321. }
  322. return voteSet.votes[valIndex]
  323. }
  324. func (voteSet *VoteSet) HasTwoThirdsMajority() bool {
  325. if voteSet == nil {
  326. return false
  327. }
  328. voteSet.mtx.Lock()
  329. defer voteSet.mtx.Unlock()
  330. return voteSet.maj23 != nil
  331. }
  332. func (voteSet *VoteSet) IsCommit() bool {
  333. if voteSet == nil {
  334. return false
  335. }
  336. if voteSet.type_ != VoteTypePrecommit {
  337. return false
  338. }
  339. voteSet.mtx.Lock()
  340. defer voteSet.mtx.Unlock()
  341. return voteSet.maj23 != nil
  342. }
  343. func (voteSet *VoteSet) HasTwoThirdsAny() bool {
  344. if voteSet == nil {
  345. return false
  346. }
  347. voteSet.mtx.Lock()
  348. defer voteSet.mtx.Unlock()
  349. return voteSet.sum > voteSet.valSet.TotalVotingPower()*2/3
  350. }
  351. func (voteSet *VoteSet) HasAll() bool {
  352. voteSet.mtx.Lock()
  353. defer voteSet.mtx.Unlock()
  354. return voteSet.sum == voteSet.valSet.TotalVotingPower()
  355. }
  356. // If there was a +2/3 majority for blockID, return blockID and true.
  357. // Else, return the empty BlockID{} and false.
  358. func (voteSet *VoteSet) TwoThirdsMajority() (blockID BlockID, ok bool) {
  359. if voteSet == nil {
  360. return BlockID{}, false
  361. }
  362. voteSet.mtx.Lock()
  363. defer voteSet.mtx.Unlock()
  364. if voteSet.maj23 != nil {
  365. return *voteSet.maj23, true
  366. }
  367. return BlockID{}, false
  368. }
  369. //--------------------------------------------------------------------------------
  370. // Strings and JSON
  371. func (voteSet *VoteSet) String() string {
  372. if voteSet == nil {
  373. return "nil-VoteSet"
  374. }
  375. return voteSet.StringIndented("")
  376. }
  377. func (voteSet *VoteSet) StringIndented(indent string) string {
  378. voteSet.mtx.Lock()
  379. defer voteSet.mtx.Unlock()
  380. voteStrings := make([]string, len(voteSet.votes))
  381. for i, vote := range voteSet.votes {
  382. if vote == nil {
  383. voteStrings[i] = "nil-Vote"
  384. } else {
  385. voteStrings[i] = vote.String()
  386. }
  387. }
  388. return fmt.Sprintf(`VoteSet{
  389. %s H:%v R:%v T:%v
  390. %s %v
  391. %s %v
  392. %s %v
  393. %s}`,
  394. indent, voteSet.height, voteSet.round, voteSet.type_,
  395. indent, strings.Join(voteStrings, "\n"+indent+" "),
  396. indent, voteSet.votesBitArray,
  397. indent, voteSet.peerMaj23s,
  398. indent)
  399. }
  400. // Marshal the VoteSet to JSON. Same as String(), just in JSON,
  401. // and without the height/round/type_ (since its already included in the votes).
  402. func (voteSet *VoteSet) MarshalJSON() ([]byte, error) {
  403. voteSet.mtx.Lock()
  404. defer voteSet.mtx.Unlock()
  405. return cdc.MarshalJSON(VoteSetJSON{
  406. voteSet.voteStrings(),
  407. voteSet.bitArrayString(),
  408. voteSet.peerMaj23s,
  409. })
  410. }
  411. // More human readable JSON of the vote set
  412. // NOTE: insufficient for unmarshalling from (compressed votes)
  413. // TODO: make the peerMaj23s nicer to read (eg just the block hash)
  414. type VoteSetJSON struct {
  415. Votes []string `json:"votes"`
  416. VotesBitArray string `json:"votes_bit_array"`
  417. PeerMaj23s map[P2PID]BlockID `json:"peer_maj_23s"`
  418. }
  419. // Return the bit-array of votes including
  420. // the fraction of power that has voted like:
  421. // "BA{29:xx__x__x_x___x__x_______xxx__} 856/1304 = 0.66"
  422. func (voteSet *VoteSet) BitArrayString() string {
  423. voteSet.mtx.Lock()
  424. defer voteSet.mtx.Unlock()
  425. return voteSet.bitArrayString()
  426. }
  427. func (voteSet *VoteSet) bitArrayString() string {
  428. bAString := voteSet.votesBitArray.String()
  429. voted, total, fracVoted := voteSet.sumTotalFrac()
  430. return fmt.Sprintf("%s %d/%d = %.2f", bAString, voted, total, fracVoted)
  431. }
  432. // Returns a list of votes compressed to more readable strings.
  433. func (voteSet *VoteSet) VoteStrings() []string {
  434. voteSet.mtx.Lock()
  435. defer voteSet.mtx.Unlock()
  436. return voteSet.voteStrings()
  437. }
  438. func (voteSet *VoteSet) voteStrings() []string {
  439. voteStrings := make([]string, len(voteSet.votes))
  440. for i, vote := range voteSet.votes {
  441. if vote == nil {
  442. voteStrings[i] = "nil-Vote"
  443. } else {
  444. voteStrings[i] = vote.String()
  445. }
  446. }
  447. return voteStrings
  448. }
  449. func (voteSet *VoteSet) StringShort() string {
  450. if voteSet == nil {
  451. return "nil-VoteSet"
  452. }
  453. voteSet.mtx.Lock()
  454. defer voteSet.mtx.Unlock()
  455. _, _, frac := voteSet.sumTotalFrac()
  456. return fmt.Sprintf(`VoteSet{H:%v R:%v T:%v +2/3:%v(%v) %v %v}`,
  457. voteSet.height, voteSet.round, voteSet.type_, voteSet.maj23, frac, voteSet.votesBitArray, voteSet.peerMaj23s)
  458. }
  459. // return the power voted, the total, and the fraction
  460. func (voteSet *VoteSet) sumTotalFrac() (int64, int64, float64) {
  461. voted, total := voteSet.sum, voteSet.valSet.TotalVotingPower()
  462. fracVoted := float64(voted) / float64(total)
  463. return voted, total, fracVoted
  464. }
  465. //--------------------------------------------------------------------------------
  466. // Commit
  467. func (voteSet *VoteSet) MakeCommit() *Commit {
  468. if voteSet.type_ != VoteTypePrecommit {
  469. cmn.PanicSanity("Cannot MakeCommit() unless VoteSet.Type is VoteTypePrecommit")
  470. }
  471. voteSet.mtx.Lock()
  472. defer voteSet.mtx.Unlock()
  473. // Make sure we have a 2/3 majority
  474. if voteSet.maj23 == nil {
  475. cmn.PanicSanity("Cannot MakeCommit() unless a blockhash has +2/3")
  476. }
  477. // For every validator, get the precommit
  478. votesCopy := make([]*Vote, len(voteSet.votes))
  479. copy(votesCopy, voteSet.votes)
  480. return &Commit{
  481. BlockID: *voteSet.maj23,
  482. Precommits: votesCopy,
  483. }
  484. }
  485. //--------------------------------------------------------------------------------
  486. /*
  487. Votes for a particular block
  488. There are two ways a *blockVotes gets created for a blockKey.
  489. 1. first (non-conflicting) vote of a validator w/ blockKey (peerMaj23=false)
  490. 2. A peer claims to have a 2/3 majority w/ blockKey (peerMaj23=true)
  491. */
  492. type blockVotes struct {
  493. peerMaj23 bool // peer claims to have maj23
  494. bitArray *cmn.BitArray // valIndex -> hasVote?
  495. votes []*Vote // valIndex -> *Vote
  496. sum int64 // vote sum
  497. }
  498. func newBlockVotes(peerMaj23 bool, numValidators int) *blockVotes {
  499. return &blockVotes{
  500. peerMaj23: peerMaj23,
  501. bitArray: cmn.NewBitArray(numValidators),
  502. votes: make([]*Vote, numValidators),
  503. sum: 0,
  504. }
  505. }
  506. func (vs *blockVotes) addVerifiedVote(vote *Vote, votingPower int64) {
  507. valIndex := vote.ValidatorIndex
  508. if existing := vs.votes[valIndex]; existing == nil {
  509. vs.bitArray.SetIndex(valIndex, true)
  510. vs.votes[valIndex] = vote
  511. vs.sum += votingPower
  512. }
  513. }
  514. func (vs *blockVotes) getByIndex(index int) *Vote {
  515. if vs == nil {
  516. return nil
  517. }
  518. return vs.votes[index]
  519. }
  520. //--------------------------------------------------------------------------------
  521. // Common interface between *consensus.VoteSet and types.Commit
  522. type VoteSetReader interface {
  523. Height() int64
  524. Round() int
  525. Type() byte
  526. Size() int
  527. BitArray() *cmn.BitArray
  528. GetByIndex(int) *Vote
  529. IsCommit() bool
  530. }