github.com/Team-Kujira/tendermint@v0.34.24-indexer/state/validation_test.go (about) 1 package state_test 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/mock" 9 "github.com/stretchr/testify/require" 10 11 abci "github.com/tendermint/tendermint/abci/types" 12 "github.com/tendermint/tendermint/crypto/ed25519" 13 "github.com/tendermint/tendermint/crypto/tmhash" 14 "github.com/tendermint/tendermint/libs/log" 15 memmock "github.com/tendermint/tendermint/mempool/mock" 16 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 17 sm "github.com/tendermint/tendermint/state" 18 "github.com/tendermint/tendermint/state/mocks" 19 "github.com/tendermint/tendermint/types" 20 tmtime "github.com/tendermint/tendermint/types/time" 21 ) 22 23 const validationTestsStopHeight int64 = 10 24 25 func TestValidateBlockHeader(t *testing.T) { 26 proxyApp := newTestApp() 27 require.NoError(t, proxyApp.Start()) 28 defer proxyApp.Stop() //nolint:errcheck // ignore for tests 29 30 state, stateDB, privVals := makeState(3, 1) 31 stateStore := sm.NewStore(stateDB, sm.StoreOptions{ 32 DiscardABCIResponses: false, 33 }) 34 blockExec := sm.NewBlockExecutor( 35 stateStore, 36 log.TestingLogger(), 37 proxyApp.Consensus(), 38 memmock.Mempool{}, 39 sm.EmptyEvidencePool{}, 40 ) 41 lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) 42 43 // some bad values 44 wrongHash := tmhash.Sum([]byte("this hash is wrong")) 45 wrongVersion1 := state.Version.Consensus 46 wrongVersion1.Block += 2 47 wrongVersion2 := state.Version.Consensus 48 wrongVersion2.App += 2 49 50 // Manipulation of any header field causes failure. 51 testCases := []struct { 52 name string 53 malleateBlock func(block *types.Block) 54 }{ 55 {"Version wrong1", func(block *types.Block) { block.Version = wrongVersion1 }}, 56 {"Version wrong2", func(block *types.Block) { block.Version = wrongVersion2 }}, 57 {"ChainID wrong", func(block *types.Block) { block.ChainID = "not-the-real-one" }}, 58 {"Height wrong", func(block *types.Block) { block.Height += 10 }}, 59 {"Time wrong", func(block *types.Block) { block.Time = block.Time.Add(-time.Second * 1) }}, 60 61 {"LastBlockID wrong", func(block *types.Block) { block.LastBlockID.PartSetHeader.Total += 10 }}, 62 {"LastCommitHash wrong", func(block *types.Block) { block.LastCommitHash = wrongHash }}, 63 {"DataHash wrong", func(block *types.Block) { block.DataHash = wrongHash }}, 64 65 {"ValidatorsHash wrong", func(block *types.Block) { block.ValidatorsHash = wrongHash }}, 66 {"NextValidatorsHash wrong", func(block *types.Block) { block.NextValidatorsHash = wrongHash }}, 67 {"ConsensusHash wrong", func(block *types.Block) { block.ConsensusHash = wrongHash }}, 68 {"AppHash wrong", func(block *types.Block) { block.AppHash = wrongHash }}, 69 {"LastResultsHash wrong", func(block *types.Block) { block.LastResultsHash = wrongHash }}, 70 71 {"EvidenceHash wrong", func(block *types.Block) { block.EvidenceHash = wrongHash }}, 72 {"Proposer wrong", func(block *types.Block) { block.ProposerAddress = ed25519.GenPrivKey().PubKey().Address() }}, 73 {"Proposer invalid", func(block *types.Block) { block.ProposerAddress = []byte("wrong size") }}, 74 } 75 76 // Build up state for multiple heights 77 for height := int64(1); height < validationTestsStopHeight; height++ { 78 proposerAddr := state.Validators.GetProposer().Address 79 /* 80 Invalid blocks don't pass 81 */ 82 for _, tc := range testCases { 83 block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, nil, proposerAddr) 84 tc.malleateBlock(block) 85 err := blockExec.ValidateBlock(state, block) 86 require.Error(t, err, tc.name) 87 } 88 89 /* 90 A good block passes 91 */ 92 var err error 93 state, _, lastCommit, err = makeAndCommitGoodBlock(state, height, lastCommit, proposerAddr, blockExec, privVals, nil) 94 require.NoError(t, err, "height %d", height) 95 } 96 } 97 98 func TestValidateBlockCommit(t *testing.T) { 99 proxyApp := newTestApp() 100 require.NoError(t, proxyApp.Start()) 101 defer proxyApp.Stop() //nolint:errcheck // ignore for tests 102 103 state, stateDB, privVals := makeState(1, 1) 104 stateStore := sm.NewStore(stateDB, sm.StoreOptions{ 105 DiscardABCIResponses: false, 106 }) 107 blockExec := sm.NewBlockExecutor( 108 stateStore, 109 log.TestingLogger(), 110 proxyApp.Consensus(), 111 memmock.Mempool{}, 112 sm.EmptyEvidencePool{}, 113 ) 114 lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) 115 wrongSigsCommit := types.NewCommit(1, 0, types.BlockID{}, nil) 116 badPrivVal := types.NewMockPV() 117 118 for height := int64(1); height < validationTestsStopHeight; height++ { 119 proposerAddr := state.Validators.GetProposer().Address 120 if height > 1 { 121 /* 122 #2589: ensure state.LastValidators.VerifyCommit fails here 123 */ 124 // should be height-1 instead of height 125 wrongHeightVote, err := types.MakeVote( 126 height, 127 state.LastBlockID, 128 state.Validators, 129 privVals[proposerAddr.String()], 130 chainID, 131 time.Now(), 132 ) 133 require.NoError(t, err, "height %d", height) 134 wrongHeightCommit := types.NewCommit( 135 wrongHeightVote.Height, 136 wrongHeightVote.Round, 137 state.LastBlockID, 138 []types.CommitSig{wrongHeightVote.CommitSig()}, 139 ) 140 block, _ := state.MakeBlock(height, makeTxs(height), wrongHeightCommit, nil, proposerAddr) 141 err = blockExec.ValidateBlock(state, block) 142 _, isErrInvalidCommitHeight := err.(types.ErrInvalidCommitHeight) 143 require.True(t, isErrInvalidCommitHeight, "expected ErrInvalidCommitHeight at height %d but got: %v", height, err) 144 145 /* 146 #2589: test len(block.LastCommit.Signatures) == state.LastValidators.Size() 147 */ 148 block, _ = state.MakeBlock(height, makeTxs(height), wrongSigsCommit, nil, proposerAddr) 149 err = blockExec.ValidateBlock(state, block) 150 _, isErrInvalidCommitSignatures := err.(types.ErrInvalidCommitSignatures) 151 require.True(t, isErrInvalidCommitSignatures, 152 "expected ErrInvalidCommitSignatures at height %d, but got: %v", 153 height, 154 err, 155 ) 156 } 157 158 /* 159 A good block passes 160 */ 161 var err error 162 var blockID types.BlockID 163 state, blockID, lastCommit, err = makeAndCommitGoodBlock( 164 state, 165 height, 166 lastCommit, 167 proposerAddr, 168 blockExec, 169 privVals, 170 nil, 171 ) 172 require.NoError(t, err, "height %d", height) 173 174 /* 175 wrongSigsCommit is fine except for the extra bad precommit 176 */ 177 goodVote, err := types.MakeVote(height, 178 blockID, 179 state.Validators, 180 privVals[proposerAddr.String()], 181 chainID, 182 time.Now(), 183 ) 184 require.NoError(t, err, "height %d", height) 185 186 bpvPubKey, err := badPrivVal.GetPubKey() 187 require.NoError(t, err) 188 189 badVote := &types.Vote{ 190 ValidatorAddress: bpvPubKey.Address(), 191 ValidatorIndex: 0, 192 Height: height, 193 Round: 0, 194 Timestamp: tmtime.Now(), 195 Type: tmproto.PrecommitType, 196 BlockID: blockID, 197 } 198 199 g := goodVote.ToProto() 200 b := badVote.ToProto() 201 202 err = badPrivVal.SignVote(chainID, g) 203 require.NoError(t, err, "height %d", height) 204 err = badPrivVal.SignVote(chainID, b) 205 require.NoError(t, err, "height %d", height) 206 207 goodVote.Signature, badVote.Signature = g.Signature, b.Signature 208 209 wrongSigsCommit = types.NewCommit(goodVote.Height, goodVote.Round, 210 blockID, []types.CommitSig{goodVote.CommitSig(), badVote.CommitSig()}) 211 } 212 } 213 214 func TestValidateBlockEvidence(t *testing.T) { 215 proxyApp := newTestApp() 216 require.NoError(t, proxyApp.Start()) 217 defer proxyApp.Stop() //nolint:errcheck // ignore for tests 218 219 state, stateDB, privVals := makeState(4, 1) 220 stateStore := sm.NewStore(stateDB, sm.StoreOptions{ 221 DiscardABCIResponses: false, 222 }) 223 defaultEvidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) 224 225 evpool := &mocks.EvidencePool{} 226 evpool.On("CheckEvidence", mock.AnythingOfType("types.EvidenceList")).Return(nil) 227 evpool.On("Update", mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return() 228 evpool.On("ABCIEvidence", mock.AnythingOfType("int64"), mock.AnythingOfType("[]types.Evidence")).Return( 229 []abci.Evidence{}) 230 231 state.ConsensusParams.Evidence.MaxBytes = 1000 232 blockExec := sm.NewBlockExecutor( 233 stateStore, 234 log.TestingLogger(), 235 proxyApp.Consensus(), 236 memmock.Mempool{}, 237 evpool, 238 ) 239 lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) 240 241 for height := int64(1); height < validationTestsStopHeight; height++ { 242 proposerAddr := state.Validators.GetProposer().Address 243 maxBytesEvidence := state.ConsensusParams.Evidence.MaxBytes 244 if height > 1 { 245 /* 246 A block with too much evidence fails 247 */ 248 evidence := make([]types.Evidence, 0) 249 var currentBytes int64 250 // more bytes than the maximum allowed for evidence 251 for currentBytes <= maxBytesEvidence { 252 newEv := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), 253 privVals[proposerAddr.String()], chainID) 254 evidence = append(evidence, newEv) 255 currentBytes += int64(len(newEv.Bytes())) 256 } 257 block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, evidence, proposerAddr) 258 err := blockExec.ValidateBlock(state, block) 259 if assert.Error(t, err) { 260 _, ok := err.(*types.ErrEvidenceOverflow) 261 require.True(t, ok, "expected error to be of type ErrEvidenceOverflow at height %d but got %v", height, err) 262 } 263 } 264 265 /* 266 A good block with several pieces of good evidence passes 267 */ 268 evidence := make([]types.Evidence, 0) 269 var currentBytes int64 270 // precisely the amount of allowed evidence 271 for { 272 newEv := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime, 273 privVals[proposerAddr.String()], chainID) 274 currentBytes += int64(len(newEv.Bytes())) 275 if currentBytes >= maxBytesEvidence { 276 break 277 } 278 evidence = append(evidence, newEv) 279 } 280 281 var err error 282 state, _, lastCommit, err = makeAndCommitGoodBlock( 283 state, 284 height, 285 lastCommit, 286 proposerAddr, 287 blockExec, 288 privVals, 289 evidence, 290 ) 291 require.NoError(t, err, "height %d", height) 292 } 293 }