github.com/cosmos/cosmos-sdk@v0.50.10/x/auth/keeper/deterministic_test.go (about) 1 package keeper_test 2 3 import ( 4 "encoding/hex" 5 "sort" 6 "sync/atomic" 7 "testing" 8 9 "github.com/stretchr/testify/suite" 10 "pgregory.net/rapid" 11 12 "cosmossdk.io/core/header" 13 corestore "cosmossdk.io/core/store" 14 storetypes "cosmossdk.io/store/types" 15 16 "github.com/cosmos/cosmos-sdk/baseapp" 17 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" 18 "github.com/cosmos/cosmos-sdk/runtime" 19 "github.com/cosmos/cosmos-sdk/testutil" 20 "github.com/cosmos/cosmos-sdk/testutil/testdata" 21 sdk "github.com/cosmos/cosmos-sdk/types" 22 moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 23 "github.com/cosmos/cosmos-sdk/x/auth" 24 authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" 25 "github.com/cosmos/cosmos-sdk/x/auth/keeper" 26 "github.com/cosmos/cosmos-sdk/x/auth/types" 27 ) 28 29 type DeterministicTestSuite struct { 30 suite.Suite 31 32 accountNumberLanes uint64 33 34 key *storetypes.KVStoreKey 35 storeService corestore.KVStoreService 36 ctx sdk.Context 37 queryClient types.QueryClient 38 accountKeeper keeper.AccountKeeper 39 encCfg moduletestutil.TestEncodingConfig 40 maccPerms map[string][]string 41 } 42 43 var ( 44 addr = sdk.MustAccAddressFromBech32("cosmos1j364pjm8jkxxmujj0vp2xjg0y7w8tyveuamfm6") 45 pub, _ = hex.DecodeString("01090C02812F010C25200ED40E004105160196E801F70005070EA21603FF06001E") 46 permissions = []string{"burner", "minter", "staking", "random"} 47 ) 48 49 func TestDeterministicTestSuite(t *testing.T) { 50 suite.Run(t, new(DeterministicTestSuite)) 51 } 52 53 func (suite *DeterministicTestSuite) SetupTest() { 54 suite.encCfg = moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}) 55 56 suite.Require() 57 key := storetypes.NewKVStoreKey(types.StoreKey) 58 storeService := runtime.NewKVStoreService(key) 59 testCtx := testutil.DefaultContextWithDB(suite.T(), key, storetypes.NewTransientStoreKey("transient_test")) 60 suite.ctx = testCtx.Ctx.WithHeaderInfo(header.Info{}) 61 62 maccPerms := map[string][]string{ 63 "fee_collector": nil, 64 "mint": {"minter"}, 65 "bonded_tokens_pool": {"burner", "staking"}, 66 "not_bonded_tokens_pool": {"burner", "staking"}, 67 multiPerm: {"burner", "minter", "staking"}, 68 randomPerm: {"random"}, 69 } 70 71 suite.accountKeeper = keeper.NewAccountKeeper( 72 suite.encCfg.Codec, 73 storeService, 74 types.ProtoBaseAccount, 75 maccPerms, 76 authcodec.NewBech32Codec("cosmos"), 77 "cosmos", 78 types.NewModuleAddress("gov").String(), 79 ) 80 81 queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.encCfg.InterfaceRegistry) 82 types.RegisterQueryServer(queryHelper, keeper.NewQueryServer(suite.accountKeeper)) 83 suite.queryClient = types.NewQueryClient(queryHelper) 84 85 suite.key = key 86 suite.storeService = storeService 87 suite.maccPerms = maccPerms 88 suite.accountNumberLanes = 1 89 } 90 91 // createAndSetAccount creates a random account and sets to the keeper store. 92 func (suite *DeterministicTestSuite) createAndSetAccounts(t *rapid.T, count int) []sdk.AccountI { 93 accs := make([]sdk.AccountI, 0, count) 94 95 // We need all generated account-numbers unique 96 accNums := rapid.SliceOfNDistinct(rapid.Uint64(), count, count, func(i uint64) uint64 { 97 return i 98 }).Draw(t, "acc-nums") 99 100 // then we change account numbers in such a way that there cannot be accounts with the same account number 101 lane := atomic.AddUint64(&suite.accountNumberLanes, 1) 102 for i := range accNums { 103 accNums[i] += lane * 1000 104 } 105 106 for i := 0; i < count; i++ { 107 pub := pubkeyGenerator(t).Draw(t, "pubkey") 108 addr := sdk.AccAddress(pub.Address()) 109 accNum := accNums[i] 110 seq := rapid.Uint64().Draw(t, "sequence") 111 112 acc1 := types.NewBaseAccount(addr, &pub, accNum, seq) 113 suite.accountKeeper.SetAccount(suite.ctx, acc1) 114 accs = append(accs, acc1) 115 } 116 return accs 117 } 118 119 func (suite *DeterministicTestSuite) TestGRPCQueryAccount() { 120 rapid.Check(suite.T(), func(t *rapid.T) { 121 accs := suite.createAndSetAccounts(t, 1) 122 req := &types.QueryAccountRequest{Address: accs[0].GetAddress().String()} 123 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.Account, 0, true) 124 }) 125 126 // Regression tests 127 accNum := uint64(10087) 128 seq := uint64(98) 129 130 acc1 := types.NewBaseAccount(addr, &secp256k1.PubKey{Key: pub}, accNum, seq) 131 suite.accountKeeper.SetAccount(suite.ctx, acc1) 132 133 req := &types.QueryAccountRequest{Address: acc1.GetAddress().String()} 134 135 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.Account, 1543, false) 136 } 137 138 // pubkeyGenerator creates and returns a random pubkey generator using rapid. 139 func pubkeyGenerator(t *rapid.T) *rapid.Generator[secp256k1.PubKey] { 140 return rapid.Custom(func(t *rapid.T) secp256k1.PubKey { 141 pkBz := rapid.SliceOfN(rapid.Byte(), 33, 33).Draw(t, "hex") 142 return secp256k1.PubKey{Key: pkBz} 143 }) 144 } 145 146 func (suite *DeterministicTestSuite) TestGRPCQueryAccounts() { 147 rapid.Check(suite.T(), func(t *rapid.T) { 148 numAccs := rapid.IntRange(1, 10).Draw(t, "accounts") 149 accs := suite.createAndSetAccounts(t, numAccs) 150 151 req := &types.QueryAccountsRequest{Pagination: testdata.PaginationGenerator(t, uint64(numAccs)).Draw(t, "accounts")} 152 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.Accounts, 0, true) 153 154 for i := 0; i < numAccs; i++ { 155 suite.accountKeeper.RemoveAccount(suite.ctx, accs[i]) 156 } 157 }) 158 159 // Regression test 160 addr1, err := suite.accountKeeper.AddressCodec().StringToBytes("cosmos1892yr6fzlj7ud0kfkah2ctrav3a4p4n060ze8f") 161 suite.Require().NoError(err) 162 pub1, err := hex.DecodeString("D1002E1B019000010BB7034500E71F011F1CA90D5B000E134BFB0F3603030D0303") 163 suite.Require().NoError(err) 164 accNum1 := uint64(107) 165 seq1 := uint64(10001) 166 167 accNum2 := uint64(100) 168 seq2 := uint64(10) 169 170 acc1 := types.NewBaseAccount(addr1, &secp256k1.PubKey{Key: pub1}, accNum1, seq1) 171 acc2 := types.NewBaseAccount(addr, &secp256k1.PubKey{Key: pub}, accNum2, seq2) 172 173 suite.accountKeeper.SetAccount(suite.ctx, acc1) 174 suite.accountKeeper.SetAccount(suite.ctx, acc2) 175 176 req := &types.QueryAccountsRequest{} 177 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.Accounts, 1716, false) 178 } 179 180 func (suite *DeterministicTestSuite) TestGRPCQueryAccountAddressByID() { 181 rapid.Check(suite.T(), func(t *rapid.T) { 182 accs := suite.createAndSetAccounts(t, 1) 183 req := &types.QueryAccountAddressByIDRequest{AccountId: accs[0].GetAccountNumber()} 184 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.AccountAddressByID, 0, true) 185 }) 186 187 // Regression test 188 accNum := uint64(10087) 189 seq := uint64(0) 190 191 acc1 := types.NewBaseAccount(addr, &secp256k1.PubKey{Key: pub}, accNum, seq) 192 193 suite.accountKeeper.SetAccount(suite.ctx, acc1) 194 req := &types.QueryAccountAddressByIDRequest{AccountId: accNum} 195 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.AccountAddressByID, 1123, false) 196 } 197 198 func (suite *DeterministicTestSuite) TestGRPCQueryParameters() { 199 rapid.Check(suite.T(), func(t *rapid.T) { 200 params := types.NewParams( 201 rapid.Uint64Min(1).Draw(t, "max-memo-characters"), 202 rapid.Uint64Min(1).Draw(t, "tx-sig-limit"), 203 rapid.Uint64Min(1).Draw(t, "tx-size-cost-per-byte"), 204 rapid.Uint64Min(1).Draw(t, "sig-verify-cost-ed25519"), 205 rapid.Uint64Min(1).Draw(t, "sig-verify-cost-Secp256k1"), 206 ) 207 err := suite.accountKeeper.Params.Set(suite.ctx, params) 208 suite.Require().NoError(err) 209 210 req := &types.QueryParamsRequest{} 211 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.Params, 0, true) 212 }) 213 214 // Regression test 215 params := types.NewParams(15, 167, 100, 1, 21457) 216 217 err := suite.accountKeeper.Params.Set(suite.ctx, params) 218 suite.Require().NoError(err) 219 220 req := &types.QueryParamsRequest{} 221 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.Params, 1042, false) 222 } 223 224 func (suite *DeterministicTestSuite) TestGRPCQueryAccountInfo() { 225 rapid.Check(suite.T(), func(t *rapid.T) { 226 accs := suite.createAndSetAccounts(t, 1) 227 suite.Require().Len(accs, 1) 228 229 req := &types.QueryAccountInfoRequest{Address: accs[0].GetAddress().String()} 230 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.AccountInfo, 0, true) 231 }) 232 233 // Regression test 234 accNum := uint64(10087) 235 seq := uint64(10) 236 237 acc := types.NewBaseAccount(addr, &secp256k1.PubKey{Key: pub}, accNum, seq) 238 239 suite.accountKeeper.SetAccount(suite.ctx, acc) 240 req := &types.QueryAccountInfoRequest{Address: acc.GetAddress().String()} 241 testdata.DeterministicIterations(suite.ctx, suite.T(), req, suite.queryClient.AccountInfo, 1543, false) 242 } 243 244 func (suite *DeterministicTestSuite) createAndReturnQueryClient(ak keeper.AccountKeeper) types.QueryClient { 245 queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.encCfg.InterfaceRegistry) 246 types.RegisterQueryServer(queryHelper, keeper.NewQueryServer(ak)) 247 return types.NewQueryClient(queryHelper) 248 } 249 250 func (suite *DeterministicTestSuite) setModuleAccounts( 251 ctx sdk.Context, ak keeper.AccountKeeper, maccs []string, 252 ) []sdk.AccountI { 253 sort.Strings(maccs) 254 moduleAccounts := make([]sdk.AccountI, 0, len(maccs)) 255 for _, m := range maccs { 256 acc, _ := ak.GetModuleAccountAndPermissions(ctx, m) 257 acc1, ok := acc.(sdk.AccountI) 258 suite.Require().True(ok) 259 moduleAccounts = append(moduleAccounts, acc1) 260 } 261 262 return moduleAccounts 263 } 264 265 func (suite *DeterministicTestSuite) TestGRPCQueryModuleAccounts() { 266 rapid.Check(suite.T(), func(t *rapid.T) { 267 maccsCount := rapid.IntRange(1, 10).Draw(t, "accounts") 268 maccs := make([]string, maccsCount) 269 270 for i := 0; i < maccsCount; i++ { 271 maccs[i] = rapid.StringMatching(`[a-z]{5,}`).Draw(t, "module-name") 272 } 273 274 maccPerms := make(map[string][]string) 275 for i := 0; i < maccsCount; i++ { 276 mPerms := make([]string, 0, 4) 277 for _, permission := range permissions { 278 if rapid.Bool().Draw(t, "permissions") { 279 mPerms = append(mPerms, permission) 280 } 281 } 282 283 if len(mPerms) == 0 { 284 num := rapid.IntRange(0, 3).Draw(t, "num") 285 mPerms = append(mPerms, permissions[num]) 286 } 287 288 maccPerms[maccs[i]] = mPerms 289 } 290 291 ak := keeper.NewAccountKeeper( 292 suite.encCfg.Codec, 293 suite.storeService, 294 types.ProtoBaseAccount, 295 maccPerms, 296 authcodec.NewBech32Codec("cosmos"), 297 "cosmos", 298 types.NewModuleAddress("gov").String(), 299 ) 300 suite.setModuleAccounts(suite.ctx, ak, maccs) 301 302 queryClient := suite.createAndReturnQueryClient(ak) 303 req := &types.QueryModuleAccountsRequest{} 304 testdata.DeterministicIterations(suite.ctx, suite.T(), req, queryClient.ModuleAccounts, 0, true) 305 }) 306 307 maccs := make([]string, 0, len(suite.maccPerms)) 308 for k := range suite.maccPerms { 309 maccs = append(maccs, k) 310 } 311 312 suite.setModuleAccounts(suite.ctx, suite.accountKeeper, maccs) 313 314 queryClient := suite.createAndReturnQueryClient(suite.accountKeeper) 315 req := &types.QueryModuleAccountsRequest{} 316 testdata.DeterministicIterations(suite.ctx, suite.T(), req, queryClient.ModuleAccounts, 8565, false) 317 } 318 319 func (suite *DeterministicTestSuite) TestGRPCQueryModuleAccountByName() { 320 rapid.Check(suite.T(), func(t *rapid.T) { 321 mName := rapid.StringMatching(`[a-z]{5,}`).Draw(t, "module-name") 322 323 maccPerms := make(map[string][]string) 324 mPerms := make([]string, 0, 4) 325 for _, permission := range permissions { 326 if rapid.Bool().Draw(t, "permissions") { 327 mPerms = append(mPerms, permission) 328 } 329 } 330 331 if len(mPerms) == 0 { 332 num := rapid.IntRange(0, 3).Draw(t, "num") 333 mPerms = append(mPerms, permissions[num]) 334 } 335 336 maccPerms[mName] = mPerms 337 338 ak := keeper.NewAccountKeeper( 339 suite.encCfg.Codec, 340 suite.storeService, 341 types.ProtoBaseAccount, 342 maccPerms, 343 authcodec.NewBech32Codec("cosmos"), 344 "cosmos", 345 types.NewModuleAddress("gov").String(), 346 ) 347 suite.setModuleAccounts(suite.ctx, ak, []string{mName}) 348 349 queryClient := suite.createAndReturnQueryClient(ak) 350 req := &types.QueryModuleAccountByNameRequest{Name: mName} 351 testdata.DeterministicIterations(suite.ctx, suite.T(), req, queryClient.ModuleAccountByName, 0, true) 352 }) 353 354 maccs := make([]string, 0, len(suite.maccPerms)) 355 for k := range suite.maccPerms { 356 maccs = append(maccs, k) 357 } 358 359 suite.setModuleAccounts(suite.ctx, suite.accountKeeper, maccs) 360 361 queryClient := suite.createAndReturnQueryClient(suite.accountKeeper) 362 req := &types.QueryModuleAccountByNameRequest{Name: "mint"} 363 testdata.DeterministicIterations(suite.ctx, suite.T(), req, queryClient.ModuleAccountByName, 1372, false) 364 }