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 }