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.

560 lines
17 KiB

  1. package types
  2. import (
  3. "bytes"
  4. "context"
  5. "sort"
  6. "testing"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. "github.com/tendermint/tendermint/crypto"
  10. tmrand "github.com/tendermint/tendermint/libs/rand"
  11. tmtime "github.com/tendermint/tendermint/libs/time"
  12. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  13. )
  14. func TestVoteSet_AddVote_Good(t *testing.T) {
  15. height, round := int64(1), int32(0)
  16. voteSet, _, privValidators := randVoteSet(height, round, tmproto.PrevoteType, 10, 1)
  17. val0 := privValidators[0]
  18. val0p, err := val0.GetPubKey(context.Background())
  19. require.NoError(t, err)
  20. val0Addr := val0p.Address()
  21. assert.Nil(t, voteSet.GetByAddress(val0Addr))
  22. assert.False(t, voteSet.BitArray().GetIndex(0))
  23. blockID, ok := voteSet.TwoThirdsMajority()
  24. assert.False(t, ok || !blockID.IsZero(), "there should be no 2/3 majority")
  25. vote := &Vote{
  26. ValidatorAddress: val0Addr,
  27. ValidatorIndex: 0, // since privValidators are in order
  28. Height: height,
  29. Round: round,
  30. Type: tmproto.PrevoteType,
  31. Timestamp: tmtime.Now(),
  32. BlockID: BlockID{nil, PartSetHeader{}},
  33. }
  34. _, err = signAddVote(val0, vote, voteSet)
  35. require.NoError(t, err)
  36. assert.NotNil(t, voteSet.GetByAddress(val0Addr))
  37. assert.True(t, voteSet.BitArray().GetIndex(0))
  38. blockID, ok = voteSet.TwoThirdsMajority()
  39. assert.False(t, ok || !blockID.IsZero(), "there should be no 2/3 majority")
  40. }
  41. func TestVoteSet_AddVote_Bad(t *testing.T) {
  42. height, round := int64(1), int32(0)
  43. voteSet, _, privValidators := randVoteSet(height, round, tmproto.PrevoteType, 10, 1)
  44. voteProto := &Vote{
  45. ValidatorAddress: nil,
  46. ValidatorIndex: -1,
  47. Height: height,
  48. Round: round,
  49. Timestamp: tmtime.Now(),
  50. Type: tmproto.PrevoteType,
  51. BlockID: BlockID{nil, PartSetHeader{}},
  52. }
  53. // val0 votes for nil.
  54. {
  55. pubKey, err := privValidators[0].GetPubKey(context.Background())
  56. require.NoError(t, err)
  57. addr := pubKey.Address()
  58. vote := withValidator(voteProto, addr, 0)
  59. added, err := signAddVote(privValidators[0], vote, voteSet)
  60. if !added || err != nil {
  61. t.Errorf("expected VoteSet.Add to succeed")
  62. }
  63. }
  64. // val0 votes again for some block.
  65. {
  66. pubKey, err := privValidators[0].GetPubKey(context.Background())
  67. require.NoError(t, err)
  68. addr := pubKey.Address()
  69. vote := withValidator(voteProto, addr, 0)
  70. added, err := signAddVote(privValidators[0], withBlockHash(vote, tmrand.Bytes(32)), voteSet)
  71. if added || err == nil {
  72. t.Errorf("expected VoteSet.Add to fail, conflicting vote.")
  73. }
  74. }
  75. // val1 votes on another height
  76. {
  77. pubKey, err := privValidators[1].GetPubKey(context.Background())
  78. require.NoError(t, err)
  79. addr := pubKey.Address()
  80. vote := withValidator(voteProto, addr, 1)
  81. added, err := signAddVote(privValidators[1], withHeight(vote, height+1), voteSet)
  82. if added || err == nil {
  83. t.Errorf("expected VoteSet.Add to fail, wrong height")
  84. }
  85. }
  86. // val2 votes on another round
  87. {
  88. pubKey, err := privValidators[2].GetPubKey(context.Background())
  89. require.NoError(t, err)
  90. addr := pubKey.Address()
  91. vote := withValidator(voteProto, addr, 2)
  92. added, err := signAddVote(privValidators[2], withRound(vote, round+1), voteSet)
  93. if added || err == nil {
  94. t.Errorf("expected VoteSet.Add to fail, wrong round")
  95. }
  96. }
  97. // val3 votes of another type.
  98. {
  99. pubKey, err := privValidators[3].GetPubKey(context.Background())
  100. require.NoError(t, err)
  101. addr := pubKey.Address()
  102. vote := withValidator(voteProto, addr, 3)
  103. added, err := signAddVote(privValidators[3], withType(vote, byte(tmproto.PrecommitType)), voteSet)
  104. if added || err == nil {
  105. t.Errorf("expected VoteSet.Add to fail, wrong type")
  106. }
  107. }
  108. }
  109. func TestVoteSet_2_3Majority(t *testing.T) {
  110. height, round := int64(1), int32(0)
  111. voteSet, _, privValidators := randVoteSet(height, round, tmproto.PrevoteType, 10, 1)
  112. voteProto := &Vote{
  113. ValidatorAddress: nil, // NOTE: must fill in
  114. ValidatorIndex: -1, // NOTE: must fill in
  115. Height: height,
  116. Round: round,
  117. Type: tmproto.PrevoteType,
  118. Timestamp: tmtime.Now(),
  119. BlockID: BlockID{nil, PartSetHeader{}},
  120. }
  121. // 6 out of 10 voted for nil.
  122. for i := int32(0); i < 6; i++ {
  123. pubKey, err := privValidators[i].GetPubKey(context.Background())
  124. require.NoError(t, err)
  125. addr := pubKey.Address()
  126. vote := withValidator(voteProto, addr, i)
  127. _, err = signAddVote(privValidators[i], vote, voteSet)
  128. require.NoError(t, err)
  129. }
  130. blockID, ok := voteSet.TwoThirdsMajority()
  131. assert.False(t, ok || !blockID.IsZero(), "there should be no 2/3 majority")
  132. // 7th validator voted for some blockhash
  133. {
  134. pubKey, err := privValidators[6].GetPubKey(context.Background())
  135. require.NoError(t, err)
  136. addr := pubKey.Address()
  137. vote := withValidator(voteProto, addr, 6)
  138. _, err = signAddVote(privValidators[6], withBlockHash(vote, tmrand.Bytes(32)), voteSet)
  139. require.NoError(t, err)
  140. blockID, ok = voteSet.TwoThirdsMajority()
  141. assert.False(t, ok || !blockID.IsZero(), "there should be no 2/3 majority")
  142. }
  143. // 8th validator voted for nil.
  144. {
  145. pubKey, err := privValidators[7].GetPubKey(context.Background())
  146. require.NoError(t, err)
  147. addr := pubKey.Address()
  148. vote := withValidator(voteProto, addr, 7)
  149. _, err = signAddVote(privValidators[7], vote, voteSet)
  150. require.NoError(t, err)
  151. blockID, ok = voteSet.TwoThirdsMajority()
  152. assert.True(t, ok || blockID.IsZero(), "there should be 2/3 majority for nil")
  153. }
  154. }
  155. func TestVoteSet_2_3MajorityRedux(t *testing.T) {
  156. height, round := int64(1), int32(0)
  157. voteSet, _, privValidators := randVoteSet(height, round, tmproto.PrevoteType, 100, 1)
  158. blockHash := crypto.CRandBytes(32)
  159. blockPartsTotal := uint32(123)
  160. blockPartSetHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)}
  161. voteProto := &Vote{
  162. ValidatorAddress: nil, // NOTE: must fill in
  163. ValidatorIndex: -1, // NOTE: must fill in
  164. Height: height,
  165. Round: round,
  166. Timestamp: tmtime.Now(),
  167. Type: tmproto.PrevoteType,
  168. BlockID: BlockID{blockHash, blockPartSetHeader},
  169. }
  170. // 66 out of 100 voted for nil.
  171. for i := int32(0); i < 66; i++ {
  172. pubKey, err := privValidators[i].GetPubKey(context.Background())
  173. require.NoError(t, err)
  174. addr := pubKey.Address()
  175. vote := withValidator(voteProto, addr, i)
  176. _, err = signAddVote(privValidators[i], vote, voteSet)
  177. require.NoError(t, err)
  178. }
  179. blockID, ok := voteSet.TwoThirdsMajority()
  180. assert.False(t, ok || !blockID.IsZero(),
  181. "there should be no 2/3 majority")
  182. // 67th validator voted for nil
  183. {
  184. pubKey, err := privValidators[66].GetPubKey(context.Background())
  185. require.NoError(t, err)
  186. adrr := pubKey.Address()
  187. vote := withValidator(voteProto, adrr, 66)
  188. _, err = signAddVote(privValidators[66], withBlockHash(vote, nil), voteSet)
  189. require.NoError(t, err)
  190. blockID, ok = voteSet.TwoThirdsMajority()
  191. assert.False(t, ok || !blockID.IsZero(),
  192. "there should be no 2/3 majority: last vote added was nil")
  193. }
  194. // 68th validator voted for a different BlockParts PartSetHeader
  195. {
  196. pubKey, err := privValidators[67].GetPubKey(context.Background())
  197. require.NoError(t, err)
  198. addr := pubKey.Address()
  199. vote := withValidator(voteProto, addr, 67)
  200. blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)}
  201. _, err = signAddVote(privValidators[67], withBlockPartSetHeader(vote, blockPartsHeader), voteSet)
  202. require.NoError(t, err)
  203. blockID, ok = voteSet.TwoThirdsMajority()
  204. assert.False(t, ok || !blockID.IsZero(),
  205. "there should be no 2/3 majority: last vote added had different PartSetHeader Hash")
  206. }
  207. // 69th validator voted for different BlockParts Total
  208. {
  209. pubKey, err := privValidators[68].GetPubKey(context.Background())
  210. require.NoError(t, err)
  211. addr := pubKey.Address()
  212. vote := withValidator(voteProto, addr, 68)
  213. blockPartsHeader := PartSetHeader{blockPartsTotal + 1, blockPartSetHeader.Hash}
  214. _, err = signAddVote(privValidators[68], withBlockPartSetHeader(vote, blockPartsHeader), voteSet)
  215. require.NoError(t, err)
  216. blockID, ok = voteSet.TwoThirdsMajority()
  217. assert.False(t, ok || !blockID.IsZero(),
  218. "there should be no 2/3 majority: last vote added had different PartSetHeader Total")
  219. }
  220. // 70th validator voted for different BlockHash
  221. {
  222. pubKey, err := privValidators[69].GetPubKey(context.Background())
  223. require.NoError(t, err)
  224. addr := pubKey.Address()
  225. vote := withValidator(voteProto, addr, 69)
  226. _, err = signAddVote(privValidators[69], withBlockHash(vote, tmrand.Bytes(32)), voteSet)
  227. require.NoError(t, err)
  228. blockID, ok = voteSet.TwoThirdsMajority()
  229. assert.False(t, ok || !blockID.IsZero(),
  230. "there should be no 2/3 majority: last vote added had different BlockHash")
  231. }
  232. // 71st validator voted for the right BlockHash & BlockPartSetHeader
  233. {
  234. pubKey, err := privValidators[70].GetPubKey(context.Background())
  235. require.NoError(t, err)
  236. addr := pubKey.Address()
  237. vote := withValidator(voteProto, addr, 70)
  238. _, err = signAddVote(privValidators[70], vote, voteSet)
  239. require.NoError(t, err)
  240. blockID, ok = voteSet.TwoThirdsMajority()
  241. assert.True(t, ok && blockID.Equals(BlockID{blockHash, blockPartSetHeader}),
  242. "there should be 2/3 majority")
  243. }
  244. }
  245. func TestVoteSet_Conflicts(t *testing.T) {
  246. height, round := int64(1), int32(0)
  247. voteSet, _, privValidators := randVoteSet(height, round, tmproto.PrevoteType, 4, 1)
  248. blockHash1 := tmrand.Bytes(32)
  249. blockHash2 := tmrand.Bytes(32)
  250. voteProto := &Vote{
  251. ValidatorAddress: nil,
  252. ValidatorIndex: -1,
  253. Height: height,
  254. Round: round,
  255. Timestamp: tmtime.Now(),
  256. Type: tmproto.PrevoteType,
  257. BlockID: BlockID{nil, PartSetHeader{}},
  258. }
  259. val0, err := privValidators[0].GetPubKey(context.Background())
  260. require.NoError(t, err)
  261. val0Addr := val0.Address()
  262. // val0 votes for nil.
  263. {
  264. vote := withValidator(voteProto, val0Addr, 0)
  265. added, err := signAddVote(privValidators[0], vote, voteSet)
  266. if !added || err != nil {
  267. t.Errorf("expected VoteSet.Add to succeed")
  268. }
  269. }
  270. // val0 votes again for blockHash1.
  271. {
  272. vote := withValidator(voteProto, val0Addr, 0)
  273. added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash1), voteSet)
  274. assert.False(t, added, "conflicting vote")
  275. assert.Error(t, err, "conflicting vote")
  276. }
  277. // start tracking blockHash1
  278. err = voteSet.SetPeerMaj23("peerA", BlockID{blockHash1, PartSetHeader{}})
  279. require.NoError(t, err)
  280. // val0 votes again for blockHash1.
  281. {
  282. vote := withValidator(voteProto, val0Addr, 0)
  283. added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash1), voteSet)
  284. assert.True(t, added, "called SetPeerMaj23()")
  285. assert.Error(t, err, "conflicting vote")
  286. }
  287. // attempt tracking blockHash2, should fail because already set for peerA.
  288. err = voteSet.SetPeerMaj23("peerA", BlockID{blockHash2, PartSetHeader{}})
  289. require.Error(t, err)
  290. // val0 votes again for blockHash1.
  291. {
  292. vote := withValidator(voteProto, val0Addr, 0)
  293. added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash2), voteSet)
  294. assert.False(t, added, "duplicate SetPeerMaj23() from peerA")
  295. assert.Error(t, err, "conflicting vote")
  296. }
  297. // val1 votes for blockHash1.
  298. {
  299. pv, err := privValidators[1].GetPubKey(context.Background())
  300. assert.NoError(t, err)
  301. addr := pv.Address()
  302. vote := withValidator(voteProto, addr, 1)
  303. added, err := signAddVote(privValidators[1], withBlockHash(vote, blockHash1), voteSet)
  304. if !added || err != nil {
  305. t.Errorf("expected VoteSet.Add to succeed")
  306. }
  307. }
  308. // check
  309. if voteSet.HasTwoThirdsMajority() {
  310. t.Errorf("we shouldn't have 2/3 majority yet")
  311. }
  312. if voteSet.HasTwoThirdsAny() {
  313. t.Errorf("we shouldn't have 2/3 if any votes yet")
  314. }
  315. // val2 votes for blockHash2.
  316. {
  317. pv, err := privValidators[2].GetPubKey(context.Background())
  318. assert.NoError(t, err)
  319. addr := pv.Address()
  320. vote := withValidator(voteProto, addr, 2)
  321. added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash2), voteSet)
  322. if !added || err != nil {
  323. t.Errorf("expected VoteSet.Add to succeed")
  324. }
  325. }
  326. // check
  327. if voteSet.HasTwoThirdsMajority() {
  328. t.Errorf("we shouldn't have 2/3 majority yet")
  329. }
  330. if !voteSet.HasTwoThirdsAny() {
  331. t.Errorf("we should have 2/3 if any votes")
  332. }
  333. // now attempt tracking blockHash1
  334. err = voteSet.SetPeerMaj23("peerB", BlockID{blockHash1, PartSetHeader{}})
  335. require.NoError(t, err)
  336. // val2 votes for blockHash1.
  337. {
  338. pv, err := privValidators[2].GetPubKey(context.Background())
  339. assert.NoError(t, err)
  340. addr := pv.Address()
  341. vote := withValidator(voteProto, addr, 2)
  342. added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash1), voteSet)
  343. assert.True(t, added)
  344. assert.Error(t, err, "conflicting vote")
  345. }
  346. // check
  347. if !voteSet.HasTwoThirdsMajority() {
  348. t.Errorf("we should have 2/3 majority for blockHash1")
  349. }
  350. blockIDMaj23, _ := voteSet.TwoThirdsMajority()
  351. if !bytes.Equal(blockIDMaj23.Hash, blockHash1) {
  352. t.Errorf("got the wrong 2/3 majority blockhash")
  353. }
  354. if !voteSet.HasTwoThirdsAny() {
  355. t.Errorf("we should have 2/3 if any votes")
  356. }
  357. }
  358. func TestVoteSet_MakeCommit(t *testing.T) {
  359. height, round := int64(1), int32(0)
  360. voteSet, _, privValidators := randVoteSet(height, round, tmproto.PrecommitType, 10, 1)
  361. blockHash, blockPartSetHeader := crypto.CRandBytes(32), PartSetHeader{123, crypto.CRandBytes(32)}
  362. voteProto := &Vote{
  363. ValidatorAddress: nil,
  364. ValidatorIndex: -1,
  365. Height: height,
  366. Round: round,
  367. Timestamp: tmtime.Now(),
  368. Type: tmproto.PrecommitType,
  369. BlockID: BlockID{blockHash, blockPartSetHeader},
  370. }
  371. // 6 out of 10 voted for some block.
  372. for i := int32(0); i < 6; i++ {
  373. pv, err := privValidators[i].GetPubKey(context.Background())
  374. assert.NoError(t, err)
  375. addr := pv.Address()
  376. vote := withValidator(voteProto, addr, i)
  377. _, err = signAddVote(privValidators[i], vote, voteSet)
  378. if err != nil {
  379. t.Error(err)
  380. }
  381. }
  382. // MakeCommit should fail.
  383. assert.Panics(t, func() { voteSet.MakeCommit() }, "Doesn't have +2/3 majority")
  384. // 7th voted for some other block.
  385. {
  386. pv, err := privValidators[6].GetPubKey(context.Background())
  387. assert.NoError(t, err)
  388. addr := pv.Address()
  389. vote := withValidator(voteProto, addr, 6)
  390. vote = withBlockHash(vote, tmrand.Bytes(32))
  391. vote = withBlockPartSetHeader(vote, PartSetHeader{123, tmrand.Bytes(32)})
  392. _, err = signAddVote(privValidators[6], vote, voteSet)
  393. require.NoError(t, err)
  394. }
  395. // The 8th voted like everyone else.
  396. {
  397. pv, err := privValidators[7].GetPubKey(context.Background())
  398. assert.NoError(t, err)
  399. addr := pv.Address()
  400. vote := withValidator(voteProto, addr, 7)
  401. _, err = signAddVote(privValidators[7], vote, voteSet)
  402. require.NoError(t, err)
  403. }
  404. // The 9th voted for nil.
  405. {
  406. pv, err := privValidators[8].GetPubKey(context.Background())
  407. assert.NoError(t, err)
  408. addr := pv.Address()
  409. vote := withValidator(voteProto, addr, 8)
  410. vote.BlockID = BlockID{}
  411. _, err = signAddVote(privValidators[8], vote, voteSet)
  412. require.NoError(t, err)
  413. }
  414. commit := voteSet.MakeCommit()
  415. // Commit should have 10 elements
  416. assert.Equal(t, 10, len(commit.Signatures))
  417. // Ensure that Commit is good.
  418. if err := commit.ValidateBasic(); err != nil {
  419. t.Errorf("error in Commit.ValidateBasic(): %v", err)
  420. }
  421. }
  422. // NOTE: privValidators are in order
  423. func randVoteSet(
  424. height int64,
  425. round int32,
  426. signedMsgType tmproto.SignedMsgType,
  427. numValidators int,
  428. votingPower int64,
  429. ) (*VoteSet, *ValidatorSet, []PrivValidator) {
  430. valSet, privValidators := randValidatorPrivValSet(numValidators, votingPower)
  431. return NewVoteSet("test_chain_id", height, round, signedMsgType, valSet), valSet, privValidators
  432. }
  433. func deterministicVoteSet(
  434. ctx context.Context,
  435. height int64,
  436. round int32,
  437. signedMsgType tmproto.SignedMsgType,
  438. votingPower int64,
  439. ) (*VoteSet, *ValidatorSet, []PrivValidator) {
  440. valSet, privValidators := deterministicValidatorSet(ctx)
  441. return NewVoteSet("test_chain_id", height, round, signedMsgType, valSet), valSet, privValidators
  442. }
  443. func randValidatorPrivValSet(numValidators int, votingPower int64) (*ValidatorSet, []PrivValidator) {
  444. var (
  445. valz = make([]*Validator, numValidators)
  446. privValidators = make([]PrivValidator, numValidators)
  447. )
  448. for i := 0; i < numValidators; i++ {
  449. val, privValidator := randValidator(false, votingPower)
  450. valz[i] = val
  451. privValidators[i] = privValidator
  452. }
  453. sort.Sort(PrivValidatorsByAddress(privValidators))
  454. return NewValidatorSet(valz), privValidators
  455. }
  456. // Convenience: Return new vote with different validator address/index
  457. func withValidator(vote *Vote, addr []byte, idx int32) *Vote {
  458. vote = vote.Copy()
  459. vote.ValidatorAddress = addr
  460. vote.ValidatorIndex = idx
  461. return vote
  462. }
  463. // Convenience: Return new vote with different height
  464. func withHeight(vote *Vote, height int64) *Vote {
  465. vote = vote.Copy()
  466. vote.Height = height
  467. return vote
  468. }
  469. // Convenience: Return new vote with different round
  470. func withRound(vote *Vote, round int32) *Vote {
  471. vote = vote.Copy()
  472. vote.Round = round
  473. return vote
  474. }
  475. // Convenience: Return new vote with different type
  476. func withType(vote *Vote, signedMsgType byte) *Vote {
  477. vote = vote.Copy()
  478. vote.Type = tmproto.SignedMsgType(signedMsgType)
  479. return vote
  480. }
  481. // Convenience: Return new vote with different blockHash
  482. func withBlockHash(vote *Vote, blockHash []byte) *Vote {
  483. vote = vote.Copy()
  484. vote.BlockID.Hash = blockHash
  485. return vote
  486. }
  487. // Convenience: Return new vote with different blockParts
  488. func withBlockPartSetHeader(vote *Vote, blockPartsHeader PartSetHeader) *Vote {
  489. vote = vote.Copy()
  490. vote.BlockID.PartSetHeader = blockPartsHeader
  491. return vote
  492. }