2019-10-23 02:14:45 -07:00
|
|
|
package simulation
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/rand"
|
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
2019-12-05 01:29:54 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
2020-11-09 08:01:43 -08:00
|
|
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
2019-10-23 02:14:45 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/simapp/helpers"
|
2019-12-05 01:29:54 -08:00
|
|
|
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
2019-10-23 02:14:45 -07:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2020-03-23 04:55:44 -07:00
|
|
|
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
2020-02-20 06:24:26 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/bank/types"
|
2021-05-13 06:51:21 -07:00
|
|
|
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
2019-10-23 02:14:45 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/simulation"
|
|
|
|
)
|
|
|
|
|
2019-12-05 01:29:54 -08:00
|
|
|
// Simulation operation weights constants
|
|
|
|
const (
|
|
|
|
OpWeightMsgSend = "op_weight_msg_send"
|
|
|
|
OpWeightMsgMultiSend = "op_weight_msg_multisend"
|
|
|
|
)
|
|
|
|
|
|
|
|
// WeightedOperations returns all the operations from the module with their respective weights
|
2020-01-30 13:31:16 -08:00
|
|
|
func WeightedOperations(
|
2021-04-29 03:46:22 -07:00
|
|
|
appParams simtypes.AppParams, cdc codec.JSONCodec, ak types.AccountKeeper, bk keeper.Keeper,
|
2020-01-30 13:31:16 -08:00
|
|
|
) simulation.WeightedOperations {
|
2019-12-05 01:29:54 -08:00
|
|
|
|
|
|
|
var weightMsgSend, weightMsgMultiSend int
|
|
|
|
appParams.GetOrGenerate(cdc, OpWeightMsgSend, &weightMsgSend, nil,
|
|
|
|
func(_ *rand.Rand) {
|
|
|
|
weightMsgSend = simappparams.DefaultWeightMsgSend
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
appParams.GetOrGenerate(cdc, OpWeightMsgMultiSend, &weightMsgMultiSend, nil,
|
|
|
|
func(_ *rand.Rand) {
|
|
|
|
weightMsgMultiSend = simappparams.DefaultWeightMsgMultiSend
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
return simulation.WeightedOperations{
|
|
|
|
simulation.NewWeightedOperation(
|
|
|
|
weightMsgSend,
|
|
|
|
SimulateMsgSend(ak, bk),
|
|
|
|
),
|
|
|
|
simulation.NewWeightedOperation(
|
|
|
|
weightMsgMultiSend,
|
|
|
|
SimulateMsgMultiSend(ak, bk),
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-23 02:14:45 -07:00
|
|
|
// SimulateMsgSend tests and runs a single msg send where both
|
|
|
|
// accounts already exist.
|
2020-03-23 04:55:44 -07:00
|
|
|
func SimulateMsgSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operation {
|
2019-10-23 02:14:45 -07:00
|
|
|
return func(
|
|
|
|
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
2020-03-23 04:55:44 -07:00
|
|
|
accs []simtypes.Account, chainID string,
|
|
|
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
2021-05-13 06:51:21 -07:00
|
|
|
from, to, coins, skip := randomSendFields(r, ctx, accs, bk, ak)
|
2019-10-23 02:14:45 -07:00
|
|
|
|
2020-07-08 10:43:08 -07:00
|
|
|
// Check send_enabled status of each coin denom
|
2021-05-10 09:17:55 -07:00
|
|
|
if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil {
|
2020-07-08 10:43:08 -07:00
|
|
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSend, err.Error()), nil, nil
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if skip {
|
2020-05-26 09:52:23 -07:00
|
|
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSend, "skip all transfers"), nil, nil
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
2021-05-13 06:51:21 -07:00
|
|
|
msg := types.NewMsgSend(from.Address, to.Address, coins)
|
2019-10-23 02:14:45 -07:00
|
|
|
|
2021-05-13 06:51:21 -07:00
|
|
|
err := sendMsgSend(r, app, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{from.PrivKey})
|
|
|
|
if err != nil {
|
|
|
|
return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SimulateMsgSendToModuleAccount tests and runs a single msg send where both
|
|
|
|
// accounts already exist.
|
|
|
|
func SimulateMsgSendToModuleAccount(ak types.AccountKeeper, bk keeper.Keeper, moduleAccCount int) simtypes.Operation {
|
|
|
|
return func(
|
|
|
|
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
|
|
|
accs []simtypes.Account, chainID string,
|
|
|
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
|
|
|
from := accs[0]
|
|
|
|
|
|
|
|
to := getModuleAccounts(ak, ctx, moduleAccCount)[0]
|
|
|
|
|
|
|
|
spendable := bk.SpendableCoins(ctx, from.Address)
|
|
|
|
coins := simtypes.RandSubsetCoins(r, spendable)
|
|
|
|
|
|
|
|
// Check send_enabled status of each coin denom
|
|
|
|
if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil {
|
|
|
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSend, err.Error()), nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
msg := types.NewMsgSend(from.Address, to.Address, coins)
|
|
|
|
|
|
|
|
err := sendMsgSend(r, app, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{from.PrivKey})
|
2019-10-23 02:14:45 -07:00
|
|
|
if err != nil {
|
2020-05-26 09:52:23 -07:00
|
|
|
return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
2021-01-25 08:41:30 -08:00
|
|
|
return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// sendMsgSend sends a transaction with a MsgSend from a provided random account.
|
|
|
|
func sendMsgSend(
|
2020-01-30 13:31:16 -08:00
|
|
|
r *rand.Rand, app *baseapp.BaseApp, bk keeper.Keeper, ak types.AccountKeeper,
|
2020-11-09 08:01:43 -08:00
|
|
|
msg *types.MsgSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey,
|
2019-12-05 01:29:54 -08:00
|
|
|
) error {
|
2019-10-23 02:14:45 -07:00
|
|
|
|
2019-12-05 01:29:54 -08:00
|
|
|
var (
|
|
|
|
fees sdk.Coins
|
|
|
|
err error
|
|
|
|
)
|
2020-01-30 13:31:16 -08:00
|
|
|
|
2020-09-25 03:25:37 -07:00
|
|
|
from, err := sdk.AccAddressFromBech32(msg.FromAddress)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
account := ak.GetAccount(ctx, from)
|
2020-01-30 13:31:16 -08:00
|
|
|
spendable := bk.SpendableCoins(ctx, account.GetAddress())
|
|
|
|
|
|
|
|
coins, hasNeg := spendable.SafeSub(msg.Amount)
|
2019-10-23 02:14:45 -07:00
|
|
|
if !hasNeg {
|
2020-03-23 04:55:44 -07:00
|
|
|
fees, err = simtypes.RandomFees(r, ctx, coins)
|
2019-10-23 02:14:45 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2020-10-27 04:33:48 -07:00
|
|
|
txGen := simappparams.MakeTestEncodingConfig().TxConfig
|
2020-07-14 10:33:31 -07:00
|
|
|
tx, err := helpers.GenTx(
|
|
|
|
txGen,
|
2019-10-23 02:14:45 -07:00
|
|
|
[]sdk.Msg{msg},
|
|
|
|
fees,
|
2019-12-18 06:48:22 -08:00
|
|
|
helpers.DefaultGenTxGas,
|
2019-10-23 02:14:45 -07:00
|
|
|
chainID,
|
|
|
|
[]uint64{account.GetAccountNumber()},
|
|
|
|
[]uint64{account.GetSequence()},
|
|
|
|
privkeys...,
|
|
|
|
)
|
2020-07-14 10:33:31 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-10-23 02:14:45 -07:00
|
|
|
|
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 = app.SimDeliver(txGen.TxEncoder(), tx)
|
2019-12-27 09:57:54 -08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SimulateMsgMultiSend tests and runs a single msg multisend, with randomized, capped number of inputs/outputs.
|
|
|
|
// all accounts in msg fields exist in state
|
2020-03-23 04:55:44 -07:00
|
|
|
func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operation {
|
2019-10-23 02:14:45 -07:00
|
|
|
return func(
|
|
|
|
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
2020-03-23 04:55:44 -07:00
|
|
|
accs []simtypes.Account, chainID string,
|
|
|
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
2019-10-23 02:14:45 -07:00
|
|
|
|
|
|
|
// random number of inputs/outputs between [1, 3]
|
|
|
|
inputs := make([]types.Input, r.Intn(3)+1)
|
|
|
|
outputs := make([]types.Output, r.Intn(3)+1)
|
|
|
|
|
|
|
|
// collect signer privKeys
|
2020-11-09 08:01:43 -08:00
|
|
|
privs := make([]cryptotypes.PrivKey, len(inputs))
|
2019-10-23 02:14:45 -07:00
|
|
|
|
|
|
|
// use map to check if address already exists as input
|
|
|
|
usedAddrs := make(map[string]bool)
|
|
|
|
|
|
|
|
var totalSentCoins sdk.Coins
|
|
|
|
for i := range inputs {
|
|
|
|
// generate random input fields, ignore to address
|
2021-05-13 06:51:21 -07:00
|
|
|
from, _, coins, skip := randomSendFields(r, ctx, accs, bk, ak)
|
2019-10-23 02:14:45 -07:00
|
|
|
|
|
|
|
// make sure account is fresh and not used in previous input
|
2021-05-13 06:51:21 -07:00
|
|
|
for usedAddrs[from.Address.String()] {
|
|
|
|
from, _, coins, skip = randomSendFields(r, ctx, accs, bk, ak)
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if skip {
|
2020-05-26 09:52:23 -07:00
|
|
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, "skip all transfers"), nil, nil
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// set input address in used address map
|
2021-05-13 06:51:21 -07:00
|
|
|
usedAddrs[from.Address.String()] = true
|
2019-10-23 02:14:45 -07:00
|
|
|
|
|
|
|
// set signer privkey
|
2021-05-13 06:51:21 -07:00
|
|
|
privs[i] = from.PrivKey
|
2019-10-23 02:14:45 -07:00
|
|
|
|
|
|
|
// set next input and accumulate total sent coins
|
2021-05-13 06:51:21 -07:00
|
|
|
inputs[i] = types.NewInput(from.Address, coins)
|
2020-01-03 12:44:53 -08:00
|
|
|
totalSentCoins = totalSentCoins.Add(coins...)
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
2020-07-08 10:43:08 -07:00
|
|
|
// Check send_enabled status of each sent coin denom
|
2021-05-10 09:17:55 -07:00
|
|
|
if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil {
|
2020-07-08 10:43:08 -07:00
|
|
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, err.Error()), nil, nil
|
|
|
|
}
|
|
|
|
|
2019-10-23 02:14:45 -07:00
|
|
|
for o := range outputs {
|
2020-03-23 04:55:44 -07:00
|
|
|
outAddr, _ := simtypes.RandomAcc(r, accs)
|
2019-10-23 02:14:45 -07:00
|
|
|
|
|
|
|
var outCoins sdk.Coins
|
|
|
|
// split total sent coins into random subsets for output
|
|
|
|
if o == len(outputs)-1 {
|
|
|
|
outCoins = totalSentCoins
|
|
|
|
} else {
|
|
|
|
// take random subset of remaining coins for output
|
|
|
|
// and update remaining coins
|
2020-03-23 04:55:44 -07:00
|
|
|
outCoins = simtypes.RandSubsetCoins(r, totalSentCoins)
|
2019-10-23 02:14:45 -07:00
|
|
|
totalSentCoins = totalSentCoins.Sub(outCoins)
|
|
|
|
}
|
|
|
|
|
|
|
|
outputs[o] = types.NewOutput(outAddr.Address, outCoins)
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove any output that has no coins
|
2021-05-13 06:51:21 -07:00
|
|
|
|
|
|
|
for i := 0; i < len(outputs); {
|
2019-10-23 02:14:45 -07:00
|
|
|
if outputs[i].Coins.Empty() {
|
|
|
|
outputs[i] = outputs[len(outputs)-1]
|
|
|
|
outputs = outputs[:len(outputs)-1]
|
|
|
|
} else {
|
|
|
|
// continue onto next coin
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-03 12:52:05 -07:00
|
|
|
msg := &types.MsgMultiSend{
|
2019-10-23 02:14:45 -07:00
|
|
|
Inputs: inputs,
|
|
|
|
Outputs: outputs,
|
|
|
|
}
|
2021-05-13 06:51:21 -07:00
|
|
|
err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, privs)
|
|
|
|
if err != nil {
|
|
|
|
return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err
|
|
|
|
}
|
2019-10-23 02:14:45 -07:00
|
|
|
|
2021-05-13 06:51:21 -07:00
|
|
|
return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SimulateMsgMultiSendToModuleAccount sends coins to Module Accounts
|
|
|
|
func SimulateMsgMultiSendToModuleAccount(ak types.AccountKeeper, bk keeper.Keeper, moduleAccCount int) simtypes.Operation {
|
|
|
|
return func(
|
|
|
|
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
|
|
|
accs []simtypes.Account, chainID string,
|
|
|
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
|
|
|
|
|
|
|
inputs := make([]types.Input, 2)
|
|
|
|
outputs := make([]types.Output, moduleAccCount)
|
|
|
|
// collect signer privKeys
|
|
|
|
privs := make([]cryptotypes.PrivKey, len(inputs))
|
|
|
|
|
|
|
|
var totalSentCoins sdk.Coins
|
|
|
|
for i := range inputs {
|
|
|
|
sender := accs[i]
|
|
|
|
privs[i] = sender.PrivKey
|
|
|
|
spendable := bk.SpendableCoins(ctx, sender.Address)
|
|
|
|
coins := simtypes.RandSubsetCoins(r, spendable)
|
|
|
|
inputs[i] = types.NewInput(sender.Address, coins)
|
|
|
|
totalSentCoins = totalSentCoins.Add(coins...)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil {
|
|
|
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, err.Error()), nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
moduleAccounts := getModuleAccounts(ak, ctx, moduleAccCount)
|
|
|
|
for i := range outputs {
|
|
|
|
var outCoins sdk.Coins
|
|
|
|
// split total sent coins into random subsets for output
|
|
|
|
if i == len(outputs)-1 {
|
|
|
|
outCoins = totalSentCoins
|
|
|
|
} else {
|
|
|
|
// take random subset of remaining coins for output
|
|
|
|
// and update remaining coins
|
|
|
|
outCoins = simtypes.RandSubsetCoins(r, totalSentCoins)
|
|
|
|
totalSentCoins = totalSentCoins.Sub(outCoins)
|
|
|
|
}
|
|
|
|
|
|
|
|
outputs[i] = types.NewOutput(moduleAccounts[i].Address, outCoins)
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove any output that has no coins
|
|
|
|
|
|
|
|
for i := 0; i < len(outputs); {
|
|
|
|
if outputs[i].Coins.Empty() {
|
|
|
|
outputs[i] = outputs[len(outputs)-1]
|
|
|
|
outputs = outputs[:len(outputs)-1]
|
|
|
|
} else {
|
|
|
|
// continue onto next coin
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
msg := &types.MsgMultiSend{
|
|
|
|
Inputs: inputs,
|
|
|
|
Outputs: outputs,
|
|
|
|
}
|
2020-01-30 13:31:16 -08:00
|
|
|
err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, privs)
|
2019-10-23 02:14:45 -07:00
|
|
|
if err != nil {
|
2020-05-26 09:52:23 -07:00
|
|
|
return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
2021-01-25 08:41:30 -08:00
|
|
|
return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// sendMsgMultiSend sends a transaction with a MsgMultiSend from a provided random
|
|
|
|
// account.
|
|
|
|
func sendMsgMultiSend(
|
2020-01-30 13:31:16 -08:00
|
|
|
r *rand.Rand, app *baseapp.BaseApp, bk keeper.Keeper, ak types.AccountKeeper,
|
2020-11-09 08:01:43 -08:00
|
|
|
msg *types.MsgMultiSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey,
|
2019-12-05 01:29:54 -08:00
|
|
|
) error {
|
2019-10-23 02:14:45 -07:00
|
|
|
|
|
|
|
accountNumbers := make([]uint64, len(msg.Inputs))
|
|
|
|
sequenceNumbers := make([]uint64, len(msg.Inputs))
|
|
|
|
|
|
|
|
for i := 0; i < len(msg.Inputs); i++ {
|
2020-09-25 03:25:37 -07:00
|
|
|
addr, err := sdk.AccAddressFromBech32(msg.Inputs[i].Address)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
acc := ak.GetAccount(ctx, addr)
|
2019-10-23 02:14:45 -07:00
|
|
|
accountNumbers[i] = acc.GetAccountNumber()
|
|
|
|
sequenceNumbers[i] = acc.GetSequence()
|
|
|
|
}
|
|
|
|
|
2019-12-05 01:29:54 -08:00
|
|
|
var (
|
|
|
|
fees sdk.Coins
|
|
|
|
err error
|
|
|
|
)
|
2020-01-30 13:31:16 -08:00
|
|
|
|
2020-09-25 03:25:37 -07:00
|
|
|
addr, err := sdk.AccAddressFromBech32(msg.Inputs[0].Address)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2020-01-30 13:31:16 -08:00
|
|
|
// feePayer is the first signer, i.e. first input address
|
2020-09-25 03:25:37 -07:00
|
|
|
feePayer := ak.GetAccount(ctx, addr)
|
2020-01-30 13:31:16 -08:00
|
|
|
spendable := bk.SpendableCoins(ctx, feePayer.GetAddress())
|
|
|
|
|
|
|
|
coins, hasNeg := spendable.SafeSub(msg.Inputs[0].Coins)
|
2019-10-23 02:14:45 -07:00
|
|
|
if !hasNeg {
|
2020-03-23 04:55:44 -07:00
|
|
|
fees, err = simtypes.RandomFees(r, ctx, coins)
|
2019-10-23 02:14:45 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-27 04:33:48 -07:00
|
|
|
txGen := simappparams.MakeTestEncodingConfig().TxConfig
|
2020-07-14 10:33:31 -07:00
|
|
|
tx, err := helpers.GenTx(
|
|
|
|
txGen,
|
2019-10-23 02:14:45 -07:00
|
|
|
[]sdk.Msg{msg},
|
|
|
|
fees,
|
2019-12-18 06:48:22 -08:00
|
|
|
helpers.DefaultGenTxGas,
|
2019-10-23 02:14:45 -07:00
|
|
|
chainID,
|
|
|
|
accountNumbers,
|
|
|
|
sequenceNumbers,
|
|
|
|
privkeys...,
|
|
|
|
)
|
2020-07-14 10:33:31 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-10-23 02:14:45 -07:00
|
|
|
|
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 = app.SimDeliver(txGen.TxEncoder(), tx)
|
2019-12-27 09:57:54 -08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// randomSendFields returns the sender and recipient simulation accounts as well
|
|
|
|
// as the transferred amount.
|
|
|
|
func randomSendFields(
|
2020-03-23 04:55:44 -07:00
|
|
|
r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, bk keeper.Keeper, ak types.AccountKeeper,
|
2020-05-02 12:26:59 -07:00
|
|
|
) (simtypes.Account, simtypes.Account, sdk.Coins, bool) {
|
2019-10-23 02:14:45 -07:00
|
|
|
|
2021-05-13 06:51:21 -07:00
|
|
|
from, _ := simtypes.RandomAcc(r, accs)
|
|
|
|
to, _ := simtypes.RandomAcc(r, accs)
|
2019-10-23 02:14:45 -07:00
|
|
|
|
|
|
|
// disallow sending money to yourself
|
2021-05-13 06:51:21 -07:00
|
|
|
for from.PubKey.Equals(to.PubKey) {
|
|
|
|
to, _ = simtypes.RandomAcc(r, accs)
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
2021-05-13 06:51:21 -07:00
|
|
|
acc := ak.GetAccount(ctx, from.Address)
|
2019-10-23 02:14:45 -07:00
|
|
|
if acc == nil {
|
2021-05-13 06:51:21 -07:00
|
|
|
return from, to, nil, true
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
2020-01-30 13:31:16 -08:00
|
|
|
spendable := bk.SpendableCoins(ctx, acc.GetAddress())
|
2019-10-23 02:14:45 -07:00
|
|
|
|
2020-03-23 04:55:44 -07:00
|
|
|
sendCoins := simtypes.RandSubsetCoins(r, spendable)
|
2019-10-23 02:14:45 -07:00
|
|
|
if sendCoins.Empty() {
|
2021-05-13 06:51:21 -07:00
|
|
|
return from, to, nil, true
|
|
|
|
}
|
|
|
|
|
|
|
|
return from, to, sendCoins, false
|
|
|
|
}
|
|
|
|
|
|
|
|
func getModuleAccounts(ak types.AccountKeeper, ctx sdk.Context, moduleAccCount int) []simtypes.Account {
|
|
|
|
|
|
|
|
moduleAccounts := make([]simtypes.Account, moduleAccCount)
|
|
|
|
|
|
|
|
for i := 0; i < moduleAccCount; i++ {
|
|
|
|
addr := ak.GetModuleAddress(distributiontypes.ModuleName)
|
|
|
|
acc := ak.GetAccount(ctx, addr)
|
|
|
|
mAcc := simtypes.Account{
|
|
|
|
Address: acc.GetAddress(),
|
|
|
|
PrivKey: nil,
|
|
|
|
ConsKey: nil,
|
|
|
|
PubKey: acc.GetPubKey(),
|
|
|
|
}
|
|
|
|
moduleAccounts[i] = mAcc
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|
|
|
|
|
2021-05-13 06:51:21 -07:00
|
|
|
return moduleAccounts
|
2019-10-23 02:14:45 -07:00
|
|
|
}
|