github.com/Finschia/ostracon@v1.1.5/state/helpers_test.go (about) 1 package state_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "time" 7 8 abci "github.com/tendermint/tendermint/abci/types" 9 tmstate "github.com/tendermint/tendermint/proto/tendermint/state" 10 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 11 dbm "github.com/tendermint/tm-db" 12 13 ocabci "github.com/Finschia/ostracon/abci/types" 14 "github.com/Finschia/ostracon/crypto" 15 "github.com/Finschia/ostracon/crypto/ed25519" 16 tmrand "github.com/Finschia/ostracon/libs/rand" 17 "github.com/Finschia/ostracon/proxy" 18 sm "github.com/Finschia/ostracon/state" 19 "github.com/Finschia/ostracon/types" 20 tmtime "github.com/Finschia/ostracon/types/time" 21 ) 22 23 type paramsChangeTestCase struct { 24 height int64 25 params tmproto.ConsensusParams 26 } 27 28 func newTestApp() proxy.AppConns { 29 app := &testApp{} 30 cc := proxy.NewLocalClientCreator(app) 31 return proxy.NewAppConns(cc) 32 } 33 34 func makeAndCommitGoodBlock( 35 state sm.State, 36 height int64, 37 lastCommit *types.Commit, 38 proposerAddr []byte, 39 blockExec *sm.BlockExecutor, 40 privVals map[string]types.PrivValidator, 41 evidence []types.Evidence) (sm.State, types.BlockID, *types.Commit, error) { 42 // A good block passes 43 state, blockID, err := makeAndApplyGoodBlock(state, 44 privVals[state.Validators.SelectProposer(state.LastProofHash, height, 0).Address.String()], 45 height, lastCommit, proposerAddr, blockExec, evidence) 46 if err != nil { 47 return state, types.BlockID{}, nil, err 48 } 49 50 // Simulate a lastCommit for this block from all validators for the next height 51 commit, err := makeValidCommit(height, blockID, state.Validators, privVals) 52 if err != nil { 53 return state, types.BlockID{}, nil, err 54 } 55 return state, blockID, commit, nil 56 } 57 58 func makeAndApplyGoodBlock(state sm.State, privVal types.PrivValidator, height int64, lastCommit *types.Commit, 59 proposerAddr []byte, blockExec *sm.BlockExecutor, evidence []types.Evidence) (sm.State, types.BlockID, error) { 60 message := state.MakeHashMessage(0) 61 proof, _ := privVal.GenerateVRFProof(message) 62 block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, evidence, proposerAddr, 0, proof) 63 if err := blockExec.ValidateBlock(state, 0, block); err != nil { 64 return state, types.BlockID{}, err 65 } 66 blockID := types.BlockID{Hash: block.Hash(), 67 PartSetHeader: types.PartSetHeader{Total: 3, Hash: tmrand.Bytes(32)}} 68 state, _, err := blockExec.ApplyBlock(state, blockID, block, nil) 69 if err != nil { 70 return state, types.BlockID{}, err 71 } 72 return state, blockID, nil 73 } 74 75 func makeValidCommit( 76 height int64, 77 blockID types.BlockID, 78 vals *types.ValidatorSet, 79 privVals map[string]types.PrivValidator, 80 ) (*types.Commit, error) { 81 sigs := make([]types.CommitSig, 0) 82 for i := 0; i < vals.Size(); i++ { 83 _, val := vals.GetByIndex(int32(i)) 84 vote, err := types.MakeVote(height, blockID, vals, privVals[val.Address.String()], chainID, time.Now()) 85 if err != nil { 86 return nil, err 87 } 88 sigs = append(sigs, vote.CommitSig()) 89 } 90 return types.NewCommit(height, 0, blockID, sigs), nil 91 } 92 93 // make some bogus txs 94 func makeTxs(height int64) (txs []types.Tx) { 95 for i := 0; i < nTxsPerBlock; i++ { 96 txs = append(txs, types.Tx([]byte{byte(height), byte(i)})) 97 } 98 return txs 99 } 100 101 func makePrivVal() types.PrivValidator { 102 pk := ed25519.GenPrivKeyFromSecret([]byte("test private validator")) 103 return types.NewMockPVWithParams(pk, false, false) 104 } 105 106 func makeState(nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValidator) { 107 vals := make([]types.GenesisValidator, nVals) 108 privVals := make(map[string]types.PrivValidator, nVals) 109 for i := 0; i < nVals; i++ { 110 secret := []byte(fmt.Sprintf("test%d", i)) 111 pk := ed25519.GenPrivKeyFromSecret(secret) 112 valAddr := pk.PubKey().Address() 113 vals[i] = types.GenesisValidator{ 114 Address: valAddr, 115 PubKey: pk.PubKey(), 116 Power: 1000, 117 Name: fmt.Sprintf("test%d", i), 118 } 119 privVals[valAddr.String()] = types.NewMockPVWithParams(pk, false, false) 120 } 121 s, _ := sm.MakeGenesisState(&types.GenesisDoc{ 122 ChainID: chainID, 123 Validators: vals, 124 AppHash: nil, 125 }) 126 127 stateDB := dbm.NewMemDB() 128 stateStore := sm.NewStore(stateDB, sm.StoreOptions{ 129 DiscardABCIResponses: false, 130 }) 131 if err := stateStore.Save(s); err != nil { 132 panic(err) 133 } 134 135 for i := 1; i < height; i++ { 136 s.LastBlockHeight++ 137 s.LastValidators = s.Validators.Copy() 138 if err := stateStore.Save(s); err != nil { 139 panic(err) 140 } 141 } 142 143 return s, stateDB, privVals 144 } 145 146 func makeBlock(state sm.State, height int64) *types.Block { 147 return makeBlockWithPrivVal(state, makePrivVal(), height) 148 } 149 150 func makeBlockWithPrivVal(state sm.State, privVal types.PrivValidator, height int64) *types.Block { 151 message := state.MakeHashMessage(0) 152 proof, _ := privVal.GenerateVRFProof(message) 153 pubKey, _ := privVal.GetPubKey() 154 block, _ := state.MakeBlock( 155 height, 156 makeTxs(state.LastBlockHeight), 157 new(types.Commit), 158 nil, 159 pubKey.Address(), 160 0, 161 proof, 162 ) 163 return block 164 } 165 166 func genValSet(size int) *types.ValidatorSet { 167 vals := make([]*types.Validator, size) 168 for i := 0; i < size; i++ { 169 vals[i] = types.NewValidator(ed25519.GenPrivKey().PubKey(), 10) 170 } 171 return types.NewValidatorSet(vals) 172 } 173 174 func makeHeaderPartsResponsesValPubKeyChange( 175 state sm.State, 176 pubkey crypto.PubKey, 177 ) (types.Header, types.Entropy, types.BlockID, *tmstate.ABCIResponses) { 178 179 block := makeBlock(state, state.LastBlockHeight+1) 180 abciResponses := &tmstate.ABCIResponses{ 181 BeginBlock: &abci.ResponseBeginBlock{}, 182 EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil}, 183 } 184 // If the pubkey is new, remove the old and add the new. 185 _, val := state.NextValidators.GetByIndex(0) 186 if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) { 187 abciResponses.EndBlock = &abci.ResponseEndBlock{ 188 ValidatorUpdates: []abci.ValidatorUpdate{ 189 types.OC2PB.NewValidatorUpdate(val.PubKey, 0), 190 types.OC2PB.NewValidatorUpdate(pubkey, 10), 191 }, 192 } 193 } 194 195 return block.Header, block.Entropy, types.BlockID{Hash: block.Hash(), PartSetHeader: types.PartSetHeader{}}, abciResponses 196 } 197 198 func makeHeaderPartsResponsesValPowerChange( 199 state sm.State, 200 power int64, 201 ) (types.Header, types.Entropy, types.BlockID, *tmstate.ABCIResponses) { 202 203 block := makeBlock(state, state.LastBlockHeight+1) 204 abciResponses := &tmstate.ABCIResponses{ 205 BeginBlock: &abci.ResponseBeginBlock{}, 206 EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil}, 207 } 208 209 // If the pubkey is new, remove the old and add the new. 210 _, val := state.NextValidators.GetByIndex(0) 211 if val.VotingPower != power { 212 abciResponses.EndBlock = &abci.ResponseEndBlock{ 213 ValidatorUpdates: []abci.ValidatorUpdate{ 214 types.OC2PB.NewValidatorUpdate(val.PubKey, power), 215 }, 216 } 217 } 218 219 return block.Header, block.Entropy, types.BlockID{Hash: block.Hash(), PartSetHeader: types.PartSetHeader{}}, abciResponses 220 } 221 222 func makeHeaderPartsResponsesParams( 223 state sm.State, 224 params tmproto.ConsensusParams, 225 ) (types.Header, types.Entropy, types.BlockID, *tmstate.ABCIResponses) { 226 227 block := makeBlock(state, state.LastBlockHeight+1) 228 abciResponses := &tmstate.ABCIResponses{ 229 BeginBlock: &abci.ResponseBeginBlock{}, 230 EndBlock: &abci.ResponseEndBlock{ConsensusParamUpdates: types.OC2PB.ConsensusParams(¶ms)}, 231 } 232 return block.Header, block.Entropy, types.BlockID{Hash: block.Hash(), PartSetHeader: types.PartSetHeader{}}, abciResponses 233 } 234 235 func randomGenesisDoc() *types.GenesisDoc { 236 pubkey := ed25519.GenPrivKey().PubKey() 237 return &types.GenesisDoc{ 238 GenesisTime: tmtime.Now(), 239 ChainID: "abc", 240 Validators: []types.GenesisValidator{ 241 { 242 Address: pubkey.Address(), 243 PubKey: pubkey, 244 Power: 10, 245 Name: "myval", 246 }, 247 }, 248 ConsensusParams: types.DefaultConsensusParams(), 249 } 250 } 251 252 //---------------------------------------------------------------------------- 253 254 type testApp struct { 255 ocabci.BaseApplication 256 257 CommitVotes []abci.VoteInfo 258 ByzantineValidators []abci.Evidence 259 ValidatorUpdates []abci.ValidatorUpdate 260 } 261 262 var _ ocabci.Application = (*testApp)(nil) 263 var TestAppVersion uint64 = 66 264 265 func (app *testApp) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) { 266 return abci.ResponseInfo{} 267 } 268 269 func (app *testApp) BeginBlock(req ocabci.RequestBeginBlock) abci.ResponseBeginBlock { 270 app.CommitVotes = req.LastCommitInfo.Votes 271 app.ByzantineValidators = req.ByzantineValidators 272 return abci.ResponseBeginBlock{} 273 } 274 275 func (app *testApp) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock { 276 return abci.ResponseEndBlock{ 277 ValidatorUpdates: app.ValidatorUpdates, 278 ConsensusParamUpdates: &abci.ConsensusParams{ 279 Version: &tmproto.VersionParams{ 280 AppVersion: TestAppVersion}}} 281 } 282 283 func (app *testApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { 284 return abci.ResponseDeliverTx{Events: []abci.Event{}} 285 } 286 287 func (app *testApp) CheckTxSync(req abci.RequestCheckTx) ocabci.ResponseCheckTx { 288 return ocabci.ResponseCheckTx{} 289 } 290 291 func (app *testApp) CheckTxAsync(req abci.RequestCheckTx, callback ocabci.CheckTxCallback) { 292 callback(ocabci.ResponseCheckTx{}) 293 } 294 295 func (app *testApp) Commit() abci.ResponseCommit { 296 return abci.ResponseCommit{RetainHeight: 1} 297 } 298 299 func (app *testApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { 300 return 301 }