cosmos-sdk/x/simulation/util.go

126 lines
3.7 KiB
Go
Raw Normal View History

2018-07-16 18:25:15 -07:00
package simulation
2018-07-16 18:15:50 -07:00
import (
"encoding/json"
2018-07-17 16:27:51 -07:00
"fmt"
2018-11-08 07:32:53 -08:00
"math/rand"
"testing"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/simapp/helpers"
sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
2018-07-16 18:15:50 -07:00
)
2018-11-07 08:57:53 -08:00
func getTestingMode(tb testing.TB) (testingMode bool, t *testing.T, b *testing.B) {
testingMode = false
2018-11-07 08:57:53 -08:00
if _t, ok := tb.(*testing.T); ok {
t = _t
testingMode = true
} else {
b = tb.(*testing.B)
}
2019-03-14 11:13:15 -07:00
return testingMode, t, b
}
2018-11-08 07:32:53 -08:00
// getBlockSize returns a block size as determined from the transition matrix.
// It targets making average block size the provided parameter. The three
// states it moves between are:
// - "over stuffed" blocks with average size of 2 * avgblocksize,
// - normal sized blocks, hitting avgBlocksize on average,
// - and empty blocks, with no txs / only txs scheduled from the past.
2019-08-07 09:54:13 -07:00
func getBlockSize(r *rand.Rand, params Params, lastBlockSizeState, avgBlockSize int) (state, blockSize int) {
2018-11-08 07:32:53 -08:00
// TODO: Make default blocksize transition matrix actually make the average
// blocksize equal to avgBlockSize.
state = params.BlockSizeTransitionMatrix().NextState(r, lastBlockSizeState)
2019-08-07 09:54:13 -07:00
2018-11-08 07:32:53 -08:00
switch state {
case 0:
2019-08-07 09:54:13 -07:00
blockSize = r.Intn(avgBlockSize * 4)
2018-11-08 07:32:53 -08:00
case 1:
2019-08-07 09:54:13 -07:00
blockSize = r.Intn(avgBlockSize * 2)
2018-11-08 07:32:53 -08:00
default:
2019-08-07 09:54:13 -07:00
blockSize = 0
2018-11-08 07:32:53 -08:00
}
2019-08-07 09:54:13 -07:00
return state, blockSize
2018-11-08 07:32:53 -08:00
}
2018-11-09 07:31:56 -08:00
func mustMarshalJSONIndent(o interface{}) []byte {
bz, err := json.MarshalIndent(o, "", " ")
if err != nil {
panic(fmt.Sprintf("failed to JSON encode: %s", err))
}
return bz
}
// OperationInput is a struct that holds all the needed values to generate a tx and deliver it
type OperationInput struct {
R *rand.Rand
App *baseapp.BaseApp
TxGen client.TxConfig
Cdc *codec.ProtoCodec
Msg sdk.Msg
MsgType string
CoinsSpentInMsg sdk.Coins
Context sdk.Context
SimAccount simtypes.Account
AccountKeeper AccountKeeper
Bankkeeper BankKeeper
ModuleName string
}
// GenAndDeliverTxWithRandFees generates a transaction with a random fee and delivers it.
func GenAndDeliverTxWithRandFees(txCtx OperationInput) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
account := txCtx.AccountKeeper.GetAccount(txCtx.Context, txCtx.SimAccount.Address)
spendable := txCtx.Bankkeeper.SpendableCoins(txCtx.Context, account.GetAddress())
var fees sdk.Coins
var err error
coins, hasNeg := spendable.SafeSub(txCtx.CoinsSpentInMsg)
if hasNeg {
return simtypes.NoOpMsg(txCtx.ModuleName, txCtx.MsgType, "message doesn't leave room for fees"), nil, err
}
fees, err = simtypes.RandomFees(txCtx.R, txCtx.Context, coins)
if err != nil {
return simtypes.NoOpMsg(txCtx.ModuleName, txCtx.MsgType, "unable to generate fees"), nil, err
}
return GenAndDeliverTx(txCtx, fees)
}
// GenAndDeliverTx generates a transactions and delivers it.
func GenAndDeliverTx(txCtx OperationInput, fees sdk.Coins) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
account := txCtx.AccountKeeper.GetAccount(txCtx.Context, txCtx.SimAccount.Address)
tx, err := helpers.GenTx(
txCtx.TxGen,
[]sdk.Msg{txCtx.Msg},
fees,
helpers.DefaultGenTxGas,
txCtx.Context.ChainID(),
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
txCtx.SimAccount.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(txCtx.ModuleName, txCtx.MsgType, "unable to generate mock tx"), nil, err
}
refactor!: BaseApp {Check,Deliver}Tx with middleware design (#9920) <!-- The default pull request template is for types feat, fix, or refactor. For other templates, add one of the following parameters to the url: - template=docs.md - template=other.md --> ## Description ref: #9585 This PR if the 1st step (out of 2) in the #9585 refactor. It transforms baseapp's ABCI {Check,Deliver}Tx into middleware stacks. A middleware is defined by the following interfaces: ```go // types/tx package type Handler interface { CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) SimulateTx(ctx context.Context, tx sdk.Tx, req RequestSimulateTx) (ResponseSimulateTx, error) } type Middleware func(Handler) Handler ``` This Pr doesn't migrate antehandlers, but only baseapp's runTx and runMsgs as middlewares. It bundles antehandlers into one single middleware (for now). More specifically, it introduces the 5 following middlewares: | Middleware | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | RunMsgsTxMiddleware | This middleware replaces the old baseapp's `runMsgs`. | | LegacyAnteMiddleware | This middleware is temporary, it bundles all antehandlers into one middleware. It's only created for the purpose of breaking the refactor into 2 pieces. **It will be removed in Part 2**, and each antehandler will be replaced by its own middleware. | | IndexEventsTxMiddleware | This is a simple middleware that chooses which events to index in Tendermint. Replaces `baseapp.indexEvents` (which unfortunately still exists in baseapp too, because it's used to index Begin/EndBlock events) | | RecoveryTxMiddleware | This index recovers from panics. It replaces baseapp.runTx's panic recovery. | | GasTxMiddleware | This replaces the [`Setup`](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth/ante/setup.go) Antehandler. It sets a GasMeter on sdk.Context. Note that before, GasMeter was set on sdk.Context inside the antehandlers, and there was some mess around the fact that antehandlers had their own panic recovery system so that the GasMeter could be read by baseapp's recovery system. Now, this mess is all removed: one middleware sets GasMeter, another one handles recovery. | --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [x] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [x] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [x] added a changelog entry to `CHANGELOG.md` - [x] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [x] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
2021-08-25 07:40:33 -07:00
_, _, err = txCtx.App.SimDeliver(txCtx.TxGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(txCtx.ModuleName, txCtx.MsgType, "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(txCtx.Msg, true, "", txCtx.Cdc), nil, nil
}