2019-10-23 02:14:45 -07:00
package simulation
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/baseapp"
2019-12-05 01:29:54 -08:00
"github.com/cosmos/cosmos-sdk/codec"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
2019-10-23 02:14:45 -07:00
sdk "github.com/cosmos/cosmos-sdk/types"
2020-03-23 04:55:44 -07:00
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
2019-10-23 02:14:45 -07:00
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
)
2019-12-05 01:29:54 -08:00
// Simulation operation weights constants
const (
OpWeightMsgSetWithdrawAddress = "op_weight_msg_set_withdraw_address"
OpWeightMsgWithdrawDelegationReward = "op_weight_msg_withdraw_delegation_reward"
OpWeightMsgWithdrawValidatorCommission = "op_weight_msg_withdraw_validator_commission"
2019-12-10 20:02:15 -08:00
OpWeightMsgFundCommunityPool = "op_weight_msg_fund_community_pool"
2019-12-05 01:29:54 -08:00
)
// WeightedOperations returns all the operations from the module with their respective weights
func WeightedOperations (
2021-04-29 03:46:22 -07:00
appParams simtypes . AppParams , cdc codec . JSONCodec , ak types . AccountKeeper ,
2020-01-30 13:31:16 -08:00
bk types . BankKeeper , k keeper . Keeper , sk stakingkeeper . Keeper ,
2019-12-05 01:29:54 -08:00
) simulation . WeightedOperations {
var weightMsgSetWithdrawAddress int
appParams . GetOrGenerate ( cdc , OpWeightMsgSetWithdrawAddress , & weightMsgSetWithdrawAddress , nil ,
func ( _ * rand . Rand ) {
weightMsgSetWithdrawAddress = simappparams . DefaultWeightMsgSetWithdrawAddress
} ,
)
var weightMsgWithdrawDelegationReward int
appParams . GetOrGenerate ( cdc , OpWeightMsgWithdrawDelegationReward , & weightMsgWithdrawDelegationReward , nil ,
func ( _ * rand . Rand ) {
weightMsgWithdrawDelegationReward = simappparams . DefaultWeightMsgWithdrawDelegationReward
} ,
)
var weightMsgWithdrawValidatorCommission int
appParams . GetOrGenerate ( cdc , OpWeightMsgWithdrawValidatorCommission , & weightMsgWithdrawValidatorCommission , nil ,
func ( _ * rand . Rand ) {
weightMsgWithdrawValidatorCommission = simappparams . DefaultWeightMsgWithdrawValidatorCommission
} ,
)
2019-12-10 20:02:15 -08:00
var weightMsgFundCommunityPool int
appParams . GetOrGenerate ( cdc , OpWeightMsgFundCommunityPool , & weightMsgFundCommunityPool , nil ,
func ( _ * rand . Rand ) {
weightMsgFundCommunityPool = simappparams . DefaultWeightMsgFundCommunityPool
} ,
)
2019-12-05 01:29:54 -08:00
return simulation . WeightedOperations {
simulation . NewWeightedOperation (
weightMsgSetWithdrawAddress ,
2020-01-30 13:31:16 -08:00
SimulateMsgSetWithdrawAddress ( ak , bk , k ) ,
2019-12-05 01:29:54 -08:00
) ,
simulation . NewWeightedOperation (
weightMsgWithdrawDelegationReward ,
2020-01-30 13:31:16 -08:00
SimulateMsgWithdrawDelegatorReward ( ak , bk , k , sk ) ,
2019-12-05 01:29:54 -08:00
) ,
simulation . NewWeightedOperation (
weightMsgWithdrawValidatorCommission ,
2020-01-30 13:31:16 -08:00
SimulateMsgWithdrawValidatorCommission ( ak , bk , k , sk ) ,
2019-12-05 01:29:54 -08:00
) ,
2019-12-10 20:02:15 -08:00
simulation . NewWeightedOperation (
weightMsgFundCommunityPool ,
2020-01-30 13:31:16 -08:00
SimulateMsgFundCommunityPool ( ak , bk , k , sk ) ,
2019-12-10 20:02:15 -08:00
) ,
2019-12-05 01:29:54 -08:00
}
}
2019-10-23 02:14:45 -07:00
// SimulateMsgSetWithdrawAddress generates a MsgSetWithdrawAddress with random values.
2020-03-23 04:55:44 -07:00
func SimulateMsgSetWithdrawAddress ( ak types . AccountKeeper , bk types . BankKeeper , k keeper . Keeper ) simtypes . Operation {
2019-10-23 02:14:45 -07:00
return func (
2020-03-23 04:55:44 -07:00
r * rand . Rand , app * baseapp . BaseApp , ctx sdk . Context , accs [ ] simtypes . Account , chainID string ,
) ( simtypes . OperationMsg , [ ] simtypes . FutureOperation , error ) {
2019-10-23 02:14:45 -07:00
if ! k . GetWithdrawAddrEnabled ( ctx ) {
2020-05-26 09:52:23 -07:00
return simtypes . NoOpMsg ( types . ModuleName , types . TypeMsgSetWithdrawAddress , "withdrawal is not enabled" ) , nil , nil
2019-10-23 02:14:45 -07:00
}
2020-03-23 04:55:44 -07:00
simAccount , _ := simtypes . RandomAcc ( r , accs )
simToAccount , _ := simtypes . RandomAcc ( r , accs )
2020-01-30 13:31:16 -08:00
2019-10-23 02:14:45 -07:00
account := ak . GetAccount ( ctx , simAccount . Address )
2020-01-30 13:31:16 -08:00
spendable := bk . SpendableCoins ( ctx , account . GetAddress ( ) )
2019-10-23 02:14:45 -07:00
msg := types . NewMsgSetWithdrawAddress ( simAccount . Address , simToAccount . Address )
2021-06-07 02:03:24 -07:00
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 ,
CoinsSpentInMsg : spendable ,
}
return simulation . GenAndDeliverTxWithRandFees ( txCtx )
2019-10-23 02:14:45 -07:00
}
}
// SimulateMsgWithdrawDelegatorReward generates a MsgWithdrawDelegatorReward with random values.
2020-03-23 04:55:44 -07:00
func SimulateMsgWithdrawDelegatorReward ( ak types . AccountKeeper , bk types . BankKeeper , k keeper . Keeper , sk stakingkeeper . Keeper ) simtypes . Operation {
2019-12-05 01:29:54 -08:00
return func (
2020-03-23 04:55:44 -07:00
r * rand . Rand , app * baseapp . BaseApp , ctx sdk . Context , accs [ ] simtypes . Account , chainID string ,
) ( simtypes . OperationMsg , [ ] simtypes . FutureOperation , error ) {
simAccount , _ := simtypes . RandomAcc ( r , accs )
2019-10-23 02:14:45 -07:00
delegations := sk . GetAllDelegatorDelegations ( ctx , simAccount . Address )
if len ( delegations ) == 0 {
2020-05-26 09:52:23 -07:00
return simtypes . NoOpMsg ( types . ModuleName , types . TypeMsgWithdrawDelegatorReward , "number of delegators equal 0" ) , nil , nil
2019-10-23 02:14:45 -07:00
}
delegation := delegations [ r . Intn ( len ( delegations ) ) ]
validator := sk . Validator ( ctx , delegation . GetValidatorAddr ( ) )
if validator == nil {
2020-05-26 09:52:23 -07:00
return simtypes . NoOpMsg ( types . ModuleName , types . TypeMsgWithdrawDelegatorReward , "validator is nil" ) , nil , fmt . Errorf ( "validator %s not found" , delegation . GetValidatorAddr ( ) )
2019-10-23 02:14:45 -07:00
}
account := ak . GetAccount ( ctx , simAccount . Address )
2020-01-30 13:31:16 -08:00
spendable := bk . SpendableCoins ( ctx , account . GetAddress ( ) )
2019-10-23 02:14:45 -07:00
msg := types . NewMsgWithdrawDelegatorReward ( simAccount . Address , validator . GetOperator ( ) )
2021-06-07 02:03:24 -07:00
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 ,
CoinsSpentInMsg : spendable ,
}
return simulation . GenAndDeliverTxWithRandFees ( txCtx )
2019-10-23 02:14:45 -07:00
}
}
// SimulateMsgWithdrawValidatorCommission generates a MsgWithdrawValidatorCommission with random values.
2020-03-23 04:55:44 -07:00
func SimulateMsgWithdrawValidatorCommission ( ak types . AccountKeeper , bk types . BankKeeper , k keeper . Keeper , sk stakingkeeper . Keeper ) simtypes . Operation {
2019-10-23 02:14:45 -07:00
return func (
2020-03-23 04:55:44 -07:00
r * rand . Rand , app * baseapp . BaseApp , ctx sdk . Context , accs [ ] simtypes . Account , chainID string ,
) ( simtypes . OperationMsg , [ ] simtypes . FutureOperation , error ) {
2019-10-23 02:14:45 -07:00
validator , ok := stakingkeeper . RandomValidator ( r , sk , ctx )
if ! ok {
2020-05-26 09:52:23 -07:00
return simtypes . NoOpMsg ( types . ModuleName , types . TypeMsgWithdrawValidatorCommission , "random validator is not ok" ) , nil , nil
2019-10-23 02:14:45 -07:00
}
commission := k . GetValidatorAccumulatedCommission ( ctx , validator . GetOperator ( ) )
2020-02-11 06:58:37 -08:00
if commission . Commission . IsZero ( ) {
2020-05-26 09:52:23 -07:00
return simtypes . NoOpMsg ( types . ModuleName , types . TypeMsgWithdrawValidatorCommission , "validator commission is zero" ) , nil , nil
2019-10-23 02:14:45 -07:00
}
2020-03-23 04:55:44 -07:00
simAccount , found := simtypes . FindAccount ( accs , sdk . AccAddress ( validator . GetOperator ( ) ) )
2019-10-23 02:14:45 -07:00
if ! found {
2020-05-26 09:52:23 -07:00
return simtypes . NoOpMsg ( types . ModuleName , types . TypeMsgWithdrawValidatorCommission , "could not find account" ) , nil , fmt . Errorf ( "validator %s not found" , validator . GetOperator ( ) )
2019-10-23 02:14:45 -07:00
}
account := ak . GetAccount ( ctx , simAccount . Address )
2020-01-30 13:31:16 -08:00
spendable := bk . SpendableCoins ( ctx , account . GetAddress ( ) )
2019-10-23 02:14:45 -07:00
msg := types . NewMsgWithdrawValidatorCommission ( validator . GetOperator ( ) )
2021-06-07 02:03:24 -07:00
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 ,
CoinsSpentInMsg : spendable ,
}
return simulation . GenAndDeliverTxWithRandFees ( txCtx )
2019-10-23 02:14:45 -07:00
}
}
2019-12-10 20:02:15 -08:00
// SimulateMsgFundCommunityPool simulates MsgFundCommunityPool execution where
// a random account sends a random amount of its funds to the community pool.
2020-03-23 04:55:44 -07:00
func SimulateMsgFundCommunityPool ( ak types . AccountKeeper , bk types . BankKeeper , k keeper . Keeper , sk stakingkeeper . Keeper ) simtypes . Operation {
2019-12-10 20:02:15 -08:00
return func (
2020-03-23 04:55:44 -07:00
r * rand . Rand , app * baseapp . BaseApp , ctx sdk . Context , accs [ ] simtypes . Account , chainID string ,
) ( simtypes . OperationMsg , [ ] simtypes . FutureOperation , error ) {
2019-12-10 20:02:15 -08:00
2020-03-23 04:55:44 -07:00
funder , _ := simtypes . RandomAcc ( r , accs )
2019-12-10 20:02:15 -08:00
account := ak . GetAccount ( ctx , funder . Address )
2020-01-30 13:31:16 -08:00
spendable := bk . SpendableCoins ( ctx , account . GetAddress ( ) )
2019-12-10 20:02:15 -08:00
2020-03-23 04:55:44 -07:00
fundAmount := simtypes . RandSubsetCoins ( r , spendable )
2019-12-10 20:02:15 -08:00
if fundAmount . Empty ( ) {
2020-05-26 09:52:23 -07:00
return simtypes . NoOpMsg ( types . ModuleName , types . TypeMsgFundCommunityPool , "fund amount is empty" ) , nil , nil
2019-12-10 20:02:15 -08:00
}
var (
fees sdk . Coins
err error
)
2022-04-20 05:36:10 -07:00
coins , hasNeg := spendable . SafeSub ( fundAmount ... )
2019-12-10 20:02:15 -08:00
if ! hasNeg {
2020-03-23 04:55:44 -07:00
fees , err = simtypes . RandomFees ( r , ctx , coins )
2019-12-10 20:02:15 -08:00
if err != nil {
2020-05-26 09:52:23 -07:00
return simtypes . NoOpMsg ( types . ModuleName , types . TypeMsgFundCommunityPool , "unable to generate fees" ) , nil , err
2019-12-10 20:02:15 -08:00
}
}
msg := types . NewMsgFundCommunityPool ( fundAmount , funder . Address )
2021-06-07 02:03:24 -07:00
txCtx := simulation . OperationInput {
App : app ,
TxGen : simappparams . MakeTestEncodingConfig ( ) . TxConfig ,
Cdc : nil ,
Msg : msg ,
MsgType : msg . Type ( ) ,
Context : ctx ,
SimAccount : funder ,
AccountKeeper : ak ,
ModuleName : types . ModuleName ,
2019-12-10 20:02:15 -08:00
}
2021-06-07 02:03:24 -07:00
return simulation . GenAndDeliverTx ( txCtx , fees )
2019-12-10 20:02:15 -08:00
}
}