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.

335 lines
10 KiB

  1. package consensus
  2. import (
  3. "bytes"
  4. "fmt"
  5. "sort"
  6. "testing"
  7. "time"
  8. dbm "github.com/tendermint/go-db"
  9. bc "github.com/tendermint/tendermint/blockchain"
  10. _ "github.com/tendermint/tendermint/config/tendermint_test"
  11. "github.com/tendermint/tendermint/events"
  12. mempl "github.com/tendermint/tendermint/mempool"
  13. "github.com/tendermint/tendermint/proxy"
  14. sm "github.com/tendermint/tendermint/state"
  15. "github.com/tendermint/tendermint/types"
  16. "github.com/tendermint/tmsp/example"
  17. )
  18. var chainID string
  19. func init() {
  20. chainID = config.GetString("chain_id")
  21. }
  22. type validatorStub struct {
  23. Height int
  24. Round int
  25. *types.PrivValidator
  26. }
  27. func NewValidatorStub(privValidator *types.PrivValidator) *validatorStub {
  28. return &validatorStub{
  29. PrivValidator: privValidator,
  30. }
  31. }
  32. func (vs *validatorStub) signVote(voteType byte, hash []byte, header types.PartSetHeader) (*types.Vote, error) {
  33. vote := &types.Vote{
  34. Height: vs.Height,
  35. Round: vs.Round,
  36. Type: voteType,
  37. BlockHash: hash,
  38. BlockPartsHeader: header,
  39. }
  40. err := vs.PrivValidator.SignVote(chainID, vote)
  41. return vote, err
  42. }
  43. // convenienve function for testing
  44. func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSetHeader) *types.Vote {
  45. v, err := vs.signVote(voteType, hash, header)
  46. if err != nil {
  47. panic(fmt.Errorf("failed to sign vote: %v", err))
  48. }
  49. return v
  50. }
  51. // create proposal block from cs1 but sign it with vs
  52. func decideProposal(cs1 *ConsensusState, cs2 *validatorStub, height, round int) (proposal *types.Proposal, block *types.Block) {
  53. block, blockParts := cs1.createProposalBlock()
  54. if block == nil { // on error
  55. panic("error creating proposal block")
  56. }
  57. // Make proposal
  58. proposal = types.NewProposal(height, round, blockParts.Header(), cs1.Votes.POLRound())
  59. if err := cs2.SignProposal(chainID, proposal); err != nil {
  60. panic(err)
  61. }
  62. return
  63. }
  64. //-------------------------------------------------------------------------------
  65. // utils
  66. func nilRound(t *testing.T, startRound int, cs1 *ConsensusState, vss ...*validatorStub) {
  67. height, round := cs1.Height, cs1.Round
  68. waitFor(t, cs1, height, round, RoundStepPrevote)
  69. signAddVoteToFromMany(types.VoteTypePrevote, cs1, nil, cs1.ProposalBlockParts.Header(), vss...)
  70. waitFor(t, cs1, height, round, RoundStepPrecommit)
  71. signAddVoteToFromMany(types.VoteTypePrecommit, cs1, nil, cs1.ProposalBlockParts.Header(), vss...)
  72. waitFor(t, cs1, height, round+1, RoundStepNewRound)
  73. }
  74. // NOTE: this switches the propser as far as `perspectiveOf` is concerned,
  75. // but for simplicity we return a block it generated.
  76. func changeProposer(t *testing.T, perspectiveOf *ConsensusState, newProposer *validatorStub) *types.Block {
  77. _, v1 := perspectiveOf.Validators.GetByAddress(perspectiveOf.privValidator.Address)
  78. v1.Accum, v1.VotingPower = 0, 0
  79. if updated := perspectiveOf.Validators.Update(v1); !updated {
  80. t.Fatal("failed to update validator")
  81. }
  82. _, v2 := perspectiveOf.Validators.GetByAddress(newProposer.Address)
  83. v2.Accum, v2.VotingPower = 100, 100
  84. if updated := perspectiveOf.Validators.Update(v2); !updated {
  85. t.Fatal("failed to update validator")
  86. }
  87. // make the proposal
  88. propBlock, _ := perspectiveOf.createProposalBlock()
  89. if propBlock == nil {
  90. t.Fatal("Failed to create proposal block with cs2")
  91. }
  92. return propBlock
  93. }
  94. func fixVotingPower(t *testing.T, cs1 *ConsensusState, addr2 []byte) {
  95. _, v1 := cs1.Validators.GetByAddress(cs1.privValidator.Address)
  96. _, v2 := cs1.Validators.GetByAddress(addr2)
  97. v1.Accum, v1.VotingPower = v2.Accum, v2.VotingPower
  98. if updated := cs1.Validators.Update(v1); !updated {
  99. t.Fatal("failed to update validator")
  100. }
  101. }
  102. func addVoteToFromMany(to *ConsensusState, votes []*types.Vote, froms ...*validatorStub) {
  103. if len(votes) != len(froms) {
  104. panic("len(votes) and len(froms) must match")
  105. }
  106. for i, from := range froms {
  107. addVoteToFrom(to, from, votes[i])
  108. }
  109. }
  110. func addVoteToFrom(to *ConsensusState, from *validatorStub, vote *types.Vote) {
  111. valIndex, _ := to.Validators.GetByAddress(from.PrivValidator.Address)
  112. added, err := to.TryAddVote(valIndex, vote, "")
  113. if _, ok := err.(*types.ErrVoteConflictingSignature); ok {
  114. // let it fly
  115. } else if !added {
  116. fmt.Println("to, from, vote:", to.Height, from.Height, vote.Height)
  117. panic(fmt.Sprintln("Failed to add vote. Err:", err))
  118. } else if err != nil {
  119. panic(fmt.Sprintln("Failed to add vote:", err))
  120. }
  121. }
  122. func signVoteMany(voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) []*types.Vote {
  123. votes := make([]*types.Vote, len(vss))
  124. for i, vs := range vss {
  125. votes[i] = signVote(vs, voteType, hash, header)
  126. }
  127. return votes
  128. }
  129. // add vote to one cs from another
  130. func signAddVoteToFromMany(voteType byte, to *ConsensusState, hash []byte, header types.PartSetHeader, froms ...*validatorStub) {
  131. for _, from := range froms {
  132. vote := signVote(from, voteType, hash, header)
  133. addVoteToFrom(to, from, vote)
  134. }
  135. }
  136. func signAddVoteToFrom(voteType byte, to *ConsensusState, from *validatorStub, hash []byte, header types.PartSetHeader) *types.Vote {
  137. vote := signVote(from, voteType, hash, header)
  138. addVoteToFrom(to, from, vote)
  139. return vote
  140. }
  141. func ensureNoNewStep(t *testing.T, cs *ConsensusState) {
  142. timeout := time.NewTicker(2 * time.Second)
  143. select {
  144. case <-timeout.C:
  145. break
  146. case <-cs.NewStepCh():
  147. panic("We should be stuck waiting for more votes, not moving to the next step")
  148. }
  149. }
  150. func ensureNewStep(t *testing.T, cs *ConsensusState) *RoundState {
  151. timeout := time.NewTicker(2 * time.Second)
  152. select {
  153. case <-timeout.C:
  154. panic("We should have gone to the next step, not be stuck waiting")
  155. case rs := <-cs.NewStepCh():
  156. return rs
  157. }
  158. }
  159. func waitFor(t *testing.T, cs *ConsensusState, height int, round int, step RoundStepType) {
  160. for {
  161. rs := ensureNewStep(t, cs)
  162. if CompareHRS(rs.Height, rs.Round, rs.Step, height, round, step) < 0 {
  163. continue
  164. } else {
  165. break
  166. }
  167. }
  168. }
  169. func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *validatorStub, blockHash []byte) {
  170. prevotes := cs.Votes.Prevotes(round)
  171. var vote *types.Vote
  172. if vote = prevotes.GetByAddress(privVal.Address); vote == nil {
  173. panic("Failed to find prevote from validator")
  174. }
  175. if blockHash == nil {
  176. if vote.BlockHash != nil {
  177. panic(fmt.Sprintf("Expected prevote to be for nil, got %X", vote.BlockHash))
  178. }
  179. } else {
  180. if !bytes.Equal(vote.BlockHash, blockHash) {
  181. panic(fmt.Sprintf("Expected prevote to be for %X, got %X", blockHash, vote.BlockHash))
  182. }
  183. }
  184. }
  185. func incrementHeight(vss ...*validatorStub) {
  186. for _, vs := range vss {
  187. vs.Height += 1
  188. }
  189. }
  190. func incrementRound(vss ...*validatorStub) {
  191. for _, vs := range vss {
  192. vs.Round += 1
  193. }
  194. }
  195. func validatePrecommit(t *testing.T, cs *ConsensusState, thisRound, lockRound int, privVal *validatorStub, votedBlockHash, lockedBlockHash []byte) {
  196. precommits := cs.Votes.Precommits(thisRound)
  197. var vote *types.Vote
  198. if vote = precommits.GetByAddress(privVal.Address); vote == nil {
  199. panic("Failed to find precommit from validator")
  200. }
  201. if votedBlockHash == nil {
  202. if vote.BlockHash != nil {
  203. panic("Expected precommit to be for nil")
  204. }
  205. } else {
  206. if !bytes.Equal(vote.BlockHash, votedBlockHash) {
  207. panic("Expected precommit to be for proposal block")
  208. }
  209. }
  210. if lockedBlockHash == nil {
  211. if cs.LockedRound != lockRound || cs.LockedBlock != nil {
  212. 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))
  213. }
  214. } else {
  215. if cs.LockedRound != lockRound || !bytes.Equal(cs.LockedBlock.Hash(), lockedBlockHash) {
  216. 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))
  217. }
  218. }
  219. }
  220. func validatePrevoteAndPrecommit(t *testing.T, cs *ConsensusState, thisRound, lockRound int, privVal *validatorStub, votedBlockHash, lockedBlockHash []byte) {
  221. // verify the prevote
  222. validatePrevote(t, cs, thisRound, privVal, votedBlockHash)
  223. // verify precommit
  224. cs.mtx.Lock()
  225. validatePrecommit(t, cs, thisRound, lockRound, privVal, votedBlockHash, lockedBlockHash)
  226. cs.mtx.Unlock()
  227. }
  228. func simpleConsensusState(nValidators int) (*ConsensusState, []*validatorStub) {
  229. // Get State
  230. state, privVals := randGenesisState(nValidators, false, 10)
  231. // fmt.Println(state.Validators)
  232. vss := make([]*validatorStub, nValidators)
  233. // make consensus state for lead validator
  234. // Get BlockStore
  235. blockDB := dbm.NewMemDB()
  236. blockStore := bc.NewBlockStore(blockDB)
  237. // one for mempool, one for consensus
  238. app := example.NewCounterApplication(false)
  239. appCMem := app.Open()
  240. appCCon := app.Open()
  241. proxyAppCtxMem := proxy.NewLocalAppContext(appCMem)
  242. proxyAppCtxCon := proxy.NewLocalAppContext(appCCon)
  243. // Make Mempool
  244. mempool := mempl.NewMempool(proxyAppCtxMem)
  245. // Make ConsensusReactor
  246. cs := NewConsensusState(state, proxyAppCtxCon, blockStore, mempool)
  247. cs.SetPrivValidator(privVals[0])
  248. evsw := events.NewEventSwitch()
  249. cs.SetFireable(evsw)
  250. // read off the NewHeightStep
  251. <-cs.NewStepCh()
  252. for i := 0; i < nValidators; i++ {
  253. vss[i] = NewValidatorStub(privVals[i])
  254. }
  255. // since cs1 starts at 1
  256. incrementHeight(vss[1:]...)
  257. return cs, vss
  258. }
  259. func randGenesisState(numValidators int, randPower bool, minPower int64) (*sm.State, []*types.PrivValidator) {
  260. db := dbm.NewMemDB()
  261. genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower)
  262. s0 := sm.MakeGenesisState(db, genDoc)
  263. s0.Save()
  264. return s0, privValidators
  265. }
  266. func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.GenesisDoc, []*types.PrivValidator) {
  267. validators := make([]types.GenesisValidator, numValidators)
  268. privValidators := make([]*types.PrivValidator, numValidators)
  269. for i := 0; i < numValidators; i++ {
  270. val, privVal := types.RandValidator(randPower, minPower)
  271. validators[i] = types.GenesisValidator{
  272. PubKey: val.PubKey,
  273. Amount: val.VotingPower,
  274. }
  275. privValidators[i] = privVal
  276. }
  277. sort.Sort(types.PrivValidatorsByAddress(privValidators))
  278. return &types.GenesisDoc{
  279. GenesisTime: time.Now(),
  280. ChainID: config.GetString("chain_id"),
  281. Validators: validators,
  282. }, privValidators
  283. }