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  }