github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/wasm/simulation/operations.go (about) 1 package simulation 2 3 // 4 //import ( 5 // "encoding/json" 6 // "io/ioutil" 7 // "math/rand" 8 // 9 // wasmvmtypes "github.com/CosmWasm/wasmvm/types" 10 // "github.com/cosmos/cosmos-sdk/baseapp" 11 // simappparams "github.com/cosmos/cosmos-sdk/simapp/params" 12 // sdk "github.com/cosmos/cosmos-sdk/types" 13 // sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 14 // "github.com/cosmos/cosmos-sdk/types/module" 15 // simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 16 // "github.com/cosmos/cosmos-sdk/x/simulation" 17 // 18 // "github.com/CosmWasm/wasmd/app/params" 19 // wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" 20 // "github.com/CosmWasm/wasmd/x/wasm/keeper/testdata" 21 // "github.com/CosmWasm/wasmd/x/wasm/types" 22 //) 23 // 24 //// Simulation operation weights constants 25 ////nolint:gosec 26 //const ( 27 // OpWeightMsgStoreCode = "op_weight_msg_store_code" 28 // OpWeightMsgInstantiateContract = "op_weight_msg_instantiate_contract" 29 // OpWeightMsgExecuteContract = "op_weight_msg_execute_contract" 30 // OpReflectContractPath = "op_reflect_contract_path" 31 //) 32 // 33 //// WasmKeeper is a subset of the wasm keeper used by simulations 34 //type WasmKeeper interface { 35 // GetParams(ctx sdk.Context) types.Params 36 // IterateCodeInfos(ctx sdk.Context, cb func(uint64, types.CodeInfo) bool) 37 // IterateContractInfo(ctx sdk.Context, cb func(sdk.AccAddress, types.ContractInfo) bool) 38 // QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) 39 // PeekAutoIncrementID(ctx sdk.Context, lastIDKey []byte) uint64 40 //} 41 //type BankKeeper interface { 42 // simulation.BankKeeper 43 // IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool 44 //} 45 // 46 //// WeightedOperations returns all the operations from the module with their respective weights 47 //func WeightedOperations( 48 // simstate *module.SimulationState, 49 // ak types.AccountKeeper, 50 // bk BankKeeper, 51 // wasmKeeper WasmKeeper, 52 //) simulation.WeightedOperations { 53 // var ( 54 // weightMsgStoreCode int 55 // weightMsgInstantiateContract int 56 // weightMsgExecuteContract int 57 // wasmContractPath string 58 // ) 59 // 60 // simstate.AppParams.GetOrGenerate(simstate.Cdc, OpWeightMsgStoreCode, &weightMsgStoreCode, nil, 61 // func(_ *rand.Rand) { 62 // weightMsgStoreCode = params.DefaultWeightMsgStoreCode 63 // }, 64 // ) 65 // 66 // simstate.AppParams.GetOrGenerate(simstate.Cdc, OpWeightMsgInstantiateContract, &weightMsgInstantiateContract, nil, 67 // func(_ *rand.Rand) { 68 // weightMsgInstantiateContract = params.DefaultWeightMsgInstantiateContract 69 // }, 70 // ) 71 // simstate.AppParams.GetOrGenerate(simstate.Cdc, OpWeightMsgExecuteContract, &weightMsgInstantiateContract, nil, 72 // func(_ *rand.Rand) { 73 // weightMsgExecuteContract = params.DefaultWeightMsgExecuteContract 74 // }, 75 // ) 76 // simstate.AppParams.GetOrGenerate(simstate.Cdc, OpReflectContractPath, &wasmContractPath, nil, 77 // func(_ *rand.Rand) { 78 // wasmContractPath = "" 79 // }, 80 // ) 81 // 82 // var wasmBz []byte 83 // if wasmContractPath == "" { 84 // wasmBz = testdata.ReflectContractWasm() 85 // } else { 86 // var err error 87 // wasmBz, err = ioutil.ReadFile(wasmContractPath) 88 // if err != nil { 89 // panic(err) 90 // } 91 // } 92 // 93 // return simulation.WeightedOperations{ 94 // simulation.NewWeightedOperation( 95 // weightMsgStoreCode, 96 // SimulateMsgStoreCode(ak, bk, wasmKeeper, wasmBz, 5_000_000), 97 // ), 98 // simulation.NewWeightedOperation( 99 // weightMsgInstantiateContract, 100 // SimulateMsgInstantiateContract(ak, bk, wasmKeeper, DefaultSimulationCodeIDSelector), 101 // ), 102 // simulation.NewWeightedOperation( 103 // weightMsgExecuteContract, 104 // SimulateMsgExecuteContract( 105 // ak, 106 // bk, 107 // wasmKeeper, 108 // DefaultSimulationExecuteContractSelector, 109 // DefaultSimulationExecuteSenderSelector, 110 // DefaultSimulationExecutePayloader, 111 // ), 112 // ), 113 // } 114 //} 115 // 116 //// SimulateMsgStoreCode generates a MsgStoreCode with random values 117 //func SimulateMsgStoreCode(ak types.AccountKeeper, bk simulation.BankKeeper, wasmKeeper WasmKeeper, wasmBz []byte, gas uint64) simtypes.Operation { 118 // return func( 119 // r *rand.Rand, 120 // app *baseapp.BaseApp, 121 // ctx sdk.Context, 122 // accs []simtypes.Account, 123 // chainID string, 124 // ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 125 // if wasmKeeper.GetParams(ctx).CodeUploadAccess.Permission != types.AccessTypeEverybody { 126 // return simtypes.NoOpMsg(types.ModuleName, types.MsgStoreCode{}.Type(), "no chain permission"), nil, nil 127 // } 128 // 129 // simAccount, _ := simtypes.RandomAcc(r, accs) 130 // 131 // permission := wasmKeeper.GetParams(ctx).InstantiateDefaultPermission 132 // config := permission.With(simAccount.Address) 133 // 134 // msg := types.MsgStoreCode{ 135 // Sender: simAccount.Address.String(), 136 // WASMByteCode: wasmBz, 137 // InstantiatePermission: &config, 138 // } 139 // 140 // txCtx := simulation.OperationInput{ 141 // R: r, 142 // App: app, 143 // TxGen: simappparams.MakeTestEncodingConfig().TxConfig, 144 // Cdc: nil, 145 // Msg: &msg, 146 // MsgType: msg.Type(), 147 // Context: ctx, 148 // SimAccount: simAccount, 149 // AccountKeeper: ak, 150 // Bankkeeper: bk, 151 // ModuleName: types.ModuleName, 152 // } 153 // 154 // return GenAndDeliverTxWithRandFees(txCtx, gas) 155 // } 156 //} 157 // 158 //// CodeIDSelector returns code id to be used in simulations 159 //type CodeIDSelector = func(ctx sdk.Context, wasmKeeper WasmKeeper) uint64 160 // 161 //// DefaultSimulationCodeIDSelector picks the first code id 162 //func DefaultSimulationCodeIDSelector(ctx sdk.Context, wasmKeeper WasmKeeper) uint64 { 163 // var codeID uint64 164 // wasmKeeper.IterateCodeInfos(ctx, func(u uint64, info types.CodeInfo) bool { 165 // if info.InstantiateConfig.Permission != types.AccessTypeEverybody { 166 // return false 167 // } 168 // codeID = u 169 // return true 170 // }) 171 // return codeID 172 //} 173 // 174 //// SimulateMsgInstantiateContract generates a MsgInstantiateContract with random values 175 //func SimulateMsgInstantiateContract(ak types.AccountKeeper, bk BankKeeper, wasmKeeper WasmKeeper, codeSelector CodeIDSelector) simtypes.Operation { 176 // return func( 177 // r *rand.Rand, 178 // app *baseapp.BaseApp, 179 // ctx sdk.Context, 180 // accs []simtypes.Account, 181 // chainID string, 182 // ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 183 // simAccount, _ := simtypes.RandomAcc(r, accs) 184 // 185 // codeID := codeSelector(ctx, wasmKeeper) 186 // if codeID == 0 { 187 // return simtypes.NoOpMsg(types.ModuleName, types.MsgInstantiateContract{}.Type(), "no codes with permission available"), nil, nil 188 // } 189 // deposit := sdk.Coins{} 190 // spendableCoins := bk.SpendableCoins(ctx, simAccount.Address) 191 // for _, v := range spendableCoins { 192 // if bk.IsSendEnabledCoin(ctx, v) { 193 // deposit = deposit.Add(simtypes.RandSubsetCoins(r, sdk.NewCoins(v))...) 194 // } 195 // } 196 // 197 // msg := types.MsgInstantiateContract{ 198 // Sender: simAccount.Address.String(), 199 // Admin: simtypes.RandomAccounts(r, 1)[0].Address.String(), 200 // CodeID: codeID, 201 // Label: simtypes.RandStringOfLength(r, 10), 202 // Msg: []byte(`{}`), 203 // Funds: deposit, 204 // } 205 // 206 // txCtx := simulation.OperationInput{ 207 // R: r, 208 // App: app, 209 // TxGen: simappparams.MakeTestEncodingConfig().TxConfig, 210 // Cdc: nil, 211 // Msg: &msg, 212 // MsgType: msg.Type(), 213 // Context: ctx, 214 // SimAccount: simAccount, 215 // AccountKeeper: ak, 216 // Bankkeeper: bk, 217 // ModuleName: types.ModuleName, 218 // CoinsSpentInMsg: deposit, 219 // } 220 // 221 // return simulation.GenAndDeliverTxWithRandFees(txCtx) 222 // } 223 //} 224 // 225 //// MsgExecuteContractSelector returns contract address to be used in simulations 226 //type MsgExecuteContractSelector = func(ctx sdk.Context, wasmKeeper WasmKeeper) sdk.AccAddress 227 // 228 //// MsgExecutePayloader extension point to modify msg with custom payload 229 //type MsgExecutePayloader func(msg *types.MsgExecuteContract) error 230 // 231 //// MsgExecuteSenderSelector extension point that returns the sender address 232 //type MsgExecuteSenderSelector func(wasmKeeper WasmKeeper, ctx sdk.Context, contractAddr sdk.AccAddress, accs []simtypes.Account) (simtypes.Account, error) 233 // 234 //// SimulateMsgExecuteContract create a execute message a reflect contract instance 235 //func SimulateMsgExecuteContract( 236 // ak types.AccountKeeper, 237 // bk BankKeeper, 238 // wasmKeeper WasmKeeper, 239 // contractSelector MsgExecuteContractSelector, 240 // senderSelector MsgExecuteSenderSelector, 241 // payloader MsgExecutePayloader, 242 //) simtypes.Operation { 243 // return func( 244 // r *rand.Rand, 245 // app *baseapp.BaseApp, 246 // ctx sdk.Context, 247 // accs []simtypes.Account, 248 // chainID string, 249 // ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 250 // contractAddr := contractSelector(ctx, wasmKeeper) 251 // if contractAddr == nil { 252 // return simtypes.NoOpMsg(types.ModuleName, types.MsgExecuteContract{}.Type(), "no contract instance available"), nil, nil 253 // } 254 // simAccount, err := senderSelector(wasmKeeper, ctx, contractAddr, accs) 255 // if err != nil { 256 // return simtypes.NoOpMsg(types.ModuleName, types.MsgExecuteContract{}.Type(), "query contract owner"), nil, err 257 // } 258 // 259 // deposit := sdk.Coins{} 260 // spendableCoins := bk.SpendableCoins(ctx, simAccount.Address) 261 // for _, v := range spendableCoins { 262 // if bk.IsSendEnabledCoin(ctx, v) { 263 // deposit = deposit.Add(simtypes.RandSubsetCoins(r, sdk.NewCoins(v))...) 264 // } 265 // } 266 // if deposit.IsZero() { 267 // return simtypes.NoOpMsg(types.ModuleName, types.MsgExecuteContract{}.Type(), "broke account"), nil, nil 268 // } 269 // msg := types.MsgExecuteContract{ 270 // Sender: simAccount.Address.String(), 271 // Contract: contractAddr.String(), 272 // Funds: deposit, 273 // } 274 // if err := payloader(&msg); err != nil { 275 // return simtypes.NoOpMsg(types.ModuleName, types.MsgExecuteContract{}.Type(), "contract execute payload"), nil, err 276 // } 277 // 278 // txCtx := simulation.OperationInput{ 279 // R: r, 280 // App: app, 281 // TxGen: simappparams.MakeTestEncodingConfig().TxConfig, 282 // Cdc: nil, 283 // Msg: &msg, 284 // MsgType: msg.Type(), 285 // Context: ctx, 286 // SimAccount: simAccount, 287 // AccountKeeper: ak, 288 // Bankkeeper: bk, 289 // ModuleName: types.ModuleName, 290 // CoinsSpentInMsg: deposit, 291 // } 292 // return simulation.GenAndDeliverTxWithRandFees(txCtx) 293 // } 294 //} 295 // 296 //// DefaultSimulationExecuteContractSelector picks the first contract address 297 //func DefaultSimulationExecuteContractSelector(ctx sdk.Context, wasmKeeper WasmKeeper) sdk.AccAddress { 298 // var r sdk.AccAddress 299 // wasmKeeper.IterateContractInfo(ctx, func(address sdk.AccAddress, info types.ContractInfo) bool { 300 // r = address 301 // return true 302 // }) 303 // return r 304 //} 305 // 306 //// DefaultSimulationExecuteSenderSelector queries reflect contract for owner address and selects accounts 307 //func DefaultSimulationExecuteSenderSelector(wasmKeeper WasmKeeper, ctx sdk.Context, contractAddr sdk.AccAddress, accs []simtypes.Account) (simtypes.Account, error) { 308 // var none simtypes.Account 309 // bz, err := json.Marshal(testdata.ReflectQueryMsg{Owner: &struct{}{}}) 310 // if err != nil { 311 // return none, sdkerrors.Wrap(err, "build smart query") 312 // } 313 // got, err := wasmKeeper.QuerySmart(ctx, contractAddr, bz) 314 // if err != nil { 315 // return none, sdkerrors.Wrap(err, "exec smart query") 316 // } 317 // var ownerRes testdata.OwnerResponse 318 // if err := json.Unmarshal(got, &ownerRes); err != nil || ownerRes.Owner == "" { 319 // return none, sdkerrors.Wrap(err, "parse smart query response") 320 // } 321 // ownerAddr, err := sdk.AccAddressFromBech32(ownerRes.Owner) 322 // if err != nil { 323 // return none, sdkerrors.Wrap(err, "parse contract owner address") 324 // } 325 // simAccount, ok := simtypes.FindAccount(accs, ownerAddr) 326 // if !ok { 327 // return none, sdkerrors.Wrap(err, "unknown contract owner address") 328 // } 329 // return simAccount, nil 330 //} 331 // 332 //// DefaultSimulationExecutePayloader implements a bank msg to send the 333 //// tokens from contract account back to original sender 334 //func DefaultSimulationExecutePayloader(msg *types.MsgExecuteContract) error { 335 // reflectSend := testdata.ReflectHandleMsg{ 336 // Reflect: &testdata.ReflectPayload{ 337 // Msgs: []wasmvmtypes.CosmosMsg{{ 338 // Bank: &wasmvmtypes.BankMsg{ 339 // Send: &wasmvmtypes.SendMsg{ 340 // ToAddress: msg.Sender, // 341 // Amount: wasmkeeper.ConvertSdkCoinsToWasmCoins(msg.Funds), 342 // }, 343 // }, 344 // }}, 345 // }, 346 // } 347 // reflectSendBz, err := json.Marshal(reflectSend) 348 // if err != nil { 349 // return err 350 // } 351 // msg.Msg = reflectSendBz 352 // return nil 353 //}