github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/params/proposal_handler_test.go (about) 1 package params 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 8 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store" 9 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/mpt" 10 storetypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types" 11 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 12 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 13 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/bank" 14 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 15 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/secp256k1" 16 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 17 tmdb "github.com/fibonacci-chain/fbc/libs/tm-db" 18 govtypes "github.com/fibonacci-chain/fbc/x/gov/types" 19 "github.com/fibonacci-chain/fbc/x/params/types" 20 "github.com/stretchr/testify/suite" 21 ) 22 23 type mockStakingKeeper struct { 24 vals map[string]struct{} 25 } 26 27 func newMockStakingKeeper(vals ...sdk.AccAddress) *mockStakingKeeper { 28 valsMap := make(map[string]struct{}) 29 for _, val := range vals { 30 valsMap[val.String()] = struct{}{} 31 } 32 return &mockStakingKeeper{valsMap} 33 } 34 35 func (sk *mockStakingKeeper) IsValidator(_ sdk.Context, addr sdk.AccAddress) bool { 36 _, ok := sk.vals[addr.String()] 37 return ok 38 } 39 40 func makeTestCodec() *codec.Codec { 41 var cdc = codec.New() 42 auth.RegisterCodec(cdc) 43 RegisterCodec(cdc) 44 codec.RegisterCrypto(cdc) 45 46 return cdc 47 } 48 49 type ProposalHandlerSuite struct { 50 suite.Suite 51 ms storetypes.CommitMultiStore 52 paramsKeeper Keeper 53 bankKeeper bank.BaseKeeper 54 55 validatorPriv secp256k1.PrivKeySecp256k1 56 regularPriv secp256k1.PrivKeySecp256k1 57 } 58 59 func TestProposalHandler(t *testing.T) { 60 suite.Run(t, new(ProposalHandlerSuite)) 61 } 62 63 func (suite *ProposalHandlerSuite) SetupTest() { 64 db := tmdb.NewMemDB() 65 storeKey := sdk.NewKVStoreKey(StoreKey) 66 tstoreKey := sdk.NewTransientStoreKey(TStoreKey) 67 keyAcc := sdk.NewKVStoreKey(auth.StoreKey) 68 keyMpt := sdk.NewKVStoreKey(mpt.StoreKey) 69 70 suite.ms = store.NewCommitMultiStore(tmdb.NewMemDB()) 71 suite.ms.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db) 72 suite.ms.MountStoreWithDB(tstoreKey, sdk.StoreTypeTransient, db) 73 suite.ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db) 74 suite.ms.MountStoreWithDB(keyMpt, sdk.StoreTypeMPT, db) 75 err := suite.ms.LoadLatestVersion() 76 suite.NoError(err) 77 78 cdc := makeTestCodec() 79 80 suite.paramsKeeper = NewKeeper(cdc, storeKey, tstoreKey, log.NewNopLogger()) 81 82 accountKeeper := auth.NewAccountKeeper( 83 cdc, 84 keyAcc, 85 keyMpt, 86 suite.paramsKeeper.Subspace(auth.DefaultParamspace), 87 auth.ProtoBaseAccount, // prototype 88 ) 89 suite.bankKeeper = bank.NewBaseKeeper( 90 accountKeeper, 91 suite.paramsKeeper.Subspace(bank.DefaultParamspace), 92 make(map[string]bool), 93 ) 94 95 suite.validatorPriv = secp256k1.GenPrivKeySecp256k1([]byte("private key to validator")) 96 suite.regularPriv = secp256k1.GenPrivKeySecp256k1([]byte("private key to regular")) 97 98 suite.paramsKeeper.SetStakingKeeper(newMockStakingKeeper(sdk.AccAddress(suite.validatorPriv.PubKey().Address()))) 99 suite.paramsKeeper.SetBankKeeper(suite.bankKeeper) 100 } 101 102 func (suite *ProposalHandlerSuite) Context(height int64) sdk.Context { 103 return sdk.NewContext(suite.ms, abci.Header{Height: height}, false, log.NewNopLogger()) 104 } 105 106 func (suite *ProposalHandlerSuite) TestCheckUpgradeProposal() { 107 minDeposit := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))) 108 109 tests := []struct { 110 proposer sdk.AccAddress 111 proposerCoins sdk.SysCoins 112 proposalInitDeposit sdk.SysCoins 113 expectHeight uint64 114 currentHeight int64 115 maxBlockHeight uint64 116 nameHasExist bool 117 expectError bool 118 }{ 119 { // proposer is not a validator 120 proposer: sdk.AccAddress(suite.regularPriv.PubKey().Address()), 121 proposerCoins: minDeposit.MulDec(sdk.NewDecWithPrec(3, 0)), 122 proposalInitDeposit: minDeposit.MulDec(sdk.NewDecWithPrec(2, 0)), 123 expectHeight: 20, 124 currentHeight: 10, 125 maxBlockHeight: 100, 126 expectError: true, 127 }, 128 { // proposer has no enough coins 129 proposer: sdk.AccAddress(suite.validatorPriv.PubKey().Address()), 130 proposerCoins: minDeposit.MulDec(sdk.NewDecWithPrec(1, 0)), 131 proposalInitDeposit: minDeposit.MulDec(sdk.NewDecWithPrec(2, 0)), 132 expectHeight: 20, 133 currentHeight: 10, 134 maxBlockHeight: 100, 135 expectError: true, 136 }, 137 { // proposal init coin is too small 138 proposer: sdk.AccAddress(suite.validatorPriv.PubKey().Address()), 139 proposerCoins: minDeposit.MulDec(sdk.NewDecWithPrec(2, 0)), 140 proposalInitDeposit: minDeposit.MulDec(sdk.NewDecWithPrec(1, 2)), 141 expectHeight: 20, 142 currentHeight: 10, 143 maxBlockHeight: 100, 144 expectError: true, 145 }, 146 { // expectHeight is not zero and smaller than current height 147 proposer: sdk.AccAddress(suite.validatorPriv.PubKey().Address()), 148 proposerCoins: minDeposit.MulDec(sdk.NewDecWithPrec(3, 0)), 149 proposalInitDeposit: minDeposit.MulDec(sdk.NewDecWithPrec(2, 0)), 150 expectHeight: 10, 151 currentHeight: 11, 152 maxBlockHeight: 100, 153 expectError: true, 154 }, 155 { // expectHeight is not zero and equal current height 156 proposer: sdk.AccAddress(suite.validatorPriv.PubKey().Address()), 157 proposerCoins: minDeposit.MulDec(sdk.NewDecWithPrec(3, 0)), 158 proposalInitDeposit: minDeposit.MulDec(sdk.NewDecWithPrec(2, 0)), 159 expectHeight: 11, 160 currentHeight: 11, 161 maxBlockHeight: 100, 162 expectError: true, 163 }, 164 { // expectHeight is not zero but too far away from current height 165 proposer: sdk.AccAddress(suite.validatorPriv.PubKey().Address()), 166 proposerCoins: minDeposit.MulDec(sdk.NewDecWithPrec(3, 0)), 167 proposalInitDeposit: minDeposit.MulDec(sdk.NewDecWithPrec(2, 0)), 168 expectHeight: 22, 169 currentHeight: 11, 170 maxBlockHeight: 10, 171 expectError: true, 172 }, 173 { // expectHeight is 0 174 proposer: sdk.AccAddress(suite.validatorPriv.PubKey().Address()), 175 proposerCoins: minDeposit.MulDec(sdk.NewDecWithPrec(3, 0)), 176 proposalInitDeposit: minDeposit.MulDec(sdk.NewDecWithPrec(2, 0)), 177 expectHeight: 0, 178 currentHeight: 11, 179 maxBlockHeight: 10, 180 expectError: false, 181 }, 182 { // expectHeight is not zero but name has been exist 183 proposer: sdk.AccAddress(suite.validatorPriv.PubKey().Address()), 184 proposerCoins: minDeposit.MulDec(sdk.NewDecWithPrec(3, 0)), 185 proposalInitDeposit: minDeposit.MulDec(sdk.NewDecWithPrec(2, 0)), 186 expectHeight: 12, 187 currentHeight: 11, 188 maxBlockHeight: 10, 189 nameHasExist: true, 190 expectError: true, 191 }, 192 193 { // expectHeight is not zero and every thing is ok 194 proposer: sdk.AccAddress(suite.validatorPriv.PubKey().Address()), 195 proposerCoins: minDeposit.MulDec(sdk.NewDecWithPrec(3, 0)), 196 proposalInitDeposit: minDeposit.MulDec(sdk.NewDecWithPrec(2, 0)), 197 expectHeight: 12, 198 currentHeight: 11, 199 maxBlockHeight: 10, 200 expectError: false, 201 }, 202 } 203 204 for i, tt := range tests { 205 ctx := suite.Context(tt.currentHeight) 206 err := suite.bankKeeper.SetCoins(ctx, tt.proposer, tt.proposerCoins) 207 suite.NoError(err) 208 param := types.DefaultParams() 209 param.MaxBlockHeight = tt.maxBlockHeight 210 param.MinDeposit = minDeposit 211 suite.paramsKeeper.SetParams(ctx, param) 212 213 upgradeProposal := types.NewUpgradeProposal("title", "desc", fmt.Sprintf("upgrade-name-%d", i), tt.expectHeight, "") 214 msg := govtypes.NewMsgSubmitProposal(upgradeProposal, tt.proposalInitDeposit, tt.proposer) 215 if tt.nameHasExist { 216 info := types.UpgradeInfo{ 217 Name: upgradeProposal.Name, 218 ExpectHeight: upgradeProposal.ExpectHeight, 219 Config: upgradeProposal.Config, 220 EffectiveHeight: 0, 221 Status: 0, 222 } 223 suite.NoError(suite.paramsKeeper.writeUpgradeInfo(ctx, info, false)) 224 } 225 226 err = suite.paramsKeeper.CheckMsgSubmitProposal(ctx, msg) 227 if tt.expectError { 228 suite.Error(err) 229 continue 230 } 231 232 suite.NoError(err) 233 if !tt.nameHasExist { 234 _, err := suite.paramsKeeper.readUpgradeInfo(ctx, upgradeProposal.Name) 235 suite.Error(err) 236 } 237 } 238 239 } 240 241 func (suite *ProposalHandlerSuite) TestCheckUpgradeVote() { 242 tests := []struct { 243 expectHeight uint64 244 currentHeight int64 245 expectError bool 246 }{ 247 {0, 10, false}, 248 {0, 1111, false}, 249 {10, 11, true}, 250 {10, 10, true}, 251 {10, 9, false}, 252 } 253 254 for i, tt := range tests { 255 ctx := suite.Context(tt.currentHeight) 256 content := types.UpgradeProposal{ExpectHeight: tt.expectHeight} 257 proposal := govtypes.Proposal{Content: content, ProposalID: uint64(i)} 258 vote := govtypes.Vote{} 259 260 _, err := suite.paramsKeeper.VoteHandler(ctx, proposal, vote) 261 if tt.expectError { 262 suite.Error(err) 263 } else { 264 suite.NoError(err) 265 } 266 } 267 } 268 269 func (suite *ProposalHandlerSuite) TestAfterSubmitProposalHandler() { 270 ctx := suite.Context(10) 271 expectInfo := types.UpgradeInfo{ 272 Name: "name1", 273 EffectiveHeight: 0, 274 Status: types.UpgradeStatusEffective, 275 } 276 proposal := govtypes.Proposal{ 277 Content: types.UpgradeProposal{ 278 Name: expectInfo.Name, 279 ExpectHeight: expectInfo.ExpectHeight, 280 Config: expectInfo.Config, 281 }, 282 ProposalID: 1, 283 } 284 285 suite.paramsKeeper.AfterSubmitProposalHandler(ctx, proposal) 286 287 expectInfo.Status = types.UpgradeStatusPreparing 288 info, err := suite.paramsKeeper.readUpgradeInfo(ctx, expectInfo.Name) 289 suite.NoError(err) 290 suite.Equal(expectInfo, info) 291 }