github.com/KiraCore/sekai@v0.3.43/app/test_helpers.go (about)

     1  package app
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"fmt"
     8  	"strconv"
     9  	"testing"
    10  
    11  	sdkmath "cosmossdk.io/math"
    12  	stakingtypes "github.com/KiraCore/sekai/x/staking/types"
    13  	cometbftdb "github.com/cometbft/cometbft-db"
    14  	abci "github.com/cometbft/cometbft/abci/types"
    15  	"github.com/cometbft/cometbft/crypto/secp256k1"
    16  	"github.com/cometbft/cometbft/libs/log"
    17  	tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
    18  	tmtypes "github.com/cometbft/cometbft/types"
    19  	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
    20  	cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
    21  	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
    22  	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
    23  	"github.com/cosmos/cosmos-sdk/testutil/mock"
    24  	simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
    25  	sdk "github.com/cosmos/cosmos-sdk/types"
    26  	"github.com/cosmos/cosmos-sdk/types/errors"
    27  	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    28  	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
    29  	minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
    30  	"github.com/stretchr/testify/require"
    31  )
    32  
    33  // Initializes a new SekaiApp
    34  func Setup(isCheckTx bool) *SekaiApp {
    35  	db := cometbftdb.NewMemDB()
    36  	app := NewInitApp(
    37  		log.NewNopLogger(),
    38  		db,
    39  		nil,
    40  		true,
    41  		map[int64]bool{},
    42  		DefaultNodeHome,
    43  		5,
    44  		MakeEncodingConfig(),
    45  		simtestutil.EmptyAppOptions{},
    46  	)
    47  	if !isCheckTx {
    48  		genesisState := GenesisStateWithValSet(app)
    49  		stateBytes, err := json.MarshalIndent(genesisState, "", " ")
    50  		if err != nil {
    51  			panic(err)
    52  		}
    53  
    54  		app.InitChain(
    55  			abci.RequestInitChain{
    56  				Validators:      []abci.ValidatorUpdate{},
    57  				ConsensusParams: simtestutil.DefaultConsensusParams,
    58  				AppStateBytes:   stateBytes,
    59  			},
    60  		)
    61  	}
    62  
    63  	return app
    64  }
    65  
    66  func GenesisStateWithValSet(app *SekaiApp) GenesisState {
    67  	privVal := mock.NewPV()
    68  	pubKey, _ := privVal.GetPubKey()
    69  	validator := tmtypes.NewValidator(pubKey, 1)
    70  	valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
    71  
    72  	// generate genesis account
    73  	senderPrivKey := secp256k1.GenPrivKey()
    74  	senderPrivKey.PubKey().Address()
    75  	acc := authtypes.NewBaseAccountWithAddress(senderPrivKey.PubKey().Address().Bytes())
    76  	balance := banktypes.Balance{
    77  		Address: acc.GetAddress().String(),
    78  		Coins:   sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000000000000))),
    79  	}
    80  
    81  	//////////////////////
    82  	balances := []banktypes.Balance{balance}
    83  	genesisState := NewDefaultGenesisState()
    84  	genAccs := []authtypes.GenesisAccount{acc}
    85  	authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
    86  	genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
    87  
    88  	validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
    89  
    90  	initValPowers := []abci.ValidatorUpdate{}
    91  
    92  	for _, val := range valSet.Validators {
    93  		pk, _ := cryptocodec.FromTmPubKeyInterface(val.PubKey)
    94  		pkAny, _ := codectypes.NewAnyWithValue(pk)
    95  		validator := stakingtypes.Validator{
    96  			ValKey: sdk.ValAddress(val.Address),
    97  			PubKey: pkAny,
    98  			Status: stakingtypes.Active,
    99  			Rank:   0,
   100  			Streak: 0,
   101  		}
   102  		validators = append(validators, validator)
   103  
   104  		// add initial validator powers so consumer InitGenesis runs correctly
   105  		pub, _ := val.ToProto()
   106  		initValPowers = append(initValPowers, abci.ValidatorUpdate{
   107  			Power:  val.VotingPower,
   108  			PubKey: pub.PubKey,
   109  		})
   110  	}
   111  	// set validators and delegations
   112  	stakingGenesis := &stakingtypes.GenesisState{
   113  		Validators: validators,
   114  	}
   115  	genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)
   116  
   117  	totalSupply := sdk.NewCoins()
   118  	for _, b := range balances {
   119  		// add genesis acc tokens to total supply
   120  		totalSupply = totalSupply.Add(b.Coins...)
   121  	}
   122  
   123  	// update total supply
   124  	bankGenesis := banktypes.NewGenesisState(
   125  		banktypes.DefaultGenesisState().Params,
   126  		balances,
   127  		totalSupply,
   128  		[]banktypes.Metadata{},
   129  		[]banktypes.SendEnabled{},
   130  	)
   131  	genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)
   132  
   133  	return genesisState
   134  }
   135  
   136  type GenerateAccountStrategy func(int) []sdk.AccAddress
   137  
   138  // createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
   139  func createRandomAccounts(accNum int) []sdk.AccAddress {
   140  	testAddrs := make([]sdk.AccAddress, accNum)
   141  	for i := 0; i < accNum; i++ {
   142  		pk := ed25519.GenPrivKey().PubKey()
   143  		testAddrs[i] = sdk.AccAddress(pk.Address())
   144  	}
   145  
   146  	return testAddrs
   147  }
   148  
   149  // createIncrementalAccounts is a strategy used by addTestAddrs() in order to generated addresses in ascending order.
   150  func createIncrementalAccounts(accNum int) []sdk.AccAddress {
   151  	var addresses []sdk.AccAddress
   152  	var buffer bytes.Buffer
   153  
   154  	// start at 100 so we can make up to 999 test addresses with valid test addresses
   155  	for i := 100; i < (accNum + 100); i++ {
   156  		numString := strconv.Itoa(i)
   157  		buffer.WriteString("A58856F0FD53BF058B4909A21AEC019107BA6") //base address string
   158  
   159  		buffer.WriteString(numString) //adding on final two digits to make addresses unique
   160  		res, _ := sdk.AccAddressFromHexUnsafe(buffer.String())
   161  		bech := res.String()
   162  		addr, _ := TestAddr(buffer.String(), bech)
   163  
   164  		addresses = append(addresses, addr)
   165  		buffer.Reset()
   166  	}
   167  
   168  	return addresses
   169  }
   170  
   171  // AddTestAddrsFromPubKeys adds the addresses into the SimApp providing only the public keys.
   172  func AddTestAddrsFromPubKeys(app *SekaiApp, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt sdk.Int) {
   173  	initCoins := sdk.NewCoins(sdk.NewCoin(app.CustomStakingKeeper.DefaultDenom(ctx), accAmt))
   174  
   175  	// fill all the addresses with some coins, set the loose pool tokens simultaneously
   176  	for _, pubKey := range pubKeys {
   177  		saveAccount(app, ctx, sdk.AccAddress(pubKey.Address()), initCoins)
   178  	}
   179  }
   180  
   181  // AddTestAddrs constructs and returns accNum amount of accounts with an
   182  // initial balance of accAmt in random order
   183  func AddTestAddrs(app *SekaiApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress {
   184  	return addTestAddrs(app, ctx, accNum, accAmt, createRandomAccounts)
   185  }
   186  
   187  // AddTestAddrs constructs and returns accNum amount of accounts with an
   188  // initial balance of accAmt in random order
   189  func AddTestAddrsIncremental(app *SekaiApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress {
   190  	return addTestAddrs(app, ctx, accNum, accAmt, createIncrementalAccounts)
   191  }
   192  
   193  func addTestAddrs(app *SekaiApp, ctx sdk.Context, accNum int, accAmt sdk.Int, strategy GenerateAccountStrategy) []sdk.AccAddress {
   194  	testAddrs := strategy(accNum)
   195  
   196  	initCoins := sdk.NewCoins(sdk.NewCoin(app.CustomStakingKeeper.DefaultDenom(ctx), accAmt))
   197  
   198  	// fill all the addresses with some coins, set the loose pool tokens simultaneously
   199  	for _, addr := range testAddrs {
   200  		saveAccount(app, ctx, addr, initCoins)
   201  	}
   202  
   203  	return testAddrs
   204  }
   205  
   206  // saveAccount saves the provided account into the simapp with balance based on initCoins.
   207  func saveAccount(app *SekaiApp, ctx sdk.Context, addr sdk.AccAddress, initCoins sdk.Coins) {
   208  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   209  	app.AccountKeeper.SetAccount(ctx, acc)
   210  	err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, initCoins)
   211  	if err != nil {
   212  		panic(err)
   213  	}
   214  	err = app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, initCoins)
   215  	if err != nil {
   216  		panic(err)
   217  	}
   218  }
   219  
   220  // ConvertAddrsToValAddrs converts the provided addresses to ValAddress.
   221  func ConvertAddrsToValAddrs(addrs []sdk.AccAddress) []sdk.ValAddress {
   222  	valAddrs := make([]sdk.ValAddress, len(addrs))
   223  
   224  	for i, addr := range addrs {
   225  		valAddrs[i] = sdk.ValAddress(addr)
   226  	}
   227  
   228  	return valAddrs
   229  }
   230  
   231  func TestAddr(addr string, bech string) (sdk.AccAddress, error) {
   232  	res, err := sdk.AccAddressFromHexUnsafe(addr)
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  	bechexpected := res.String()
   237  	if bech != bechexpected {
   238  		return nil, fmt.Errorf("bech encoding doesn't match reference")
   239  	}
   240  
   241  	bechres, err := sdk.AccAddressFromBech32(bech)
   242  	if err != nil {
   243  		return nil, err
   244  	}
   245  	if !bytes.Equal(bechres, res) {
   246  		return nil, err
   247  	}
   248  
   249  	return res, nil
   250  }
   251  
   252  // CheckBalance checks the balance of an account.
   253  func CheckBalance(t *testing.T, app *SekaiApp, addr sdk.AccAddress, balances sdk.Coins) {
   254  	ctxCheck := app.BaseApp.NewContext(true, tmproto.Header{})
   255  	require.True(t, balances.IsEqual(app.BankKeeper.GetAllBalances(ctxCheck, addr)))
   256  }
   257  
   258  func incrementAllSequenceNumbers(initSeqNums []uint64) {
   259  	for i := 0; i < len(initSeqNums); i++ {
   260  		initSeqNums[i]++
   261  	}
   262  }
   263  
   264  // CreateTestPubKeys returns a total of numPubKeys public keys in ascending order.
   265  func CreateTestPubKeys(numPubKeys int) []cryptotypes.PubKey {
   266  	var publicKeys []cryptotypes.PubKey
   267  	var buffer bytes.Buffer
   268  
   269  	// start at 10 to avoid changing 1 to 01, 2 to 02, etc
   270  	for i := 100; i < (numPubKeys + 100); i++ {
   271  		numString := strconv.Itoa(i)
   272  		buffer.WriteString("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AF") // base pubkey string
   273  		buffer.WriteString(numString)                                                       // adding on final two digits to make pubkeys unique
   274  		publicKeys = append(publicKeys, NewPubKeyFromHex(buffer.String()))
   275  		buffer.Reset()
   276  	}
   277  
   278  	return publicKeys
   279  }
   280  
   281  // NewPubKeyFromHex returns a PubKey from a hex string.
   282  func NewPubKeyFromHex(pk string) (res cryptotypes.PubKey) {
   283  	pkBytes, err := hex.DecodeString(pk)
   284  	if err != nil {
   285  		panic(err)
   286  	}
   287  	if len(pkBytes) != ed25519.PubKeySize {
   288  		panic(errors.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size"))
   289  	}
   290  	return &ed25519.PubKey{Key: pkBytes}
   291  }
   292  
   293  // EmptyAppOptions is a stub implementing AppOptions
   294  type EmptyAppOptions struct{}
   295  
   296  // Get implements AppOptions
   297  func (ao EmptyAppOptions) Get(o string) interface{} {
   298  	return nil
   299  }