github.com/cosmos/cosmos-sdk@v0.50.10/x/simulation/util.go (about)

     1  package simulation
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"math/rand"
     7  	"testing"
     8  
     9  	"github.com/cosmos/cosmos-sdk/baseapp"
    10  	"github.com/cosmos/cosmos-sdk/client"
    11  	"github.com/cosmos/cosmos-sdk/codec"
    12  	simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
    13  	sdk "github.com/cosmos/cosmos-sdk/types"
    14  	simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
    15  )
    16  
    17  func getTestingMode(tb testing.TB) (testingMode bool, t *testing.T, b *testing.B) {
    18  	testingMode = false
    19  
    20  	if _t, ok := tb.(*testing.T); ok {
    21  		t = _t
    22  		testingMode = true
    23  	} else {
    24  		b = tb.(*testing.B)
    25  	}
    26  
    27  	return testingMode, t, b
    28  }
    29  
    30  // getBlockSize returns a block size as determined from the transition matrix.
    31  // It targets making average block size the provided parameter. The three
    32  // states it moves between are:
    33  //   - "over stuffed" blocks with average size of 2 * avgblocksize,
    34  //   - normal sized blocks, hitting avgBlocksize on average,
    35  //   - and empty blocks, with no txs / only txs scheduled from the past.
    36  func getBlockSize(r *rand.Rand, params Params, lastBlockSizeState, avgBlockSize int) (state, blockSize int) {
    37  	// TODO: Make default blocksize transition matrix actually make the average
    38  	// blocksize equal to avgBlockSize.
    39  	state = params.BlockSizeTransitionMatrix().NextState(r, lastBlockSizeState)
    40  
    41  	switch state {
    42  	case 0:
    43  		blockSize = r.Intn(avgBlockSize * 4)
    44  
    45  	case 1:
    46  		blockSize = r.Intn(avgBlockSize * 2)
    47  
    48  	default:
    49  		blockSize = 0
    50  	}
    51  
    52  	return state, blockSize
    53  }
    54  
    55  func mustMarshalJSONIndent(o interface{}) []byte {
    56  	bz, err := json.MarshalIndent(o, "", "  ")
    57  	if err != nil {
    58  		panic(fmt.Sprintf("failed to JSON encode: %s", err))
    59  	}
    60  
    61  	return bz
    62  }
    63  
    64  // OperationInput is a struct that holds all the needed values to generate a tx and deliver it
    65  type OperationInput struct {
    66  	R               *rand.Rand
    67  	App             *baseapp.BaseApp
    68  	TxGen           client.TxConfig
    69  	Cdc             *codec.ProtoCodec
    70  	Msg             sdk.Msg
    71  	CoinsSpentInMsg sdk.Coins
    72  	Context         sdk.Context
    73  	SimAccount      simtypes.Account
    74  	AccountKeeper   AccountKeeper
    75  	Bankkeeper      BankKeeper
    76  	ModuleName      string
    77  }
    78  
    79  // GenAndDeliverTxWithRandFees generates a transaction with a random fee and delivers it.
    80  func GenAndDeliverTxWithRandFees(txCtx OperationInput) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
    81  	account := txCtx.AccountKeeper.GetAccount(txCtx.Context, txCtx.SimAccount.Address)
    82  	spendable := txCtx.Bankkeeper.SpendableCoins(txCtx.Context, account.GetAddress())
    83  
    84  	var fees sdk.Coins
    85  	var err error
    86  
    87  	coins, hasNeg := spendable.SafeSub(txCtx.CoinsSpentInMsg...)
    88  	if hasNeg {
    89  		return simtypes.NoOpMsg(txCtx.ModuleName, sdk.MsgTypeURL(txCtx.Msg), "message doesn't leave room for fees"), nil, err
    90  	}
    91  
    92  	fees, err = simtypes.RandomFees(txCtx.R, txCtx.Context, coins)
    93  	if err != nil {
    94  		return simtypes.NoOpMsg(txCtx.ModuleName, sdk.MsgTypeURL(txCtx.Msg), "unable to generate fees"), nil, err
    95  	}
    96  	return GenAndDeliverTx(txCtx, fees)
    97  }
    98  
    99  // GenAndDeliverTx generates a transactions and delivers it.
   100  func GenAndDeliverTx(txCtx OperationInput, fees sdk.Coins) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
   101  	account := txCtx.AccountKeeper.GetAccount(txCtx.Context, txCtx.SimAccount.Address)
   102  	tx, err := simtestutil.GenSignedMockTx(
   103  		txCtx.R,
   104  		txCtx.TxGen,
   105  		[]sdk.Msg{txCtx.Msg},
   106  		fees,
   107  		simtestutil.DefaultGenTxGas,
   108  		txCtx.Context.ChainID(),
   109  		[]uint64{account.GetAccountNumber()},
   110  		[]uint64{account.GetSequence()},
   111  		txCtx.SimAccount.PrivKey,
   112  	)
   113  	if err != nil {
   114  		return simtypes.NoOpMsg(txCtx.ModuleName, sdk.MsgTypeURL(txCtx.Msg), "unable to generate mock tx"), nil, err
   115  	}
   116  
   117  	_, _, err = txCtx.App.SimDeliver(txCtx.TxGen.TxEncoder(), tx)
   118  	if err != nil {
   119  		return simtypes.NoOpMsg(txCtx.ModuleName, sdk.MsgTypeURL(txCtx.Msg), "unable to deliver tx"), nil, err
   120  	}
   121  
   122  	return simtypes.NewOperationMsg(txCtx.Msg, true, ""), nil, nil
   123  }