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.

544 lines
15 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
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
10 years ago
8 years ago
10 years ago
10 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/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. mtx sync.Mutex
  47. valSet *ValidatorSet
  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. } else {
  81. return voteSet.height
  82. }
  83. }
  84. func (voteSet *VoteSet) Round() int {
  85. if voteSet == nil {
  86. return -1
  87. } else {
  88. return voteSet.round
  89. }
  90. }
  91. func (voteSet *VoteSet) Type() byte {
  92. if voteSet == nil {
  93. return 0x00
  94. } else {
  95. return voteSet.type_
  96. }
  97. }
  98. func (voteSet *VoteSet) Size() int {
  99. if voteSet == nil {
  100. return 0
  101. } else {
  102. return voteSet.valSet.Size()
  103. }
  104. }
  105. // Returns added=true if vote is valid and new.
  106. // Otherwise returns err=ErrVote[
  107. // UnexpectedStep | InvalidIndex | InvalidAddress |
  108. // InvalidSignature | InvalidBlockHash | ConflictingVotes ]
  109. // Duplicate votes return added=false, err=nil.
  110. // Conflicting votes return added=*, err=ErrVoteConflictingVotes.
  111. // NOTE: vote should not be mutated after adding.
  112. // NOTE: VoteSet must not be nil
  113. // NOTE: Vote must not be nil
  114. func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error) {
  115. if voteSet == nil {
  116. cmn.PanicSanity("AddVote() on nil VoteSet")
  117. }
  118. voteSet.mtx.Lock()
  119. defer voteSet.mtx.Unlock()
  120. return voteSet.addVote(vote)
  121. }
  122. // NOTE: Validates as much as possible before attempting to verify the signature.
  123. func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
  124. if vote == nil {
  125. return false, ErrVoteNil
  126. }
  127. valIndex := vote.ValidatorIndex
  128. valAddr := vote.ValidatorAddress
  129. blockKey := vote.BlockID.Key()
  130. // Ensure that validator index was set
  131. if valIndex < 0 {
  132. return false, errors.Wrap(ErrVoteInvalidValidatorIndex, "Index < 0")
  133. } else if len(valAddr) == 0 {
  134. return false, errors.Wrap(ErrVoteInvalidValidatorAddress, "Empty address")
  135. }
  136. // Make sure the step matches.
  137. if (vote.Height != voteSet.height) ||
  138. (vote.Round != voteSet.round) ||
  139. (vote.Type != voteSet.type_) {
  140. return false, errors.Wrapf(ErrVoteUnexpectedStep, "Got %d/%d/%d, expected %d/%d/%d",
  141. voteSet.height, voteSet.round, voteSet.type_,
  142. vote.Height, vote.Round, vote.Type)
  143. }
  144. // Ensure that signer is a validator.
  145. lookupAddr, val := voteSet.valSet.GetByIndex(valIndex)
  146. if val == nil {
  147. return false, errors.Wrapf(ErrVoteInvalidValidatorIndex,
  148. "Cannot find validator %d in valSet of size %d", valIndex, voteSet.valSet.Size())
  149. }
  150. // Ensure that the signer has the right address
  151. if !bytes.Equal(valAddr, lookupAddr) {
  152. return false, errors.Wrapf(ErrVoteInvalidValidatorAddress,
  153. "vote.ValidatorAddress (%X) does not match address (%X) for vote.ValidatorIndex (%d)\nEnsure the genesis file is correct across all validators.",
  154. valAddr, lookupAddr, valIndex)
  155. }
  156. // If we already know of this vote, return false.
  157. if existing, ok := voteSet.getVote(valIndex, blockKey); ok {
  158. if existing.Signature.Equals(vote.Signature) {
  159. return false, nil // duplicate
  160. } else {
  161. return false, errors.Wrapf(ErrVoteNonDeterministicSignature, "Existing vote: %v; New vote: %v", existing, vote)
  162. }
  163. }
  164. // Check signature.
  165. if err := vote.Verify(voteSet.chainID, val.PubKey); err != nil {
  166. return false, errors.Wrapf(err, "Failed to verify vote with ChainID %s and PubKey %s", voteSet.chainID, val.PubKey)
  167. }
  168. // Add vote and get conflicting vote if any
  169. added, conflicting := voteSet.addVerifiedVote(vote, blockKey, val.VotingPower)
  170. if conflicting != nil {
  171. return added, NewConflictingVoteError(val, conflicting, vote)
  172. } else {
  173. if !added {
  174. cmn.PanicSanity("Expected to add non-conflicting vote")
  175. }
  176. return added, nil
  177. }
  178. }
  179. // Returns (vote, true) if vote exists for valIndex and blockKey
  180. func (voteSet *VoteSet) getVote(valIndex int, blockKey string) (vote *Vote, ok bool) {
  181. if existing := voteSet.votes[valIndex]; existing != nil && existing.BlockID.Key() == blockKey {
  182. return existing, true
  183. }
  184. if existing := voteSet.votesByBlock[blockKey].getByIndex(valIndex); existing != nil {
  185. return existing, true
  186. }
  187. return nil, false
  188. }
  189. // Assumes signature is valid.
  190. // If conflicting vote exists, returns it.
  191. func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower int64) (added bool, conflicting *Vote) {
  192. valIndex := vote.ValidatorIndex
  193. // Already exists in voteSet.votes?
  194. if existing := voteSet.votes[valIndex]; existing != nil {
  195. if existing.BlockID.Equals(vote.BlockID) {
  196. cmn.PanicSanity("addVerifiedVote does not expect duplicate votes")
  197. } else {
  198. conflicting = existing
  199. }
  200. // Replace vote if blockKey matches voteSet.maj23.
  201. if voteSet.maj23 != nil && voteSet.maj23.Key() == blockKey {
  202. voteSet.votes[valIndex] = vote
  203. voteSet.votesBitArray.SetIndex(valIndex, true)
  204. }
  205. // Otherwise don't add it to voteSet.votes
  206. } else {
  207. // Add to voteSet.votes and incr .sum
  208. voteSet.votes[valIndex] = vote
  209. voteSet.votesBitArray.SetIndex(valIndex, true)
  210. voteSet.sum += votingPower
  211. }
  212. votesByBlock, ok := voteSet.votesByBlock[blockKey]
  213. if ok {
  214. if conflicting != nil && !votesByBlock.peerMaj23 {
  215. // There's a conflict and no peer claims that this block is special.
  216. return false, conflicting
  217. }
  218. // We'll add the vote in a bit.
  219. } else {
  220. // .votesByBlock doesn't exist...
  221. if conflicting != nil {
  222. // ... and there's a conflicting vote.
  223. // We're not even tracking this blockKey, so just forget it.
  224. return false, conflicting
  225. } else {
  226. // ... and there's no conflicting vote.
  227. // Start tracking this blockKey
  228. votesByBlock = newBlockVotes(false, voteSet.valSet.Size())
  229. voteSet.votesByBlock[blockKey] = votesByBlock
  230. // We'll add the vote in a bit.
  231. }
  232. }
  233. // Before adding to votesByBlock, see if we'll exceed quorum
  234. origSum := votesByBlock.sum
  235. quorum := voteSet.valSet.TotalVotingPower()*2/3 + 1
  236. // Add vote to votesByBlock
  237. votesByBlock.addVerifiedVote(vote, votingPower)
  238. // If we just crossed the quorum threshold and have 2/3 majority...
  239. if origSum < quorum && quorum <= votesByBlock.sum {
  240. // Only consider the first quorum reached
  241. if voteSet.maj23 == nil {
  242. maj23BlockID := vote.BlockID
  243. voteSet.maj23 = &maj23BlockID
  244. // And also copy votes over to voteSet.votes
  245. for i, vote := range votesByBlock.votes {
  246. if vote != nil {
  247. voteSet.votes[i] = vote
  248. }
  249. }
  250. }
  251. }
  252. return true, conflicting
  253. }
  254. // If a peer claims that it has 2/3 majority for given blockKey, call this.
  255. // NOTE: if there are too many peers, or too much peer churn,
  256. // this can cause memory issues.
  257. // TODO: implement ability to remove peers too
  258. // NOTE: VoteSet must not be nil
  259. func (voteSet *VoteSet) SetPeerMaj23(peerID P2PID, blockID BlockID) error {
  260. if voteSet == nil {
  261. cmn.PanicSanity("SetPeerMaj23() on nil VoteSet")
  262. }
  263. voteSet.mtx.Lock()
  264. defer voteSet.mtx.Unlock()
  265. blockKey := blockID.Key()
  266. // Make sure peer hasn't already told us something.
  267. if existing, ok := voteSet.peerMaj23s[peerID]; ok {
  268. if existing.Equals(blockID) {
  269. return nil // Nothing to do
  270. } else {
  271. return fmt.Errorf("SetPeerMaj23: Received conflicting blockID from peer %v. Got %v, expected %v",
  272. peerID, blockID, existing)
  273. }
  274. }
  275. voteSet.peerMaj23s[peerID] = blockID
  276. // Create .votesByBlock entry if needed.
  277. votesByBlock, ok := voteSet.votesByBlock[blockKey]
  278. if ok {
  279. if votesByBlock.peerMaj23 {
  280. return nil // Nothing to do
  281. } else {
  282. votesByBlock.peerMaj23 = true
  283. // No need to copy votes, already there.
  284. }
  285. } else {
  286. votesByBlock = newBlockVotes(true, voteSet.valSet.Size())
  287. voteSet.votesByBlock[blockKey] = votesByBlock
  288. // No need to copy votes, no votes to copy over.
  289. }
  290. return nil
  291. }
  292. func (voteSet *VoteSet) BitArray() *cmn.BitArray {
  293. if voteSet == nil {
  294. return nil
  295. }
  296. voteSet.mtx.Lock()
  297. defer voteSet.mtx.Unlock()
  298. return voteSet.votesBitArray.Copy()
  299. }
  300. func (voteSet *VoteSet) BitArrayByBlockID(blockID BlockID) *cmn.BitArray {
  301. if voteSet == nil {
  302. return nil
  303. }
  304. voteSet.mtx.Lock()
  305. defer voteSet.mtx.Unlock()
  306. votesByBlock, ok := voteSet.votesByBlock[blockID.Key()]
  307. if ok {
  308. return votesByBlock.bitArray.Copy()
  309. }
  310. return nil
  311. }
  312. // NOTE: if validator has conflicting votes, returns "canonical" vote
  313. func (voteSet *VoteSet) GetByIndex(valIndex int) *Vote {
  314. if voteSet == nil {
  315. return nil
  316. }
  317. voteSet.mtx.Lock()
  318. defer voteSet.mtx.Unlock()
  319. return voteSet.votes[valIndex]
  320. }
  321. func (voteSet *VoteSet) GetByAddress(address []byte) *Vote {
  322. if voteSet == nil {
  323. return nil
  324. }
  325. voteSet.mtx.Lock()
  326. defer voteSet.mtx.Unlock()
  327. valIndex, val := voteSet.valSet.GetByAddress(address)
  328. if val == nil {
  329. cmn.PanicSanity("GetByAddress(address) returned nil")
  330. }
  331. return voteSet.votes[valIndex]
  332. }
  333. func (voteSet *VoteSet) HasTwoThirdsMajority() bool {
  334. if voteSet == nil {
  335. return false
  336. }
  337. voteSet.mtx.Lock()
  338. defer voteSet.mtx.Unlock()
  339. return voteSet.maj23 != nil
  340. }
  341. func (voteSet *VoteSet) IsCommit() bool {
  342. if voteSet == nil {
  343. return false
  344. }
  345. if voteSet.type_ != VoteTypePrecommit {
  346. return false
  347. }
  348. voteSet.mtx.Lock()
  349. defer voteSet.mtx.Unlock()
  350. return voteSet.maj23 != nil
  351. }
  352. func (voteSet *VoteSet) HasTwoThirdsAny() bool {
  353. if voteSet == nil {
  354. return false
  355. }
  356. voteSet.mtx.Lock()
  357. defer voteSet.mtx.Unlock()
  358. return voteSet.sum > voteSet.valSet.TotalVotingPower()*2/3
  359. }
  360. func (voteSet *VoteSet) HasAll() bool {
  361. return voteSet.sum == voteSet.valSet.TotalVotingPower()
  362. }
  363. // Returns either a blockhash (or nil) that received +2/3 majority.
  364. // If there exists no such majority, returns (nil, PartSetHeader{}, false).
  365. func (voteSet *VoteSet) TwoThirdsMajority() (blockID BlockID, ok bool) {
  366. if voteSet == nil {
  367. return BlockID{}, false
  368. }
  369. voteSet.mtx.Lock()
  370. defer voteSet.mtx.Unlock()
  371. if voteSet.maj23 != nil {
  372. return *voteSet.maj23, true
  373. } else {
  374. return BlockID{}, false
  375. }
  376. }
  377. func (voteSet *VoteSet) String() string {
  378. if voteSet == nil {
  379. return "nil-VoteSet"
  380. }
  381. return voteSet.StringIndented("")
  382. }
  383. func (voteSet *VoteSet) StringIndented(indent string) string {
  384. voteStrings := make([]string, len(voteSet.votes))
  385. for i, vote := range voteSet.votes {
  386. if vote == nil {
  387. voteStrings[i] = "nil-Vote"
  388. } else {
  389. voteStrings[i] = vote.String()
  390. }
  391. }
  392. return fmt.Sprintf(`VoteSet{
  393. %s H:%v R:%v T:%v
  394. %s %v
  395. %s %v
  396. %s %v
  397. %s}`,
  398. indent, voteSet.height, voteSet.round, voteSet.type_,
  399. indent, strings.Join(voteStrings, "\n"+indent+" "),
  400. indent, voteSet.votesBitArray,
  401. indent, voteSet.peerMaj23s,
  402. indent)
  403. }
  404. func (voteSet *VoteSet) StringShort() string {
  405. if voteSet == nil {
  406. return "nil-VoteSet"
  407. }
  408. voteSet.mtx.Lock()
  409. defer voteSet.mtx.Unlock()
  410. return fmt.Sprintf(`VoteSet{H:%v R:%v T:%v +2/3:%v %v %v}`,
  411. voteSet.height, voteSet.round, voteSet.type_, voteSet.maj23, voteSet.votesBitArray, voteSet.peerMaj23s)
  412. }
  413. //--------------------------------------------------------------------------------
  414. // Commit
  415. func (voteSet *VoteSet) MakeCommit() *Commit {
  416. if voteSet.type_ != VoteTypePrecommit {
  417. cmn.PanicSanity("Cannot MakeCommit() unless VoteSet.Type is VoteTypePrecommit")
  418. }
  419. voteSet.mtx.Lock()
  420. defer voteSet.mtx.Unlock()
  421. // Make sure we have a 2/3 majority
  422. if voteSet.maj23 == nil {
  423. cmn.PanicSanity("Cannot MakeCommit() unless a blockhash has +2/3")
  424. }
  425. // For every validator, get the precommit
  426. votesCopy := make([]*Vote, len(voteSet.votes))
  427. copy(votesCopy, voteSet.votes)
  428. return &Commit{
  429. BlockID: *voteSet.maj23,
  430. Precommits: votesCopy,
  431. }
  432. }
  433. //--------------------------------------------------------------------------------
  434. /*
  435. Votes for a particular block
  436. There are two ways a *blockVotes gets created for a blockKey.
  437. 1. first (non-conflicting) vote of a validator w/ blockKey (peerMaj23=false)
  438. 2. A peer claims to have a 2/3 majority w/ blockKey (peerMaj23=true)
  439. */
  440. type blockVotes struct {
  441. peerMaj23 bool // peer claims to have maj23
  442. bitArray *cmn.BitArray // valIndex -> hasVote?
  443. votes []*Vote // valIndex -> *Vote
  444. sum int64 // vote sum
  445. }
  446. func newBlockVotes(peerMaj23 bool, numValidators int) *blockVotes {
  447. return &blockVotes{
  448. peerMaj23: peerMaj23,
  449. bitArray: cmn.NewBitArray(numValidators),
  450. votes: make([]*Vote, numValidators),
  451. sum: 0,
  452. }
  453. }
  454. func (vs *blockVotes) addVerifiedVote(vote *Vote, votingPower int64) {
  455. valIndex := vote.ValidatorIndex
  456. if existing := vs.votes[valIndex]; existing == nil {
  457. vs.bitArray.SetIndex(valIndex, true)
  458. vs.votes[valIndex] = vote
  459. vs.sum += votingPower
  460. }
  461. }
  462. func (vs *blockVotes) getByIndex(index int) *Vote {
  463. if vs == nil {
  464. return nil
  465. }
  466. return vs.votes[index]
  467. }
  468. //--------------------------------------------------------------------------------
  469. // Common interface between *consensus.VoteSet and types.Commit
  470. type VoteSetReader interface {
  471. Height() int64
  472. Round() int
  473. Type() byte
  474. Size() int
  475. BitArray() *cmn.BitArray
  476. GetByIndex(int) *Vote
  477. IsCommit() bool
  478. }