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 weighted operations run simulation #1055

Merged
merged 16 commits into from
Nov 2, 2022
8 changes: 6 additions & 2 deletions app/params/weights.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ const (
DefaultWeightCommunitySpendProposal int = 5
DefaultWeightTextProposal int = 5
DefaultWeightParamChangeProposal int = 5
DefaultWeightMsgStoreCode int = 50
DefaultWeightMsgInstantiateContract int = 100

DefaultWeightMsgStoreCode int = 100
DefaultWeightMsgInstantiateContract int = 50
Copy link
Contributor

Choose a reason for hiding this comment

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

Why flipping store and instantiate weights?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have fixed

DefaultWeightMsgExecuteContract int = 100
DefaultWeightMsgUpdateAdmin int = 100
Copy link
Contributor

Choose a reason for hiding this comment

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

I would expect this to happen quire rarely. How about 25?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have changed

DefaultWeightMsgClearAdmin int = 100
Copy link
Contributor

Choose a reason for hiding this comment

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

I would expect this to happen quire rarely. How about 10?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have changed

DefaultWeightMsgMigrateContract int = 100
Copy link
Contributor

Choose a reason for hiding this comment

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

I would expect more instantiations than migrations. How about 50?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have changed

)
Binary file added x/wasm/keeper/testdata/reflect_1_1.wasm
Binary file not shown.
267 changes: 265 additions & 2 deletions x/wasm/simulation/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ package simulation

import (
"encoding/json"
"fmt"
"math/rand"
"os"

wasmvmtypes "github.com/CosmWasm/wasmvm/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/simapp/helpers"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/gogo/protobuf/proto"

"github.com/CosmWasm/wasmd/app/params"
wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
Expand All @@ -27,6 +30,9 @@ const (
OpWeightMsgStoreCode = "op_weight_msg_store_code"
OpWeightMsgInstantiateContract = "op_weight_msg_instantiate_contract"
OpWeightMsgExecuteContract = "op_weight_msg_execute_contract"
OpWeightMsgUpdateAdmin = "op_weight_msg_update_admin"
OpWeightMsgClearAdmin = "op_weight_msg_clear_admin"
OpWeightMsgMigrateContract = "op_weight_msg_migrate_contract"
OpReflectContractPath = "op_reflect_contract_path"
)

Expand Down Expand Up @@ -54,6 +60,9 @@ func WeightedOperations(
weightMsgStoreCode int
weightMsgInstantiateContract int
weightMsgExecuteContract int
weightMsgUpdateAdmin int
weightMsgClearAdmin int
weightMsgMigrateContract int
wasmContractPath string
)

Expand All @@ -62,7 +71,6 @@ func WeightedOperations(
weightMsgStoreCode = params.DefaultWeightMsgStoreCode
},
)

simstate.AppParams.GetOrGenerate(simstate.Cdc, OpWeightMsgInstantiateContract, &weightMsgInstantiateContract, nil,
func(_ *rand.Rand) {
weightMsgInstantiateContract = params.DefaultWeightMsgInstantiateContract
Expand All @@ -73,6 +81,21 @@ func WeightedOperations(
weightMsgExecuteContract = params.DefaultWeightMsgExecuteContract
},
)
simstate.AppParams.GetOrGenerate(simstate.Cdc, OpWeightMsgUpdateAdmin, &weightMsgUpdateAdmin, nil,
func(_ *rand.Rand) {
weightMsgUpdateAdmin = params.DefaultWeightMsgUpdateAdmin
},
)
simstate.AppParams.GetOrGenerate(simstate.Cdc, OpWeightMsgClearAdmin, &weightMsgClearAdmin, nil,
func(_ *rand.Rand) {
weightMsgClearAdmin = params.DefaultWeightMsgClearAdmin
},
)
simstate.AppParams.GetOrGenerate(simstate.Cdc, OpWeightMsgMigrateContract, &weightMsgMigrateContract, nil,
func(_ *rand.Rand) {
weightMsgMigrateContract = params.DefaultWeightMsgMigrateContract
},
)
simstate.AppParams.GetOrGenerate(simstate.Cdc, OpReflectContractPath, &wasmContractPath, nil,
func(_ *rand.Rand) {
wasmContractPath = ""
Expand Down Expand Up @@ -110,6 +133,244 @@ func WeightedOperations(
DefaultSimulationExecutePayloader,
),
),
simulation.NewWeightedOperation(
weightMsgUpdateAdmin,
SimulateMsgUpdateAmin(
ak,
bk,
wasmKeeper,
DefaultSimulationUpdateAdminContractSelector,
),
),
simulation.NewWeightedOperation(
weightMsgClearAdmin,
SimulateMsgClearAdmin(
ak,
bk,
wasmKeeper,
DefaultSimulationClearAdminContractSelector,
),
),
simulation.NewWeightedOperation(
weightMsgMigrateContract,
SimulateMsgMigrateContract(
ak,
bk,
wasmKeeper,
DefaultSimulationMigrateContractSelector,
DefaultSimulationMigrateCodeIDSelector,
),
),
}
}

type MsgMigrateContractSelector func(sdk.Context, WasmKeeper, string) (sdk.AccAddress, types.ContractInfo)
type MsgMigrateCodeIDSelector func(sdk.Context, WasmKeeper, uint64) uint64

func DefaultSimulationMigrateContractSelector(ctx sdk.Context, wasmKeeper WasmKeeper, adminAddress string) (sdk.AccAddress, types.ContractInfo) {
var contractAddress sdk.AccAddress
var contractInfo types.ContractInfo
wasmKeeper.IterateContractInfo(ctx, func(address sdk.AccAddress, info types.ContractInfo) bool {
if info.Admin != adminAddress {
return false
}
contractAddress = address
contractInfo = info
return true
})
return contractAddress, contractInfo
}

func DefaultSimulationMigrateCodeIDSelector(ctx sdk.Context, wasmKeeper WasmKeeper, currentCodeID uint64) uint64 {
var codeID uint64
wasmKeeper.IterateCodeInfos(ctx, func(u uint64, info types.CodeInfo) bool {
if (info.InstantiateConfig.Permission != types.AccessTypeEverybody) || (u == currentCodeID) {
return false
}
codeID = u
return true
})
return codeID
}

func SimulateMsgMigrateContract(
ak types.AccountKeeper,
bk BankKeeper,
wasmKeeper WasmKeeper,
contractSelector MsgMigrateContractSelector,
codeIDSelector MsgMigrateCodeIDSelector,
) 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)
ctAddress, _ := contractSelector(ctx, wasmKeeper, simAccount.Address.String())
if ctAddress == nil {
return simtypes.NoOpMsg(types.ModuleName, types.MsgMigrateContract{}.Type(), "no contract instance available"), nil, nil
}

var wasmBz []byte
var err error
wasmBz, err = os.ReadFile("./../x/wasm/keeper/testdata/reflect_1_1.wasm")
Copy link
Contributor

Choose a reason for hiding this comment

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

I tried to avoid hard coding any contracts here. See L106-7.
As we only store reflect contracts you can just pick a different code id and drop the store code part.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have fixed to embed

if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.MsgMigrateContract{}.Type(), "no new wasmbyte code"), nil, err
}

permission := types.AccessTypeOnlyAddress
config := permission.With(simAccount.Address)

msg := types.MsgStoreCode{
Sender: simAccount.Address.String(),
WASMByteCode: wasmBz,
InstantiatePermission: &config,
}

txCtx := BuildOperationInput(r, app, ctx, &msg, simAccount, ak, bk, nil)
account := txCtx.AccountKeeper.GetAccount(txCtx.Context, txCtx.SimAccount.Address)
spendable := txCtx.Bankkeeper.SpendableCoins(txCtx.Context, account.GetAddress())

var fees sdk.Coins
fees, err = simtypes.RandomFees(txCtx.R, txCtx.Context, spendable)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.MsgMigrateContract{}.Type(), "unable to generate fees"), nil, err
}

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(types.ModuleName, types.MsgMigrateContract{}.Type(), "unable to generate mock tx"), nil, err
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return simtypes.NoOpMsg(types.ModuleName, types.MsgMigrateContract{}.Type(), "unable to generate mock tx"), nil, err
return simtypes.NoOpMsg(types.ModuleName, types.MsgMigrateContract{}.Type(), "unable to generate tx"), nil, err

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have changed

}

_, data, err := app.Deliver(txCtx.TxGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.MsgMigrateContract{}.Type(), "unable to deliver tx"), nil, err
}

var result sdk.TxMsgData
err = proto.Unmarshal(data.Data, &result)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.MsgMigrateContract{}.Type(), "unable to read response data"), nil, err
}

fmt.Printf("%v\n", result.Data[0].MsgType)
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's avoid Printfs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have removed


var msgStoreCodeRespone types.MsgStoreCodeResponse
err = proto.Unmarshal(result.Data[0].Data, &msgStoreCodeRespone)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.MsgMigrateContract{}.Type(), "unable to unmarshall response data"), nil, err
}

fmt.Printf("%v\n", msgStoreCodeRespone.CodeID)

migrateMsg := types.MsgMigrateContract{
Sender: simAccount.Address.String(),
Contract: ctAddress.String(),
CodeID: msgStoreCodeRespone.CodeID,
Msg: []byte(`{}`),
}

txCtx = BuildOperationInput(r, app, ctx, &migrateMsg, simAccount, ak, bk, nil)
return simulation.GenAndDeliverTxWithRandFees(txCtx)
}
}

type MsgClearAdminContractSelector func(sdk.Context, WasmKeeper, string) sdk.AccAddress

func DefaultSimulationClearAdminContractSelector(ctx sdk.Context, wasmKeeper WasmKeeper, adminAddress string) sdk.AccAddress {
var ctAddress sdk.AccAddress
wasmKeeper.IterateContractInfo(ctx, func(addr sdk.AccAddress, info types.ContractInfo) bool {
if info.Admin != adminAddress {
return false
}
ctAddress = addr
return true
})
return ctAddress
}

func SimulateMsgClearAdmin(
ak types.AccountKeeper,
bk BankKeeper,
wasmKeeper WasmKeeper,
contractSelector MsgClearAdminContractSelector,
) simtypes.Operation {
return func(
r *rand.Rand,
app *baseapp.BaseApp,
ctx sdk.Context,
accounts []simtypes.Account,
chainID string,
) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) {
simAccount, _ := simtypes.RandomAcc(r, accounts)
ctAddress := contractSelector(ctx, wasmKeeper, simAccount.Address.String())
if ctAddress == nil {
return simtypes.NoOpMsg(types.ModuleName, types.MsgClearAdmin{}.Type(), "no contract instance available"), nil, nil
}

msg := types.MsgClearAdmin{
Sender: simAccount.Address.String(),
Contract: ctAddress.String(),
}
txCtx := BuildOperationInput(r, app, ctx, &msg, simAccount, ak, bk, nil)
return simulation.GenAndDeliverTxWithRandFees(txCtx)
}
}

type MsgUpdateAdminContractSelector func(sdk.Context, WasmKeeper, string) (sdk.AccAddress, types.ContractInfo)

// DefaultSimulationUpdateAdminContractSelector picks the first contract which Admin != ""
func DefaultSimulationUpdateAdminContractSelector(ctx sdk.Context, wasmKeeper WasmKeeper, adminAddress string) (sdk.AccAddress, types.ContractInfo) {
var contractAddress sdk.AccAddress
var contractInfo types.ContractInfo
wasmKeeper.IterateContractInfo(ctx, func(address sdk.AccAddress, info types.ContractInfo) bool {
if info.Admin != adminAddress {
return false
}
contractAddress = address
contractInfo = info
return true
})
return contractAddress, contractInfo
}

func SimulateMsgUpdateAmin(
ak types.AccountKeeper,
bk BankKeeper,
wasmKeeper WasmKeeper,
contractSelector MsgUpdateAdminContractSelector,
) 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)
ctAddress, _ := contractSelector(ctx, wasmKeeper, simAccount.Address.String())
if ctAddress == nil {
return simtypes.NoOpMsg(types.ModuleName, types.MsgUpdateAdmin{}.Type(), "no contract instance available"), nil, nil
}

msg := types.MsgUpdateAdmin{
Sender: simAccount.Address.String(),
NewAdmin: simtypes.RandomAccounts(r, 1)[0].Address.String(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's use simtypes.RandomAcc(r, accs) instead to not run dry

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have fixed

Contract: ctAddress.String(),
}
txCtx := BuildOperationInput(r, app, ctx, &msg, simAccount, ak, bk, nil)
return simulation.GenAndDeliverTxWithRandFees(txCtx)
}
}

Expand Down Expand Up @@ -180,9 +441,11 @@ func SimulateMsgInstantiateContract(ak types.AccountKeeper, bk BankKeeper, wasmK
}
}

adminAccount, _ := simtypes.RandomAcc(r, accs)

msg := types.MsgInstantiateContract{
Sender: simAccount.Address.String(),
Admin: simtypes.RandomAccounts(r, 1)[0].Address.String(),
Admin: adminAccount.Address.String(),
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

CodeID: codeID,
Label: simtypes.RandStringOfLength(r, 10),
Msg: []byte(`{}`),
Expand Down