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 simulation for gov #1064

Merged
merged 12 commits into from
Nov 1, 2022
7 changes: 7 additions & 0 deletions app/params/weights.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@ const (
DefaultWeightCommunitySpendProposal int = 5
DefaultWeightTextProposal int = 5
DefaultWeightParamChangeProposal int = 5

DefaultWeightMsgStoreCode int = 50
DefaultWeightMsgInstantiateContract int = 100
DefaultWeightMsgExecuteContract int = 100

DefaultWeightStoreCodeProposal int = 5
DefaultWeightInstantiateContractProposal int = 5
DefaultWeightUpdateAdminProposal int = 5
DefaultWeightExecuteContractProposal int = 5
DefaultWeightClearAdminProposal int = 5
)
4 changes: 2 additions & 2 deletions x/wasm/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
}

// ProposalContents doesn't return any content functions for governance proposals.
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return simulation.ProposalContents(am.bankKeeper, am.keeper)
}

// RandomizedParams creates randomized bank param changes for the simulator.
Expand Down
221 changes: 221 additions & 0 deletions x/wasm/simulation/proposals.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
package simulation

import (
"math/rand"

"github.com/CosmWasm/wasmd/app/params"
"github.com/CosmWasm/wasmd/x/wasm/keeper/testdata"
"github.com/CosmWasm/wasmd/x/wasm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
)

const (
WeightStoreCodeProposal = "weight_store_code_proposal"
WeightInstantiateContractProposal = "weight_instantiate_contract_proposal"
WeightUpdateAdminProposal = "weight_update_admin_proposal"
WeightExeContractProposal = "weight_execute_contract_proposal"
WeightClearAdminProposal = "weight_clear_admin_proposal"
)

func ProposalContents(bk BankKeeper, wasmKeeper WasmKeeper) []simtypes.WeightedProposalContent {
return []simtypes.WeightedProposalContent{
// simulation.NewWeightedProposalContent(
// WeightStoreCodeProposal,
// params.DefaultWeightStoreCodeProposal,
// SimulateStoreCodeProposal(wasmKeeper),
// ),
simulation.NewWeightedProposalContent(
WeightInstantiateContractProposal,
params.DefaultWeightInstantiateContractProposal,
SimulateInstantiateContractProposal(
bk,
wasmKeeper,
DefaultSimulationCodeIDSelector,
),
),
simulation.NewWeightedProposalContent(
WeightUpdateAdminProposal,
params.DefaultWeightUpdateAdminProposal,
SimulateUpdateAdminProposal(
wasmKeeper,
DefaultSimulateUpdateAdminProposalContractSelector,
),
),
simulation.NewWeightedProposalContent(
WeightExeContractProposal,
params.DefaultWeightExecuteContractProposal,
SimulateExecuteContractProposal(
bk,
wasmKeeper,
DefaultSimulationExecuteContractSelector,
DefaultSimulationExecuteSenderSelector,
DefaultSimulationExecutePayloader,
),
),
simulation.NewWeightedProposalContent(
WeightClearAdminProposal,
params.DefaultWeightClearAdminProposal,
SimulateClearAdminProposal(
wasmKeeper,
DefaultSimulateClearAdminProposalContractSelector,
),
),
}
}

// simulate store code proposal (unused now)
// Current problem: out of gas (defaul gaswanted config of gov SimulateMsgSubmitProposal is 10_000_000)
Copy link
Member

Choose a reason for hiding this comment

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

Do you have a proposal for a better gas value? We can open an issue/PR on the SDK to get this addressed

Copy link
Contributor Author

@GNaD13 GNaD13 Nov 1, 2022

Choose a reason for hiding this comment

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

I think we have 2 solution to solve this problem:

  • Open a PR to increase defaul gaswanted so that this proposal can easily pass
  • Write a simple .wasm code which size is smaller than current. So that it can decrease the gas used.

But the 2 solution quite difficult. Because this may change all the current sims test. One more thing, in the future, we need to implement sudo entry point for Sudo proposal (it will increase the size of .wasm contract)

Copy link
Member

Choose a reason for hiding this comment

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

Store code and sudo gov operations are well covered by integration tests already. Simulations are just for regression and fuzzing. They don't add super much value here IMHO. Let's have a follow up task to revisit the store code when we are on SDK v0.47. There is some work on the gov module.

// but this proposal may need more than it
func SimulateStoreCodeProposal(wasmKeeper WasmKeeper) simtypes.ContentSimulatorFn {
return func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content {
simAccount, _ := simtypes.RandomAcc(r, accs)

wasmBz := testdata.ReflectContractWasm()

permission := wasmKeeper.GetParams(ctx).InstantiateDefaultPermission.With(simAccount.Address)

return types.NewStoreCodeProposal(
simtypes.RandStringOfLength(r, 10),
simtypes.RandStringOfLength(r, 10),
simAccount.Address.String(),
wasmBz,
&permission,
false,
)
}
}

// Simulate instantiate contract proposal
func SimulateInstantiateContractProposal(bk BankKeeper, wasmKeeper WasmKeeper, codeSelector CodeIDSelector) simtypes.ContentSimulatorFn {
return func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content {
simAccount, _ := simtypes.RandomAcc(r, accs)
// admin
adminAccount, _ := simtypes.RandomAcc(r, accs)
// get codeID
codeID := codeSelector(ctx, wasmKeeper)
if codeID == 0 {
return nil
}

return types.NewInstantiateContractProposal(
simtypes.RandStringOfLength(r, 10),
simtypes.RandStringOfLength(r, 10),
simAccount.Address.String(),
adminAccount.Address.String(),
codeID,
simtypes.RandStringOfLength(r, 10),
[]byte(`{}`),
sdk.Coins{},
)
}
}

// Simulate execute contract proposal
func SimulateExecuteContractProposal(
bk BankKeeper,
wasmKeeper WasmKeeper,
contractSelector MsgExecuteContractSelector,
senderSelector MsgExecuteSenderSelector,
payloader MsgExecutePayloader,
) simtypes.ContentSimulatorFn {
return func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content {
ctAddress := contractSelector(ctx, wasmKeeper)
if ctAddress == nil {
return nil
}

simAccount, err := senderSelector(wasmKeeper, ctx, ctAddress, accs)
if err != nil {
return nil
}

msg := types.MsgExecuteContract{
Sender: simAccount.Address.String(),
Contract: ctAddress.String(),
Funds: sdk.Coins{},
}

if err := payloader(&msg); err != nil {
return nil
}

return types.NewExecuteContractProposal(
simtypes.RandStringOfLength(r, 10),
simtypes.RandStringOfLength(r, 10),
simAccount.Address.String(),
ctAddress.String(),
msg.Msg,
sdk.Coins{},
)
}
}

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

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

// Simulate update admin contract proposal
func SimulateUpdateAdminProposal(wasmKeeper WasmKeeper, contractSelector UpdateAdminContractSelector) simtypes.ContentSimulatorFn {
return func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content {
simAccount, _ := simtypes.RandomAcc(r, accs)
ctAddress, _ := contractSelector(ctx, wasmKeeper, simAccount.Address.String())
if ctAddress == nil {
return nil
}

return types.NewUpdateAdminProposal(
simtypes.RandStringOfLength(r, 10),
simtypes.RandStringOfLength(r, 10),
simtypes.RandomAccounts(r, 1)[0].Address.String(),
ctAddress.String(),
)
}
}

type ClearAdminContractSelector func(sdk.Context, WasmKeeper) sdk.AccAddress

func DefaultSimulateClearAdminProposalContractSelector(
ctx sdk.Context,
wasmKeeper WasmKeeper,
) sdk.AccAddress {
var contractAddr sdk.AccAddress
wasmKeeper.IterateContractInfo(ctx, func(address sdk.AccAddress, info types.ContractInfo) bool {
contractAddr = address
return true
})
return contractAddr
}

// Simulate clear admin proposal
func SimulateClearAdminProposal(wasmKeeper WasmKeeper, contractSelector ClearAdminContractSelector) simtypes.ContentSimulatorFn {
return func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content {
ctAddress := contractSelector(ctx, wasmKeeper)
if ctAddress == nil {
return nil
}

return types.NewClearAdminProposal(
simtypes.RandStringOfLength(r, 10),
simtypes.RandStringOfLength(r, 10),
ctAddress.String(),
)
}
}
52 changes: 52 additions & 0 deletions x/wasm/types/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ func init() { // register new content types with the sdk
govtypes.RegisterProposalTypeCodec(&UpdateInstantiateConfigProposal{}, "wasm/UpdateInstantiateConfigProposal")
}

func NewStoreCodeProposal(
title string,
description string,
runAs string,
wasmBz []byte,
permission *AccessConfig,
unpinCode bool,
) *StoreCodeProposal {
return &StoreCodeProposal{title, description, runAs, wasmBz, permission, unpinCode}
}

// ProposalRoute returns the routing key of a parameter change proposal.
func (p StoreCodeProposal) ProposalRoute() string { return RouterKey }

Expand Down Expand Up @@ -143,6 +154,19 @@ func (p StoreCodeProposal) MarshalYAML() (interface{}, error) {
}, nil
}

func NewInstantiateContractProposal(
title string,
description string,
runAs string,
admin string,
codeID uint64,
label string,
msg RawContractMessage,
funds sdk.Coins,
) *InstantiateContractProposal {
return &InstantiateContractProposal{title, description, runAs, admin, codeID, label, msg, funds}
}

// ProposalRoute returns the routing key of a parameter change proposal.
func (p InstantiateContractProposal) ProposalRoute() string { return RouterKey }

Expand Down Expand Up @@ -334,6 +358,17 @@ func (p SudoContractProposal) MarshalYAML() (interface{}, error) {
}, nil
}

func NewExecuteContractProposal(
title string,
description string,
runAs string,
contract string,
msg RawContractMessage,
funds sdk.Coins,
) *ExecuteContractProposal {
return &ExecuteContractProposal{title, description, runAs, contract, msg, funds}
}

// ProposalRoute returns the routing key of a parameter change proposal.
func (p ExecuteContractProposal) ProposalRoute() string { return RouterKey }

Expand Down Expand Up @@ -397,6 +432,15 @@ func (p ExecuteContractProposal) MarshalYAML() (interface{}, error) {
}, nil
}

func NewUpdateAdminProposal(
title string,
description string,
newAdmin string,
contract string,
) *UpdateAdminProposal {
return &UpdateAdminProposal{title, description, newAdmin, contract}
}

// ProposalRoute returns the routing key of a parameter change proposal.
func (p UpdateAdminProposal) ProposalRoute() string { return RouterKey }

Expand Down Expand Up @@ -433,6 +477,14 @@ func (p UpdateAdminProposal) String() string {
`, p.Title, p.Description, p.Contract, p.NewAdmin)
}

func NewClearAdminProposal(
title string,
description string,
contract string,
) *ClearAdminProposal {
return &ClearAdminProposal{title, description, contract}
}

// ProposalRoute returns the routing key of a parameter change proposal.
func (p ClearAdminProposal) ProposalRoute() string { return RouterKey }

Expand Down