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