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.

396 lines
12 KiB

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