debugging simulation

This commit is contained in:
rigelrozanski 2018-10-05 20:32:06 -04:00
parent 83c2781c1c
commit e304b9c600
16 changed files with 97 additions and 56 deletions

View File

@ -201,8 +201,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
// load the initial stake information
validators, err := stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
if err != nil {
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
// return sdk.ErrGenesisParse("").TraceCause(err, "")
panic(err) // TODO find a way to do this w/o panics
}
// load the address to pubkey map
@ -212,8 +211,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
distr.InitGenesis(ctx, app.distrKeeper, genesisState.DistrData)
err = GaiaValidateGenesisState(genesisState)
if err != nil {
// TODO find a way to do this w/o panics
panic(err)
panic(err) // TODO find a way to do this w/o panics
}
return abci.ResponseInitChain{

View File

@ -15,6 +15,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/gov"
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
@ -52,18 +53,23 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
Coins: coins,
})
}
govGenesis := gov.DefaultGenesisState()
// Default genesis state
stakeGenesis := stake.DefaultGenesisState()
var validators []stake.Validator
var delegations []stake.Delegation
// XXX Try different numbers of initially bonded validators
numInitiallyBonded := int64(50)
valAddrs := make([]sdk.ValAddress, numInitiallyBonded)
for i := 0; i < int(numInitiallyBonded); i++ {
validator := stake.NewValidator(sdk.ValAddress(accs[i].Address), accs[i].PubKey, stake.Description{})
valAddr := sdk.ValAddress(accs[i].Address)
valAddrs[i] = valAddr
validator := stake.NewValidator(valAddr, accs[i].PubKey, stake.Description{})
validator.Tokens = sdk.NewDec(100)
validator.DelegatorShares = sdk.NewDec(100)
delegation := stake.Delegation{accs[i].Address, sdk.ValAddress(accs[i].Address), sdk.NewDec(100), 0}
delegation := stake.Delegation{accs[i].Address, valAddr, sdk.NewDec(100), 0}
validators = append(validators, validator)
delegations = append(delegations, delegation)
}
@ -73,10 +79,12 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
// No inflation, for now
stakeGenesis.Params.InflationMax = sdk.NewDec(0)
stakeGenesis.Params.InflationMin = sdk.NewDec(0)
genesis := GenesisState{
Accounts: genesisAccounts,
StakeData: stakeGenesis,
GovData: govGenesis,
DistrData: distr.DefaultGenesisWithValidators(valAddrs),
GovData: gov.DefaultGenesisState(),
}
// Marshal genesis

View File

@ -6,7 +6,7 @@
The pool of a new delegator bond will be 0 for the height at which the bond was
added, or the withdrawal has taken place. This is achieved by setting
`DelegatorDistInfo.WithdrawalHeight` to the height of the triggering transaction.
`DelegationDistInfo.WithdrawalHeight` to the height of the triggering transaction.
## Commission rate change

View File

@ -59,10 +59,10 @@ properties change (aka bonded tokens etc.) its properties will remain constant
and the delegator's _accumulation_ factor can be calculated passively knowing
only the height of the last withdrawal and its current properties.
- DelegatorDistInfo: ` 0x02 | DelegatorAddr | ValOperatorAddr -> amino(delegatorDist)`
- DelegationDistInfo: ` 0x02 | DelegatorAddr | ValOperatorAddr -> amino(delegatorDist)`
```golang
type DelegatorDistInfo struct {
type DelegationDistInfo struct {
WithdrawalHeight int64 // last time this delegation withdrew rewards
}
```

View File

@ -172,9 +172,9 @@ For delegations (including validator's self-delegation) all rewards from reward
pool have already had the validator's commission taken away.
```
func (di DelegatorDistInfo) WithdrawRewards(g FeePool, vi ValidatorDistInfo,
func (di DelegationDistInfo) WithdrawRewards(g FeePool, vi ValidatorDistInfo,
height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (
di DelegatorDistInfo, g FeePool, withdrawn DecCoins)
di DelegationDistInfo, g FeePool, withdrawn DecCoins)
vi.UpdateTotalDelAccum(height, totalDelShares)
g = vi.TakeFeePoolRewards(g, height, totalBonded, vdTokens, commissionRate)

View File

@ -12,7 +12,7 @@ type (
Hooks = keeper.Hooks
DelegatorWithdrawInfo = types.DelegatorWithdrawInfo
DelegatorDistInfo = types.DelegatorDistInfo
DelegationDistInfo = types.DelegationDistInfo
ValidatorDistInfo = types.ValidatorDistInfo
TotalAccum = types.TotalAccum
FeePool = types.FeePool
@ -34,14 +34,15 @@ var (
GetDelegatorWithdrawAddrKey = keeper.GetDelegatorWithdrawAddrKey
FeePoolKey = keeper.FeePoolKey
ValidatorDistInfoKey = keeper.ValidatorDistInfoKey
DelegatorDistInfoKey = keeper.DelegatorDistInfoKey
DelegationDistInfoKey = keeper.DelegationDistInfoKey
DelegatorWithdrawInfoKey = keeper.DelegatorWithdrawInfoKey
ProposerKey = keeper.ProposerKey
InitialFeePool = types.InitialFeePool
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
DefaultGenesisWithValidators = types.DefaultGenesisWithValidators
RegisterCodec = types.RegisterCodec

View File

@ -13,8 +13,8 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) {
for _, vdi := range data.ValidatorDistInfos {
keeper.SetValidatorDistInfo(ctx, vdi)
}
for _, ddi := range data.DelegatorDistInfos {
keeper.SetDelegatorDistInfo(ctx, ddi)
for _, ddi := range data.DelegationDistInfos {
keeper.SetDelegationDistInfo(ctx, ddi)
}
for _, dw := range data.DelegatorWithdrawInfos {
keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr)

View File

@ -6,8 +6,8 @@ import (
)
// get the delegator distribution info
func (k Keeper) GetDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
valOperatorAddr sdk.ValAddress) (ddi types.DelegatorDistInfo) {
func (k Keeper) GetDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
valOperatorAddr sdk.ValAddress) (ddi types.DelegationDistInfo) {
store := ctx.KVStore(k.storeKey)
@ -21,14 +21,14 @@ func (k Keeper) GetDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
}
// set the delegator distribution info
func (k Keeper) SetDelegatorDistInfo(ctx sdk.Context, ddi types.DelegatorDistInfo) {
func (k Keeper) SetDelegationDistInfo(ctx sdk.Context, ddi types.DelegationDistInfo) {
store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(ddi)
store.Set(GetDelegationDistInfoKey(ddi.DelegatorAddr, ddi.ValOperatorAddr), b)
}
// remove a delegator distribution info
func (k Keeper) RemoveDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
func (k Keeper) RemoveDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
valOperatorAddr sdk.ValAddress) {
store := ctx.KVStore(k.storeKey)
@ -69,7 +69,7 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA
height := ctx.BlockHeight()
bondedTokens := k.stakeKeeper.TotalPower(ctx)
feePool := k.GetFeePool(ctx)
delInfo := k.GetDelegatorDistInfo(ctx, delegatorAddr, validatorAddr)
delInfo := k.GetDelegationDistInfo(ctx, delegatorAddr, validatorAddr)
valInfo := k.GetValidatorDistInfo(ctx, validatorAddr)
validator := k.stakeKeeper.Validator(ctx, validatorAddr)
delegation := k.stakeKeeper.Delegation(ctx, delegatorAddr, validatorAddr)
@ -109,7 +109,7 @@ func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress,
// iterate over all the delegations
operationAtDelegation := func(_ int64, del sdk.Delegation) (stop bool) {
valAddr := del.GetValidator()
delInfo := k.GetDelegatorDistInfo(ctx, delAddr, valAddr)
delInfo := k.GetDelegationDistInfo(ctx, delAddr, valAddr)
valInfo := k.GetValidatorDistInfo(ctx, valAddr)
validator := k.stakeKeeper.Validator(ctx, valAddr)
delegation := k.stakeKeeper.Delegation(ctx, delAddr, valAddr)
@ -119,7 +119,7 @@ func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress,
withdraw = withdraw.Plus(diWithdraw)
k.SetFeePool(ctx, feePool)
k.SetValidatorDistInfo(ctx, valInfo)
k.SetDelegatorDistInfo(ctx, delInfo)
k.SetDelegationDistInfo(ctx, delInfo)
return false
}
k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation)

View File

@ -20,13 +20,13 @@ func (k Keeper) GetAllVDIs(ctx sdk.Context) (vdis []types.ValidatorDistInfo) {
}
// Get the set of all delegator-distribution-info's with no limits, used during genesis dump
func (k Keeper) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegatorDistInfo) {
func (k Keeper) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegationDistInfo) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, DelegatorDistInfoKey)
iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var ddi types.DelegatorDistInfo
var ddi types.DelegationDistInfo
k.cdc.MustUnmarshalBinary(iterator.Value(), &ddi)
ddis = append(ddis, ddi)
}
@ -36,7 +36,7 @@ func (k Keeper) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegatorDistInfo) {
// Get the set of all delegator-withdraw addresses with no limits, used during genesis dump
func (k Keeper) GetAllDWIs(ctx sdk.Context) (dwis []types.DelegatorWithdrawInfo) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, DelegatorDistInfoKey)
iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {

View File

@ -37,12 +37,12 @@ func (k Keeper) onValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) {
func (k Keeper) onDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress,
valAddr sdk.ValAddress) {
ddi := types.DelegatorDistInfo{
ddi := types.DelegationDistInfo{
DelegatorAddr: delAddr,
ValOperatorAddr: valAddr,
WithdrawalHeight: ctx.BlockHeight(),
}
k.SetDelegatorDistInfo(ctx, ddi)
k.SetDelegationDistInfo(ctx, ddi)
ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("ddi created: %v", ddi))
}
@ -57,7 +57,7 @@ func (k Keeper) onDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddre
func (k Keeper) onDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress,
valAddr sdk.ValAddress) {
k.RemoveDelegatorDistInfo(ctx, delAddr, valAddr)
k.RemoveDelegationDistInfo(ctx, delAddr, valAddr)
}
//_________________________________________________________________________________________

View File

@ -8,7 +8,7 @@ import (
var (
FeePoolKey = []byte{0x00} // key for global distribution state
ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution
DelegatorDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution
DelegationDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution
DelegatorWithdrawInfoKey = []byte{0x03} // prefix for each key to a delegator withdraw info
// transient
@ -22,14 +22,14 @@ func GetValidatorDistInfoKey(operatorAddr sdk.ValAddress) []byte {
}
// gets the key for delegator distribution for a validator
// VALUE: distribution/types.DelegatorDistInfo
// VALUE: distribution/types.DelegationDistInfo
func GetDelegationDistInfoKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
return append(GetDelegationDistInfosKey(delAddr), valAddr.Bytes()...)
}
// gets the prefix for a delegator's distributions across all validators
func GetDelegationDistInfosKey(delAddr sdk.AccAddress) []byte {
return append(DelegatorDistInfoKey, delAddr.Bytes()...)
return append(DelegationDistInfoKey, delAddr.Bytes()...)
}
// gets the prefix for a delegator's withdraw info

View File

@ -5,16 +5,16 @@ import (
)
// distribution info for a delegation - used to determine entitled rewards
type DelegatorDistInfo struct {
type DelegationDistInfo struct {
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
ValOperatorAddr sdk.ValAddress `json:"val_operator_addr"`
WithdrawalHeight int64 `json:"withdrawal_height"` // last time this delegation withdrew rewards
}
func NewDelegatorDistInfo(delegatorAddr sdk.AccAddress, valOperatorAddr sdk.ValAddress,
currentHeight int64) DelegatorDistInfo {
func NewDelegationDistInfo(delegatorAddr sdk.AccAddress, valOperatorAddr sdk.ValAddress,
currentHeight int64) DelegationDistInfo {
return DelegatorDistInfo{
return DelegationDistInfo{
DelegatorAddr: delegatorAddr,
ValOperatorAddr: valOperatorAddr,
WithdrawalHeight: currentHeight,
@ -22,9 +22,9 @@ func NewDelegatorDistInfo(delegatorAddr sdk.AccAddress, valOperatorAddr sdk.ValA
}
// withdraw rewards from delegator
func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo,
func (di DelegationDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo,
height int64, totalBonded, vdTokens, totalDelShares, delegatorShares,
commissionRate sdk.Dec) (DelegatorDistInfo, ValidatorDistInfo, FeePool, DecCoins) {
commissionRate sdk.Dec) (DelegationDistInfo, ValidatorDistInfo, FeePool, DecCoins) {
vi = vi.UpdateTotalDelAccum(height, totalDelShares)

View File

@ -18,10 +18,10 @@ func TestWithdrawRewards(t *testing.T) {
validatorDelShares := sdk.NewDec(10)
totalBondedTokens := validatorTokens.Add(sdk.NewDec(90)) // validator-1 is 10% of total power
di1 := NewDelegatorDistInfo(delAddr1, valAddr1, height)
di1 := NewDelegationDistInfo(delAddr1, valAddr1, height)
di1Shares := sdk.NewDec(5) // this delegator has half the shares in the validator
di2 := NewDelegatorDistInfo(delAddr2, valAddr1, height)
di2 := NewDelegationDistInfo(delAddr2, valAddr1, height)
di2Shares := sdk.NewDec(5)
// simulate adding some stake for inflation

View File

@ -14,18 +14,18 @@ type GenesisState struct {
FeePool FeePool `json:"fee_pool"`
CommunityTax sdk.Dec `json:"community_tax"`
ValidatorDistInfos []ValidatorDistInfo `json:"validator_dist_infos"`
DelegatorDistInfos []DelegatorDistInfo `json:"delegator_dist_infos"`
DelegationDistInfos []DelegationDistInfo `json:"delegator_dist_infos"`
DelegatorWithdrawInfos []DelegatorWithdrawInfo `json:"delegator_withdraw_infos"`
}
func NewGenesisState(feePool FeePool, communityTax sdk.Dec,
vdis []ValidatorDistInfo, ddis []DelegatorDistInfo, dwis []DelegatorWithdrawInfo) GenesisState {
vdis []ValidatorDistInfo, ddis []DelegationDistInfo, dwis []DelegatorWithdrawInfo) GenesisState {
return GenesisState{
FeePool: feePool,
CommunityTax: communityTax,
ValidatorDistInfos: vdis,
DelegatorDistInfos: ddis,
DelegationDistInfos: ddis,
DelegatorWithdrawInfos: dwis,
}
}
@ -37,3 +37,23 @@ func DefaultGenesisState() GenesisState {
CommunityTax: sdk.NewDecWithPrec(2, 2), // 2%
}
}
// default genesis utility function, initialize for starting validator set
func DefaultGenesisWithValidators(valAddrs []sdk.ValAddress) GenesisState {
vdis := make([]ValidatorDistInfo, len(valAddrs))
ddis := make([]DelegationDistInfo, len(valAddrs))
for i, valAddr := range valAddrs {
vdis[i] = NewValidatorDistInfo(valAddr, 0)
accAddr := sdk.AccAddress(valAddr)
ddis[i] = NewDelegationDistInfo(accAddr, valAddr, 0)
}
return GenesisState{
FeePool: InitialFeePool(),
CommunityTax: sdk.NewDecWithPrec(2, 2), // 2%
ValidatorDistInfos: vdis,
DelegationDistInfos: ddis,
}
}

View File

@ -278,8 +278,6 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co
func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress,
shares sdk.Dec) (amount sdk.Dec, err sdk.Error) {
k.OnDelegationSharesModified(ctx, delAddr, valAddr)
// check if delegation has any shares in it unbond
delegation, found := k.GetDelegation(ctx, delAddr, valAddr)
if !found {
@ -287,6 +285,8 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA
return
}
k.OnDelegationSharesModified(ctx, delAddr, valAddr)
// retrieve the amount to remove
if delegation.Shares.LT(shares) {
err = types.ErrNotEnoughDelegationShares(k.Codespace(), delegation.Shares.String())

View File

@ -16,7 +16,9 @@ import (
// SimulateMsgCreateValidator
func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.Operation {
handler := stake.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account, event func(string)) (
action string, fOp []simulation.FutureOperation, err error) {
denom := k.GetParams(ctx).BondDenom
description := stake.Description{
@ -71,7 +73,9 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation
// SimulateMsgEditValidator
func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation {
handler := stake.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account, event func(string)) (
action string, fOp []simulation.FutureOperation, err error) {
description := stake.Description{
Moniker: simulation.RandStringOfLength(r, 10),
@ -109,7 +113,9 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation {
// SimulateMsgDelegate
func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation {
handler := stake.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account, event func(string)) (
action string, fOp []simulation.FutureOperation, err error) {
denom := k.GetParams(ctx).BondDenom
validatorAcc := simulation.RandomAcc(r, accs)
@ -145,7 +151,9 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat
// SimulateMsgBeginUnbonding
func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.Operation {
handler := stake.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account, event func(string)) (
action string, fOp []simulation.FutureOperation, err error) {
denom := k.GetParams(ctx).BondDenom
validatorAcc := simulation.RandomAcc(r, accs)
@ -181,7 +189,9 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.
// SimulateMsgCompleteUnbonding
func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation {
handler := stake.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account, event func(string)) (
action string, fOp []simulation.FutureOperation, err error) {
validatorAcc := simulation.RandomAcc(r, accs)
validatorAddress := sdk.ValAddress(validatorAcc.Address)
@ -208,7 +218,9 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation {
// SimulateMsgBeginRedelegate
func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation {
handler := stake.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account, event func(string)) (
action string, fOp []simulation.FutureOperation, err error) {
denom := k.GetParams(ctx).BondDenom
sourceValidatorAcc := simulation.RandomAcc(r, accs)
@ -248,7 +260,9 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation
// SimulateMsgCompleteRedelegate
func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation {
handler := stake.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account, event func(string)) (
action string, fOp []simulation.FutureOperation, err error) {
validatorSrcAcc := simulation.RandomAcc(r, accs)
validatorSrcAddress := sdk.ValAddress(validatorSrcAcc.Address)