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