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.

617 lines
18 KiB

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