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