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.

225 lines
6.9 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package consensus
  2. import (
  3. "bytes"
  4. "fmt"
  5. "testing"
  6. "time"
  7. bc "github.com/tendermint/tendermint/blockchain"
  8. dbm "github.com/tendermint/tendermint/db"
  9. mempl "github.com/tendermint/tendermint/mempool"
  10. "github.com/tendermint/tendermint/p2p"
  11. sm "github.com/tendermint/tendermint/state"
  12. "github.com/tendermint/tendermint/types"
  13. )
  14. //-------------------------------------------------------------------------------
  15. // utils
  16. func changeProposer(t *testing.T, perspectiveOf, newProposer *ConsensusState) *types.Block {
  17. _, v1 := perspectiveOf.Validators.GetByAddress(perspectiveOf.privValidator.Address)
  18. v1.Accum, v1.VotingPower = 0, 0
  19. if updated := perspectiveOf.Validators.Update(v1); !updated {
  20. t.Fatal("failed to update validator")
  21. }
  22. _, v2 := perspectiveOf.Validators.GetByAddress(newProposer.privValidator.Address)
  23. v2.Accum, v2.VotingPower = 100, 100
  24. if updated := perspectiveOf.Validators.Update(v2); !updated {
  25. t.Fatal("failed to update validator")
  26. }
  27. // make the proposal
  28. propBlock, _ := newProposer.createProposalBlock()
  29. if propBlock == nil {
  30. t.Fatal("Failed to create proposal block with cs2")
  31. }
  32. return propBlock
  33. }
  34. func fixVotingPower(t *testing.T, cs1 *ConsensusState, addr2 []byte) {
  35. _, v1 := cs1.Validators.GetByAddress(cs1.privValidator.Address)
  36. _, v2 := cs1.Validators.GetByAddress(addr2)
  37. v1.Accum, v1.VotingPower = v2.Accum, v2.VotingPower
  38. if updated := cs1.Validators.Update(v1); !updated {
  39. t.Fatal("failed to update validator")
  40. }
  41. }
  42. func addVoteToFromMany(to *ConsensusState, votes []*types.Vote, froms ...*ConsensusState) {
  43. if len(votes) != len(froms) {
  44. panic("len(votes) and len(froms) must match")
  45. }
  46. for i, from := range froms {
  47. addVoteToFrom(to, from, votes[i])
  48. }
  49. }
  50. func addVoteToFrom(to, from *ConsensusState, vote *types.Vote) {
  51. valIndex, _ := to.Validators.GetByAddress(from.privValidator.Address)
  52. added, err := to.TryAddVote(valIndex, vote, "")
  53. if _, ok := err.(*types.ErrVoteConflictingSignature); ok {
  54. // let it fly
  55. } else if !added {
  56. panic("Failed to add vote")
  57. } else if err != nil {
  58. panic(fmt.Sprintln("Failed to add vote:", err))
  59. }
  60. }
  61. func signVote(from *ConsensusState, voteType byte, hash []byte, header types.PartSetHeader) *types.Vote {
  62. vote, err := from.signVote(voteType, hash, header)
  63. if err != nil {
  64. panic(fmt.Sprintln("Failed to sign vote", err))
  65. }
  66. return vote
  67. }
  68. func signVoteMany(voteType byte, hash []byte, header types.PartSetHeader, css ...*ConsensusState) []*types.Vote {
  69. votes := make([]*types.Vote, len(css))
  70. for i, cs := range css {
  71. votes[i] = signVote(cs, voteType, hash, header)
  72. }
  73. return votes
  74. }
  75. // add vote to one cs from another
  76. func signAddVoteToFromMany(voteType byte, to *ConsensusState, hash []byte, header types.PartSetHeader, froms ...*ConsensusState) {
  77. for _, from := range froms {
  78. vote := signVote(from, voteType, hash, header)
  79. addVoteToFrom(to, from, vote)
  80. }
  81. }
  82. func signAddVoteToFrom(voteType byte, to, from *ConsensusState, hash []byte, header types.PartSetHeader) *types.Vote {
  83. vote := signVote(from, voteType, hash, header)
  84. addVoteToFrom(to, from, vote)
  85. return vote
  86. }
  87. func ensureNoNewStep(t *testing.T, cs *ConsensusState) {
  88. timeout := time.NewTicker(2 * time.Second)
  89. select {
  90. case <-timeout.C:
  91. break
  92. case <-cs.NewStepCh():
  93. panic("We should be stuck waiting for more votes, not moving to the next step")
  94. }
  95. }
  96. func ensureNewStep(t *testing.T, cs *ConsensusState) {
  97. timeout := time.NewTicker(2 * time.Second)
  98. select {
  99. case <-timeout.C:
  100. panic("We should have gone to the next step, not be stuck waiting")
  101. case <-cs.NewStepCh():
  102. break
  103. }
  104. }
  105. func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *types.PrivValidator, blockHash []byte) {
  106. prevotes := cs.Votes.Prevotes(round)
  107. var vote *types.Vote
  108. if vote = prevotes.GetByAddress(privVal.Address); vote == nil {
  109. panic("Failed to find prevote from validator")
  110. }
  111. if blockHash == nil {
  112. if vote.BlockHash != nil {
  113. panic(fmt.Sprintf("Expected prevote to be for nil, got %X", vote.BlockHash))
  114. }
  115. } else {
  116. if !bytes.Equal(vote.BlockHash, blockHash) {
  117. panic(fmt.Sprintf("Expected prevote to be for %X, got %X", blockHash, vote.BlockHash))
  118. }
  119. }
  120. }
  121. func incrementRound(css ...*ConsensusState) {
  122. for _, cs := range css {
  123. cs.Round += 1
  124. }
  125. }
  126. func validatePrecommit(t *testing.T, cs *ConsensusState, thisRound, lockRound int, privVal *types.PrivValidator, votedBlockHash, lockedBlockHash []byte) {
  127. precommits := cs.Votes.Precommits(thisRound)
  128. var vote *types.Vote
  129. if vote = precommits.GetByAddress(privVal.Address); vote == nil {
  130. panic("Failed to find precommit from validator")
  131. }
  132. if votedBlockHash == nil {
  133. if vote.BlockHash != nil {
  134. panic("Expected precommit to be for nil")
  135. }
  136. } else {
  137. if !bytes.Equal(vote.BlockHash, votedBlockHash) {
  138. panic("Expected precommit to be for proposal block")
  139. }
  140. }
  141. if lockedBlockHash == nil {
  142. if cs.LockedRound != lockRound || cs.LockedBlock != nil {
  143. panic(fmt.Sprintf("Expected to be locked on nil at round %d. Got locked at round %d with block %v", lockRound, cs.LockedRound, cs.LockedBlock))
  144. }
  145. } else {
  146. if cs.LockedRound != lockRound || !bytes.Equal(cs.LockedBlock.Hash(), lockedBlockHash) {
  147. panic(fmt.Sprintf("Expected block to be locked on round %d, got %d. Got locked block %X, expected %X", lockRound, cs.LockedRound, cs.LockedBlock.Hash(), lockedBlockHash))
  148. }
  149. }
  150. }
  151. func validatePrevoteAndPrecommit(t *testing.T, cs *ConsensusState, thisRound, lockRound int, privVal *types.PrivValidator, votedBlockHash, lockedBlockHash []byte, f func()) {
  152. // verify the prevote
  153. validatePrevote(t, cs, thisRound, privVal, votedBlockHash)
  154. if f != nil {
  155. f()
  156. }
  157. // wait to finish precommit
  158. <-cs.NewStepCh()
  159. // verify precommit
  160. cs.mtx.Lock()
  161. validatePrecommit(t, cs, thisRound, lockRound, privVal, votedBlockHash, lockedBlockHash)
  162. cs.mtx.Unlock()
  163. }
  164. func simpleConsensusState(nValidators int) ([]*ConsensusState, []*types.PrivValidator) {
  165. // Get State
  166. state, privAccs, privVals := sm.RandGenesisState(10, true, 1000, nValidators, false, 10)
  167. _, _ = privAccs, privVals
  168. fmt.Println(state.BondedValidators)
  169. css := make([]*ConsensusState, nValidators)
  170. for i := 0; i < nValidators; i++ {
  171. // Get BlockStore
  172. blockDB := dbm.NewMemDB()
  173. blockStore := bc.NewBlockStore(blockDB)
  174. // Make MempoolReactor
  175. mempool := mempl.NewMempool(state.Copy())
  176. mempoolReactor := mempl.NewMempoolReactor(mempool)
  177. mempoolReactor.SetSwitch(p2p.NewSwitch())
  178. // Make ConsensusReactor
  179. cs := NewConsensusState(state, blockStore, mempoolReactor)
  180. cs.SetPrivValidator(privVals[i])
  181. // read off the NewHeightStep
  182. <-cs.NewStepCh()
  183. css[i] = cs
  184. }
  185. return css, privVals
  186. }
  187. func randConsensusState() (*ConsensusState, []*types.PrivValidator) {
  188. state, _, privValidators := sm.RandGenesisState(20, false, 1000, 10, false, 1000)
  189. blockStore := bc.NewBlockStore(dbm.NewMemDB())
  190. mempool := mempl.NewMempool(state)
  191. mempoolReactor := mempl.NewMempoolReactor(mempool)
  192. cs := NewConsensusState(state, blockStore, mempoolReactor)
  193. return cs, privValidators
  194. }