github.com/cosmos/cosmos-sdk@v0.50.10/x/group/simulation/operations.go (about) 1 package simulation 2 3 import ( 4 "context" 5 "fmt" 6 "math/rand" 7 "strings" 8 "time" 9 10 "github.com/cosmos/cosmos-sdk/baseapp" 11 "github.com/cosmos/cosmos-sdk/client" 12 "github.com/cosmos/cosmos-sdk/codec" 13 cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 14 simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" 15 sdk "github.com/cosmos/cosmos-sdk/types" 16 simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 17 "github.com/cosmos/cosmos-sdk/x/group" 18 "github.com/cosmos/cosmos-sdk/x/group/keeper" 19 "github.com/cosmos/cosmos-sdk/x/simulation" 20 ) 21 22 var initialGroupID = uint64(100000000000000) 23 24 // group message types 25 var ( 26 TypeMsgCreateGroup = sdk.MsgTypeURL(&group.MsgCreateGroup{}) 27 TypeMsgUpdateGroupMembers = sdk.MsgTypeURL(&group.MsgUpdateGroupMembers{}) 28 TypeMsgUpdateGroupAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupAdmin{}) 29 TypeMsgUpdateGroupMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupMetadata{}) 30 TypeMsgCreateGroupWithPolicy = sdk.MsgTypeURL(&group.MsgCreateGroupWithPolicy{}) 31 TypeMsgCreateGroupPolicy = sdk.MsgTypeURL(&group.MsgCreateGroupPolicy{}) 32 TypeMsgUpdateGroupPolicyAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyAdmin{}) 33 TypeMsgUpdateGroupPolicyDecisionPolicy = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyDecisionPolicy{}) 34 TypeMsgUpdateGroupPolicyMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyMetadata{}) 35 TypeMsgSubmitProposal = sdk.MsgTypeURL(&group.MsgSubmitProposal{}) 36 TypeMsgWithdrawProposal = sdk.MsgTypeURL(&group.MsgWithdrawProposal{}) 37 TypeMsgVote = sdk.MsgTypeURL(&group.MsgVote{}) 38 TypeMsgExec = sdk.MsgTypeURL(&group.MsgExec{}) 39 TypeMsgLeaveGroup = sdk.MsgTypeURL(&group.MsgLeaveGroup{}) 40 ) 41 42 // Simulation operation weights constants 43 const ( 44 OpMsgCreateGroup = "op_weight_msg_create_group" 45 OpMsgUpdateGroupAdmin = "op_weight_msg_update_group_admin" 46 OpMsgUpdateGroupMetadata = "op_wieght_msg_update_group_metadata" 47 OpMsgUpdateGroupMembers = "op_weight_msg_update_group_members" 48 OpMsgCreateGroupPolicy = "op_weight_msg_create_group_account" 49 OpMsgCreateGroupWithPolicy = "op_weight_msg_create_group_with_policy" 50 OpMsgUpdateGroupPolicyAdmin = "op_weight_msg_update_group_account_admin" 51 OpMsgUpdateGroupPolicyDecisionPolicy = "op_weight_msg_update_group_account_decision_policy" 52 OpMsgUpdateGroupPolicyMetaData = "op_weight_msg_update_group_account_metadata" 53 OpMsgSubmitProposal = "op_weight_msg_submit_proposal" 54 OpMsgWithdrawProposal = "op_weight_msg_withdraw_proposal" 55 OpMsgVote = "op_weight_msg_vote" 56 OpMsgExec = "ops_weight_msg_exec" 57 OpMsgLeaveGroup = "ops_weight_msg_leave_group" 58 ) 59 60 // If update group or group policy txn's executed, `SimulateMsgVote` & `SimulateMsgExec` txn's returns `noOp`. 61 // That's why we have less weight for update group & group-policy txn's. 62 const ( 63 WeightMsgCreateGroup = 100 64 WeightMsgCreateGroupPolicy = 50 65 WeightMsgSubmitProposal = 90 66 WeightMsgVote = 90 67 WeightMsgExec = 90 68 WeightMsgLeaveGroup = 5 69 WeightMsgUpdateGroupMetadata = 5 70 WeightMsgUpdateGroupAdmin = 5 71 WeightMsgUpdateGroupMembers = 5 72 WeightMsgUpdateGroupPolicyAdmin = 5 73 WeightMsgUpdateGroupPolicyDecisionPolicy = 5 74 WeightMsgUpdateGroupPolicyMetadata = 5 75 WeightMsgWithdrawProposal = 20 76 WeightMsgCreateGroupWithPolicy = 50 77 ) 78 79 // WeightedOperations returns all the operations from the module with their respective weights 80 func WeightedOperations( 81 registry cdctypes.InterfaceRegistry, 82 appParams simtypes.AppParams, cdc codec.JSONCodec, txGen client.TxConfig, 83 ak group.AccountKeeper, bk group.BankKeeper, k keeper.Keeper, 84 appCdc cdctypes.AnyUnpacker, 85 ) simulation.WeightedOperations { 86 var ( 87 weightMsgCreateGroup int 88 weightMsgUpdateGroupAdmin int 89 weightMsgUpdateGroupMetadata int 90 weightMsgUpdateGroupMembers int 91 weightMsgCreateGroupPolicy int 92 weightMsgUpdateGroupPolicyAdmin int 93 weightMsgUpdateGroupPolicyDecisionPolicy int 94 weightMsgUpdateGroupPolicyMetadata int 95 weightMsgSubmitProposal int 96 weightMsgVote int 97 weightMsgExec int 98 weightMsgLeaveGroup int 99 weightMsgWithdrawProposal int 100 weightMsgCreateGroupWithPolicy int 101 ) 102 103 appParams.GetOrGenerate(OpMsgCreateGroup, &weightMsgCreateGroup, nil, func(_ *rand.Rand) { 104 weightMsgCreateGroup = WeightMsgCreateGroup 105 }) 106 appParams.GetOrGenerate(OpMsgCreateGroupPolicy, &weightMsgCreateGroupPolicy, nil, func(_ *rand.Rand) { 107 weightMsgCreateGroupPolicy = WeightMsgCreateGroupPolicy 108 }) 109 appParams.GetOrGenerate(OpMsgLeaveGroup, &weightMsgLeaveGroup, nil, func(_ *rand.Rand) { 110 weightMsgLeaveGroup = WeightMsgLeaveGroup 111 }) 112 appParams.GetOrGenerate(OpMsgCreateGroupWithPolicy, &weightMsgCreateGroupWithPolicy, nil, func(_ *rand.Rand) { 113 weightMsgCreateGroupWithPolicy = WeightMsgCreateGroupWithPolicy 114 }) 115 appParams.GetOrGenerate(OpMsgSubmitProposal, &weightMsgSubmitProposal, nil, func(_ *rand.Rand) { 116 weightMsgSubmitProposal = WeightMsgSubmitProposal 117 }) 118 appParams.GetOrGenerate(OpMsgVote, &weightMsgVote, nil, func(_ *rand.Rand) { 119 weightMsgVote = WeightMsgVote 120 }) 121 appParams.GetOrGenerate(OpMsgExec, &weightMsgExec, nil, func(_ *rand.Rand) { 122 weightMsgExec = WeightMsgExec 123 }) 124 appParams.GetOrGenerate(OpMsgUpdateGroupMetadata, &weightMsgUpdateGroupMetadata, nil, func(_ *rand.Rand) { 125 weightMsgUpdateGroupMetadata = WeightMsgUpdateGroupMetadata 126 }) 127 appParams.GetOrGenerate(OpMsgUpdateGroupAdmin, &weightMsgUpdateGroupAdmin, nil, func(_ *rand.Rand) { 128 weightMsgUpdateGroupAdmin = WeightMsgUpdateGroupAdmin 129 }) 130 appParams.GetOrGenerate(OpMsgUpdateGroupMembers, &weightMsgUpdateGroupMembers, nil, func(_ *rand.Rand) { 131 weightMsgUpdateGroupMembers = WeightMsgUpdateGroupMembers 132 }) 133 appParams.GetOrGenerate(OpMsgUpdateGroupPolicyAdmin, &weightMsgUpdateGroupPolicyAdmin, nil, func(_ *rand.Rand) { 134 weightMsgUpdateGroupPolicyAdmin = WeightMsgUpdateGroupPolicyAdmin 135 }) 136 appParams.GetOrGenerate(OpMsgUpdateGroupPolicyDecisionPolicy, &weightMsgUpdateGroupPolicyDecisionPolicy, nil, func(_ *rand.Rand) { 137 weightMsgUpdateGroupPolicyDecisionPolicy = WeightMsgUpdateGroupPolicyDecisionPolicy 138 }) 139 appParams.GetOrGenerate(OpMsgUpdateGroupPolicyMetaData, &weightMsgUpdateGroupPolicyMetadata, nil, func(_ *rand.Rand) { 140 weightMsgUpdateGroupPolicyMetadata = WeightMsgUpdateGroupPolicyMetadata 141 }) 142 appParams.GetOrGenerate(OpMsgWithdrawProposal, &weightMsgWithdrawProposal, nil, func(_ *rand.Rand) { 143 weightMsgWithdrawProposal = WeightMsgWithdrawProposal 144 }) 145 146 pCdc := codec.NewProtoCodec(registry) 147 148 // create two proposals for weightedOperations 149 var createProposalOps simulation.WeightedOperations 150 for i := 0; i < 2; i++ { 151 createProposalOps = append(createProposalOps, simulation.NewWeightedOperation( 152 weightMsgSubmitProposal, 153 SimulateMsgSubmitProposal(pCdc, txGen, ak, bk, k), 154 )) 155 } 156 157 wPreCreateProposalOps := simulation.WeightedOperations{ 158 simulation.NewWeightedOperation( 159 weightMsgCreateGroup, 160 SimulateMsgCreateGroup(pCdc, txGen, ak, bk), 161 ), 162 simulation.NewWeightedOperation( 163 weightMsgCreateGroupPolicy, 164 SimulateMsgCreateGroupPolicy(pCdc, txGen, ak, bk, k), 165 ), 166 simulation.NewWeightedOperation( 167 weightMsgCreateGroupWithPolicy, 168 SimulateMsgCreateGroupWithPolicy(pCdc, txGen, ak, bk), 169 ), 170 } 171 172 wPostCreateProposalOps := simulation.WeightedOperations{ 173 simulation.NewWeightedOperation( 174 WeightMsgWithdrawProposal, 175 SimulateMsgWithdrawProposal(pCdc, txGen, ak, bk, k), 176 ), 177 simulation.NewWeightedOperation( 178 weightMsgVote, 179 SimulateMsgVote(pCdc, txGen, ak, bk, k), 180 ), 181 simulation.NewWeightedOperation( 182 weightMsgExec, 183 SimulateMsgExec(pCdc, txGen, ak, bk, k), 184 ), 185 simulation.NewWeightedOperation( 186 weightMsgUpdateGroupMetadata, 187 SimulateMsgUpdateGroupMetadata(pCdc, txGen, ak, bk, k), 188 ), 189 simulation.NewWeightedOperation( 190 weightMsgUpdateGroupAdmin, 191 SimulateMsgUpdateGroupAdmin(pCdc, txGen, ak, bk, k), 192 ), 193 simulation.NewWeightedOperation( 194 weightMsgUpdateGroupMembers, 195 SimulateMsgUpdateGroupMembers(pCdc, txGen, ak, bk, k), 196 ), 197 simulation.NewWeightedOperation( 198 weightMsgUpdateGroupPolicyAdmin, 199 SimulateMsgUpdateGroupPolicyAdmin(pCdc, txGen, ak, bk, k), 200 ), 201 simulation.NewWeightedOperation( 202 weightMsgUpdateGroupPolicyDecisionPolicy, 203 SimulateMsgUpdateGroupPolicyDecisionPolicy(pCdc, txGen, ak, bk, k), 204 ), 205 simulation.NewWeightedOperation( 206 weightMsgUpdateGroupPolicyMetadata, 207 SimulateMsgUpdateGroupPolicyMetadata(pCdc, txGen, ak, bk, k), 208 ), 209 simulation.NewWeightedOperation( 210 weightMsgLeaveGroup, 211 SimulateMsgLeaveGroup(pCdc, txGen, k, ak, bk), 212 ), 213 } 214 215 return append(wPreCreateProposalOps, append(createProposalOps, wPostCreateProposalOps...)...) 216 } 217 218 // SimulateMsgCreateGroup generates a MsgCreateGroup with random values 219 func SimulateMsgCreateGroup( 220 cdc *codec.ProtoCodec, 221 txGen client.TxConfig, 222 ak group.AccountKeeper, 223 bk group.BankKeeper, 224 ) simtypes.Operation { 225 return func( 226 r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simtypes.Account, chainID string, 227 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 228 acc, _ := simtypes.RandomAcc(r, accounts) 229 account := ak.GetAccount(ctx, acc.Address) 230 accAddr := acc.Address.String() 231 232 spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) 233 fees, err := simtypes.RandomFees(r, ctx, spendableCoins) 234 if err != nil { 235 return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "fee error"), nil, err 236 } 237 238 members := genGroupMembers(r, accounts) 239 msg := &group.MsgCreateGroup{Admin: accAddr, Members: members, Metadata: simtypes.RandStringOfLength(r, 10)} 240 241 tx, err := simtestutil.GenSignedMockTx( 242 r, 243 txGen, 244 []sdk.Msg{msg}, 245 fees, 246 simtestutil.DefaultGenTxGas, 247 chainID, 248 []uint64{account.GetAccountNumber()}, 249 []uint64{account.GetSequence()}, 250 acc.PrivKey, 251 ) 252 if err != nil { 253 return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "unable to generate mock tx"), nil, err 254 } 255 256 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 257 if err != nil { 258 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 259 } 260 261 return simtypes.NewOperationMsg(msg, true, ""), nil, err 262 } 263 } 264 265 // SimulateMsgCreateGroupWithPolicy generates a MsgCreateGroupWithPolicy with random values 266 func SimulateMsgCreateGroupWithPolicy( 267 cdc *codec.ProtoCodec, 268 txGen client.TxConfig, 269 ak group.AccountKeeper, 270 bk group.BankKeeper, 271 ) simtypes.Operation { 272 return func( 273 r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simtypes.Account, chainID string, 274 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 275 acc, _ := simtypes.RandomAcc(r, accounts) 276 account := ak.GetAccount(ctx, acc.Address) 277 accAddr := acc.Address.String() 278 279 spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) 280 fees, err := simtypes.RandomFees(r, ctx, spendableCoins) 281 if err != nil { 282 return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "fee error"), nil, err 283 } 284 285 members := genGroupMembers(r, accounts) 286 decisionPolicy := &group.ThresholdDecisionPolicy{ 287 Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), 288 Windows: &group.DecisionPolicyWindows{ 289 VotingPeriod: time.Second * time.Duration(30*24*60*60), 290 }, 291 } 292 293 msg := &group.MsgCreateGroupWithPolicy{ 294 Admin: accAddr, 295 Members: members, 296 GroupMetadata: simtypes.RandStringOfLength(r, 10), 297 GroupPolicyMetadata: simtypes.RandStringOfLength(r, 10), 298 GroupPolicyAsAdmin: r.Float32() < 0.5, 299 } 300 msg.SetDecisionPolicy(decisionPolicy) 301 if err != nil { 302 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to set decision policy"), nil, err 303 } 304 305 tx, err := simtestutil.GenSignedMockTx( 306 r, 307 txGen, 308 []sdk.Msg{msg}, 309 fees, 310 simtestutil.DefaultGenTxGas, 311 chainID, 312 []uint64{account.GetAccountNumber()}, 313 []uint64{account.GetSequence()}, 314 acc.PrivKey, 315 ) 316 if err != nil { 317 return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupWithPolicy, "unable to generate mock tx"), nil, err 318 } 319 320 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 321 if err != nil { 322 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 323 } 324 325 return simtypes.NewOperationMsg(msg, true, ""), nil, nil 326 } 327 } 328 329 // SimulateMsgCreateGroupPolicy generates a NewMsgCreateGroupPolicy with random values 330 func SimulateMsgCreateGroupPolicy( 331 cdc *codec.ProtoCodec, 332 txGen client.TxConfig, 333 ak group.AccountKeeper, 334 bk group.BankKeeper, 335 k keeper.Keeper, 336 ) simtypes.Operation { 337 return func( 338 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 339 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 340 groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts) 341 if err != nil { 342 return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, ""), nil, err 343 } 344 if groupInfo == nil { 345 return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, ""), nil, nil 346 } 347 groupID := groupInfo.Id 348 349 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 350 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 351 if err != nil { 352 return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "fee error"), nil, err 353 } 354 355 msg, err := group.NewMsgCreateGroupPolicy( 356 acc.Address, 357 groupID, 358 simtypes.RandStringOfLength(r, 10), 359 &group.ThresholdDecisionPolicy{ 360 Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), 361 Windows: &group.DecisionPolicyWindows{ 362 VotingPeriod: time.Second * time.Duration(30*24*60*60), 363 }, 364 }, 365 ) 366 if err != nil { 367 return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, err.Error()), nil, err 368 } 369 370 tx, err := simtestutil.GenSignedMockTx( 371 r, 372 txGen, 373 []sdk.Msg{msg}, 374 fees, 375 simtestutil.DefaultGenTxGas, 376 chainID, 377 []uint64{account.GetAccountNumber()}, 378 []uint64{account.GetSequence()}, 379 acc.PrivKey, 380 ) 381 if err != nil { 382 return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "unable to generate mock tx"), nil, err 383 } 384 385 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 386 if err != nil { 387 fmt.Printf("ERR DELIVER %v\n", err) 388 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 389 } 390 391 return simtypes.NewOperationMsg(msg, true, ""), nil, err 392 } 393 } 394 395 // SimulateMsgSubmitProposal generates a NewMsgSubmitProposal with random values 396 func SimulateMsgSubmitProposal( 397 cdc *codec.ProtoCodec, 398 txGen client.TxConfig, 399 ak group.AccountKeeper, 400 bk group.BankKeeper, 401 k keeper.Keeper, 402 ) simtypes.Operation { 403 return func( 404 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 405 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 406 g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts) 407 if err != nil { 408 return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, err 409 } 410 if g == nil { 411 return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "no group found"), nil, nil 412 } 413 if groupPolicy == nil { 414 return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "no group policy found"), nil, nil 415 } 416 groupID := g.Id 417 groupPolicyAddr := groupPolicy.Address 418 419 // Return a no-op if we know the proposal cannot be created 420 policy, err := groupPolicy.GetDecisionPolicy() 421 if err != nil { 422 return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, nil 423 } 424 err = policy.Validate(*g, group.DefaultConfig()) 425 if err != nil { 426 return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, nil 427 } 428 429 // Pick a random member from the group 430 acc, account, err := randomMember(sdkCtx, r, k, ak, accounts, groupID) 431 if err != nil { 432 return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, err 433 } 434 if account == nil { 435 return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "no group member found"), nil, nil 436 } 437 438 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 439 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 440 if err != nil { 441 return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "fee error"), nil, err 442 } 443 444 msg := &group.MsgSubmitProposal{ 445 GroupPolicyAddress: groupPolicyAddr, 446 Proposers: []string{acc.Address.String()}, 447 Metadata: simtypes.RandStringOfLength(r, 10), 448 Title: "Test Proposal", 449 Summary: "Summary of the proposal", 450 } 451 452 tx, err := simtestutil.GenSignedMockTx( 453 r, 454 txGen, 455 []sdk.Msg{msg}, 456 fees, 457 simtestutil.DefaultGenTxGas, 458 chainID, 459 []uint64{account.GetAccountNumber()}, 460 []uint64{account.GetSequence()}, 461 acc.PrivKey, 462 ) 463 if err != nil { 464 return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "unable to generate mock tx"), nil, err 465 } 466 467 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 468 if err != nil { 469 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 470 } 471 472 return simtypes.NewOperationMsg(msg, true, ""), nil, err 473 } 474 } 475 476 // SimulateMsgUpdateGroupAdmin generates a MsgUpdateGroupAdmin with random values 477 func SimulateMsgUpdateGroupAdmin( 478 cdc *codec.ProtoCodec, 479 txGen client.TxConfig, 480 ak group.AccountKeeper, 481 bk group.BankKeeper, 482 k keeper.Keeper, 483 ) simtypes.Operation { 484 return func( 485 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 486 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 487 groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts) 488 if err != nil { 489 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, ""), nil, err 490 } 491 if groupInfo == nil { 492 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, ""), nil, nil 493 } 494 groupID := groupInfo.Id 495 496 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 497 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 498 if err != nil { 499 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "fee error"), nil, err 500 } 501 502 if len(accounts) == 1 { 503 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "can't set a new admin with only one account"), nil, nil 504 } 505 newAdmin, _ := simtypes.RandomAcc(r, accounts) 506 // disallow setting current admin as new admin 507 for acc.PubKey.Equals(newAdmin.PubKey) { 508 newAdmin, _ = simtypes.RandomAcc(r, accounts) 509 } 510 511 msg := &group.MsgUpdateGroupAdmin{ 512 GroupId: groupID, 513 Admin: account.GetAddress().String(), 514 NewAdmin: newAdmin.Address.String(), 515 } 516 517 tx, err := simtestutil.GenSignedMockTx( 518 r, 519 txGen, 520 []sdk.Msg{msg}, 521 fees, 522 simtestutil.DefaultGenTxGas, 523 chainID, 524 []uint64{account.GetAccountNumber()}, 525 []uint64{account.GetSequence()}, 526 acc.PrivKey, 527 ) 528 if err != nil { 529 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "unable to generate mock tx"), nil, err 530 } 531 532 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 533 if err != nil { 534 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 535 } 536 537 return simtypes.NewOperationMsg(msg, true, ""), nil, err 538 } 539 } 540 541 // SimulateMsgUpdateGroupMetadata generates a MsgUpdateGroupMetadata with random values 542 func SimulateMsgUpdateGroupMetadata( 543 cdc *codec.ProtoCodec, 544 txGen client.TxConfig, 545 ak group.AccountKeeper, 546 bk group.BankKeeper, 547 k keeper.Keeper, 548 ) simtypes.Operation { 549 return func( 550 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 551 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 552 groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts) 553 if err != nil { 554 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, ""), nil, err 555 } 556 if groupInfo == nil { 557 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, ""), nil, nil 558 } 559 groupID := groupInfo.Id 560 561 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 562 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 563 if err != nil { 564 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "fee error"), nil, err 565 } 566 567 msg := &group.MsgUpdateGroupMetadata{ 568 GroupId: groupID, 569 Admin: account.GetAddress().String(), 570 Metadata: simtypes.RandStringOfLength(r, 10), 571 } 572 573 tx, err := simtestutil.GenSignedMockTx( 574 r, 575 txGen, 576 []sdk.Msg{msg}, 577 fees, 578 simtestutil.DefaultGenTxGas, 579 chainID, 580 []uint64{account.GetAccountNumber()}, 581 []uint64{account.GetSequence()}, 582 acc.PrivKey, 583 ) 584 if err != nil { 585 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "unable to generate mock tx"), nil, err 586 } 587 588 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 589 if err != nil { 590 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 591 } 592 593 return simtypes.NewOperationMsg(msg, true, ""), nil, err 594 } 595 } 596 597 // SimulateMsgUpdateGroupMembers generates a MsgUpdateGroupMembers with random values 598 func SimulateMsgUpdateGroupMembers( 599 cdc *codec.ProtoCodec, 600 txGen client.TxConfig, 601 ak group.AccountKeeper, 602 bk group.BankKeeper, 603 k keeper.Keeper, 604 ) simtypes.Operation { 605 return func( 606 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 607 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 608 groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts) 609 if err != nil { 610 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, ""), nil, err 611 } 612 if groupInfo == nil { 613 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, ""), nil, nil 614 } 615 groupID := groupInfo.Id 616 617 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 618 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 619 if err != nil { 620 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "fee error"), nil, err 621 } 622 623 members := genGroupMembers(r, accounts) 624 ctx := sdk.UnwrapSDKContext(sdkCtx) 625 res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupID}) 626 if err != nil { 627 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "group members"), nil, err 628 } 629 630 // set existing random group member weight to zero to remove from the group 631 existigMembers := res.Members 632 if len(existigMembers) > 0 { 633 memberToRemove := existigMembers[r.Intn(len(existigMembers))] 634 var isDuplicateMember bool 635 for idx, m := range members { 636 if m.Address == memberToRemove.Member.Address { 637 members[idx].Weight = "0" 638 isDuplicateMember = true 639 break 640 } 641 } 642 643 if !isDuplicateMember { 644 m := memberToRemove.Member 645 m.Weight = "0" 646 members = append(members, group.MemberToMemberRequest(m)) 647 } 648 } 649 650 msg := &group.MsgUpdateGroupMembers{ 651 GroupId: groupID, 652 Admin: acc.Address.String(), 653 MemberUpdates: members, 654 } 655 656 tx, err := simtestutil.GenSignedMockTx( 657 r, 658 txGen, 659 []sdk.Msg{msg}, 660 fees, 661 simtestutil.DefaultGenTxGas, 662 chainID, 663 []uint64{account.GetAccountNumber()}, 664 []uint64{account.GetSequence()}, 665 acc.PrivKey, 666 ) 667 if err != nil { 668 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "unable to generate mock tx"), nil, err 669 } 670 671 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 672 if err != nil { 673 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 674 } 675 676 return simtypes.NewOperationMsg(msg, true, ""), nil, err 677 } 678 } 679 680 // SimulateMsgUpdateGroupPolicyAdmin generates a MsgUpdateGroupPolicyAdmin with random values 681 func SimulateMsgUpdateGroupPolicyAdmin( 682 cdc *codec.ProtoCodec, 683 txGen client.TxConfig, 684 ak group.AccountKeeper, 685 bk group.BankKeeper, 686 k keeper.Keeper, 687 ) simtypes.Operation { 688 return func( 689 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 690 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 691 _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts) 692 if err != nil { 693 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, ""), nil, err 694 } 695 if groupPolicy == nil { 696 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "no group policy found"), nil, nil 697 } 698 groupPolicyAddr := groupPolicy.Address 699 700 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 701 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 702 if err != nil { 703 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "fee error"), nil, err 704 } 705 706 if len(accounts) == 1 { 707 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "can't set a new admin with only one account"), nil, nil 708 } 709 newAdmin, _ := simtypes.RandomAcc(r, accounts) 710 // disallow setting current admin as new admin 711 for acc.PubKey.Equals(newAdmin.PubKey) { 712 newAdmin, _ = simtypes.RandomAcc(r, accounts) 713 } 714 715 msg := &group.MsgUpdateGroupPolicyAdmin{ 716 Admin: acc.Address.String(), 717 GroupPolicyAddress: groupPolicyAddr, 718 NewAdmin: newAdmin.Address.String(), 719 } 720 721 tx, err := simtestutil.GenSignedMockTx( 722 r, 723 txGen, 724 []sdk.Msg{msg}, 725 fees, 726 simtestutil.DefaultGenTxGas, 727 chainID, 728 []uint64{account.GetAccountNumber()}, 729 []uint64{account.GetSequence()}, 730 acc.PrivKey, 731 ) 732 if err != nil { 733 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "unable to generate mock tx"), nil, err 734 } 735 736 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 737 if err != nil { 738 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 739 } 740 741 return simtypes.NewOperationMsg(msg, true, ""), nil, err 742 } 743 } 744 745 // // SimulateMsgUpdateGroupPolicyDecisionPolicy generates a NewMsgUpdateGroupPolicyDecisionPolicy with random values 746 func SimulateMsgUpdateGroupPolicyDecisionPolicy( 747 cdc *codec.ProtoCodec, 748 txGen client.TxConfig, 749 ak group.AccountKeeper, 750 bk group.BankKeeper, 751 k keeper.Keeper, 752 ) simtypes.Operation { 753 return func( 754 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 755 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 756 _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts) 757 if err != nil { 758 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, ""), nil, err 759 } 760 if groupPolicy == nil { 761 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "no group policy found"), nil, nil 762 } 763 groupPolicyAddr := groupPolicy.Address 764 765 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 766 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 767 if err != nil { 768 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "fee error"), nil, err 769 } 770 771 groupPolicyBech32, err := sdk.AccAddressFromBech32(groupPolicyAddr) 772 if err != nil { 773 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, fmt.Sprintf("fail to decide bech32 address: %s", err.Error())), nil, nil 774 } 775 776 msg, err := group.NewMsgUpdateGroupPolicyDecisionPolicy(acc.Address, groupPolicyBech32, &group.ThresholdDecisionPolicy{ 777 Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), 778 Windows: &group.DecisionPolicyWindows{ 779 VotingPeriod: time.Second * time.Duration(simtypes.RandIntBetween(r, 100, 1000)), 780 }, 781 }) 782 if err != nil { 783 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, err.Error()), nil, err 784 } 785 786 tx, err := simtestutil.GenSignedMockTx( 787 r, 788 txGen, 789 []sdk.Msg{msg}, 790 fees, 791 simtestutil.DefaultGenTxGas, 792 chainID, 793 []uint64{account.GetAccountNumber()}, 794 []uint64{account.GetSequence()}, 795 acc.PrivKey, 796 ) 797 if err != nil { 798 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "unable to generate mock tx"), nil, err 799 } 800 801 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 802 if err != nil { 803 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 804 } 805 return simtypes.NewOperationMsg(msg, true, ""), nil, err 806 } 807 } 808 809 // // SimulateMsgUpdateGroupPolicyMetadata generates a MsgUpdateGroupPolicyMetadata with random values 810 func SimulateMsgUpdateGroupPolicyMetadata( 811 cdc *codec.ProtoCodec, 812 txGen client.TxConfig, 813 ak group.AccountKeeper, 814 bk group.BankKeeper, 815 k keeper.Keeper, 816 ) simtypes.Operation { 817 return func( 818 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 819 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 820 _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts) 821 if err != nil { 822 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, ""), nil, err 823 } 824 if groupPolicy == nil { 825 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "no group policy found"), nil, nil 826 } 827 groupPolicyAddr := groupPolicy.Address 828 829 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 830 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 831 if err != nil { 832 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "fee error"), nil, err 833 } 834 835 msg := &group.MsgUpdateGroupPolicyMetadata{ 836 Admin: acc.Address.String(), 837 GroupPolicyAddress: groupPolicyAddr, 838 Metadata: simtypes.RandStringOfLength(r, 10), 839 } 840 841 tx, err := simtestutil.GenSignedMockTx( 842 r, 843 txGen, 844 []sdk.Msg{msg}, 845 fees, 846 simtestutil.DefaultGenTxGas, 847 chainID, 848 []uint64{account.GetAccountNumber()}, 849 []uint64{account.GetSequence()}, 850 acc.PrivKey, 851 ) 852 if err != nil { 853 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err 854 } 855 856 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 857 if err != nil { 858 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 859 } 860 861 return simtypes.NewOperationMsg(msg, true, ""), nil, err 862 } 863 } 864 865 // SimulateMsgWithdrawProposal generates a MsgWithdrawProposal with random values 866 func SimulateMsgWithdrawProposal( 867 cdc *codec.ProtoCodec, 868 txGen client.TxConfig, 869 ak group.AccountKeeper, 870 bk group.BankKeeper, 871 k keeper.Keeper, 872 ) simtypes.Operation { 873 return func( 874 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 875 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 876 g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts) 877 if err != nil { 878 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, ""), nil, err 879 } 880 if g == nil { 881 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no group found"), nil, nil 882 } 883 if groupPolicy == nil { 884 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no group policy found"), nil, nil 885 } 886 887 groupPolicyAddr := groupPolicy.Address 888 policy, err := groupPolicy.GetDecisionPolicy() 889 if err != nil { 890 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, err.Error()), nil, nil 891 } 892 err = policy.Validate(*g, group.DefaultConfig()) 893 if err != nil { 894 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, err.Error()), nil, nil 895 } 896 897 proposalsResult, err := k.ProposalsByGroupPolicy(sdkCtx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr}) 898 if err != nil { 899 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "fail to query group info"), nil, err 900 } 901 902 proposals := proposalsResult.GetProposals() 903 if len(proposals) == 0 { 904 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no proposals found"), nil, nil 905 } 906 907 var proposal *group.Proposal 908 proposalID := -1 909 910 for _, p := range proposals { 911 if p.Status == group.PROPOSAL_STATUS_SUBMITTED { 912 timeout := p.VotingPeriodEnd 913 proposal = p 914 proposalID = int(p.Id) 915 if timeout.Before(sdkCtx.BlockTime()) || timeout.Equal(sdkCtx.BlockTime()) { 916 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "voting period ended: skipping"), nil, nil 917 } 918 break 919 } 920 } 921 922 // return no-op if no proposal found 923 if proposalID == -1 { 924 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no proposals found"), nil, nil 925 } 926 927 // select a random proposer 928 proposers := proposal.Proposers 929 n := randIntInRange(r, len(proposers)) 930 proposerIdx := findAccount(accounts, proposers[n]) 931 proposer := accounts[proposerIdx] 932 proposerAcc := ak.GetAccount(sdkCtx, proposer.Address) 933 934 spendableCoins := bk.SpendableCoins(sdkCtx, proposer.Address) 935 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 936 if err != nil { 937 return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "fee error"), nil, err 938 } 939 940 msg := &group.MsgWithdrawProposal{ 941 ProposalId: uint64(proposalID), 942 Address: proposer.Address.String(), 943 } 944 945 tx, err := simtestutil.GenSignedMockTx( 946 r, 947 txGen, 948 []sdk.Msg{msg}, 949 fees, 950 simtestutil.DefaultGenTxGas, 951 chainID, 952 []uint64{proposerAcc.GetAccountNumber()}, 953 []uint64{proposerAcc.GetSequence()}, 954 proposer.PrivKey, 955 ) 956 if err != nil { 957 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err 958 } 959 960 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 961 962 if err != nil { 963 if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group policy was modified") { 964 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "no-op:group/group-policy was modified"), nil, nil 965 } 966 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 967 } 968 969 return simtypes.NewOperationMsg(msg, true, ""), nil, err 970 } 971 } 972 973 // SimulateMsgVote generates a MsgVote with random values 974 func SimulateMsgVote( 975 cdc *codec.ProtoCodec, 976 txGen client.TxConfig, 977 ak group.AccountKeeper, 978 bk group.BankKeeper, 979 k keeper.Keeper, 980 ) simtypes.Operation { 981 return func( 982 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 983 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 984 g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts) 985 if err != nil { 986 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, ""), nil, err 987 } 988 if g == nil { 989 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group found"), nil, nil 990 } 991 if groupPolicy == nil { 992 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group policy found"), nil, nil 993 } 994 groupPolicyAddr := groupPolicy.Address 995 996 // Pick a random member from the group 997 acc, account, err := randomMember(sdkCtx, r, k, ak, accounts, g.Id) 998 if err != nil { 999 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, ""), nil, err 1000 } 1001 if account == nil { 1002 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group member found"), nil, nil 1003 } 1004 1005 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 1006 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 1007 if err != nil { 1008 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fee error"), nil, err 1009 } 1010 1011 proposalsResult, err := k.ProposalsByGroupPolicy(sdkCtx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr}) 1012 if err != nil { 1013 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fail to query group info"), nil, err 1014 } 1015 proposals := proposalsResult.GetProposals() 1016 if len(proposals) == 0 { 1017 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil 1018 } 1019 1020 proposalID := -1 1021 1022 for _, p := range proposals { 1023 if p.Status == group.PROPOSAL_STATUS_SUBMITTED { 1024 timeout := p.VotingPeriodEnd 1025 proposalID = int(p.Id) 1026 if timeout.Before(sdkCtx.BlockTime()) || timeout.Equal(sdkCtx.BlockTime()) { 1027 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "voting period ended: skipping"), nil, nil 1028 } 1029 break 1030 } 1031 } 1032 1033 // return no-op if no proposal found 1034 if proposalID == -1 { 1035 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil 1036 } 1037 1038 // Ensure member hasn't already voted 1039 res, _ := k.VoteByProposalVoter(sdkCtx, &group.QueryVoteByProposalVoterRequest{ 1040 Voter: acc.Address.String(), 1041 ProposalId: uint64(proposalID), 1042 }) 1043 if res != nil { 1044 return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "member has already voted"), nil, nil 1045 } 1046 1047 msg := &group.MsgVote{ 1048 ProposalId: uint64(proposalID), 1049 Voter: acc.Address.String(), 1050 Option: group.VOTE_OPTION_YES, 1051 Metadata: simtypes.RandStringOfLength(r, 10), 1052 } 1053 tx, err := simtestutil.GenSignedMockTx( 1054 r, 1055 txGen, 1056 []sdk.Msg{msg}, 1057 fees, 1058 simtestutil.DefaultGenTxGas, 1059 chainID, 1060 []uint64{account.GetAccountNumber()}, 1061 []uint64{account.GetSequence()}, 1062 acc.PrivKey, 1063 ) 1064 if err != nil { 1065 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err 1066 } 1067 1068 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 1069 1070 if err != nil { 1071 if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group policy was modified") { 1072 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "no-op:group/group-policy was modified"), nil, nil 1073 } 1074 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 1075 } 1076 1077 return simtypes.NewOperationMsg(msg, true, ""), nil, err 1078 } 1079 } 1080 1081 // // SimulateMsgExec generates a MsgExec with random values 1082 func SimulateMsgExec( 1083 cdc *codec.ProtoCodec, 1084 txGen client.TxConfig, 1085 ak group.AccountKeeper, 1086 bk group.BankKeeper, 1087 k keeper.Keeper, 1088 ) simtypes.Operation { 1089 return func( 1090 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 1091 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 1092 _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts) 1093 if err != nil { 1094 return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, ""), nil, err 1095 } 1096 if groupPolicy == nil { 1097 return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no group policy found"), nil, nil 1098 } 1099 groupPolicyAddr := groupPolicy.Address 1100 1101 spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) 1102 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 1103 if err != nil { 1104 return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "fee error"), nil, err 1105 } 1106 1107 proposalsResult, err := k.ProposalsByGroupPolicy(sdkCtx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr}) 1108 if err != nil { 1109 return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "fail to query group info"), nil, err 1110 } 1111 proposals := proposalsResult.GetProposals() 1112 if len(proposals) == 0 { 1113 return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no proposals found"), nil, nil 1114 } 1115 1116 proposalID := -1 1117 1118 for _, proposal := range proposals { 1119 if proposal.Status == group.PROPOSAL_STATUS_ACCEPTED { 1120 proposalID = int(proposal.Id) 1121 break 1122 } 1123 } 1124 1125 // return no-op if no proposal found 1126 if proposalID == -1 { 1127 return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no proposals found"), nil, nil 1128 } 1129 1130 msg := &group.MsgExec{ 1131 ProposalId: uint64(proposalID), 1132 Executor: acc.Address.String(), 1133 } 1134 tx, err := simtestutil.GenSignedMockTx( 1135 r, 1136 txGen, 1137 []sdk.Msg{msg}, 1138 fees, 1139 simtestutil.DefaultGenTxGas, 1140 chainID, 1141 []uint64{account.GetAccountNumber()}, 1142 []uint64{account.GetSequence()}, 1143 acc.PrivKey, 1144 ) 1145 if err != nil { 1146 return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err 1147 } 1148 1149 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 1150 if err != nil { 1151 if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group policy was modified") { 1152 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "no-op:group/group-policy was modified"), nil, nil 1153 } 1154 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err 1155 } 1156 1157 return simtypes.NewOperationMsg(msg, true, ""), nil, err 1158 } 1159 } 1160 1161 // SimulateMsgLeaveGroup generates a MsgLeaveGroup with random values 1162 func SimulateMsgLeaveGroup( 1163 cdc *codec.ProtoCodec, 1164 txGen client.TxConfig, 1165 k keeper.Keeper, 1166 ak group.AccountKeeper, 1167 bk group.BankKeeper, 1168 ) simtypes.Operation { 1169 return func( 1170 r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, 1171 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 1172 groupInfo, policyInfo, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts) 1173 if err != nil { 1174 return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, ""), nil, err 1175 } 1176 1177 if policyInfo == nil { 1178 return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "no policy found"), nil, nil 1179 } 1180 1181 // Pick a random member from the group 1182 acc, account, err := randomMember(sdkCtx, r, k, ak, accounts, groupInfo.Id) 1183 if err != nil { 1184 return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, ""), nil, err 1185 } 1186 if account == nil { 1187 return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "no group member found"), nil, nil 1188 } 1189 1190 spendableCoins := bk.SpendableCoins(sdkCtx, acc.Address) 1191 fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) 1192 if err != nil { 1193 return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "fee error"), nil, err 1194 } 1195 1196 msg := &group.MsgLeaveGroup{ 1197 Address: acc.Address.String(), 1198 GroupId: groupInfo.Id, 1199 } 1200 1201 tx, err := simtestutil.GenSignedMockTx( 1202 r, 1203 txGen, 1204 []sdk.Msg{msg}, 1205 fees, 1206 simtestutil.DefaultGenTxGas, 1207 chainID, 1208 []uint64{account.GetAccountNumber()}, 1209 []uint64{account.GetSequence()}, 1210 acc.PrivKey, 1211 ) 1212 if err != nil { 1213 return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "unable to generate mock tx"), nil, err 1214 } 1215 1216 _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) 1217 if err != nil { 1218 return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), err.Error()), nil, err 1219 } 1220 1221 return simtypes.NewOperationMsg(msg, true, ""), nil, err 1222 } 1223 } 1224 1225 func randomGroup(r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper, 1226 ctx sdk.Context, accounts []simtypes.Account, 1227 ) (groupInfo *group.GroupInfo, acc simtypes.Account, account sdk.AccountI, err error) { 1228 groupID := k.GetGroupSequence(ctx) 1229 1230 switch { 1231 case groupID > initialGroupID: 1232 // select a random ID between (initialGroupID, groupID] 1233 // if there is at least one group information, then the groupID at this time must be greater than or equal to 1 1234 groupID = uint64(simtypes.RandIntBetween(r, int(initialGroupID+1), int(groupID+1))) 1235 1236 default: 1237 // This is called on the first call to this function 1238 // in order to update the global variable 1239 initialGroupID = groupID 1240 } 1241 1242 // when groupID is 0, it proves that SimulateMsgCreateGroup has never been called. that is, no group exists in the chain 1243 if groupID == 0 { 1244 return nil, simtypes.Account{}, nil, nil 1245 } 1246 1247 res, err := k.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: groupID}) 1248 if err != nil { 1249 return nil, simtypes.Account{}, nil, err 1250 } 1251 1252 groupInfo = res.Info 1253 groupAdmin := groupInfo.Admin 1254 found := -1 1255 for i := range accounts { 1256 if accounts[i].Address.String() == groupAdmin { 1257 found = i 1258 break 1259 } 1260 } 1261 if found < 0 { 1262 return nil, simtypes.Account{}, nil, nil 1263 } 1264 acc = accounts[found] 1265 account = ak.GetAccount(ctx, acc.Address) 1266 return groupInfo, acc, account, nil 1267 } 1268 1269 func randomGroupPolicy(r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper, 1270 ctx sdk.Context, accounts []simtypes.Account, 1271 ) (groupInfo *group.GroupInfo, groupPolicyInfo *group.GroupPolicyInfo, acc simtypes.Account, account sdk.AccountI, err error) { 1272 groupInfo, _, _, err = randomGroup(r, k, ak, ctx, accounts) 1273 if err != nil { 1274 return nil, nil, simtypes.Account{}, nil, err 1275 } 1276 if groupInfo == nil { 1277 return nil, nil, simtypes.Account{}, nil, nil 1278 } 1279 groupID := groupInfo.Id 1280 1281 result, err := k.GroupPoliciesByGroup(ctx, &group.QueryGroupPoliciesByGroupRequest{GroupId: groupID}) 1282 if err != nil { 1283 return groupInfo, nil, simtypes.Account{}, nil, err 1284 } 1285 1286 n := randIntInRange(r, len(result.GroupPolicies)) 1287 if n < 0 { 1288 return groupInfo, nil, simtypes.Account{}, nil, nil 1289 } 1290 groupPolicyInfo = result.GroupPolicies[n] 1291 1292 idx := findAccount(accounts, groupPolicyInfo.Admin) 1293 if idx < 0 { 1294 return groupInfo, nil, simtypes.Account{}, nil, nil 1295 } 1296 acc = accounts[idx] 1297 account = ak.GetAccount(ctx, acc.Address) 1298 return groupInfo, groupPolicyInfo, acc, account, nil 1299 } 1300 1301 func randomMember(ctx context.Context, r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper, 1302 accounts []simtypes.Account, groupID uint64, 1303 ) (acc simtypes.Account, account sdk.AccountI, err error) { 1304 res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{ 1305 GroupId: groupID, 1306 }) 1307 if err != nil { 1308 return simtypes.Account{}, nil, err 1309 } 1310 n := randIntInRange(r, len(res.Members)) 1311 if n < 0 { 1312 return simtypes.Account{}, nil, err 1313 } 1314 idx := findAccount(accounts, res.Members[n].Member.Address) 1315 if idx < 0 { 1316 return simtypes.Account{}, nil, err 1317 } 1318 acc = accounts[idx] 1319 account = ak.GetAccount(sdk.UnwrapSDKContext(ctx), acc.Address) 1320 return acc, account, nil 1321 } 1322 1323 func randIntInRange(r *rand.Rand, l int) int { 1324 if l == 0 { 1325 return -1 1326 } 1327 if l == 1 { 1328 return 0 1329 } 1330 return simtypes.RandIntBetween(r, 0, l-1) 1331 } 1332 1333 func findAccount(accounts []simtypes.Account, addr string) (idx int) { 1334 idx = -1 1335 for i := range accounts { 1336 if accounts[i].Address.String() == addr { 1337 idx = i 1338 break 1339 } 1340 } 1341 return idx 1342 } 1343 1344 func genGroupMembers(r *rand.Rand, accounts []simtypes.Account) []group.MemberRequest { 1345 if len(accounts) == 1 { 1346 return []group.MemberRequest{ 1347 { 1348 Address: accounts[0].Address.String(), 1349 Weight: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), 1350 Metadata: simtypes.RandStringOfLength(r, 10), 1351 }, 1352 } 1353 } 1354 1355 max := 5 1356 if len(accounts) < max { 1357 max = len(accounts) 1358 } 1359 1360 membersLen := simtypes.RandIntBetween(r, 1, max) 1361 members := make([]group.MemberRequest, membersLen) 1362 1363 for i := 0; i < membersLen; i++ { 1364 members[i] = group.MemberRequest{ 1365 Address: accounts[i].Address.String(), 1366 Weight: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), 1367 Metadata: simtypes.RandStringOfLength(r, 10), 1368 } 1369 } 1370 1371 return members 1372 }