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.

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