github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/state/helpers_test.go (about) 1 package state_test 2 3 import ( 4 "bytes" 5 "fmt" 6 7 abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" 8 "github.com/gnolang/gno/tm2/pkg/bft/appconn" 9 "github.com/gnolang/gno/tm2/pkg/bft/proxy" 10 sm "github.com/gnolang/gno/tm2/pkg/bft/state" 11 "github.com/gnolang/gno/tm2/pkg/bft/types" 12 "github.com/gnolang/gno/tm2/pkg/crypto" 13 "github.com/gnolang/gno/tm2/pkg/crypto/ed25519" 14 dbm "github.com/gnolang/gno/tm2/pkg/db" 15 "github.com/gnolang/gno/tm2/pkg/db/memdb" 16 ) 17 18 type paramsChangeTestCase struct { 19 height int64 20 params abci.ConsensusParams 21 } 22 23 func newTestApp() appconn.AppConns { 24 app := &testApp{} 25 cc := proxy.NewLocalClientCreator(app) 26 return appconn.NewAppConns(cc) 27 } 28 29 func makeAndCommitGoodBlock( 30 state sm.State, 31 height int64, 32 lastCommit *types.Commit, 33 proposerAddr crypto.Address, 34 blockExec *sm.BlockExecutor, 35 privVals map[string]types.PrivValidator, 36 ) (sm.State, types.BlockID, *types.Commit, error) { 37 // A good block passes 38 state, blockID, err := makeAndApplyGoodBlock(state, height, lastCommit, proposerAddr, blockExec) 39 if err != nil { 40 return state, types.BlockID{}, nil, err 41 } 42 43 // Simulate a lastCommit for this block from all validators for the next height 44 commit, err := makeValidCommit(height, blockID, state.Validators, privVals) 45 if err != nil { 46 return state, types.BlockID{}, nil, err 47 } 48 return state, blockID, commit, nil 49 } 50 51 func makeAndApplyGoodBlock(state sm.State, height int64, lastCommit *types.Commit, proposerAddr crypto.Address, 52 blockExec *sm.BlockExecutor, 53 ) (sm.State, types.BlockID, error) { 54 block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, proposerAddr) 55 if err := blockExec.ValidateBlock(state, block); err != nil { 56 return state, types.BlockID{}, err 57 } 58 blockID := types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}} 59 state, err := blockExec.ApplyBlock(state, blockID, block) 60 if err != nil { 61 return state, types.BlockID{}, err 62 } 63 return state, blockID, nil 64 } 65 66 func makeValidCommit(height int64, blockID types.BlockID, vals *types.ValidatorSet, privVals map[string]types.PrivValidator) (*types.Commit, error) { 67 sigs := make([]*types.CommitSig, 0) 68 for i := 0; i < vals.Size(); i++ { 69 _, val := vals.GetByIndex(i) 70 vote, err := types.MakeVote(height, blockID, vals, privVals[val.Address.String()], chainID) 71 if err != nil { 72 return nil, err 73 } 74 sigs = append(sigs, vote.CommitSig()) 75 } 76 return types.NewCommit(blockID, sigs), nil 77 } 78 79 // make some bogus txs 80 func makeTxs(height int64) (txs []types.Tx) { 81 for i := 0; i < nTxsPerBlock; i++ { 82 txs = append(txs, types.Tx([]byte{byte(height), byte(i)})) 83 } 84 return txs 85 } 86 87 func makeState(nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValidator) { 88 vals := make([]types.GenesisValidator, nVals) 89 privVals := make(map[string]types.PrivValidator, nVals) 90 for i := 0; i < nVals; i++ { 91 secret := []byte(fmt.Sprintf("test%d", i)) 92 pk := ed25519.GenPrivKeyFromSecret(secret) 93 valAddr := pk.PubKey().Address() 94 vals[i] = types.GenesisValidator{ 95 Address: valAddr, 96 PubKey: pk.PubKey(), 97 Power: 1000, 98 Name: fmt.Sprintf("test%d", i), 99 } 100 privVals[valAddr.String()] = types.NewMockPVWithParams(pk, false, false) 101 } 102 s, _ := sm.MakeGenesisState(&types.GenesisDoc{ 103 ChainID: chainID, 104 Validators: vals, 105 AppHash: nil, 106 }) 107 108 stateDB := memdb.NewMemDB() 109 sm.SaveState(stateDB, s) 110 111 for i := 1; i < height; i++ { 112 s.LastBlockHeight++ 113 s.LastValidators = s.Validators.Copy() 114 sm.SaveState(stateDB, s) 115 } 116 return s, stateDB, privVals 117 } 118 119 func makeBlock(state sm.State, height int64) *types.Block { 120 block, _ := state.MakeBlock(height, makeTxs(state.LastBlockHeight), new(types.Commit), state.Validators.GetProposer().Address) 121 return block 122 } 123 124 func genValSet(size int) *types.ValidatorSet { 125 vals := make([]*types.Validator, size) 126 for i := 0; i < size; i++ { 127 vals[i] = types.NewValidator(ed25519.GenPrivKey().PubKey(), 10) 128 } 129 return types.NewValidatorSet(vals) 130 } 131 132 func makeConsensusParams( // XXX search and replace 133 maxTxBytes, maxDataBytes, maxBlockBytes, maxGas int64, 134 timeIotaMS int64, 135 ) abci.ConsensusParams { 136 return abci.ConsensusParams{ 137 Block: &abci.BlockParams{ 138 MaxTxBytes: maxTxBytes, 139 MaxDataBytes: maxDataBytes, 140 MaxBlockBytes: maxBlockBytes, 141 MaxGas: maxGas, 142 TimeIotaMS: timeIotaMS, 143 }, 144 } 145 } 146 147 func makeHeaderPartsResponsesValPubKeyChange(state sm.State, pubkey crypto.PubKey) (types.Header, types.BlockID, *sm.ABCIResponses) { 148 block := makeBlock(state, state.LastBlockHeight+1) 149 abciResponses := &sm.ABCIResponses{ 150 EndBlock: abci.ResponseEndBlock{ValidatorUpdates: nil}, 151 } 152 153 // If the pubkey is new, remove the old and add the new. 154 _, val := state.NextValidators.GetByIndex(0) 155 if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) { 156 abciResponses.EndBlock = abci.ResponseEndBlock{ 157 ValidatorUpdates: []abci.ValidatorUpdate{ 158 {Address: val.Address, PubKey: val.PubKey, Power: 0}, 159 {Address: pubkey.Address(), PubKey: pubkey, Power: 10}, 160 }, 161 } 162 } 163 164 return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses 165 } 166 167 func makeHeaderPartsResponsesValPowerChange(state sm.State, power int64) (types.Header, types.BlockID, *sm.ABCIResponses) { 168 block := makeBlock(state, state.LastBlockHeight+1) 169 abciResponses := &sm.ABCIResponses{ 170 EndBlock: abci.ResponseEndBlock{ValidatorUpdates: nil}, 171 } 172 173 // If the pubkey is new, remove the old and add the new. 174 _, val := state.NextValidators.GetByIndex(0) 175 if val.VotingPower != power { 176 abciResponses.EndBlock = abci.ResponseEndBlock{ 177 ValidatorUpdates: []abci.ValidatorUpdate{ 178 {Address: val.Address, PubKey: val.PubKey, Power: power}, 179 }, 180 } 181 } 182 183 return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses 184 } 185 186 func makeHeaderPartsResponsesParams(state sm.State, params abci.ConsensusParams) (types.Header, types.BlockID, *sm.ABCIResponses) { 187 block := makeBlock(state, state.LastBlockHeight+1) 188 abciResponses := &sm.ABCIResponses{ 189 EndBlock: abci.ResponseEndBlock{ConsensusParams: ¶ms}, 190 } 191 return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses 192 } 193 194 // ---------------------------------------------------------------------------- 195 196 type testApp struct { 197 abci.BaseApplication 198 199 CommitVotes []abci.VoteInfo 200 ValidatorUpdates []abci.ValidatorUpdate 201 } 202 203 var _ abci.Application = (*testApp)(nil) 204 205 func (app *testApp) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) { 206 return abci.ResponseInfo{} 207 } 208 209 func (app *testApp) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock { 210 app.CommitVotes = req.LastCommitInfo.Votes 211 return abci.ResponseBeginBlock{} 212 } 213 214 func (app *testApp) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock { 215 return abci.ResponseEndBlock{ValidatorUpdates: app.ValidatorUpdates} 216 } 217 218 func (app *testApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { 219 return abci.ResponseDeliverTx{} 220 } 221 222 func (app *testApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { 223 return abci.ResponseCheckTx{} 224 } 225 226 func (app *testApp) Commit() abci.ResponseCommit { 227 return abci.ResponseCommit{} 228 } 229 230 func (app *testApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { 231 return 232 }