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.

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