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.

733 lines
25 KiB

max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), AppHash: tmhash.Sum([]byte("app_hash")), LastResultsHash: tmhash.Sum([]byte("last_results_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: tmhash.Sum([]byte("proposer_address")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
  1. package types
  2. import (
  3. "math"
  4. "testing"
  5. "time"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/require"
  8. "github.com/tendermint/tendermint/crypto"
  9. "github.com/tendermint/tendermint/crypto/ed25519"
  10. "github.com/tendermint/tendermint/crypto/tmhash"
  11. tmrand "github.com/tendermint/tendermint/libs/rand"
  12. tmproto "github.com/tendermint/tendermint/proto/types"
  13. )
  14. type voteData struct {
  15. vote1 *Vote
  16. vote2 *Vote
  17. valid bool
  18. }
  19. var defaultVoteTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
  20. func TestEvidence(t *testing.T) {
  21. val := NewMockPV()
  22. val2 := NewMockPV()
  23. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  24. blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
  25. blockID3 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash"))
  26. blockID4 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash2"))
  27. const chainID = "mychain"
  28. vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime)
  29. v1 := vote1.ToProto()
  30. err := val.SignVote(chainID, v1)
  31. require.NoError(t, err)
  32. badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime)
  33. bv := badVote.ToProto()
  34. err = val2.SignVote(chainID, bv)
  35. require.NoError(t, err)
  36. vote1.Signature = v1.Signature
  37. badVote.Signature = bv.Signature
  38. cases := []voteData{
  39. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, defaultVoteTime), true}, // different block ids
  40. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3, defaultVoteTime), true},
  41. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID4, defaultVoteTime), true},
  42. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime), false}, // wrong block id
  43. {vote1, makeVote(t, val, "mychain2", 0, 10, 2, 1, blockID2, defaultVoteTime), false}, // wrong chain id
  44. {vote1, makeVote(t, val, chainID, 1, 10, 2, 1, blockID2, defaultVoteTime), false}, // wrong val index
  45. {vote1, makeVote(t, val, chainID, 0, 11, 2, 1, blockID2, defaultVoteTime), false}, // wrong height
  46. {vote1, makeVote(t, val, chainID, 0, 10, 3, 1, blockID2, defaultVoteTime), false}, // wrong round
  47. {vote1, makeVote(t, val, chainID, 0, 10, 2, 2, blockID2, defaultVoteTime), false}, // wrong step
  48. {vote1, makeVote(t, val2, chainID, 0, 10, 2, 1, blockID, defaultVoteTime), false}, // wrong validator
  49. {vote1, makeVote(t, val2, chainID, 0, 10, 2, 1, blockID, time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)), false},
  50. {vote1, badVote, false}, // signed by wrong key
  51. }
  52. pubKey, err := val.GetPubKey()
  53. require.NoError(t, err)
  54. for _, c := range cases {
  55. ev := &DuplicateVoteEvidence{
  56. VoteA: c.vote1,
  57. VoteB: c.vote2,
  58. }
  59. if c.valid {
  60. assert.Nil(t, ev.Verify(chainID, pubKey), "evidence should be valid")
  61. } else {
  62. assert.NotNil(t, ev.Verify(chainID, pubKey), "evidence should be invalid")
  63. }
  64. }
  65. }
  66. func TestDuplicatedVoteEvidence(t *testing.T) {
  67. ev := randomDuplicatedVoteEvidence(t)
  68. assert.True(t, ev.Equal(ev))
  69. assert.False(t, ev.Equal(&DuplicateVoteEvidence{}))
  70. }
  71. func TestEvidenceList(t *testing.T) {
  72. ev := randomDuplicatedVoteEvidence(t)
  73. evl := EvidenceList([]Evidence{ev})
  74. assert.NotNil(t, evl.Hash())
  75. assert.True(t, evl.Has(ev))
  76. assert.False(t, evl.Has(&DuplicateVoteEvidence{}))
  77. }
  78. func TestMaxEvidenceBytes(t *testing.T) {
  79. val := NewMockPV()
  80. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  81. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  82. maxTime := time.Date(9999, 0, 0, 0, 0, 0, 0, time.UTC)
  83. const chainID = "mychain"
  84. ev := &DuplicateVoteEvidence{
  85. VoteA: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, math.MaxInt64, blockID, maxTime),
  86. VoteB: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, math.MaxInt64, blockID2, maxTime),
  87. }
  88. //TODO: Add other types of evidence to test and set MaxEvidenceBytes accordingly
  89. // evl := &LunaticValidatorEvidence{
  90. // Header: makeHeaderRandom(),
  91. // Vote: makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
  92. // InvalidHeaderField: "",
  93. // }
  94. // evp := &PhantomValidatorEvidence{
  95. // Header: makeHeaderRandom(),
  96. // Vote: makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
  97. // LastHeightValidatorWasInSet: math.MaxInt64,
  98. // }
  99. // signedHeader := SignedHeader{Header: makeHeaderRandom(), Commit: randCommit(time.Now())}
  100. // evc := &ConflictingHeadersEvidence{
  101. // H1: &signedHeader,
  102. // H2: &signedHeader,
  103. // }
  104. testCases := []struct {
  105. testName string
  106. evidence Evidence
  107. }{
  108. {"DuplicateVote", ev},
  109. // {"LunaticValidatorEvidence", evl},
  110. // {"PhantomValidatorEvidence", evp},
  111. // {"ConflictingHeadersEvidence", evc},
  112. }
  113. for _, tt := range testCases {
  114. pb, err := EvidenceToProto(tt.evidence)
  115. require.NoError(t, err, tt.testName)
  116. bz, err := pb.Marshal()
  117. require.NoError(t, err, tt.testName)
  118. assert.LessOrEqual(t, int64(len(bz)), MaxEvidenceBytes, tt.testName)
  119. }
  120. }
  121. func randomDuplicatedVoteEvidence(t *testing.T) *DuplicateVoteEvidence {
  122. val := NewMockPV()
  123. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  124. blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
  125. const chainID = "mychain"
  126. return &DuplicateVoteEvidence{
  127. VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime),
  128. VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, defaultVoteTime),
  129. }
  130. }
  131. func TestDuplicateVoteEvidenceValidation(t *testing.T) {
  132. val := NewMockPV()
  133. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  134. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  135. const chainID = "mychain"
  136. testCases := []struct {
  137. testName string
  138. malleateEvidence func(*DuplicateVoteEvidence)
  139. expectErr bool
  140. }{
  141. {"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false},
  142. {"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true},
  143. {"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true},
  144. {"Nil votes", func(ev *DuplicateVoteEvidence) {
  145. ev.VoteA = nil
  146. ev.VoteB = nil
  147. }, true},
  148. {"Invalid vote type", func(ev *DuplicateVoteEvidence) {
  149. ev.VoteA = makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0, blockID2, defaultVoteTime)
  150. }, true},
  151. {"Invalid vote order", func(ev *DuplicateVoteEvidence) {
  152. swap := ev.VoteA.Copy()
  153. ev.VoteA = ev.VoteB.Copy()
  154. ev.VoteB = swap
  155. }, true},
  156. }
  157. for _, tc := range testCases {
  158. tc := tc
  159. t.Run(tc.testName, func(t *testing.T) {
  160. vote1 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID, defaultVoteTime)
  161. vote2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID2, defaultVoteTime)
  162. ev := NewDuplicateVoteEvidence(vote1, vote2)
  163. tc.malleateEvidence(ev)
  164. assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  165. })
  166. }
  167. }
  168. func TestMockGoodEvidenceValidateBasic(t *testing.T) {
  169. goodEvidence := NewMockEvidence(int64(1), time.Now(), []byte{1})
  170. assert.Nil(t, goodEvidence.ValidateBasic())
  171. }
  172. func TestMockBadEvidenceValidateBasic(t *testing.T) {
  173. badEvidence := NewMockEvidence(int64(1), time.Now(), []byte{1})
  174. assert.Nil(t, badEvidence.ValidateBasic())
  175. }
  176. func TestLunaticValidatorEvidence(t *testing.T) {
  177. var (
  178. blockID = makeBlockIDRandom()
  179. header = makeHeaderRandom()
  180. bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
  181. val = NewMockPV()
  182. vote = makeVote(t, val, header.ChainID, 0, header.Height, 0, 2, blockID, defaultVoteTime)
  183. )
  184. header.Time = bTime
  185. ev := &LunaticValidatorEvidence{
  186. Header: header,
  187. Vote: vote,
  188. InvalidHeaderField: "AppHash",
  189. }
  190. assert.Equal(t, header.Height, ev.Height())
  191. assert.Equal(t, bTime, ev.Time())
  192. assert.EqualValues(t, vote.ValidatorAddress, ev.Address())
  193. assert.NotEmpty(t, ev.Hash())
  194. assert.NotEmpty(t, ev.Bytes())
  195. pubKey, err := val.GetPubKey()
  196. require.NoError(t, err)
  197. assert.NoError(t, ev.Verify(header.ChainID, pubKey))
  198. assert.Error(t, ev.Verify("other", pubKey))
  199. privKey2 := ed25519.GenPrivKey()
  200. pubKey2 := privKey2.PubKey()
  201. assert.Error(t, ev.Verify("other", pubKey2))
  202. assert.True(t, ev.Equal(ev))
  203. assert.NoError(t, ev.ValidateBasic())
  204. assert.NotEmpty(t, ev.String())
  205. }
  206. func TestPhantomValidatorEvidence(t *testing.T) {
  207. var (
  208. blockID = makeBlockIDRandom()
  209. header = makeHeaderRandom()
  210. val = NewMockPV()
  211. vote = makeVote(t, val, header.ChainID, 0, header.Height, 0, 2, blockID, defaultVoteTime)
  212. )
  213. ev := &PhantomValidatorEvidence{
  214. Vote: vote,
  215. LastHeightValidatorWasInSet: header.Height - 1,
  216. }
  217. assert.Equal(t, header.Height, ev.Height())
  218. assert.Equal(t, defaultVoteTime, ev.Time())
  219. assert.EqualValues(t, vote.ValidatorAddress, ev.Address())
  220. assert.NotEmpty(t, ev.Hash())
  221. assert.NotEmpty(t, ev.Bytes())
  222. pubKey, err := val.GetPubKey()
  223. require.NoError(t, err)
  224. assert.NoError(t, ev.Verify(header.ChainID, pubKey))
  225. assert.Error(t, ev.Verify("other", pubKey))
  226. privKey2 := ed25519.GenPrivKey()
  227. pubKey2 := privKey2.PubKey()
  228. assert.Error(t, ev.Verify("other", pubKey2))
  229. assert.True(t, ev.Equal(ev))
  230. assert.NoError(t, ev.ValidateBasic())
  231. assert.NotEmpty(t, ev.String())
  232. }
  233. func TestConflictingHeadersEvidence(t *testing.T) {
  234. const (
  235. chainID = "TestConflictingHeadersEvidence"
  236. height int64 = 37
  237. )
  238. var (
  239. blockID = makeBlockIDRandom()
  240. header1 = makeHeaderRandom()
  241. header2 = makeHeaderRandom()
  242. )
  243. header1.Height = height
  244. header1.LastBlockID = blockID
  245. header1.ChainID = chainID
  246. header2.Height = height
  247. header2.LastBlockID = blockID
  248. header2.ChainID = chainID
  249. voteSet1, valSet, vals := randVoteSet(height, 1, tmproto.PrecommitType, 10, 1)
  250. voteSet2 := NewVoteSet(chainID, height, 1, tmproto.PrecommitType, valSet)
  251. commit1, err := MakeCommit(BlockID{
  252. Hash: header1.Hash(),
  253. PartsHeader: PartSetHeader{
  254. Total: 100,
  255. Hash: crypto.CRandBytes(tmhash.Size),
  256. },
  257. }, height, 1, voteSet1, vals, time.Now())
  258. require.NoError(t, err)
  259. commit2, err := MakeCommit(BlockID{
  260. Hash: header2.Hash(),
  261. PartsHeader: PartSetHeader{
  262. Total: 100,
  263. Hash: crypto.CRandBytes(tmhash.Size),
  264. },
  265. }, height, 1, voteSet2, vals, time.Now())
  266. require.NoError(t, err)
  267. ev := &ConflictingHeadersEvidence{
  268. H1: &SignedHeader{
  269. Header: header1,
  270. Commit: commit1,
  271. },
  272. H2: &SignedHeader{
  273. Header: header2,
  274. Commit: commit2,
  275. },
  276. }
  277. assert.Panics(t, func() {
  278. ev.Address()
  279. })
  280. assert.Panics(t, func() {
  281. pubKey, _ := vals[0].GetPubKey()
  282. ev.Verify(chainID, pubKey)
  283. })
  284. assert.Equal(t, height, ev.Height())
  285. // assert.Equal(t, bTime, ev.Time())
  286. assert.NotEmpty(t, ev.Hash())
  287. assert.NotEmpty(t, ev.Bytes())
  288. assert.NoError(t, ev.VerifyComposite(header1, valSet))
  289. assert.True(t, ev.Equal(ev))
  290. assert.NoError(t, ev.ValidateBasic())
  291. assert.NotEmpty(t, ev.String())
  292. }
  293. func TestPotentialAmnesiaEvidence(t *testing.T) {
  294. const (
  295. chainID = "TestPotentialAmnesiaEvidence"
  296. height int64 = 37
  297. )
  298. var (
  299. val = NewMockPV()
  300. blockID = makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  301. blockID2 = makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  302. vote1 = makeVote(t, val, chainID, 0, height, 0, 2, blockID, defaultVoteTime)
  303. vote2 = makeVote(t, val, chainID, 0, height, 1, 2, blockID2, defaultVoteTime)
  304. )
  305. ev := &PotentialAmnesiaEvidence{
  306. VoteA: vote1,
  307. VoteB: vote2,
  308. }
  309. assert.Equal(t, height, ev.Height())
  310. // assert.Equal(t, bTime, ev.Time())
  311. assert.EqualValues(t, vote1.ValidatorAddress, ev.Address())
  312. assert.NotEmpty(t, ev.Hash())
  313. assert.NotEmpty(t, ev.Bytes())
  314. pubKey, err := val.GetPubKey()
  315. require.NoError(t, err)
  316. assert.NoError(t, ev.Verify(chainID, pubKey))
  317. assert.Error(t, ev.Verify("other", pubKey))
  318. privKey2 := ed25519.GenPrivKey()
  319. pubKey2 := privKey2.PubKey()
  320. assert.Error(t, ev.Verify("other", pubKey2))
  321. assert.True(t, ev.Equal(ev))
  322. assert.NoError(t, ev.ValidateBasic())
  323. assert.NotEmpty(t, ev.String())
  324. }
  325. func TestProofOfLockChange(t *testing.T) {
  326. const (
  327. chainID = "test_chain_id"
  328. height int64 = 37
  329. )
  330. // 1: valid POLC - nothing should fail
  331. voteSet, valSet, privValidators, blockID := buildVoteSet(height, 1, 3, 7, 0, tmproto.PrecommitType)
  332. pubKey, err := privValidators[7].GetPubKey()
  333. require.NoError(t, err)
  334. polc := makePOLCFromVoteSet(voteSet, pubKey, blockID)
  335. assert.Equal(t, height, polc.Height())
  336. assert.NoError(t, polc.ValidateBasic())
  337. assert.NoError(t, polc.ValidateVotes(valSet, chainID))
  338. assert.NotEmpty(t, polc.String())
  339. // tamper with one of the votes
  340. polc.Votes[0].Timestamp = time.Now().Add(1 * time.Second)
  341. err = polc.ValidateVotes(valSet, chainID)
  342. t.Log(err)
  343. assert.Error(t, err)
  344. // remove a vote such that majority wasn't reached
  345. polc.Votes = polc.Votes[1:]
  346. err = polc.ValidateVotes(valSet, chainID)
  347. t.Log(err)
  348. assert.Error(t, err)
  349. // test validate basic on a set of bad cases
  350. var badPOLCs []ProofOfLockChange
  351. // 2: node has already voted in next round
  352. pubKey, err = privValidators[0].GetPubKey()
  353. require.NoError(t, err)
  354. polc2 := makePOLCFromVoteSet(voteSet, pubKey, blockID)
  355. badPOLCs = append(badPOLCs, polc2)
  356. // 3: one vote was from a different round
  357. voteSet, _, privValidators, blockID = buildVoteSet(height, 1, 3, 7, 0, tmproto.PrecommitType)
  358. pubKey, err = privValidators[7].GetPubKey()
  359. require.NoError(t, err)
  360. polc = makePOLCFromVoteSet(voteSet, pubKey, blockID)
  361. badVote := makeVote(t, privValidators[8], chainID, 8, height, 2, 2, blockID, defaultVoteTime)
  362. polc.Votes = append(polc.Votes, *badVote)
  363. badPOLCs = append(badPOLCs, polc)
  364. // 4: one vote was from a different height
  365. polc = makePOLCFromVoteSet(voteSet, pubKey, blockID)
  366. badVote = makeVote(t, privValidators[8], chainID, 8, height+1, 1, 2, blockID, defaultVoteTime)
  367. polc.Votes = append(polc.Votes, *badVote)
  368. badPOLCs = append(badPOLCs, polc)
  369. // 5: one vote was from a different vote type
  370. polc = makePOLCFromVoteSet(voteSet, pubKey, blockID)
  371. badVote = makeVote(t, privValidators[8], chainID, 8, height, 1, 1, blockID, defaultVoteTime)
  372. polc.Votes = append(polc.Votes, *badVote)
  373. badPOLCs = append(badPOLCs, polc)
  374. // 5: one of the votes was for a nil block
  375. polc = makePOLCFromVoteSet(voteSet, pubKey, blockID)
  376. badVote = makeVote(t, privValidators[8], chainID, 8, height, 1, 2, BlockID{}, defaultVoteTime)
  377. polc.Votes = append(polc.Votes, *badVote)
  378. badPOLCs = append(badPOLCs, polc)
  379. for idx, polc := range badPOLCs {
  380. err := polc.ValidateBasic()
  381. t.Logf("case: %d: %v", idx+2, err)
  382. assert.Error(t, err)
  383. if err == nil {
  384. t.Errorf("test no. %d failed", idx+2)
  385. }
  386. }
  387. }
  388. func TestAmnesiaEvidence(t *testing.T) {
  389. const (
  390. chainID = "test_chain_id"
  391. height int64 = 37
  392. )
  393. voteSet, valSet, privValidators, blockID := buildVoteSet(height, 1, 2, 7, 0, tmproto.PrecommitType)
  394. var (
  395. val = privValidators[7]
  396. pubKey, _ = val.GetPubKey()
  397. blockID2 = makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  398. vote1 = makeVote(t, val, chainID, 7, height, 0, 2, blockID2, time.Now())
  399. vote2 = makeVote(t, val, chainID, 7, height, 1, 2, blockID,
  400. time.Now().Add(time.Second))
  401. vote3 = makeVote(t, val, chainID, 7, height, 2, 2, blockID2, time.Now())
  402. polc = makePOLCFromVoteSet(voteSet, pubKey, blockID)
  403. )
  404. require.False(t, polc.IsAbsent())
  405. pe := PotentialAmnesiaEvidence{
  406. VoteA: vote1,
  407. VoteB: vote2,
  408. }
  409. emptyAmnesiaEvidence := MakeAmnesiaEvidence(pe, EmptyPOLC())
  410. assert.NoError(t, emptyAmnesiaEvidence.ValidateBasic())
  411. violated, reason := emptyAmnesiaEvidence.ViolatedConsensus()
  412. if assert.True(t, violated) {
  413. assert.Equal(t, reason, "no proof of lock was provided")
  414. }
  415. assert.NoError(t, emptyAmnesiaEvidence.Verify(chainID, pubKey))
  416. completeAmnesiaEvidence := MakeAmnesiaEvidence(pe, polc)
  417. assert.NoError(t, completeAmnesiaEvidence.ValidateBasic())
  418. violated, reason = completeAmnesiaEvidence.ViolatedConsensus()
  419. if !assert.False(t, violated) {
  420. t.Log(reason)
  421. }
  422. assert.NoError(t, completeAmnesiaEvidence.Verify(chainID, pubKey))
  423. assert.NoError(t, completeAmnesiaEvidence.Polc.ValidateVotes(valSet, chainID))
  424. assert.True(t, completeAmnesiaEvidence.Equal(emptyAmnesiaEvidence))
  425. assert.NotEmpty(t, completeAmnesiaEvidence.Hash())
  426. assert.NotEmpty(t, completeAmnesiaEvidence.Bytes())
  427. pe2 := PotentialAmnesiaEvidence{
  428. VoteA: vote3,
  429. VoteB: vote2,
  430. }
  431. // validator has incorrectly voted for a previous round after voting for a later round
  432. ae := MakeAmnesiaEvidence(pe2, EmptyPOLC())
  433. assert.NoError(t, ae.ValidateBasic())
  434. violated, reason = ae.ViolatedConsensus()
  435. if assert.True(t, violated) {
  436. assert.Equal(t, reason, "validator went back and voted on a previous round")
  437. }
  438. var badAE []AmnesiaEvidence
  439. // 1) Polc is at an incorrect height
  440. voteSet, _, _ = buildVoteSetForBlock(height+1, 1, 2, 7, 0, tmproto.PrecommitType, blockID)
  441. polc = makePOLCFromVoteSet(voteSet, pubKey, blockID)
  442. badAE = append(badAE, MakeAmnesiaEvidence(pe, polc))
  443. // 2) Polc is of a later round
  444. voteSet, _, _ = buildVoteSetForBlock(height, 2, 2, 7, 0, tmproto.PrecommitType, blockID)
  445. polc = makePOLCFromVoteSet(voteSet, pubKey, blockID)
  446. badAE = append(badAE, MakeAmnesiaEvidence(pe, polc))
  447. // 3) Polc has a different public key
  448. voteSet, _, privValidators = buildVoteSetForBlock(height, 1, 2, 7, 0, tmproto.PrecommitType, blockID)
  449. pubKey2, _ := privValidators[7].GetPubKey()
  450. polc = makePOLCFromVoteSet(voteSet, pubKey2, blockID)
  451. badAE = append(badAE, MakeAmnesiaEvidence(pe, polc))
  452. // 4) Polc has a different block ID
  453. voteSet, _, _, blockID = buildVoteSet(height, 1, 2, 7, 0, tmproto.PrecommitType)
  454. polc = makePOLCFromVoteSet(voteSet, pubKey, blockID)
  455. badAE = append(badAE, MakeAmnesiaEvidence(pe, polc))
  456. for idx, ae := range badAE {
  457. t.Log(ae.ValidateBasic())
  458. if !assert.Error(t, ae.ValidateBasic()) {
  459. t.Errorf("test no. %d failed", idx+1)
  460. }
  461. }
  462. }
  463. func makeVote(
  464. t *testing.T, val PrivValidator, chainID string, valIndex int32, height int64, round int32, step int, blockID BlockID,
  465. time time.Time) *Vote {
  466. pubKey, err := val.GetPubKey()
  467. require.NoError(t, err)
  468. v := &Vote{
  469. ValidatorAddress: pubKey.Address(),
  470. ValidatorIndex: valIndex,
  471. Height: height,
  472. Round: round,
  473. Type: tmproto.SignedMsgType(step),
  474. BlockID: blockID,
  475. Timestamp: time,
  476. }
  477. vpb := v.ToProto()
  478. err = val.SignVote(chainID, vpb)
  479. if err != nil {
  480. panic(err)
  481. }
  482. v.Signature = vpb.Signature
  483. return v
  484. }
  485. func makeHeaderRandom() *Header {
  486. return &Header{
  487. ChainID: tmrand.Str(12),
  488. Height: int64(tmrand.Uint16()) + 1,
  489. Time: time.Now(),
  490. LastBlockID: makeBlockIDRandom(),
  491. LastCommitHash: crypto.CRandBytes(tmhash.Size),
  492. DataHash: crypto.CRandBytes(tmhash.Size),
  493. ValidatorsHash: crypto.CRandBytes(tmhash.Size),
  494. NextValidatorsHash: crypto.CRandBytes(tmhash.Size),
  495. ConsensusHash: crypto.CRandBytes(tmhash.Size),
  496. AppHash: crypto.CRandBytes(tmhash.Size),
  497. LastResultsHash: crypto.CRandBytes(tmhash.Size),
  498. EvidenceHash: crypto.CRandBytes(tmhash.Size),
  499. ProposerAddress: crypto.CRandBytes(crypto.AddressSize),
  500. }
  501. }
  502. func TestEvidenceProto(t *testing.T) {
  503. // -------- Votes --------
  504. val := NewMockPV()
  505. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  506. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  507. const chainID = "mychain"
  508. v := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 1, 0x01, blockID, defaultVoteTime)
  509. v2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 2, 0x01, blockID2, defaultVoteTime)
  510. // -------- SignedHeaders --------
  511. const height int64 = 37
  512. var (
  513. header1 = makeHeaderRandom()
  514. header2 = makeHeaderRandom()
  515. )
  516. header1.Height = height
  517. header1.LastBlockID = blockID
  518. header1.ChainID = chainID
  519. header2.Height = height
  520. header2.LastBlockID = blockID
  521. header2.ChainID = chainID
  522. voteSet1, valSet, vals := randVoteSet(height, 1, tmproto.PrecommitType, 10, 1)
  523. voteSet2 := NewVoteSet(chainID, height, 1, tmproto.PrecommitType, valSet)
  524. commit1, err := MakeCommit(BlockID{
  525. Hash: header1.Hash(),
  526. PartsHeader: PartSetHeader{
  527. Total: 100,
  528. Hash: crypto.CRandBytes(tmhash.Size),
  529. },
  530. }, height, 1, voteSet1, vals, time.Now())
  531. require.NoError(t, err)
  532. commit2, err := MakeCommit(BlockID{
  533. Hash: header2.Hash(),
  534. PartsHeader: PartSetHeader{
  535. Total: 100,
  536. Hash: crypto.CRandBytes(tmhash.Size),
  537. },
  538. }, height, 1, voteSet2, vals, time.Now())
  539. require.NoError(t, err)
  540. h1 := &SignedHeader{
  541. Header: header1,
  542. Commit: commit1,
  543. }
  544. h2 := &SignedHeader{
  545. Header: header2,
  546. Commit: commit2,
  547. }
  548. tests := []struct {
  549. testName string
  550. evidence Evidence
  551. wantErr bool
  552. wantErr2 bool
  553. }{
  554. {"&DuplicateVoteEvidence empty fail", &DuplicateVoteEvidence{}, false, true},
  555. {"&DuplicateVoteEvidence nil voteB", &DuplicateVoteEvidence{VoteA: v, VoteB: nil}, false, true},
  556. {"&DuplicateVoteEvidence nil voteA", &DuplicateVoteEvidence{VoteA: nil, VoteB: v}, false, true},
  557. {"&DuplicateVoteEvidence success", &DuplicateVoteEvidence{VoteA: v2, VoteB: v}, false, false},
  558. {"&ConflictingHeadersEvidence empty fail", &ConflictingHeadersEvidence{}, false, true},
  559. {"&ConflictingHeadersEvidence nil H2", &ConflictingHeadersEvidence{H1: h1, H2: nil}, false, true},
  560. {"&ConflictingHeadersEvidence nil H1", &ConflictingHeadersEvidence{H1: nil, H2: h2}, false, true},
  561. {"ConflictingHeadersEvidence empty fail", ConflictingHeadersEvidence{}, false, true},
  562. {"ConflictingHeadersEvidence nil H2", ConflictingHeadersEvidence{H1: h1, H2: nil}, false, true},
  563. {"ConflictingHeadersEvidence nil H1", ConflictingHeadersEvidence{H1: nil, H2: h2}, false, true},
  564. {"ConflictingHeadersEvidence success", ConflictingHeadersEvidence{H1: h1, H2: h2}, false, false},
  565. {"LunaticValidatorEvidence empty fail", LunaticValidatorEvidence{}, false, true},
  566. {"LunaticValidatorEvidence only header fail", LunaticValidatorEvidence{Header: header1}, false, true},
  567. {"LunaticValidatorEvidence only vote fail", LunaticValidatorEvidence{Vote: v}, false, true},
  568. {"LunaticValidatorEvidence header & vote fail", LunaticValidatorEvidence{Header: header1, Vote: v}, false, true},
  569. {"LunaticValidatorEvidence success", LunaticValidatorEvidence{Header: header1,
  570. Vote: v, InvalidHeaderField: "ValidatorsHash"}, false, true},
  571. {"&LunaticValidatorEvidence empty fail", &LunaticValidatorEvidence{}, false, true},
  572. {"LunaticValidatorEvidence only header fail", &LunaticValidatorEvidence{Header: header1}, false, true},
  573. {"LunaticValidatorEvidence only vote fail", &LunaticValidatorEvidence{Vote: v}, false, true},
  574. {"LunaticValidatorEvidence header & vote fail", &LunaticValidatorEvidence{Header: header1, Vote: v}, false, true},
  575. {"&LunaticValidatorEvidence empty fail", &LunaticValidatorEvidence{}, false, true},
  576. {"PotentialAmnesiaEvidence empty fail", PotentialAmnesiaEvidence{}, false, true},
  577. {"PotentialAmnesiaEvidence nil VoteB", PotentialAmnesiaEvidence{VoteA: v, VoteB: nil}, false, true},
  578. {"PotentialAmnesiaEvidence nil VoteA", PotentialAmnesiaEvidence{VoteA: nil, VoteB: v2}, false, true},
  579. {"&PotentialAmnesiaEvidence empty fail", &PotentialAmnesiaEvidence{}, false, true},
  580. {"&PotentialAmnesiaEvidence nil VoteB", &PotentialAmnesiaEvidence{VoteA: v, VoteB: nil}, false, true},
  581. {"&PotentialAmnesiaEvidence nil VoteA", &PotentialAmnesiaEvidence{VoteA: nil, VoteB: v2}, false, true},
  582. {"&PotentialAmnesiaEvidence success", &PotentialAmnesiaEvidence{VoteA: v2, VoteB: v}, false, false},
  583. {"&PhantomValidatorEvidence empty fail", &PhantomValidatorEvidence{}, false, true},
  584. {"&PhantomValidatorEvidence nil LastHeightValidatorWasInSet", &PhantomValidatorEvidence{Vote: v}, false, true},
  585. {"&PhantomValidatorEvidence nil Vote", &PhantomValidatorEvidence{LastHeightValidatorWasInSet: 2}, false, true},
  586. {"PhantomValidatorEvidence success", PhantomValidatorEvidence{Vote: v2, LastHeightValidatorWasInSet: 2},
  587. false, false},
  588. }
  589. for _, tt := range tests {
  590. tt := tt
  591. t.Run(tt.testName, func(t *testing.T) {
  592. pb, err := EvidenceToProto(tt.evidence)
  593. if tt.wantErr {
  594. assert.Error(t, err, tt.testName)
  595. return
  596. }
  597. assert.NoError(t, err, tt.testName)
  598. evi, err := EvidenceFromProto(pb)
  599. if tt.wantErr2 {
  600. assert.Error(t, err, tt.testName)
  601. return
  602. }
  603. require.Equal(t, tt.evidence, evi, tt.testName)
  604. })
  605. }
  606. }
  607. func TestProofOfLockChangeProtoBuf(t *testing.T) {
  608. // -------- Votes --------
  609. val := NewMockPV()
  610. val2 := NewMockPV()
  611. val3 := NewMockPV()
  612. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  613. const chainID = "mychain"
  614. v := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 1, 0x01, blockID, defaultVoteTime)
  615. v2 := makeVote(t, val2, chainID, math.MaxInt32, math.MaxInt64, 1, 0x01, blockID, defaultVoteTime)
  616. testCases := []struct {
  617. msg string
  618. polc ProofOfLockChange
  619. expErr bool
  620. expErr2 bool
  621. }{
  622. {"failure, empty key", ProofOfLockChange{Votes: []Vote{*v, *v2}}, true, true},
  623. {"failure, empty votes", ProofOfLockChange{PubKey: val3.PrivKey.PubKey()}, true, true},
  624. {"success empty ProofOfLockChange", EmptyPOLC(), false, false},
  625. {"success", ProofOfLockChange{Votes: []Vote{*v, *v2}, PubKey: val3.PrivKey.PubKey()}, false, false},
  626. }
  627. for _, tc := range testCases {
  628. tc := tc
  629. pbpolc, err := tc.polc.ToProto()
  630. if tc.expErr {
  631. assert.Error(t, err, tc.msg)
  632. } else {
  633. assert.NoError(t, err, tc.msg)
  634. }
  635. c, err := ProofOfLockChangeFromProto(pbpolc)
  636. if !tc.expErr2 {
  637. assert.NoError(t, err, tc.msg)
  638. assert.Equal(t, &tc.polc, c, tc.msg)
  639. } else {
  640. assert.Error(t, err, tc.msg)
  641. }
  642. }
  643. }