Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MsgStoreCode and MsgInstantiateContract support to simulations #831

Merged
merged 2 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ func NewWasmApp(
distr.NewAppModule(appCodec, app.distrKeeper, app.accountKeeper, app.bankKeeper, app.stakingKeeper),
staking.NewAppModule(appCodec, app.stakingKeeper, app.accountKeeper, app.bankKeeper),
upgrade.NewAppModule(app.upgradeKeeper),
wasm.NewAppModule(appCodec, &app.wasmKeeper, app.stakingKeeper),
wasm.NewAppModule(appCodec, &app.wasmKeeper, app.stakingKeeper, app.accountKeeper, app.bankKeeper),
evidence.NewAppModule(app.evidenceKeeper),
feegrantmodule.NewAppModule(appCodec, app.accountKeeper, app.bankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.accountKeeper, app.bankKeeper, app.interfaceRegistry),
Expand Down Expand Up @@ -632,7 +632,7 @@ func NewWasmApp(
slashing.NewAppModule(appCodec, app.slashingKeeper, app.accountKeeper, app.bankKeeper, app.stakingKeeper),
params.NewAppModule(app.paramsKeeper),
evidence.NewAppModule(app.evidenceKeeper),
wasm.NewAppModule(appCodec, &app.wasmKeeper, app.stakingKeeper),
wasm.NewAppModule(appCodec, &app.wasmKeeper, app.stakingKeeper, app.accountKeeper, app.bankKeeper),
ibc.NewAppModule(app.ibcKeeper),
transferModule,
)
Expand Down
2 changes: 2 additions & 0 deletions app/params/weights.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ const (
DefaultWeightCommunitySpendProposal int = 5
DefaultWeightTextProposal int = 5
DefaultWeightParamChangeProposal int = 5
DefaultWeightMsgStoreCode int = 100
DefaultWeightMsgInstantiateContract int = 100
)
15 changes: 13 additions & 2 deletions x/wasm/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
simKeeper "github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cast"
Expand Down Expand Up @@ -103,6 +104,8 @@ type AppModule struct {
cdc codec.Codec
keeper *Keeper
validatorSetSource keeper.ValidatorSetSource
accountKeeper types.AccountKeeper // for simulation
bankKeeper simKeeper.BankKeeper
}

// ConsensusVersion is a sequence number for state-breaking change of the
Expand All @@ -112,12 +115,20 @@ type AppModule struct {
func (AppModule) ConsensusVersion() uint64 { return 1 }

// NewAppModule creates a new AppModule object
func NewAppModule(cdc codec.Codec, keeper *Keeper, validatorSetSource keeper.ValidatorSetSource) AppModule {
func NewAppModule(
cdc codec.Codec,
keeper *Keeper,
validatorSetSource keeper.ValidatorSetSource,
ak types.AccountKeeper,
bk simKeeper.BankKeeper,
) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
cdc: cdc,
keeper: keeper,
validatorSetSource: validatorSetSource,
accountKeeper: ak,
bankKeeper: bk,
}
}

Expand Down Expand Up @@ -196,7 +207,7 @@ func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {

// WeightedOperations returns the all the gov module operations with their respective weights.
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
return nil
return simulation.WeightedOperations(&simState, am.accountKeeper, am.bankKeeper, am.keeper)
}

// ____________________________________________________________________________
Expand Down
2 changes: 1 addition & 1 deletion x/wasm/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func setupTest(t *testing.T) testData {
ctx, keepers := CreateTestInput(t, false, "iterator,staking,stargate")
cdc := keeper.MakeTestCodec(t)
data := testData{
module: NewAppModule(cdc, keepers.WasmKeeper, keepers.StakingKeeper),
module: NewAppModule(cdc, keepers.WasmKeeper, keepers.StakingKeeper, keepers.AccountKeeper, keepers.BankKeeper),
ctx: ctx,
acctKeeper: keepers.AccountKeeper,
keeper: *keepers.WasmKeeper,
Expand Down
163 changes: 163 additions & 0 deletions x/wasm/simulation/operations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package simulation

import (
_ "embed"
"math/rand"

"github.com/cosmos/cosmos-sdk/baseapp"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"

"github.com/CosmWasm/wasmd/app/params"
"github.com/CosmWasm/wasmd/x/wasm/types"
)

//go:embed testdata/reflect.wasm
var reflectContract []byte
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to embed from the keeper testdata so that we do not have to maintain copies of the file?


// Simulation operation weights constants
//nolint:gosec
const (
OpWeightMsgStoreCode = "op_weight_msg_store_code"
OpWeightMsgInstantiateContract = "op_weight_msg_instantiate_contract"
)

// WasmKeeper is a subset of the wasm keeper used by simulations
type WasmKeeper interface {
GetParams(ctx sdk.Context) types.Params
IterateCodeInfos(ctx sdk.Context, cb func(uint64, types.CodeInfo) bool)
}

// WeightedOperations returns all the operations from the module with their respective weights
func WeightedOperations(
simstate *module.SimulationState,
ak types.AccountKeeper,
bk simulation.BankKeeper,
wasmKeeper WasmKeeper,
) simulation.WeightedOperations {
var (
weightMsgStoreCode int
weightMsgInstantiateContract int
)

simstate.AppParams.GetOrGenerate(simstate.Cdc, OpWeightMsgStoreCode, &weightMsgStoreCode, nil,
func(_ *rand.Rand) {
weightMsgStoreCode = params.DefaultWeightMsgStoreCode
},
)

simstate.AppParams.GetOrGenerate(simstate.Cdc, OpWeightMsgInstantiateContract, &weightMsgInstantiateContract, nil,
func(_ *rand.Rand) {
weightMsgInstantiateContract = params.DefaultWeightMsgInstantiateContract
},
)

return simulation.WeightedOperations{
simulation.NewWeightedOperation(
weightMsgStoreCode,
SimulateMsgStoreCode(ak, bk, wasmKeeper),
),
simulation.NewWeightedOperation(
weightMsgInstantiateContract,
SimulateMsgInstantiateContract(ak, bk, wasmKeeper),
),
}
}

// SimulateMsgStoreCode generates a MsgStoreCode with random values
func SimulateMsgStoreCode(ak types.AccountKeeper, bk simulation.BankKeeper, wasmKeeper WasmKeeper) simtypes.Operation {
return func(
r *rand.Rand,
app *baseapp.BaseApp,
ctx sdk.Context,
accs []simtypes.Account,
chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
if wasmKeeper.GetParams(ctx).CodeUploadAccess.Permission != types.AccessTypeEverybody {
return simtypes.NoOpMsg(types.ModuleName, types.MsgStoreCode{}.Type(), "no chain permission"), nil, nil
}

config := &types.AccessConfig{
Permission: types.AccessTypeEverybody,
}

simAccount, _ := simtypes.RandomAcc(r, accs)
msg := types.MsgStoreCode{
Sender: simAccount.Address.String(),
WASMByteCode: reflectContract,
InstantiatePermission: config,
}

txCtx := simulation.OperationInput{
R: r,
App: app,
TxGen: simappparams.MakeTestEncodingConfig().TxConfig,
Cdc: nil,
Msg: &msg,
MsgType: msg.Type(),
Context: ctx,
SimAccount: simAccount,
AccountKeeper: ak,
Bankkeeper: bk,
ModuleName: types.ModuleName,
}

return simulation.GenAndDeliverTxWithRandFees(txCtx)
}
}

// SimulateMsgInstantiateContract generates a MsgInstantiateContract with random values
func SimulateMsgInstantiateContract(ak types.AccountKeeper, bk simulation.BankKeeper, wasmKeeper WasmKeeper) simtypes.Operation {
return func(
r *rand.Rand,
app *baseapp.BaseApp,
ctx sdk.Context,
accs []simtypes.Account,
chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
simAccount, _ := simtypes.RandomAcc(r, accs)

var codeID uint64
wasmKeeper.IterateCodeInfos(ctx, func(u uint64, info types.CodeInfo) bool {
if info.InstantiateConfig.Permission != types.AccessTypeEverybody {
return false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, just take the next

}
codeID = u
return true
})

if codeID == 0 {
return simtypes.NoOpMsg(types.ModuleName, types.MsgInstantiateContract{}.Type(), "no codes with permission available"), nil, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

spendable := bk.SpendableCoins(ctx, simAccount.Address)

msg := types.MsgInstantiateContract{
Sender: simAccount.Address.String(),
Admin: simtypes.RandomAccounts(r, 1)[0].Address.String(),
CodeID: codeID,
Label: simtypes.RandStringOfLength(r, 10),
Msg: []byte(`{}`),
Funds: simtypes.RandSubsetCoins(r, spendable),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

txCtx := simulation.OperationInput{
R: r,
App: app,
TxGen: simappparams.MakeTestEncodingConfig().TxConfig,
Cdc: nil,
Msg: &msg,
MsgType: msg.Type(),
Context: ctx,
SimAccount: simAccount,
AccountKeeper: ak,
Bankkeeper: bk,
ModuleName: types.ModuleName,
}

return simulation.GenAndDeliverTxWithRandFees(txCtx)
}
}
Binary file added x/wasm/simulation/testdata/reflect.wasm
Binary file not shown.