2021-01-25 08:41:30 -08:00
|
|
|
package simulation
|
|
|
|
|
|
|
|
import (
|
2021-05-11 08:33:33 -07:00
|
|
|
"fmt"
|
2021-01-25 08:41:30 -08:00
|
|
|
"math/rand"
|
|
|
|
|
2021-05-14 15:18:59 -07:00
|
|
|
"github.com/gogo/protobuf/proto"
|
|
|
|
|
2021-01-25 08:41:30 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
|
|
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/simapp/helpers"
|
|
|
|
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
2021-05-06 11:23:48 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/authz"
|
2021-05-11 08:33:33 -07:00
|
|
|
|
|
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
2021-01-25 08:41:30 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/authz/keeper"
|
2021-05-11 08:33:33 -07:00
|
|
|
|
2021-01-25 08:41:30 -08:00
|
|
|
banktype "github.com/cosmos/cosmos-sdk/x/bank/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/simulation"
|
|
|
|
)
|
|
|
|
|
|
|
|
// authz message types
|
2021-04-30 04:00:47 -07:00
|
|
|
var (
|
2021-05-11 08:33:33 -07:00
|
|
|
TypeMsgGrant = sdk.MsgTypeURL(&authz.MsgGrant{})
|
|
|
|
TypeMsgRevoke = sdk.MsgTypeURL(&authz.MsgRevoke{})
|
|
|
|
TypeMsgExec = sdk.MsgTypeURL(&authz.MsgExec{})
|
2021-01-25 08:41:30 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// Simulation operation weights constants
|
|
|
|
const (
|
2021-05-11 08:33:33 -07:00
|
|
|
OpWeightMsgGrant = "op_weight_msg_grant"
|
|
|
|
OpWeightRevoke = "op_weight_msg_revoke"
|
|
|
|
OpWeightExec = "op_weight_msg_execute"
|
|
|
|
)
|
|
|
|
|
|
|
|
// authz operations weights
|
|
|
|
const (
|
|
|
|
WeightGrant = 100
|
|
|
|
WeightRevoke = 90
|
|
|
|
WeightExec = 90
|
2021-01-25 08:41:30 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// WeightedOperations returns all the operations from the module with their respective weights
|
|
|
|
func WeightedOperations(
|
2021-05-06 11:23:48 -07:00
|
|
|
appParams simtypes.AppParams, cdc codec.JSONCodec, ak authz.AccountKeeper, bk authz.BankKeeper, k keeper.Keeper, appCdc cdctypes.AnyUnpacker, protoCdc *codec.ProtoCodec) simulation.WeightedOperations {
|
2021-01-25 08:41:30 -08:00
|
|
|
|
|
|
|
var (
|
2021-05-11 08:33:33 -07:00
|
|
|
weightMsgGrant int
|
|
|
|
weightRevoke int
|
|
|
|
weightExec int
|
2021-01-25 08:41:30 -08:00
|
|
|
)
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
appParams.GetOrGenerate(cdc, OpWeightMsgGrant, &weightMsgGrant, nil,
|
2021-01-25 08:41:30 -08:00
|
|
|
func(_ *rand.Rand) {
|
2021-05-11 08:33:33 -07:00
|
|
|
weightMsgGrant = WeightGrant
|
2021-01-25 08:41:30 -08:00
|
|
|
},
|
|
|
|
)
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
appParams.GetOrGenerate(cdc, OpWeightRevoke, &weightRevoke, nil,
|
2021-01-25 08:41:30 -08:00
|
|
|
func(_ *rand.Rand) {
|
2021-05-11 08:33:33 -07:00
|
|
|
weightRevoke = WeightRevoke
|
2021-01-25 08:41:30 -08:00
|
|
|
},
|
|
|
|
)
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
appParams.GetOrGenerate(cdc, OpWeightExec, &weightExec, nil,
|
2021-01-25 08:41:30 -08:00
|
|
|
func(_ *rand.Rand) {
|
2021-05-11 08:33:33 -07:00
|
|
|
weightExec = WeightExec
|
2021-01-25 08:41:30 -08:00
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
return simulation.WeightedOperations{
|
|
|
|
simulation.NewWeightedOperation(
|
2021-05-11 08:33:33 -07:00
|
|
|
weightMsgGrant,
|
|
|
|
SimulateMsgGrant(ak, bk, k, protoCdc),
|
2021-01-25 08:41:30 -08:00
|
|
|
),
|
|
|
|
simulation.NewWeightedOperation(
|
2021-05-11 08:33:33 -07:00
|
|
|
weightRevoke,
|
|
|
|
SimulateMsgRevoke(ak, bk, k, protoCdc),
|
2021-01-25 08:41:30 -08:00
|
|
|
),
|
|
|
|
simulation.NewWeightedOperation(
|
2021-05-11 08:33:33 -07:00
|
|
|
weightExec,
|
|
|
|
SimulateMsgExec(ak, bk, k, appCdc, protoCdc),
|
2021-01-25 08:41:30 -08:00
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
// SimulateMsgGrant generates a MsgGrant with random values.
|
|
|
|
func SimulateMsgGrant(ak authz.AccountKeeper, bk authz.BankKeeper, _ keeper.Keeper,
|
2021-01-25 08:41:30 -08:00
|
|
|
protoCdc *codec.ProtoCodec) simtypes.Operation {
|
|
|
|
return func(
|
|
|
|
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
|
|
|
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
2021-05-11 08:33:33 -07:00
|
|
|
granter, _ := simtypes.RandomAcc(r, accs)
|
|
|
|
grantee, _ := simtypes.RandomAcc(r, accs)
|
2021-01-25 08:41:30 -08:00
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
if granter.Address.Equals(grantee.Address) {
|
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "granter and grantee are same"), nil, nil
|
|
|
|
}
|
2021-01-25 08:41:30 -08:00
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
granterAcc := ak.GetAccount(ctx, granter.Address)
|
|
|
|
spendableCoins := bk.SpendableCoins(ctx, granter.Address)
|
2021-01-25 08:41:30 -08:00
|
|
|
fees, err := simtypes.RandomFees(r, ctx, spendableCoins)
|
|
|
|
if err != nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, err.Error()), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-04-09 05:33:27 -07:00
|
|
|
spendLimit := spendableCoins.Sub(fees)
|
|
|
|
if spendLimit == nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "spend limit is nil"), nil, nil
|
2021-04-09 05:33:27 -07:00
|
|
|
}
|
2021-01-25 08:41:30 -08:00
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
expiration := ctx.BlockTime().AddDate(1, 0, 0)
|
|
|
|
msg, err := authz.NewMsgGrant(granter.Address, grantee.Address, generateRandomAuthorization(r, spendLimit), expiration)
|
2021-01-25 08:41:30 -08:00
|
|
|
if err != nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, err.Error()), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
2021-05-11 08:33:33 -07:00
|
|
|
txCfg := simappparams.MakeTestEncodingConfig().TxConfig
|
2021-01-25 08:41:30 -08:00
|
|
|
tx, err := helpers.GenTx(
|
2021-05-11 08:33:33 -07:00
|
|
|
txCfg,
|
2021-05-07 02:31:20 -07:00
|
|
|
[]sdk.Msg{msg},
|
2021-01-25 08:41:30 -08:00
|
|
|
fees,
|
|
|
|
helpers.DefaultGenTxGas,
|
|
|
|
chainID,
|
2021-05-11 08:33:33 -07:00
|
|
|
[]uint64{granterAcc.GetAccountNumber()},
|
|
|
|
[]uint64{granterAcc.GetSequence()},
|
2021-01-25 08:41:30 -08:00
|
|
|
granter.PrivKey,
|
|
|
|
)
|
|
|
|
if err != nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "unable to generate mock tx"), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
_, _, err = app.Deliver(txCfg.TxEncoder(), tx)
|
2021-01-25 08:41:30 -08:00
|
|
|
if err != nil {
|
2021-05-07 02:31:20 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
2021-05-07 02:31:20 -07:00
|
|
|
return simtypes.NewOperationMsg(msg, true, "", protoCdc), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
func generateRandomAuthorization(r *rand.Rand, spendLimit sdk.Coins) authz.Authorization {
|
|
|
|
authorizations := make([]authz.Authorization, 2)
|
|
|
|
authorizations[0] = banktype.NewSendAuthorization(spendLimit)
|
|
|
|
authorizations[1] = authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktype.MsgSend{}))
|
|
|
|
|
|
|
|
return authorizations[r.Intn(len(authorizations))]
|
|
|
|
}
|
|
|
|
|
|
|
|
// SimulateMsgRevoke generates a MsgRevoke with random values.
|
|
|
|
func SimulateMsgRevoke(ak authz.AccountKeeper, bk authz.BankKeeper, k keeper.Keeper, protoCdc *codec.ProtoCodec) simtypes.Operation {
|
2021-01-25 08:41:30 -08:00
|
|
|
return func(
|
|
|
|
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
|
|
|
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
2021-05-11 08:33:33 -07:00
|
|
|
var granterAddr, granteeAddr sdk.AccAddress
|
|
|
|
var grant authz.Grant
|
2021-01-25 08:41:30 -08:00
|
|
|
hasGrant := false
|
2021-05-11 08:33:33 -07:00
|
|
|
|
|
|
|
k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, g authz.Grant) bool {
|
|
|
|
grant = g
|
2021-01-25 08:41:30 -08:00
|
|
|
granterAddr = granter
|
|
|
|
granteeAddr = grantee
|
|
|
|
hasGrant = true
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
if !hasGrant {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "no grants"), nil, nil
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
granterAcc, ok := simtypes.FindAccount(accs, granterAddr)
|
2021-01-25 08:41:30 -08:00
|
|
|
if !ok {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "account not found"), nil, sdkerrors.Wrapf(sdkerrors.ErrNotFound, "account not found")
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
spendableCoins := bk.SpendableCoins(ctx, granterAddr)
|
2021-01-25 08:41:30 -08:00
|
|
|
fees, err := simtypes.RandomFees(r, ctx, spendableCoins)
|
|
|
|
if err != nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "fee error"), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
a := grant.GetAuthorization()
|
|
|
|
msg := authz.NewMsgRevoke(granterAddr, granteeAddr, a.MsgTypeURL())
|
|
|
|
txCfg := simappparams.MakeTestEncodingConfig().TxConfig
|
|
|
|
account := ak.GetAccount(ctx, granterAddr)
|
2021-01-25 08:41:30 -08:00
|
|
|
tx, err := helpers.GenTx(
|
2021-05-11 08:33:33 -07:00
|
|
|
txCfg,
|
2021-05-07 02:31:20 -07:00
|
|
|
[]sdk.Msg{&msg},
|
2021-01-25 08:41:30 -08:00
|
|
|
fees,
|
|
|
|
helpers.DefaultGenTxGas,
|
|
|
|
chainID,
|
|
|
|
[]uint64{account.GetAccountNumber()},
|
|
|
|
[]uint64{account.GetSequence()},
|
2021-05-11 08:33:33 -07:00
|
|
|
granterAcc.PrivKey,
|
2021-01-25 08:41:30 -08:00
|
|
|
)
|
2021-05-11 08:33:33 -07:00
|
|
|
if err != nil {
|
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, err.Error()), nil, err
|
|
|
|
}
|
2021-01-25 08:41:30 -08:00
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
_, _, err = app.Deliver(txCfg.TxEncoder(), tx)
|
2021-01-25 08:41:30 -08:00
|
|
|
if err != nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "unable to deliver tx"), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NewOperationMsg(&msg, true, "", protoCdc), nil, nil
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
// SimulateMsgExec generates a MsgExec with random values.
|
|
|
|
func SimulateMsgExec(ak authz.AccountKeeper, bk authz.BankKeeper, k keeper.Keeper, cdc cdctypes.AnyUnpacker, protoCdc *codec.ProtoCodec) simtypes.Operation {
|
2021-01-25 08:41:30 -08:00
|
|
|
return func(
|
|
|
|
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
|
|
|
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
|
|
|
hasGrant := false
|
2021-05-06 11:23:48 -07:00
|
|
|
var targetGrant authz.Grant
|
2021-01-25 08:41:30 -08:00
|
|
|
var granterAddr sdk.AccAddress
|
|
|
|
var granteeAddr sdk.AccAddress
|
2021-05-06 11:23:48 -07:00
|
|
|
k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant authz.Grant) bool {
|
2021-01-25 08:41:30 -08:00
|
|
|
targetGrant = grant
|
|
|
|
granterAddr = granter
|
|
|
|
granteeAddr = grantee
|
|
|
|
hasGrant = true
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
if !hasGrant {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "no grant found"), nil, nil
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
grantee, ok := simtypes.FindAccount(accs, granteeAddr)
|
|
|
|
if !ok {
|
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "Account not found"), nil, sdkerrors.Wrapf(sdkerrors.ErrNotFound, "grantee account not found")
|
|
|
|
}
|
2021-01-25 08:41:30 -08:00
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
if _, ok := simtypes.FindAccount(accs, granterAddr); !ok {
|
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "Account not found"), nil, sdkerrors.Wrapf(sdkerrors.ErrNotFound, "granter account not found")
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if targetGrant.Expiration.Before(ctx.BlockHeader().Time) {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "grant expired"), nil, nil
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
coins := sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(int64(simtypes.RandIntBetween(r, 100, 1000000)))))
|
|
|
|
|
|
|
|
// Check send_enabled status of each sent coin denom
|
|
|
|
if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil {
|
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, nil
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
if targetGrant.Authorization.TypeUrl == fmt.Sprintf("/%s", proto.MessageName(&banktype.SendAuthorization{})) {
|
|
|
|
sendAuthorization := targetGrant.GetAuthorization().(*banktype.SendAuthorization)
|
|
|
|
if sendAuthorization.SpendLimit.IsAllLT(coins) {
|
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "over spend limit"), nil, nil
|
|
|
|
}
|
|
|
|
}
|
2021-01-25 08:41:30 -08:00
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
granterspendableCoins := bk.SpendableCoins(ctx, granterAddr)
|
|
|
|
if granterspendableCoins.IsAllLTE(coins) {
|
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "insufficient funds"), nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
granteeSpendableCoins := bk.SpendableCoins(ctx, granteeAddr)
|
|
|
|
fees, err := simtypes.RandomFees(r, ctx, granteeSpendableCoins)
|
2021-02-19 22:57:57 -08:00
|
|
|
if err != nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "fee error"), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
|
2021-05-11 08:33:33 -07:00
|
|
|
msg := authz.NewMsgExec(granteeAddr, []sdk.Msg{banktype.NewMsgSend(granterAddr, granteeAddr, coins)})
|
|
|
|
txCfg := simappparams.MakeTestEncodingConfig().TxConfig
|
|
|
|
granteeAcc := ak.GetAccount(ctx, granteeAddr)
|
|
|
|
|
2021-01-25 08:41:30 -08:00
|
|
|
tx, err := helpers.GenTx(
|
2021-05-11 08:33:33 -07:00
|
|
|
txCfg,
|
2021-05-07 02:31:20 -07:00
|
|
|
[]sdk.Msg{&msg},
|
2021-01-25 08:41:30 -08:00
|
|
|
fees,
|
|
|
|
helpers.DefaultGenTxGas,
|
|
|
|
chainID,
|
2021-05-11 08:33:33 -07:00
|
|
|
[]uint64{granteeAcc.GetAccountNumber()},
|
|
|
|
[]uint64{granteeAcc.GetSequence()},
|
2021-01-25 08:41:30 -08:00
|
|
|
grantee.PrivKey,
|
|
|
|
)
|
|
|
|
if err != nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
2021-05-11 08:33:33 -07:00
|
|
|
|
|
|
|
_, _, err = app.Deliver(txCfg.TxEncoder(), tx)
|
2021-01-25 08:41:30 -08:00
|
|
|
if err != nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
2021-05-11 08:33:33 -07:00
|
|
|
|
|
|
|
err = msg.UnpackInterfaces(cdc)
|
2021-01-25 08:41:30 -08:00
|
|
|
if err != nil {
|
2021-05-11 08:33:33 -07:00
|
|
|
return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "unmarshal error"), nil, err
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
2021-05-07 02:31:20 -07:00
|
|
|
return simtypes.NewOperationMsg(&msg, true, "success", protoCdc), nil, nil
|
2021-01-25 08:41:30 -08:00
|
|
|
}
|
|
|
|
}
|