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.

442 lines
12 KiB

6 years ago
6 years ago
  1. package state
  2. import (
  3. "context"
  4. "fmt"
  5. "testing"
  6. "time"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. "github.com/tendermint/tendermint/abci/example/kvstore"
  10. abci "github.com/tendermint/tendermint/abci/types"
  11. "github.com/tendermint/tendermint/crypto/ed25519"
  12. "github.com/tendermint/tendermint/crypto/secp256k1"
  13. cmn "github.com/tendermint/tendermint/libs/common"
  14. dbm "github.com/tendermint/tendermint/libs/db"
  15. "github.com/tendermint/tendermint/libs/log"
  16. tmtime "github.com/tendermint/tendermint/types/time"
  17. "github.com/tendermint/tendermint/proxy"
  18. "github.com/tendermint/tendermint/types"
  19. )
  20. var (
  21. chainID = "execution_chain"
  22. testPartSize = 65536
  23. nTxsPerBlock = 10
  24. )
  25. func TestApplyBlock(t *testing.T) {
  26. cc := proxy.NewLocalClientCreator(kvstore.NewKVStoreApplication())
  27. proxyApp := proxy.NewAppConns(cc)
  28. err := proxyApp.Start()
  29. require.Nil(t, err)
  30. defer proxyApp.Stop()
  31. state, stateDB := state(1, 1)
  32. blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(),
  33. MockMempool{}, MockEvidencePool{})
  34. block := makeBlock(state, 1)
  35. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  36. state, err = blockExec.ApplyBlock(state, blockID, block)
  37. require.Nil(t, err)
  38. // TODO check state and mempool
  39. }
  40. // TestBeginBlockValidators ensures we send absent validators list.
  41. func TestBeginBlockValidators(t *testing.T) {
  42. app := &testApp{}
  43. cc := proxy.NewLocalClientCreator(app)
  44. proxyApp := proxy.NewAppConns(cc)
  45. err := proxyApp.Start()
  46. require.Nil(t, err)
  47. defer proxyApp.Stop()
  48. state, stateDB := state(2, 2)
  49. prevHash := state.LastBlockID.Hash
  50. prevParts := types.PartSetHeader{}
  51. prevBlockID := types.BlockID{prevHash, prevParts}
  52. now := tmtime.Now()
  53. vote0 := &types.Vote{ValidatorIndex: 0, Timestamp: now, Type: types.PrecommitType}
  54. vote1 := &types.Vote{ValidatorIndex: 1, Timestamp: now}
  55. testCases := []struct {
  56. desc string
  57. lastCommitPrecommits []*types.Vote
  58. expectedAbsentValidators []int
  59. }{
  60. {"none absent", []*types.Vote{vote0, vote1}, []int{}},
  61. {"one absent", []*types.Vote{vote0, nil}, []int{1}},
  62. {"multiple absent", []*types.Vote{nil, nil}, []int{0, 1}},
  63. }
  64. for _, tc := range testCases {
  65. lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: tc.lastCommitPrecommits}
  66. // block for height 2
  67. block, _ := state.MakeBlock(2, makeTxs(2), lastCommit, nil, state.Validators.GetProposer().Address)
  68. _, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), state.Validators, stateDB)
  69. require.Nil(t, err, tc.desc)
  70. // -> app receives a list of validators with a bool indicating if they signed
  71. ctr := 0
  72. for i, v := range app.CommitVotes {
  73. if ctr < len(tc.expectedAbsentValidators) &&
  74. tc.expectedAbsentValidators[ctr] == i {
  75. assert.False(t, v.SignedLastBlock)
  76. ctr++
  77. } else {
  78. assert.True(t, v.SignedLastBlock)
  79. }
  80. }
  81. }
  82. }
  83. // TestBeginBlockByzantineValidators ensures we send byzantine validators list.
  84. func TestBeginBlockByzantineValidators(t *testing.T) {
  85. app := &testApp{}
  86. cc := proxy.NewLocalClientCreator(app)
  87. proxyApp := proxy.NewAppConns(cc)
  88. err := proxyApp.Start()
  89. require.Nil(t, err)
  90. defer proxyApp.Stop()
  91. state, stateDB := state(2, 12)
  92. prevHash := state.LastBlockID.Hash
  93. prevParts := types.PartSetHeader{}
  94. prevBlockID := types.BlockID{prevHash, prevParts}
  95. height1, idx1, val1 := int64(8), 0, state.Validators.Validators[0].Address
  96. height2, idx2, val2 := int64(3), 1, state.Validators.Validators[1].Address
  97. ev1 := types.NewMockGoodEvidence(height1, idx1, val1)
  98. ev2 := types.NewMockGoodEvidence(height2, idx2, val2)
  99. now := tmtime.Now()
  100. valSet := state.Validators
  101. testCases := []struct {
  102. desc string
  103. evidence []types.Evidence
  104. expectedByzantineValidators []abci.Evidence
  105. }{
  106. {"none byzantine", []types.Evidence{}, []abci.Evidence{}},
  107. {"one byzantine", []types.Evidence{ev1}, []abci.Evidence{types.TM2PB.Evidence(ev1, valSet, now)}},
  108. {"multiple byzantine", []types.Evidence{ev1, ev2}, []abci.Evidence{
  109. types.TM2PB.Evidence(ev1, valSet, now),
  110. types.TM2PB.Evidence(ev2, valSet, now)}},
  111. }
  112. vote0 := &types.Vote{ValidatorIndex: 0, Timestamp: now, Type: types.PrecommitType}
  113. vote1 := &types.Vote{ValidatorIndex: 1, Timestamp: now}
  114. votes := []*types.Vote{vote0, vote1}
  115. lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: votes}
  116. for _, tc := range testCases {
  117. block, _ := state.MakeBlock(10, makeTxs(2), lastCommit, nil, state.Validators.GetProposer().Address)
  118. block.Time = now
  119. block.Evidence.Evidence = tc.evidence
  120. _, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), state.Validators, stateDB)
  121. require.Nil(t, err, tc.desc)
  122. // -> app must receive an index of the byzantine validator
  123. assert.Equal(t, tc.expectedByzantineValidators, app.ByzantineValidators, tc.desc)
  124. }
  125. }
  126. func TestValidateValidatorUpdates(t *testing.T) {
  127. pubkey1 := ed25519.GenPrivKey().PubKey()
  128. pubkey2 := ed25519.GenPrivKey().PubKey()
  129. secpKey := secp256k1.GenPrivKey().PubKey()
  130. defaultValidatorParams := types.ValidatorParams{[]string{types.ABCIPubKeyTypeEd25519}}
  131. testCases := []struct {
  132. name string
  133. abciUpdates []abci.ValidatorUpdate
  134. validatorParams types.ValidatorParams
  135. shouldErr bool
  136. }{
  137. {
  138. "adding a validator is OK",
  139. []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 20}},
  140. defaultValidatorParams,
  141. false,
  142. },
  143. {
  144. "updating a validator is OK",
  145. []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey1), Power: 20}},
  146. defaultValidatorParams,
  147. false,
  148. },
  149. {
  150. "removing a validator is OK",
  151. []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}},
  152. defaultValidatorParams,
  153. false,
  154. },
  155. {
  156. "adding a validator with negative power results in error",
  157. []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: -100}},
  158. defaultValidatorParams,
  159. true,
  160. },
  161. {
  162. "adding a validator with pubkey thats not in validator params results in error",
  163. []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(secpKey), Power: -100}},
  164. defaultValidatorParams,
  165. true,
  166. },
  167. }
  168. for _, tc := range testCases {
  169. t.Run(tc.name, func(t *testing.T) {
  170. err := validateValidatorUpdates(tc.abciUpdates, tc.validatorParams)
  171. if tc.shouldErr {
  172. assert.Error(t, err)
  173. } else {
  174. assert.NoError(t, err)
  175. }
  176. })
  177. }
  178. }
  179. func TestUpdateValidators(t *testing.T) {
  180. pubkey1 := ed25519.GenPrivKey().PubKey()
  181. val1 := types.NewValidator(pubkey1, 10)
  182. pubkey2 := ed25519.GenPrivKey().PubKey()
  183. val2 := types.NewValidator(pubkey2, 20)
  184. testCases := []struct {
  185. name string
  186. currentSet *types.ValidatorSet
  187. abciUpdates []abci.ValidatorUpdate
  188. resultingSet *types.ValidatorSet
  189. shouldErr bool
  190. }{
  191. {
  192. "adding a validator is OK",
  193. types.NewValidatorSet([]*types.Validator{val1}),
  194. []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 20}},
  195. types.NewValidatorSet([]*types.Validator{val1, val2}),
  196. false,
  197. },
  198. {
  199. "updating a validator is OK",
  200. types.NewValidatorSet([]*types.Validator{val1}),
  201. []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey1), Power: 20}},
  202. types.NewValidatorSet([]*types.Validator{types.NewValidator(pubkey1, 20)}),
  203. false,
  204. },
  205. {
  206. "removing a validator is OK",
  207. types.NewValidatorSet([]*types.Validator{val1, val2}),
  208. []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}},
  209. types.NewValidatorSet([]*types.Validator{val1}),
  210. false,
  211. },
  212. {
  213. "removing a non-existing validator results in error",
  214. types.NewValidatorSet([]*types.Validator{val1}),
  215. []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}},
  216. types.NewValidatorSet([]*types.Validator{val1}),
  217. true,
  218. },
  219. }
  220. for _, tc := range testCases {
  221. t.Run(tc.name, func(t *testing.T) {
  222. updates, err := types.PB2TM.ValidatorUpdates(tc.abciUpdates)
  223. assert.NoError(t, err)
  224. err = updateValidators(tc.currentSet, updates)
  225. if tc.shouldErr {
  226. assert.Error(t, err)
  227. } else {
  228. assert.NoError(t, err)
  229. require.Equal(t, tc.resultingSet.Size(), tc.currentSet.Size())
  230. assert.Equal(t, tc.resultingSet.TotalVotingPower(), tc.currentSet.TotalVotingPower())
  231. assert.Equal(t, tc.resultingSet.Validators[0].Address, tc.currentSet.Validators[0].Address)
  232. if tc.resultingSet.Size() > 1 {
  233. assert.Equal(t, tc.resultingSet.Validators[1].Address, tc.currentSet.Validators[1].Address)
  234. }
  235. }
  236. })
  237. }
  238. }
  239. // TestEndBlockValidatorUpdates ensures we update validator set and send an event.
  240. func TestEndBlockValidatorUpdates(t *testing.T) {
  241. app := &testApp{}
  242. cc := proxy.NewLocalClientCreator(app)
  243. proxyApp := proxy.NewAppConns(cc)
  244. err := proxyApp.Start()
  245. require.Nil(t, err)
  246. defer proxyApp.Stop()
  247. state, stateDB := state(1, 1)
  248. blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(),
  249. MockMempool{}, MockEvidencePool{})
  250. eventBus := types.NewEventBus()
  251. err = eventBus.Start()
  252. require.NoError(t, err)
  253. defer eventBus.Stop()
  254. blockExec.SetEventBus(eventBus)
  255. updatesCh := make(chan interface{}, 1)
  256. err = eventBus.Subscribe(context.Background(), "TestEndBlockValidatorUpdates", types.EventQueryValidatorSetUpdates, updatesCh)
  257. require.NoError(t, err)
  258. block := makeBlock(state, 1)
  259. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  260. pubkey := ed25519.GenPrivKey().PubKey()
  261. app.ValidatorUpdates = []abci.ValidatorUpdate{
  262. {PubKey: types.TM2PB.PubKey(pubkey), Power: 10},
  263. }
  264. state, err = blockExec.ApplyBlock(state, blockID, block)
  265. require.Nil(t, err)
  266. // test new validator was added to NextValidators
  267. if assert.Equal(t, state.Validators.Size()+1, state.NextValidators.Size()) {
  268. idx, _ := state.NextValidators.GetByAddress(pubkey.Address())
  269. if idx < 0 {
  270. t.Fatalf("can't find address %v in the set %v", pubkey.Address(), state.NextValidators)
  271. }
  272. }
  273. // test we threw an event
  274. select {
  275. case e := <-updatesCh:
  276. event, ok := e.(types.EventDataValidatorSetUpdates)
  277. require.True(t, ok, "Expected event of type EventDataValidatorSetUpdates, got %T", e)
  278. if assert.NotEmpty(t, event.ValidatorUpdates) {
  279. assert.Equal(t, pubkey, event.ValidatorUpdates[0].PubKey)
  280. assert.EqualValues(t, 10, event.ValidatorUpdates[0].VotingPower)
  281. }
  282. case <-time.After(1 * time.Second):
  283. t.Fatal("Did not receive EventValidatorSetUpdates within 1 sec.")
  284. }
  285. }
  286. //----------------------------------------------------------------------------
  287. // make some bogus txs
  288. func makeTxs(height int64) (txs []types.Tx) {
  289. for i := 0; i < nTxsPerBlock; i++ {
  290. txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
  291. }
  292. return txs
  293. }
  294. func state(nVals, height int) (State, dbm.DB) {
  295. vals := make([]types.GenesisValidator, nVals)
  296. for i := 0; i < nVals; i++ {
  297. secret := []byte(fmt.Sprintf("test%d", i))
  298. pk := ed25519.GenPrivKeyFromSecret(secret)
  299. vals[i] = types.GenesisValidator{
  300. pk.PubKey().Address(),
  301. pk.PubKey(),
  302. 1000,
  303. fmt.Sprintf("test%d", i),
  304. }
  305. }
  306. s, _ := MakeGenesisState(&types.GenesisDoc{
  307. ChainID: chainID,
  308. Validators: vals,
  309. AppHash: nil,
  310. })
  311. // save validators to db for 2 heights
  312. stateDB := dbm.NewMemDB()
  313. SaveState(stateDB, s)
  314. for i := 1; i < height; i++ {
  315. s.LastBlockHeight++
  316. s.LastValidators = s.Validators.Copy()
  317. SaveState(stateDB, s)
  318. }
  319. return s, stateDB
  320. }
  321. func makeBlock(state State, height int64) *types.Block {
  322. block, _ := state.MakeBlock(height, makeTxs(state.LastBlockHeight), new(types.Commit), nil, state.Validators.GetProposer().Address)
  323. return block
  324. }
  325. //----------------------------------------------------------------------------
  326. type testApp struct {
  327. abci.BaseApplication
  328. CommitVotes []abci.VoteInfo
  329. ByzantineValidators []abci.Evidence
  330. ValidatorUpdates []abci.ValidatorUpdate
  331. }
  332. var _ abci.Application = (*testApp)(nil)
  333. func (app *testApp) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) {
  334. return abci.ResponseInfo{}
  335. }
  336. func (app *testApp) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock {
  337. app.CommitVotes = req.LastCommitInfo.Votes
  338. app.ByzantineValidators = req.ByzantineValidators
  339. return abci.ResponseBeginBlock{}
  340. }
  341. func (app *testApp) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock {
  342. return abci.ResponseEndBlock{ValidatorUpdates: app.ValidatorUpdates}
  343. }
  344. func (app *testApp) DeliverTx(tx []byte) abci.ResponseDeliverTx {
  345. return abci.ResponseDeliverTx{Tags: []cmn.KVPair{}}
  346. }
  347. func (app *testApp) CheckTx(tx []byte) abci.ResponseCheckTx {
  348. return abci.ResponseCheckTx{}
  349. }
  350. func (app *testApp) Commit() abci.ResponseCommit {
  351. return abci.ResponseCommit{}
  352. }
  353. func (app *testApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) {
  354. return
  355. }