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.

610 lines
23 KiB

  1. package evidence_test
  2. import (
  3. "bytes"
  4. "context"
  5. "testing"
  6. "time"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. dbm "github.com/tendermint/tm-db"
  10. "github.com/tendermint/tendermint/crypto"
  11. "github.com/tendermint/tendermint/crypto/tmhash"
  12. "github.com/tendermint/tendermint/internal/evidence"
  13. "github.com/tendermint/tendermint/internal/evidence/mocks"
  14. "github.com/tendermint/tendermint/internal/test/factory"
  15. "github.com/tendermint/tendermint/libs/log"
  16. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  17. sm "github.com/tendermint/tendermint/state"
  18. smmocks "github.com/tendermint/tendermint/state/mocks"
  19. "github.com/tendermint/tendermint/types"
  20. )
  21. const (
  22. defaultVotingPower = 10
  23. )
  24. func TestVerifyLightClientAttack_Lunatic(t *testing.T) {
  25. const (
  26. height int64 = 10
  27. commonHeight int64 = 4
  28. totalVals = 10
  29. byzVals = 4
  30. )
  31. attackTime := defaultEvidenceTime.Add(1 * time.Hour)
  32. // create valid lunatic evidence
  33. ev, trusted, common := makeLunaticEvidence(
  34. t, height, commonHeight, totalVals, byzVals, totalVals-byzVals, defaultEvidenceTime, attackTime)
  35. require.NoError(t, ev.ValidateBasic())
  36. // good pass -> no error
  37. err := evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet,
  38. defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour)
  39. assert.NoError(t, err)
  40. // trusted and conflicting hashes are the same -> an error should be returned
  41. err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, ev.ConflictingBlock.SignedHeader, common.ValidatorSet,
  42. defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour)
  43. assert.Error(t, err)
  44. // evidence with different total validator power should fail
  45. ev.TotalVotingPower = 1 * defaultVotingPower
  46. err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet,
  47. defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour)
  48. assert.NoError(t, err)
  49. assert.Error(t, ev.ValidateABCI(common.ValidatorSet, trusted.SignedHeader, defaultEvidenceTime))
  50. // evidence without enough malicious votes should fail
  51. ev, trusted, common = makeLunaticEvidence(
  52. t, height, commonHeight, totalVals, byzVals-1, totalVals-byzVals, defaultEvidenceTime, attackTime)
  53. err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet,
  54. defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour)
  55. assert.Error(t, err)
  56. }
  57. func TestVerify_LunaticAttackAgainstState(t *testing.T) {
  58. const (
  59. height int64 = 10
  60. commonHeight int64 = 4
  61. totalVals = 10
  62. byzVals = 4
  63. )
  64. attackTime := defaultEvidenceTime.Add(1 * time.Hour)
  65. // create valid lunatic evidence
  66. ev, trusted, common := makeLunaticEvidence(
  67. t, height, commonHeight, totalVals, byzVals, totalVals-byzVals, defaultEvidenceTime, attackTime)
  68. // now we try to test verification against state
  69. state := sm.State{
  70. LastBlockTime: defaultEvidenceTime.Add(2 * time.Hour),
  71. LastBlockHeight: height + 1,
  72. ConsensusParams: *types.DefaultConsensusParams(),
  73. }
  74. stateStore := &smmocks.Store{}
  75. stateStore.On("LoadValidators", commonHeight).Return(common.ValidatorSet, nil)
  76. stateStore.On("Load").Return(state, nil)
  77. blockStore := &mocks.BlockStore{}
  78. blockStore.On("LoadBlockMeta", commonHeight).Return(&types.BlockMeta{Header: *common.Header})
  79. blockStore.On("LoadBlockMeta", height).Return(&types.BlockMeta{Header: *trusted.Header})
  80. blockStore.On("LoadBlockCommit", commonHeight).Return(common.Commit)
  81. blockStore.On("LoadBlockCommit", height).Return(trusted.Commit)
  82. pool, err := evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, blockStore)
  83. require.NoError(t, err)
  84. evList := types.EvidenceList{ev}
  85. // check that the evidence pool correctly verifies the evidence
  86. assert.NoError(t, pool.CheckEvidence(evList))
  87. // as it was not originally in the pending bucket, it should now have been added
  88. pendingEvs, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
  89. assert.Equal(t, 1, len(pendingEvs))
  90. assert.Equal(t, ev, pendingEvs[0])
  91. // if we submit evidence only against a single byzantine validator when we see there are more validators then this
  92. // should return an error
  93. ev.ByzantineValidators = ev.ByzantineValidators[:1]
  94. t.Log(evList)
  95. assert.Error(t, pool.CheckEvidence(evList))
  96. // restore original byz vals
  97. ev.ByzantineValidators = ev.GetByzantineValidators(common.ValidatorSet, trusted.SignedHeader)
  98. // duplicate evidence should be rejected
  99. evList = types.EvidenceList{ev, ev}
  100. pool, err = evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, blockStore)
  101. require.NoError(t, err)
  102. assert.Error(t, pool.CheckEvidence(evList))
  103. // If evidence is submitted with an altered timestamp it should return an error
  104. ev.Timestamp = defaultEvidenceTime.Add(1 * time.Minute)
  105. pool, err = evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, blockStore)
  106. require.NoError(t, err)
  107. assert.Error(t, pool.AddEvidence(ev))
  108. ev.Timestamp = defaultEvidenceTime
  109. // Evidence submitted with a different validator power should fail
  110. ev.TotalVotingPower = 1
  111. pool, err = evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, blockStore)
  112. require.NoError(t, err)
  113. assert.Error(t, pool.AddEvidence(ev))
  114. ev.TotalVotingPower = common.ValidatorSet.TotalVotingPower()
  115. }
  116. func TestVerify_ForwardLunaticAttack(t *testing.T) {
  117. const (
  118. nodeHeight int64 = 8
  119. attackHeight int64 = 10
  120. commonHeight int64 = 4
  121. totalVals = 10
  122. byzVals = 5
  123. )
  124. attackTime := defaultEvidenceTime.Add(1 * time.Hour)
  125. // create a forward lunatic attack
  126. ev, trusted, common := makeLunaticEvidence(
  127. t, attackHeight, commonHeight, totalVals, byzVals, totalVals-byzVals, defaultEvidenceTime, attackTime)
  128. // now we try to test verification against state
  129. state := sm.State{
  130. LastBlockTime: defaultEvidenceTime.Add(2 * time.Hour),
  131. LastBlockHeight: nodeHeight,
  132. ConsensusParams: *types.DefaultConsensusParams(),
  133. }
  134. // modify trusted light block so that it is of a height less than the conflicting one
  135. trusted.Header.Height = state.LastBlockHeight
  136. trusted.Header.Time = state.LastBlockTime
  137. stateStore := &smmocks.Store{}
  138. stateStore.On("LoadValidators", commonHeight).Return(common.ValidatorSet, nil)
  139. stateStore.On("Load").Return(state, nil)
  140. blockStore := &mocks.BlockStore{}
  141. blockStore.On("LoadBlockMeta", commonHeight).Return(&types.BlockMeta{Header: *common.Header})
  142. blockStore.On("LoadBlockMeta", nodeHeight).Return(&types.BlockMeta{Header: *trusted.Header})
  143. blockStore.On("LoadBlockMeta", attackHeight).Return(nil)
  144. blockStore.On("LoadBlockCommit", commonHeight).Return(common.Commit)
  145. blockStore.On("LoadBlockCommit", nodeHeight).Return(trusted.Commit)
  146. blockStore.On("Height").Return(nodeHeight)
  147. pool, err := evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, blockStore)
  148. require.NoError(t, err)
  149. // check that the evidence pool correctly verifies the evidence
  150. assert.NoError(t, pool.CheckEvidence(types.EvidenceList{ev}))
  151. // now we use a time which isn't able to contradict the FLA - thus we can't verify the evidence
  152. oldBlockStore := &mocks.BlockStore{}
  153. oldHeader := trusted.Header
  154. oldHeader.Time = defaultEvidenceTime
  155. oldBlockStore.On("LoadBlockMeta", commonHeight).Return(&types.BlockMeta{Header: *common.Header})
  156. oldBlockStore.On("LoadBlockMeta", nodeHeight).Return(&types.BlockMeta{Header: *oldHeader})
  157. oldBlockStore.On("LoadBlockMeta", attackHeight).Return(nil)
  158. oldBlockStore.On("LoadBlockCommit", commonHeight).Return(common.Commit)
  159. oldBlockStore.On("LoadBlockCommit", nodeHeight).Return(trusted.Commit)
  160. oldBlockStore.On("Height").Return(nodeHeight)
  161. require.Equal(t, defaultEvidenceTime, oldBlockStore.LoadBlockMeta(nodeHeight).Header.Time)
  162. pool, err = evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, oldBlockStore)
  163. require.NoError(t, err)
  164. assert.Error(t, pool.CheckEvidence(types.EvidenceList{ev}))
  165. }
  166. func TestVerifyLightClientAttack_Equivocation(t *testing.T) {
  167. conflictingVals, conflictingPrivVals := factory.RandValidatorSet(5, 10)
  168. conflictingHeader, err := factory.MakeHeader(&types.Header{
  169. ChainID: evidenceChainID,
  170. Height: 10,
  171. Time: defaultEvidenceTime,
  172. ValidatorsHash: conflictingVals.Hash(),
  173. })
  174. require.NoError(t, err)
  175. trustedHeader, _ := factory.MakeHeader(&types.Header{
  176. ChainID: evidenceChainID,
  177. Height: 10,
  178. Time: defaultEvidenceTime,
  179. ValidatorsHash: conflictingHeader.ValidatorsHash,
  180. NextValidatorsHash: conflictingHeader.NextValidatorsHash,
  181. ConsensusHash: conflictingHeader.ConsensusHash,
  182. AppHash: conflictingHeader.AppHash,
  183. LastResultsHash: conflictingHeader.LastResultsHash,
  184. })
  185. // we are simulating a duplicate vote attack where all the validators in the conflictingVals set
  186. // except the last validator vote twice
  187. blockID := factory.MakeBlockIDWithHash(conflictingHeader.Hash())
  188. voteSet := types.NewVoteSet(evidenceChainID, 10, 1, tmproto.SignedMsgType(2), conflictingVals)
  189. commit, err := factory.MakeCommit(blockID, 10, 1, voteSet, conflictingPrivVals[:4], defaultEvidenceTime)
  190. require.NoError(t, err)
  191. ev := &types.LightClientAttackEvidence{
  192. ConflictingBlock: &types.LightBlock{
  193. SignedHeader: &types.SignedHeader{
  194. Header: conflictingHeader,
  195. Commit: commit,
  196. },
  197. ValidatorSet: conflictingVals,
  198. },
  199. CommonHeight: 10,
  200. ByzantineValidators: conflictingVals.Validators[:4],
  201. TotalVotingPower: 50,
  202. Timestamp: defaultEvidenceTime,
  203. }
  204. trustedBlockID := makeBlockID(trustedHeader.Hash(), 1000, []byte("partshash"))
  205. trustedVoteSet := types.NewVoteSet(evidenceChainID, 10, 1, tmproto.SignedMsgType(2), conflictingVals)
  206. trustedCommit, err := factory.MakeCommit(trustedBlockID, 10, 1,
  207. trustedVoteSet, conflictingPrivVals, defaultEvidenceTime)
  208. require.NoError(t, err)
  209. trustedSignedHeader := &types.SignedHeader{
  210. Header: trustedHeader,
  211. Commit: trustedCommit,
  212. }
  213. // good pass -> no error
  214. err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals,
  215. defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
  216. assert.NoError(t, err)
  217. // trusted and conflicting hashes are the same -> an error should be returned
  218. err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals,
  219. defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
  220. assert.Error(t, err)
  221. // conflicting header has different next validators hash which should have been correctly derived from
  222. // the previous round
  223. ev.ConflictingBlock.Header.NextValidatorsHash = crypto.CRandBytes(tmhash.Size)
  224. err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, nil,
  225. defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
  226. assert.Error(t, err)
  227. // revert next validators hash
  228. ev.ConflictingBlock.Header.NextValidatorsHash = trustedHeader.NextValidatorsHash
  229. state := sm.State{
  230. LastBlockTime: defaultEvidenceTime.Add(1 * time.Minute),
  231. LastBlockHeight: 11,
  232. ConsensusParams: *types.DefaultConsensusParams(),
  233. }
  234. stateStore := &smmocks.Store{}
  235. stateStore.On("LoadValidators", int64(10)).Return(conflictingVals, nil)
  236. stateStore.On("Load").Return(state, nil)
  237. blockStore := &mocks.BlockStore{}
  238. blockStore.On("LoadBlockMeta", int64(10)).Return(&types.BlockMeta{Header: *trustedHeader})
  239. blockStore.On("LoadBlockCommit", int64(10)).Return(trustedCommit)
  240. pool, err := evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, blockStore)
  241. require.NoError(t, err)
  242. evList := types.EvidenceList{ev}
  243. err = pool.CheckEvidence(evList)
  244. assert.NoError(t, err)
  245. pendingEvs, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
  246. assert.Equal(t, 1, len(pendingEvs))
  247. }
  248. func TestVerifyLightClientAttack_Amnesia(t *testing.T) {
  249. var height int64 = 10
  250. conflictingVals, conflictingPrivVals := factory.RandValidatorSet(5, 10)
  251. conflictingHeader, err := factory.MakeHeader(&types.Header{
  252. ChainID: evidenceChainID,
  253. Height: height,
  254. Time: defaultEvidenceTime,
  255. ValidatorsHash: conflictingVals.Hash(),
  256. })
  257. require.NoError(t, err)
  258. trustedHeader, _ := factory.MakeHeader(&types.Header{
  259. ChainID: evidenceChainID,
  260. Height: height,
  261. Time: defaultEvidenceTime,
  262. ValidatorsHash: conflictingHeader.ValidatorsHash,
  263. NextValidatorsHash: conflictingHeader.NextValidatorsHash,
  264. ConsensusHash: conflictingHeader.ConsensusHash,
  265. AppHash: conflictingHeader.AppHash,
  266. LastResultsHash: conflictingHeader.LastResultsHash,
  267. })
  268. // we are simulating an amnesia attack where all the validators in the conflictingVals set
  269. // except the last validator vote twice. However this time the commits are of different rounds.
  270. blockID := makeBlockID(conflictingHeader.Hash(), 1000, []byte("partshash"))
  271. voteSet := types.NewVoteSet(evidenceChainID, height, 0, tmproto.SignedMsgType(2), conflictingVals)
  272. commit, err := factory.MakeCommit(blockID, height, 0, voteSet, conflictingPrivVals, defaultEvidenceTime)
  273. require.NoError(t, err)
  274. ev := &types.LightClientAttackEvidence{
  275. ConflictingBlock: &types.LightBlock{
  276. SignedHeader: &types.SignedHeader{
  277. Header: conflictingHeader,
  278. Commit: commit,
  279. },
  280. ValidatorSet: conflictingVals,
  281. },
  282. CommonHeight: height,
  283. ByzantineValidators: nil, // with amnesia evidence no validators are submitted as abci evidence
  284. TotalVotingPower: 50,
  285. Timestamp: defaultEvidenceTime,
  286. }
  287. trustedBlockID := makeBlockID(trustedHeader.Hash(), 1000, []byte("partshash"))
  288. trustedVoteSet := types.NewVoteSet(evidenceChainID, height, 1, tmproto.SignedMsgType(2), conflictingVals)
  289. trustedCommit, err := factory.MakeCommit(trustedBlockID, height, 1,
  290. trustedVoteSet, conflictingPrivVals, defaultEvidenceTime)
  291. require.NoError(t, err)
  292. trustedSignedHeader := &types.SignedHeader{
  293. Header: trustedHeader,
  294. Commit: trustedCommit,
  295. }
  296. // good pass -> no error
  297. err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals,
  298. defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
  299. assert.NoError(t, err)
  300. // trusted and conflicting hashes are the same -> an error should be returned
  301. err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals,
  302. defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
  303. assert.Error(t, err)
  304. state := sm.State{
  305. LastBlockTime: defaultEvidenceTime.Add(1 * time.Minute),
  306. LastBlockHeight: 11,
  307. ConsensusParams: *types.DefaultConsensusParams(),
  308. }
  309. stateStore := &smmocks.Store{}
  310. stateStore.On("LoadValidators", int64(10)).Return(conflictingVals, nil)
  311. stateStore.On("Load").Return(state, nil)
  312. blockStore := &mocks.BlockStore{}
  313. blockStore.On("LoadBlockMeta", int64(10)).Return(&types.BlockMeta{Header: *trustedHeader})
  314. blockStore.On("LoadBlockCommit", int64(10)).Return(trustedCommit)
  315. pool, err := evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, blockStore)
  316. require.NoError(t, err)
  317. evList := types.EvidenceList{ev}
  318. err = pool.CheckEvidence(evList)
  319. assert.NoError(t, err)
  320. pendingEvs, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
  321. assert.Equal(t, 1, len(pendingEvs))
  322. }
  323. type voteData struct {
  324. vote1 *types.Vote
  325. vote2 *types.Vote
  326. valid bool
  327. }
  328. func TestVerifyDuplicateVoteEvidence(t *testing.T) {
  329. val := types.NewMockPV()
  330. val2 := types.NewMockPV()
  331. valSet := types.NewValidatorSet([]*types.Validator{val.ExtractIntoValidator(1)})
  332. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  333. blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
  334. blockID3 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash"))
  335. blockID4 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash2"))
  336. const chainID = "mychain"
  337. vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultEvidenceTime)
  338. v1 := vote1.ToProto()
  339. err := val.SignVote(context.Background(), chainID, v1)
  340. require.NoError(t, err)
  341. badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultEvidenceTime)
  342. bv := badVote.ToProto()
  343. err = val2.SignVote(context.Background(), chainID, bv)
  344. require.NoError(t, err)
  345. vote1.Signature = v1.Signature
  346. badVote.Signature = bv.Signature
  347. cases := []voteData{
  348. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, defaultEvidenceTime), true}, // different block ids
  349. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3, defaultEvidenceTime), true},
  350. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID4, defaultEvidenceTime), true},
  351. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultEvidenceTime), false}, // wrong block id
  352. {vote1, makeVote(t, val, "mychain2", 0, 10, 2, 1, blockID2, defaultEvidenceTime), false}, // wrong chain id
  353. {vote1, makeVote(t, val, chainID, 0, 11, 2, 1, blockID2, defaultEvidenceTime), false}, // wrong height
  354. {vote1, makeVote(t, val, chainID, 0, 10, 3, 1, blockID2, defaultEvidenceTime), false}, // wrong round
  355. {vote1, makeVote(t, val, chainID, 0, 10, 2, 2, blockID2, defaultEvidenceTime), false}, // wrong step
  356. {vote1, makeVote(t, val2, chainID, 0, 10, 2, 1, blockID2, defaultEvidenceTime), false}, // wrong validator
  357. // a different vote time doesn't matter
  358. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)), true},
  359. {vote1, badVote, false}, // signed by wrong key
  360. }
  361. require.NoError(t, err)
  362. for _, c := range cases {
  363. ev := &types.DuplicateVoteEvidence{
  364. VoteA: c.vote1,
  365. VoteB: c.vote2,
  366. ValidatorPower: 1,
  367. TotalVotingPower: 1,
  368. Timestamp: defaultEvidenceTime,
  369. }
  370. if c.valid {
  371. assert.Nil(t, evidence.VerifyDuplicateVote(ev, chainID, valSet), "evidence should be valid")
  372. } else {
  373. assert.NotNil(t, evidence.VerifyDuplicateVote(ev, chainID, valSet), "evidence should be invalid")
  374. }
  375. }
  376. // create good evidence and correct validator power
  377. goodEv := types.NewMockDuplicateVoteEvidenceWithValidator(10, defaultEvidenceTime, val, chainID)
  378. goodEv.ValidatorPower = 1
  379. goodEv.TotalVotingPower = 1
  380. badEv := types.NewMockDuplicateVoteEvidenceWithValidator(10, defaultEvidenceTime, val, chainID)
  381. badTimeEv := types.NewMockDuplicateVoteEvidenceWithValidator(10, defaultEvidenceTime.Add(1*time.Minute), val, chainID)
  382. badTimeEv.ValidatorPower = 1
  383. badTimeEv.TotalVotingPower = 1
  384. state := sm.State{
  385. ChainID: chainID,
  386. LastBlockTime: defaultEvidenceTime.Add(1 * time.Minute),
  387. LastBlockHeight: 11,
  388. ConsensusParams: *types.DefaultConsensusParams(),
  389. }
  390. stateStore := &smmocks.Store{}
  391. stateStore.On("LoadValidators", int64(10)).Return(valSet, nil)
  392. stateStore.On("Load").Return(state, nil)
  393. blockStore := &mocks.BlockStore{}
  394. blockStore.On("LoadBlockMeta", int64(10)).Return(&types.BlockMeta{Header: types.Header{Time: defaultEvidenceTime}})
  395. pool, err := evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, blockStore)
  396. require.NoError(t, err)
  397. evList := types.EvidenceList{goodEv}
  398. err = pool.CheckEvidence(evList)
  399. assert.NoError(t, err)
  400. // evidence with a different validator power should fail
  401. evList = types.EvidenceList{badEv}
  402. err = pool.CheckEvidence(evList)
  403. assert.Error(t, err)
  404. // evidence with a different timestamp should fail
  405. evList = types.EvidenceList{badTimeEv}
  406. err = pool.CheckEvidence(evList)
  407. assert.Error(t, err)
  408. }
  409. func makeLunaticEvidence(
  410. t *testing.T,
  411. height, commonHeight int64,
  412. totalVals, byzVals, phantomVals int,
  413. commonTime, attackTime time.Time,
  414. ) (ev *types.LightClientAttackEvidence, trusted *types.LightBlock, common *types.LightBlock) {
  415. commonValSet, commonPrivVals := factory.RandValidatorSet(totalVals, defaultVotingPower)
  416. require.Greater(t, totalVals, byzVals)
  417. // extract out the subset of byzantine validators in the common validator set
  418. byzValSet, byzPrivVals := commonValSet.Validators[:byzVals], commonPrivVals[:byzVals]
  419. phantomValSet, phantomPrivVals := factory.RandValidatorSet(phantomVals, defaultVotingPower)
  420. conflictingVals := phantomValSet.Copy()
  421. require.NoError(t, conflictingVals.UpdateWithChangeSet(byzValSet))
  422. conflictingPrivVals := append(phantomPrivVals, byzPrivVals...)
  423. conflictingPrivVals = orderPrivValsByValSet(t, conflictingVals, conflictingPrivVals)
  424. commonHeader, err := factory.MakeHeader(&types.Header{
  425. ChainID: evidenceChainID,
  426. Height: commonHeight,
  427. Time: commonTime,
  428. })
  429. require.NoError(t, err)
  430. trustedHeader, err := factory.MakeHeader(&types.Header{
  431. ChainID: evidenceChainID,
  432. Height: height,
  433. Time: defaultEvidenceTime,
  434. })
  435. require.NoError(t, err)
  436. conflictingHeader, err := factory.MakeHeader(&types.Header{
  437. ChainID: evidenceChainID,
  438. Height: height,
  439. Time: attackTime,
  440. ValidatorsHash: conflictingVals.Hash(),
  441. })
  442. require.NoError(t, err)
  443. blockID := factory.MakeBlockIDWithHash(conflictingHeader.Hash())
  444. voteSet := types.NewVoteSet(evidenceChainID, height, 1, tmproto.SignedMsgType(2), conflictingVals)
  445. commit, err := factory.MakeCommit(blockID, height, 1, voteSet, conflictingPrivVals, defaultEvidenceTime)
  446. require.NoError(t, err)
  447. ev = &types.LightClientAttackEvidence{
  448. ConflictingBlock: &types.LightBlock{
  449. SignedHeader: &types.SignedHeader{
  450. Header: conflictingHeader,
  451. Commit: commit,
  452. },
  453. ValidatorSet: conflictingVals,
  454. },
  455. CommonHeight: commonHeight,
  456. TotalVotingPower: commonValSet.TotalVotingPower(),
  457. ByzantineValidators: byzValSet,
  458. Timestamp: commonTime,
  459. }
  460. common = &types.LightBlock{
  461. SignedHeader: &types.SignedHeader{
  462. Header: commonHeader,
  463. // we can leave this empty because we shouldn't be checking this
  464. Commit: &types.Commit{},
  465. },
  466. ValidatorSet: commonValSet,
  467. }
  468. trustedBlockID := factory.MakeBlockIDWithHash(trustedHeader.Hash())
  469. trustedVals, privVals := factory.RandValidatorSet(totalVals, defaultVotingPower)
  470. trustedVoteSet := types.NewVoteSet(evidenceChainID, height, 1, tmproto.SignedMsgType(2), trustedVals)
  471. trustedCommit, err := factory.MakeCommit(trustedBlockID, height, 1, trustedVoteSet, privVals, defaultEvidenceTime)
  472. require.NoError(t, err)
  473. trusted = &types.LightBlock{
  474. SignedHeader: &types.SignedHeader{
  475. Header: trustedHeader,
  476. Commit: trustedCommit,
  477. },
  478. ValidatorSet: trustedVals,
  479. }
  480. return ev, trusted, common
  481. }
  482. func makeVote(
  483. t *testing.T, val types.PrivValidator, chainID string, valIndex int32, height int64,
  484. round int32, step int, blockID types.BlockID, time time.Time) *types.Vote {
  485. pubKey, err := val.GetPubKey(context.Background())
  486. require.NoError(t, err)
  487. v := &types.Vote{
  488. ValidatorAddress: pubKey.Address(),
  489. ValidatorIndex: valIndex,
  490. Height: height,
  491. Round: round,
  492. Type: tmproto.SignedMsgType(step),
  493. BlockID: blockID,
  494. Timestamp: time,
  495. }
  496. vpb := v.ToProto()
  497. err = val.SignVote(context.Background(), chainID, vpb)
  498. if err != nil {
  499. panic(err)
  500. }
  501. v.Signature = vpb.Signature
  502. return v
  503. }
  504. func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.BlockID {
  505. var (
  506. h = make([]byte, tmhash.Size)
  507. psH = make([]byte, tmhash.Size)
  508. )
  509. copy(h, hash)
  510. copy(psH, partSetHash)
  511. return types.BlockID{
  512. Hash: h,
  513. PartSetHeader: types.PartSetHeader{
  514. Total: partSetSize,
  515. Hash: psH,
  516. },
  517. }
  518. }
  519. func orderPrivValsByValSet(
  520. t *testing.T, vals *types.ValidatorSet, privVals []types.PrivValidator) []types.PrivValidator {
  521. output := make([]types.PrivValidator, len(privVals))
  522. for idx, v := range vals.Validators {
  523. for _, p := range privVals {
  524. pubKey, err := p.GetPubKey(context.Background())
  525. require.NoError(t, err)
  526. if bytes.Equal(v.Address, pubKey.Address()) {
  527. output[idx] = p
  528. break
  529. }
  530. }
  531. require.NotEmpty(t, output[idx])
  532. }
  533. return output
  534. }