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.

229 lines
7.0 KiB

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