github.com/okex/exchain@v1.8.0/libs/ibc-go/testing/simapp/test_helpers.go (about)

     1  package simapp
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"fmt"
     8  	"github.com/okex/exchain/libs/cosmos-sdk/client"
     9  	ibcmsg "github.com/okex/exchain/libs/cosmos-sdk/types/ibc-adapter"
    10  	"math/big"
    11  	"strconv"
    12  	"testing"
    13  	"time"
    14  
    15  	abci "github.com/okex/exchain/libs/tendermint/abci/types"
    16  	tmproto "github.com/okex/exchain/libs/tendermint/abci/types"
    17  	"github.com/okex/exchain/libs/tendermint/libs/log"
    18  	tmtypes "github.com/okex/exchain/libs/tendermint/types"
    19  	dbm "github.com/okex/exchain/libs/tm-db"
    20  	"github.com/stretchr/testify/require"
    21  
    22  	bam "github.com/okex/exchain/libs/cosmos-sdk/baseapp"
    23  	cryptotypes "github.com/okex/exchain/libs/cosmos-sdk/crypto/types"
    24  	sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
    25  	"github.com/okex/exchain/libs/cosmos-sdk/types/errors"
    26  	authtypes "github.com/okex/exchain/libs/cosmos-sdk/x/auth"
    27  	authexported "github.com/okex/exchain/libs/cosmos-sdk/x/auth/exported"
    28  	minttypes "github.com/okex/exchain/libs/cosmos-sdk/x/mint"
    29  	"github.com/okex/exchain/libs/ibc-go/testing/simapp/helpers"
    30  	cryptotypes2 "github.com/okex/exchain/libs/tendermint/crypto"
    31  	"github.com/okex/exchain/libs/tendermint/crypto/ed25519"
    32  )
    33  
    34  // DefaultConsensusParams defines the default Tendermint consensus params used in
    35  // SimApp testing.
    36  var DefaultConsensusParams = &abci.ConsensusParams{
    37  	Block: &abci.BlockParams{
    38  		MaxBytes: 200000,
    39  		MaxGas:   2000000,
    40  	},
    41  	Evidence: &tmproto.EvidenceParams{
    42  		MaxAgeNumBlocks: 302400,
    43  		MaxAgeDuration:  504 * time.Hour, // 3 weeks is the max duration
    44  		//MaxBytes:        10000,
    45  	},
    46  	Validator: &tmproto.ValidatorParams{
    47  		PubKeyTypes: []string{
    48  			tmtypes.ABCIPubKeyTypeEd25519,
    49  		},
    50  	},
    51  }
    52  
    53  func setup(withGenesis bool, invCheckPeriod uint) (*SimApp, GenesisState) {
    54  	db := dbm.NewMemDB()
    55  	app := NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, invCheckPeriod)
    56  	if withGenesis {
    57  		return app, NewDefaultGenesisState()
    58  	}
    59  	return app, GenesisState{}
    60  }
    61  
    62  // Setup initializes a new SimApp. A Nop logger is set in SimApp.
    63  func Setup(isCheckTx bool) *SimApp {
    64  	app, genesisState := setup(!isCheckTx, 5)
    65  	if !isCheckTx {
    66  		// init chain must be called to stop deliverState from being nil
    67  		stateBytes, err := json.MarshalIndent(genesisState, "", " ")
    68  		if err != nil {
    69  			panic(err)
    70  		}
    71  
    72  		// Initialize the chain
    73  		app.InitChain(
    74  			abci.RequestInitChain{
    75  				Validators:      []abci.ValidatorUpdate{},
    76  				ConsensusParams: DefaultConsensusParams,
    77  				AppStateBytes:   stateBytes,
    78  			},
    79  		)
    80  	}
    81  
    82  	return app
    83  }
    84  
    85  // SetupWithGenesisAccounts initializes a new SimApp with the provided genesis
    86  // accounts and possible balances.
    87  func SetupWithGenesisAccounts(genAccs []authexported.GenesisAccount, balances sdk.Coins) *SimApp {
    88  	app, genesisState := setup(true, 0)
    89  	authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
    90  	genesisState[authtypes.ModuleName] = app.AppCodec().GetCdc().MustMarshalJSON(authGenesis)
    91  
    92  	totalSupply := sdk.NewCoins()
    93  	for _, b := range balances {
    94  		totalSupply = totalSupply.Add(b)
    95  	}
    96  
    97  	stateBytes, err := json.MarshalIndent(genesisState, "", " ")
    98  	if err != nil {
    99  		panic(err)
   100  	}
   101  
   102  	app.InitChain(
   103  		abci.RequestInitChain{
   104  			Validators:      []abci.ValidatorUpdate{},
   105  			ConsensusParams: DefaultConsensusParams,
   106  			AppStateBytes:   stateBytes,
   107  		},
   108  	)
   109  
   110  	app.Commit(tmproto.RequestCommit{})
   111  	app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: app.LastBlockHeight() + 1}})
   112  
   113  	return app
   114  }
   115  
   116  type GenerateAccountStrategy func(int) []sdk.AccAddress
   117  
   118  // createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
   119  func createRandomAccounts(accNum int) []sdk.AccAddress {
   120  	testAddrs := make([]sdk.AccAddress, accNum)
   121  	for i := 0; i < accNum; i++ {
   122  		pk := ed25519.GenPrivKey().PubKey()
   123  		testAddrs[i] = sdk.AccAddress(pk.Address())
   124  	}
   125  
   126  	return testAddrs
   127  }
   128  
   129  // createIncrementalAccounts is a strategy used by addTestAddrs() in order to generated addresses in ascending order.
   130  func createIncrementalAccounts(accNum int) []sdk.AccAddress {
   131  	var addresses []sdk.AccAddress
   132  	var buffer bytes.Buffer
   133  
   134  	// start at 100 so we can make up to 999 test addresses with valid test addresses
   135  	for i := 100; i < (accNum + 100); i++ {
   136  		numString := strconv.Itoa(i)
   137  		buffer.WriteString("A58856F0FD53BF058B4909A21AEC019107BA6") // base address string
   138  
   139  		buffer.WriteString(numString) // adding on final two digits to make addresses unique
   140  		res, _ := sdk.AccAddressFromHex(buffer.String())
   141  		bech := res.String()
   142  		addr, _ := TestAddr(buffer.String(), bech)
   143  
   144  		addresses = append(addresses, addr)
   145  		buffer.Reset()
   146  	}
   147  
   148  	return addresses
   149  }
   150  
   151  // AddTestAddrsFromPubKeys adds the addresses into the SimApp providing only the public keys.
   152  func AddTestAddrsFromPubKeys(app *SimApp, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt sdk.Int) {
   153  	initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt))
   154  
   155  	for _, pk := range pubKeys {
   156  		initAccountWithCoins(app, ctx, sdk.AccAddress(pk.Address()), initCoins)
   157  	}
   158  }
   159  
   160  // AddTestAddrs constructs and returns accNum amount of accounts with an
   161  // initial balance of accAmt in random order
   162  func AddTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress {
   163  	return addTestAddrs(app, ctx, accNum, accAmt, createRandomAccounts)
   164  }
   165  
   166  // AddTestAddrs constructs and returns accNum amount of accounts with an
   167  // initial balance of accAmt in random order
   168  func AddTestAddrsIncremental(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress {
   169  	return addTestAddrs(app, ctx, accNum, accAmt, createIncrementalAccounts)
   170  }
   171  
   172  func addTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int, strategy GenerateAccountStrategy) []sdk.AccAddress {
   173  	testAddrs := strategy(accNum)
   174  
   175  	initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt))
   176  
   177  	for _, addr := range testAddrs {
   178  		initAccountWithCoins(app, ctx, addr, initCoins)
   179  	}
   180  
   181  	return testAddrs
   182  }
   183  
   184  func initAccountWithCoins(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) {
   185  	err := app.SupplyKeeper.MintCoins(ctx, minttypes.ModuleName, coins)
   186  	if err != nil {
   187  		panic(err)
   188  	}
   189  
   190  	err = app.SupplyKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins)
   191  	if err != nil {
   192  		panic(err)
   193  	}
   194  }
   195  
   196  // ConvertAddrsToValAddrs converts the provided addresses to ValAddress.
   197  func ConvertAddrsToValAddrs(addrs []sdk.AccAddress) []sdk.ValAddress {
   198  	valAddrs := make([]sdk.ValAddress, len(addrs))
   199  
   200  	for i, addr := range addrs {
   201  		valAddrs[i] = sdk.ValAddress(addr)
   202  	}
   203  
   204  	return valAddrs
   205  }
   206  
   207  func TestAddr(addr string, bech string) (sdk.AccAddress, error) {
   208  	res, err := sdk.AccAddressFromHex(addr)
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  	bechexpected := res.String()
   213  	if bech != bechexpected {
   214  		return nil, fmt.Errorf("bech encoding doesn't match reference")
   215  	}
   216  
   217  	bechres, err := sdk.AccAddressFromBech32(bech)
   218  	if err != nil {
   219  		return nil, err
   220  	}
   221  	if !bytes.Equal(bechres, res) {
   222  		return nil, err
   223  	}
   224  
   225  	return res, nil
   226  }
   227  
   228  // CheckBalance checks the balance of an account.
   229  func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, balances sdk.Coins) {
   230  	ctxCheck := app.BaseApp.NewContext(true, tmproto.Header{})
   231  	require.True(t, balances.IsEqual(app.BankKeeper.GetCoins(ctxCheck, addr)))
   232  }
   233  
   234  // SignAndDeliver signs and delivers a transaction. No simulation occurs as the
   235  // ibc testing package causes checkState and deliverState to diverge in block time.
   236  func SignAndDeliver(
   237  	t *testing.T, txCfg client.TxConfig, app *bam.BaseApp, header tmproto.Header, msgs []ibcmsg.Msg,
   238  	chainID string, accNums, accSeqs []uint64, expSimPass, expPass bool, priv ...cryptotypes2.PrivKey,
   239  ) (sdk.GasInfo, *sdk.Result, error) {
   240  
   241  	tx, err := helpers.GenTx(
   242  		txCfg,
   243  		msgs,
   244  		//sdk.CoinAdapters{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)},
   245  		sdk.CoinAdapters{sdk.NewCoinAdapter(sdk.DefaultIbcWei, sdk.NewIntFromBigInt(big.NewInt(0)))},
   246  		helpers.DefaultGenTxGas,
   247  		chainID,
   248  		accNums,
   249  		accSeqs,
   250  		1,
   251  		priv...,
   252  	)
   253  	require.NoError(t, err)
   254  
   255  	// Simulate a sending a transaction and committing a block
   256  	app.BeginBlock(abci.RequestBeginBlock{Header: header})
   257  	//convert tx to ibctx
   258  	gInfo, res, err := app.Deliver(tx)
   259  
   260  	if expPass {
   261  		require.NoError(t, err)
   262  		require.NotNil(t, res)
   263  	} else {
   264  		require.Error(t, err)
   265  		require.Nil(t, res)
   266  	}
   267  
   268  	app.EndBlock(abci.RequestEndBlock{})
   269  	app.Commit(abci.RequestCommit{})
   270  
   271  	return gInfo, res, err
   272  }
   273  
   274  // GenSequenceOfTxs generates a set of signed transactions of messages, such
   275  // that they differ only by having the sequence numbers incremented between
   276  // every transaction.
   277  func GenSequenceOfTxs(txGen client.TxConfig, msgs []ibcmsg.Msg, accNums []uint64, initSeqNums []uint64, numToGenerate int, priv ...cryptotypes2.PrivKey) ([]sdk.Tx, error) {
   278  	txs := make([]sdk.Tx, numToGenerate)
   279  	var err error
   280  	for i := 0; i < numToGenerate; i++ {
   281  		txs[i], err = helpers.GenTx(
   282  			txGen,
   283  			msgs,
   284  			//sdk.CoinAdapters{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)},
   285  			sdk.CoinAdapters{sdk.NewCoinAdapter(sdk.DefaultBondDenom, sdk.NewIntFromBigInt(big.NewInt(0)))},
   286  			helpers.DefaultGenTxGas,
   287  			"",
   288  			accNums,
   289  			initSeqNums,
   290  			1,
   291  			priv...,
   292  		)
   293  		if err != nil {
   294  			break
   295  		}
   296  		incrementAllSequenceNumbers(initSeqNums)
   297  	}
   298  
   299  	return txs, err
   300  }
   301  
   302  func incrementAllSequenceNumbers(initSeqNums []uint64) {
   303  	for i := 0; i < len(initSeqNums); i++ {
   304  		initSeqNums[i]++
   305  	}
   306  }
   307  
   308  // CreateTestPubKeys returns a total of numPubKeys public keys in ascending order.
   309  func CreateTestPubKeys(numPubKeys int) []cryptotypes2.PubKey {
   310  	var publicKeys []cryptotypes2.PubKey
   311  	var buffer bytes.Buffer
   312  
   313  	// start at 10 to avoid changing 1 to 01, 2 to 02, etc
   314  	for i := 100; i < (numPubKeys + 100); i++ {
   315  		numString := strconv.Itoa(i)
   316  		buffer.WriteString("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AF") // base pubkey string
   317  		buffer.WriteString(numString)                                                       // adding on final two digits to make pubkeys unique
   318  		publicKeys = append(publicKeys, NewPubKeyFromHex(buffer.String()))
   319  		buffer.Reset()
   320  	}
   321  
   322  	return publicKeys
   323  }
   324  
   325  // NewPubKeyFromHex returns a PubKey from a hex string.
   326  func NewPubKeyFromHex(pk string) (res cryptotypes2.PubKey) {
   327  	pkBytes, err := hex.DecodeString(pk)
   328  	if err != nil {
   329  		panic(err)
   330  	}
   331  
   332  	if len(pkBytes) != ed25519.PubKeyEd25519Size {
   333  		panic(errors.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size"))
   334  	}
   335  	key := ed25519.PubKeyEd25519{}
   336  	copy(key[:], pkBytes)
   337  
   338  	return key
   339  }
   340  
   341  // EmptyAppOptions is a stub implementing AppOptions
   342  type EmptyAppOptions struct{}
   343  
   344  // Get implements AppOptions
   345  func (ao EmptyAppOptions) Get(o string) interface{} {
   346  	return nil
   347  }
   348  
   349  // FundAccount is a utility function that funds an account by minting and sending the coins to the address
   350  // TODO(fdymylja): instead of using the mint module account, which has the permission of minting, create a "faucet" account
   351  func FundAccount(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error {
   352  	err := app.SupplyKeeper.MintCoins(ctx, minttypes.ModuleName, amounts)
   353  	if err != nil {
   354  		return err
   355  	}
   356  	return app.SupplyKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts)
   357  }