github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/internal/state/helpers_test.go (about) 1 package state_test 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "math/rand" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/require" 12 dbm "github.com/tendermint/tm-db" 13 14 abci "github.com/ari-anchor/sei-tendermint/abci/types" 15 "github.com/ari-anchor/sei-tendermint/crypto" 16 "github.com/ari-anchor/sei-tendermint/crypto/ed25519" 17 "github.com/ari-anchor/sei-tendermint/crypto/encoding" 18 sm "github.com/ari-anchor/sei-tendermint/internal/state" 19 sf "github.com/ari-anchor/sei-tendermint/internal/state/test/factory" 20 "github.com/ari-anchor/sei-tendermint/internal/test/factory" 21 tmtime "github.com/ari-anchor/sei-tendermint/libs/time" 22 tmproto "github.com/ari-anchor/sei-tendermint/proto/tendermint/types" 23 "github.com/ari-anchor/sei-tendermint/types" 24 ) 25 26 type paramsChangeTestCase struct { 27 height int64 28 params types.ConsensusParams 29 } 30 31 func makeAndCommitGoodBlock( 32 ctx context.Context, 33 t *testing.T, 34 state sm.State, 35 height int64, 36 lastCommit *types.Commit, 37 proposerAddr []byte, 38 blockExec *sm.BlockExecutor, 39 privVals map[string]types.PrivValidator, 40 evidence []types.Evidence, 41 ) (sm.State, types.BlockID, *types.ExtendedCommit) { 42 t.Helper() 43 44 // A good block passes 45 state, blockID := makeAndApplyGoodBlock(ctx, t, state, height, lastCommit, proposerAddr, blockExec, evidence) 46 47 // Simulate a lastCommit for this block from all validators for the next height 48 commit, _ := makeValidCommit(ctx, t, height, blockID, state.Validators, privVals) 49 50 return state, blockID, commit 51 } 52 53 func makeAndApplyGoodBlock( 54 ctx context.Context, 55 t *testing.T, 56 state sm.State, 57 height int64, 58 lastCommit *types.Commit, 59 proposerAddr []byte, 60 blockExec *sm.BlockExecutor, 61 evidence []types.Evidence, 62 ) (sm.State, types.BlockID) { 63 t.Helper() 64 block := state.MakeBlock(height, factory.MakeNTxs(height, 10), lastCommit, evidence, proposerAddr) 65 partSet, err := block.MakePartSet(types.BlockPartSizeBytes) 66 require.NoError(t, err) 67 68 require.NoError(t, blockExec.ValidateBlock(ctx, state, block)) 69 blockID := types.BlockID{Hash: block.Hash(), 70 PartSetHeader: partSet.Header()} 71 state, err = blockExec.ApplyBlock(ctx, state, blockID, block, nil) 72 require.NoError(t, err) 73 74 return state, blockID 75 } 76 77 func makeValidCommit( 78 ctx context.Context, 79 t *testing.T, 80 height int64, 81 blockID types.BlockID, 82 vals *types.ValidatorSet, 83 privVals map[string]types.PrivValidator, 84 ) (*types.ExtendedCommit, []*types.Vote) { 85 t.Helper() 86 sigs := make([]types.ExtendedCommitSig, vals.Size()) 87 votes := make([]*types.Vote, vals.Size()) 88 for i := 0; i < vals.Size(); i++ { 89 _, val := vals.GetByIndex(int32(i)) 90 vote, err := factory.MakeVote(ctx, privVals[val.Address.String()], chainID, int32(i), height, 0, 2, blockID, time.Now()) 91 require.NoError(t, err) 92 sigs[i] = vote.ExtendedCommitSig() 93 votes[i] = vote 94 } 95 96 return &types.ExtendedCommit{ 97 Height: height, 98 BlockID: blockID, 99 ExtendedSignatures: sigs, 100 }, votes 101 } 102 103 func makeState(t *testing.T, nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValidator) { 104 vals := make([]types.GenesisValidator, nVals) 105 privVals := make(map[string]types.PrivValidator, nVals) 106 for i := 0; i < nVals; i++ { 107 secret := []byte(fmt.Sprintf("test%d", i)) 108 pk := ed25519.GenPrivKeyFromSecret(secret) 109 valAddr := pk.PubKey().Address() 110 vals[i] = types.GenesisValidator{ 111 Address: valAddr, 112 PubKey: pk.PubKey(), 113 Power: 1000, 114 Name: fmt.Sprintf("test%d", i), 115 } 116 privVals[valAddr.String()] = types.NewMockPVWithParams(pk, false, false) 117 } 118 s, _ := sm.MakeGenesisState(&types.GenesisDoc{ 119 ChainID: chainID, 120 Validators: vals, 121 AppHash: nil, 122 }) 123 124 stateDB := dbm.NewMemDB() 125 stateStore := sm.NewStore(stateDB) 126 require.NoError(t, stateStore.Save(s)) 127 128 for i := 1; i < height; i++ { 129 s.LastBlockHeight++ 130 s.LastValidators = s.Validators.Copy() 131 132 require.NoError(t, stateStore.Save(s)) 133 } 134 135 return s, stateDB, privVals 136 } 137 138 func genValSet(size int) *types.ValidatorSet { 139 vals := make([]*types.Validator, size) 140 for i := 0; i < size; i++ { 141 vals[i] = types.NewValidator(ed25519.GenPrivKey().PubKey(), 10) 142 } 143 return types.NewValidatorSet(vals) 144 } 145 146 func makeHeaderPartsResponsesValPubKeyChange( 147 t *testing.T, 148 state sm.State, 149 pubkey crypto.PubKey, 150 ) (types.Header, types.BlockID, *abci.ResponseFinalizeBlock) { 151 152 block := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) 153 finalizeBlockResponses := &abci.ResponseFinalizeBlock{} 154 // If the pubkey is new, remove the old and add the new. 155 _, val := state.NextValidators.GetByIndex(0) 156 if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) { 157 vPbPk, err := encoding.PubKeyToProto(val.PubKey) 158 require.NoError(t, err) 159 pbPk, err := encoding.PubKeyToProto(pubkey) 160 require.NoError(t, err) 161 162 finalizeBlockResponses.ValidatorUpdates = []abci.ValidatorUpdate{ 163 {PubKey: vPbPk, Power: 0}, 164 {PubKey: pbPk, Power: 10}, 165 } 166 } 167 168 return block.Header, types.BlockID{Hash: block.Hash(), PartSetHeader: types.PartSetHeader{}}, finalizeBlockResponses 169 } 170 171 func makeHeaderPartsResponsesValPowerChange( 172 t *testing.T, 173 state sm.State, 174 power int64, 175 ) (types.Header, types.BlockID, *abci.ResponseFinalizeBlock) { 176 t.Helper() 177 178 block := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) 179 finalizeBlockResponses := &abci.ResponseFinalizeBlock{} 180 181 // If the pubkey is new, remove the old and add the new. 182 _, val := state.NextValidators.GetByIndex(0) 183 if val.VotingPower != power { 184 vPbPk, err := encoding.PubKeyToProto(val.PubKey) 185 require.NoError(t, err) 186 187 finalizeBlockResponses.ValidatorUpdates = []abci.ValidatorUpdate{ 188 {PubKey: vPbPk, Power: power}, 189 } 190 } 191 192 return block.Header, types.BlockID{Hash: block.Hash(), PartSetHeader: types.PartSetHeader{}}, finalizeBlockResponses 193 } 194 195 func makeHeaderPartsResponsesParams( 196 t *testing.T, 197 state sm.State, 198 params *types.ConsensusParams, 199 ) (types.Header, types.BlockID, *abci.ResponseFinalizeBlock) { 200 t.Helper() 201 202 block := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) 203 pbParams := params.ToProto() 204 finalizeBlockResponses := &abci.ResponseFinalizeBlock{ConsensusParamUpdates: &pbParams} 205 return block.Header, types.BlockID{Hash: block.Hash(), PartSetHeader: types.PartSetHeader{}}, finalizeBlockResponses 206 } 207 208 func randomGenesisDoc() *types.GenesisDoc { 209 pubkey := ed25519.GenPrivKey().PubKey() 210 return &types.GenesisDoc{ 211 GenesisTime: tmtime.Now(), 212 ChainID: "abc", 213 Validators: []types.GenesisValidator{ 214 { 215 Address: pubkey.Address(), 216 PubKey: pubkey, 217 Power: 10, 218 Name: "myval", 219 }, 220 }, 221 ConsensusParams: types.DefaultConsensusParams(), 222 } 223 } 224 225 // used for testing by state store 226 func makeRandomStateFromValidatorSet( 227 lastValSet *types.ValidatorSet, 228 height, lastHeightValidatorsChanged int64, 229 ) sm.State { 230 return sm.State{ 231 LastBlockHeight: height - 1, 232 NextValidators: lastValSet.CopyIncrementProposerPriority(2), 233 Validators: lastValSet.CopyIncrementProposerPriority(1), 234 LastValidators: lastValSet.Copy(), 235 LastHeightConsensusParamsChanged: height, 236 ConsensusParams: *types.DefaultConsensusParams(), 237 LastHeightValidatorsChanged: lastHeightValidatorsChanged, 238 InitialHeight: 1, 239 } 240 } 241 func makeRandomStateFromConsensusParams( 242 ctx context.Context, 243 t *testing.T, 244 consensusParams *types.ConsensusParams, 245 height, 246 lastHeightConsensusParamsChanged int64, 247 ) sm.State { 248 t.Helper() 249 val, _, err := factory.Validator(ctx, 10+int64(rand.Uint32())) 250 require.NoError(t, err) 251 valSet := types.NewValidatorSet([]*types.Validator{val}) 252 return sm.State{ 253 LastBlockHeight: height - 1, 254 ConsensusParams: *consensusParams, 255 LastHeightConsensusParamsChanged: lastHeightConsensusParamsChanged, 256 NextValidators: valSet.CopyIncrementProposerPriority(2), 257 Validators: valSet.CopyIncrementProposerPriority(1), 258 LastValidators: valSet.Copy(), 259 LastHeightValidatorsChanged: height, 260 InitialHeight: 1, 261 } 262 } 263 264 //---------------------------------------------------------------------------- 265 266 type testApp struct { 267 abci.BaseApplication 268 269 CommitVotes []abci.VoteInfo 270 ByzantineValidators []abci.Misbehavior 271 ValidatorUpdates []abci.ValidatorUpdate 272 } 273 274 var _ abci.Application = (*testApp)(nil) 275 276 func (app *testApp) Info(_ context.Context, req *abci.RequestInfo) (*abci.ResponseInfo, error) { 277 return &abci.ResponseInfo{}, nil 278 } 279 280 func (app *testApp) FinalizeBlock(_ context.Context, req *abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) { 281 app.CommitVotes = req.DecidedLastCommit.Votes 282 app.ByzantineValidators = req.ByzantineValidators 283 284 resTxs := make([]*abci.ExecTxResult, len(req.Txs)) 285 for i, tx := range req.Txs { 286 if len(tx) > 0 { 287 resTxs[i] = &abci.ExecTxResult{Code: abci.CodeTypeOK} 288 } else { 289 resTxs[i] = &abci.ExecTxResult{Code: abci.CodeTypeOK + 10} // error 290 } 291 } 292 293 return &abci.ResponseFinalizeBlock{ 294 ValidatorUpdates: app.ValidatorUpdates, 295 ConsensusParamUpdates: &tmproto.ConsensusParams{ 296 Version: &tmproto.VersionParams{ 297 AppVersion: 1, 298 }, 299 }, 300 Events: []abci.Event{}, 301 TxResults: resTxs, 302 }, nil 303 } 304 305 func (app *testApp) CheckTx(_ context.Context, req *abci.RequestCheckTx) (*abci.ResponseCheckTx, error) { 306 return &abci.ResponseCheckTx{}, nil 307 } 308 309 func (app *testApp) Commit(context.Context) (*abci.ResponseCommit, error) { 310 return &abci.ResponseCommit{RetainHeight: 1}, nil 311 } 312 313 func (app *testApp) Query(_ context.Context, req *abci.RequestQuery) (*abci.ResponseQuery, error) { 314 return &abci.ResponseQuery{}, nil 315 } 316 317 func (app *testApp) ProcessProposal(_ context.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) { 318 for _, tx := range req.Txs { 319 if len(tx) == 0 { 320 return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil 321 } 322 } 323 return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil 324 }