Merge PR #4244: Param Proposal Simulation Messages; Minting Params Fix

This commit is contained in:
Alexander Bezobchuk 2019-05-02 16:50:01 -04:00 committed by GitHub
parent 38f93128eb
commit 29ed730aff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 322 additions and 95 deletions

View File

@ -0,0 +1 @@
#4235 Add parameter change proposal messages to simulation.

View File

@ -0,0 +1,2 @@
#4235 Update the minting module params to implement params.ParamSet so
individual keys can be set via proposals instead of passing a struct.

View File

@ -30,6 +30,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
"github.com/cosmos/cosmos-sdk/x/mint"
paramsim "github.com/cosmos/cosmos-sdk/x/params/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing"
slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
@ -151,72 +152,76 @@ func appStateRandomizedFn(r *rand.Rand, accs []simulation.Account, genesisTimest
genesisAccounts = append(genesisAccounts, gacc)
}
authGenesis := auth.GenesisState{
Params: auth.Params{
MaxMemoCharacters: uint64(simulation.RandIntBetween(r, 100, 200)),
TxSigLimit: uint64(r.Intn(7) + 1),
TxSizeCostPerByte: uint64(simulation.RandIntBetween(r, 5, 15)),
SigVerifyCostED25519: uint64(simulation.RandIntBetween(r, 500, 1000)),
SigVerifyCostSecp256k1: uint64(simulation.RandIntBetween(r, 500, 1000)),
authGenesis := auth.NewGenesisState(
nil,
auth.Params{
MaxMemoCharacters: simulation.ModuleParamSimulator["MaxMemoCharacters"](r).(uint64),
TxSigLimit: simulation.ModuleParamSimulator["TxSigLimit"](r).(uint64),
TxSizeCostPerByte: simulation.ModuleParamSimulator["TxSizeCostPerByte"](r).(uint64),
SigVerifyCostED25519: simulation.ModuleParamSimulator["SigVerifyCostED25519"](r).(uint64),
SigVerifyCostSecp256k1: simulation.ModuleParamSimulator["SigVerifyCostSecp256k1"](r).(uint64),
},
}
)
fmt.Printf("Selected randomly generated auth parameters:\n\t%+v\n", authGenesis)
bankGenesis := bank.NewGenesisState(r.Int63n(2) == 0)
fmt.Printf("Selected randomly generated bank parameters:\n\t%+v\n", bankGenesis)
// Random genesis states
vp := time.Duration(r.Intn(2*172800)) * time.Second
govGenesis := gov.GenesisState{
StartingProposalID: uint64(r.Intn(100)),
DepositParams: gov.DepositParams{
MinDeposit: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, int64(r.Intn(1e3)))},
vp := simulation.ModuleParamSimulator["VotingParams/VotingPeriod"](r).(time.Duration)
govGenesis := gov.NewGenesisState(
uint64(r.Intn(100)),
gov.DepositParams{
MinDeposit: simulation.ModuleParamSimulator["DepositParams/MinDeposit"](r).(sdk.Coins),
MaxDepositPeriod: vp,
},
VotingParams: gov.VotingParams{
gov.VotingParams{
VotingPeriod: vp,
},
TallyParams: gov.TallyParams{
Quorum: sdk.NewDecWithPrec(334, 3),
Threshold: sdk.NewDecWithPrec(5, 1),
Veto: sdk.NewDecWithPrec(334, 3),
gov.TallyParams{
Quorum: simulation.ModuleParamSimulator["TallyParams/Quorum"](r).(sdk.Dec),
Threshold: simulation.ModuleParamSimulator["TallyParams/Threshold"](r).(sdk.Dec),
Veto: simulation.ModuleParamSimulator["TallyParams/Veto"](r).(sdk.Dec),
},
}
)
fmt.Printf("Selected randomly generated governance parameters:\n\t%+v\n", govGenesis)
stakingGenesis := staking.GenesisState{
Pool: staking.InitialPool(),
Params: staking.Params{
UnbondingTime: time.Duration(simulation.RandIntBetween(r, 60, 60*60*24*3*2)) * time.Second,
MaxValidators: uint16(r.Intn(250) + 1),
stakingGenesis := staking.NewGenesisState(
staking.InitialPool(),
staking.Params{
UnbondingTime: simulation.ModuleParamSimulator["UnbondingTime"](r).(time.Duration),
MaxValidators: simulation.ModuleParamSimulator["MaxValidators"](r).(uint16),
BondDenom: sdk.DefaultBondDenom,
},
}
nil,
nil,
)
fmt.Printf("Selected randomly generated staking parameters:\n\t%+v\n", stakingGenesis)
slashingGenesis := slashing.GenesisState{
Params: slashing.Params{
MaxEvidenceAge: stakingGenesis.Params.UnbondingTime,
SignedBlocksWindow: int64(simulation.RandIntBetween(r, 10, 1000)),
MinSignedPerWindow: sdk.NewDecWithPrec(int64(r.Intn(10)), 1),
DowntimeJailDuration: time.Duration(simulation.RandIntBetween(r, 60, 60*60*24)) * time.Second,
SlashFractionDoubleSign: sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(50) + 1))),
SlashFractionDowntime: sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(200) + 1))),
SignedBlocksWindow: simulation.ModuleParamSimulator["SignedBlocksWindow"](r).(int64),
MinSignedPerWindow: simulation.ModuleParamSimulator["MinSignedPerWindow"](r).(sdk.Dec),
DowntimeJailDuration: simulation.ModuleParamSimulator["DowntimeJailDuration"](r).(time.Duration),
SlashFractionDoubleSign: simulation.ModuleParamSimulator["SlashFractionDoubleSign"](r).(sdk.Dec),
SlashFractionDowntime: simulation.ModuleParamSimulator["SlashFractionDowntime"](r).(sdk.Dec),
},
}
fmt.Printf("Selected randomly generated slashing parameters:\n\t%+v\n", slashingGenesis)
mintGenesis := mint.GenesisState{
Minter: mint.InitialMinter(
mintGenesis := mint.NewGenesisState(
mint.InitialMinter(
sdk.NewDecWithPrec(int64(r.Intn(99)), 2)),
Params: mint.NewParams(
mint.NewParams(
sdk.DefaultBondDenom,
sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
sdk.NewDecWithPrec(20, 2),
sdk.NewDecWithPrec(7, 2),
sdk.NewDecWithPrec(67, 2),
uint64(60*60*8766/5)),
}
simulation.ModuleParamSimulator["InflationRateChange"](r).(sdk.Dec),
simulation.ModuleParamSimulator["InflationMax"](r).(sdk.Dec),
simulation.ModuleParamSimulator["InflationMin"](r).(sdk.Dec),
simulation.ModuleParamSimulator["GoalBonded"](r).(sdk.Dec),
uint64(60*60*8766/5),
),
)
fmt.Printf("Selected randomly generated minting parameters:\n\t%+v\n", mintGenesis)
var validators []staking.Validator
@ -282,7 +287,8 @@ func testAndRunTxs(app *GaiaApp) []simulation.WeightedOperation {
{50, distrsim.SimulateMsgSetWithdrawAddress(app.accountKeeper, app.distrKeeper)},
{50, distrsim.SimulateMsgWithdrawDelegatorReward(app.accountKeeper, app.distrKeeper)},
{50, distrsim.SimulateMsgWithdrawValidatorCommission(app.accountKeeper, app.distrKeeper)},
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper)},
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, govsim.SimulateTextProposalContent)},
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, paramsim.SimulateParamChangeProposalContent)},
{100, govsim.SimulateMsgDeposit(app.govKeeper)},
{100, stakingsim.SimulateMsgCreateValidator(app.accountKeeper, app.stakingKeeper)},
{5, stakingsim.SimulateMsgEditValidator(app.stakingKeeper)},

View File

@ -27,7 +27,7 @@ func (dp DepositParams) Equal(dp2 DepositParams) bool {
// Param around Tallying votes in governance
type TallyParams struct {
Quorum sdk.Dec `json:"quorum"` // Minimum percentage of total stake needed to vote for a result to be considered valid
Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Threshold sdk.Dec `json:"threshold"` // Minimum proportion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Dec `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
}

View File

@ -12,13 +12,18 @@ import (
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// ContentSimulator defines a function type alias for generating random proposal
// content.
type ContentSimulator func(r *rand.Rand) gov.Content
// SimulateSubmittingVotingAndSlashingForProposal simulates creating a msg Submit Proposal
// voting on the proposal, and subsequently slashing the proposal. It is implemented using
// future operations.
// TODO: Vote more intelligently, so we can actually do some checks regarding votes passing or failing
// TODO: Actually check that validator slashings happened
func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper) simulation.Operation {
func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, contentSim ContentSimulator) simulation.Operation {
handler := gov.NewHandler(k)
// The states are:
// column 1: All validators vote
// column 2: 90% vote
@ -36,38 +41,49 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper) simulation.Ope
{0, 0, 20, 30, 30, 30},
{0, 0, 0, 10, 10, 25},
})
statePercentageArray := []float64{1, .9, .75, .4, .15, 0}
curNumVotesState := 1
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) (
opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {
return func(
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account,
) (opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {
// 1) submit proposal now
sender := simulation.RandomAcc(r, accs)
msg, err := simulationCreateMsgSubmitProposal(r, sender)
content := contentSim(r)
msg, err := simulationCreateMsgSubmitProposal(r, content, sender)
if err != nil {
return simulation.NoOpMsg(), nil, err
}
ok := simulateHandleMsgSubmitProposal(msg, handler, ctx)
opMsg = simulation.NewOperationMsg(msg, ok, "")
opMsg = simulation.NewOperationMsg(msg, ok, content.ProposalType())
// don't schedule votes if proposal failed
if !ok {
return opMsg, nil, nil
}
proposalID := k.GetLastProposalID(ctx)
// 2) Schedule operations for votes
// 2.1) first pick a number of people to vote.
curNumVotesState = numVotesTransitionMatrix.NextState(r, curNumVotesState)
numVotes := int(math.Ceil(float64(len(accs)) * statePercentageArray[curNumVotesState]))
// 2.2) select who votes and when
whoVotes := r.Perm(len(accs))
// didntVote := whoVotes[numVotes:]
whoVotes = whoVotes[:numVotes]
votingPeriod := k.GetVotingParams(ctx).VotingPeriod
fops := make([]simulation.FutureOperation, numVotes+1)
for i := 0; i < numVotes; i++ {
whenVote := ctx.BlockHeader().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second)
fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, accs[whoVotes[i]], proposalID)}
}
// 3) Make an operation to ensure slashes were done correctly. (Really should be a future invariant)
// TODO: Find a way to check if a validator was slashed other than just checking their balance a block
// before and after.
@ -76,24 +92,6 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper) simulation.Ope
}
}
// SimulateMsgSubmitProposal simulates a msg Submit Proposal
// Note: Currently doesn't ensure that the proposal txt is in JSON form
func SimulateMsgSubmitProposal(k gov.Keeper) simulation.Operation {
handler := gov.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) (
opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {
sender := simulation.RandomAcc(r, accs)
msg, err := simulationCreateMsgSubmitProposal(r, sender)
if err != nil {
return simulation.NoOpMsg(), nil, err
}
ok := simulateHandleMsgSubmitProposal(msg, handler, ctx)
opMsg = simulation.NewOperationMsg(msg, ok, "")
return opMsg, nil, nil
}
}
func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, handler sdk.Handler, ctx sdk.Context) (ok bool) {
ctx, write := ctx.CacheContext()
ok = handler(ctx, msg).IsOK()
@ -103,16 +101,16 @@ func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, handler sdk.Hand
return ok
}
func simulationCreateMsgSubmitProposal(r *rand.Rand, sender simulation.Account) (msg gov.MsgSubmitProposal, err error) {
deposit := randomDeposit(r)
msg = gov.NewMsgSubmitProposal(
gov.NewTextProposal(
simulation.RandStringOfLength(r, 5),
simulation.RandStringOfLength(r, 5),
),
deposit,
sender.Address,
// SimulateTextProposalContent returns random text proposal content.
func SimulateTextProposalContent(r *rand.Rand) gov.Content {
return gov.NewTextProposal(
simulation.RandStringOfLength(r, 140),
simulation.RandStringOfLength(r, 5000),
)
}
func simulationCreateMsgSubmitProposal(r *rand.Rand, c gov.Content, s simulation.Account) (msg gov.MsgSubmitProposal, err error) {
msg = gov.NewMsgSubmitProposal(c, randomDeposit(r), s.Address)
if msg.ValidateBasic() != nil {
err = fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
}

View File

@ -6,6 +6,8 @@ import (
"github.com/cosmos/cosmos-sdk/x/params"
)
var minterKey = []byte{0x00} // the one key to use for the keeper store
const (
// ModuleName is the name of the module
ModuleName = "minting"
@ -42,23 +44,6 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey,
return keeper
}
//____________________________________________________________________
// Keys
var (
minterKey = []byte{0x00} // the one key to use for the keeper store
// params store for inflation params
ParamStoreKeyParams = []byte("params")
)
// ParamTable for staking module
func ParamKeyTable() params.KeyTable {
return params.NewKeyTable(
ParamStoreKeyParams, Params{},
)
}
//______________________________________________________________________
// get the minter
@ -81,14 +66,13 @@ func (k Keeper) SetMinter(ctx sdk.Context, minter Minter) {
//______________________________________________________________________
// get inflation params from the global param store
func (k Keeper) GetParams(ctx sdk.Context) Params {
var params Params
k.paramSpace.Get(ctx, ParamStoreKeyParams, &params)
// GetParams returns the total set of slashing parameters.
func (k Keeper) GetParams(ctx sdk.Context) (params Params) {
k.paramSpace.GetParamSet(ctx, &params)
return params
}
// set inflation params from the global param store
func (k Keeper) SetParams(ctx sdk.Context, params Params) {
k.paramSpace.Set(ctx, ParamStoreKeyParams, &params)
k.paramSpace.SetParamSet(ctx, &params)
}

View File

@ -4,6 +4,17 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/params"
)
// Parameter store keys
var (
KeyMintDenom = []byte("MintDenom")
KeyInflationRateChange = []byte("InflationRateChange")
KeyInflationMax = []byte("InflationMax")
KeyInflationMin = []byte("InflationMin")
KeyGoalBonded = []byte("GoalBonded")
KeyBlocksPerYear = []byte("BlocksPerYear")
)
// mint parameters
@ -16,6 +27,11 @@ type Params struct {
BlocksPerYear uint64 `json:"blocks_per_year"` // expected blocks per year
}
// ParamTable for minting module.
func ParamKeyTable() params.KeyTable {
return params.NewKeyTable().RegisterParamSet(&Params{})
}
func NewParams(mintDenom string, inflationRateChange, inflationMax,
inflationMin, goalBonded sdk.Dec, blocksPerYear uint64) Params {
@ -70,3 +86,15 @@ func (p Params) String() string {
p.InflationMin, p.GoalBonded, p.BlocksPerYear,
)
}
// Implements params.ParamSet
func (p *Params) ParamSetPairs() params.ParamSetPairs {
return params.ParamSetPairs{
{KeyMintDenom, &p.MintDenom},
{KeyInflationRateChange, &p.InflationRateChange},
{KeyInflationMax, &p.InflationMax},
{KeyInflationMin, &p.InflationMin},
{KeyGoalBonded, &p.GoalBonded},
{KeyBlocksPerYear, &p.BlocksPerYear},
}
}

136
x/params/simulation/msgs.go Normal file
View File

@ -0,0 +1,136 @@
package simulation
import (
"fmt"
"math/rand"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
type simParamChange struct {
subspace string
key string
subkey string
simValue func(r *rand.Rand) string
}
func (spc simParamChange) compKey() string {
return fmt.Sprintf("%s/%s/%s", spc.subkey, spc.key, spc.subkey)
}
// paramChangePool defines a static slice of possible simulated parameter changes
// where each simParamChange corresponds to a ParamChange with a simValue
// function to generate a simulated new value.
//
// TODO: governance parameters (blocked on an upgrade to go-amino)
var paramChangePool = []simParamChange{
// staking parameters
{
"staking",
"MaxValidators",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("%d", simulation.ModuleParamSimulator["MaxValidators"](r).(uint16))
},
},
{
"staking",
"UnbondingTime",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["UnbondingTime"](r).(time.Duration))
},
},
// slashing parameters
{
"slashing",
"SignedBlocksWindow",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["SignedBlocksWindow"](r).(int64))
},
},
{
"slashing",
"MinSignedPerWindow",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["MinSignedPerWindow"](r).(sdk.Dec))
},
},
{
"slashing",
"SlashFractionDowntime",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["SlashFractionDowntime"](r).(sdk.Dec))
},
},
// minting parameters
{
"mint",
"InflationRateChange",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["InflationRateChange"](r).(sdk.Dec))
},
},
// auth parameters
{
"auth",
"MaxMemoCharacters",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["MaxMemoCharacters"](r).(uint64))
},
},
{
"auth",
"TxSigLimit",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["TxSigLimit"](r).(uint64))
},
},
{
"auth",
"TxSizeCostPerByte",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["TxSizeCostPerByte"](r).(uint64))
},
},
}
// SimulateParamChangeProposalContent returns random parameter change content.
// It will generate a ParameterChangeProposal object with anywhere between 1 and
// 3 parameter changes all of which have random, but valid values.
func SimulateParamChangeProposalContent(r *rand.Rand) gov.Content {
numChanges := simulation.RandIntBetween(r, 1, len(paramChangePool)/2)
paramChanges := make([]params.ParamChange, numChanges, numChanges)
paramChangesKeys := make(map[string]struct{})
for i := 0; i < numChanges; i++ {
spc := paramChangePool[r.Intn(len(paramChangePool))]
// do not include duplicate parameter changes for a given subspace/key
_, ok := paramChangesKeys[spc.compKey()]
for ok {
spc = paramChangePool[r.Intn(len(paramChangePool))]
_, ok = paramChangesKeys[spc.compKey()]
}
paramChangesKeys[spc.compKey()] = struct{}{}
paramChanges[i] = params.NewParamChange(spc.subspace, spc.key, spc.subkey, spc.simValue(r))
}
return params.NewParameterChangeProposal(
simulation.RandStringOfLength(r, 140),
simulation.RandStringOfLength(r, 5000),
paramChanges,
)
}

View File

@ -2,6 +2,9 @@ package simulation
import (
"math/rand"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
@ -32,6 +35,75 @@ var (
{15, 92, 1},
{0, 3, 99},
})
// ModuleParamSimulator defines module parameter value simulators. All
// values simulated should be within valid acceptable range for the given
// parameter.
ModuleParamSimulator = map[string]func(r *rand.Rand) interface{}{
"MaxMemoCharacters": func(r *rand.Rand) interface{} {
return uint64(RandIntBetween(r, 100, 200))
},
"TxSigLimit": func(r *rand.Rand) interface{} {
return uint64(r.Intn(7) + 1)
},
"TxSizeCostPerByte": func(r *rand.Rand) interface{} {
return uint64(RandIntBetween(r, 5, 15))
},
"SigVerifyCostED25519": func(r *rand.Rand) interface{} {
return uint64(RandIntBetween(r, 500, 1000))
},
"SigVerifyCostSecp256k1": func(r *rand.Rand) interface{} {
return uint64(RandIntBetween(r, 500, 1000))
},
"DepositParams/MinDeposit": func(r *rand.Rand) interface{} {
return sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, int64(r.Intn(1e3)))}
},
"VotingParams/VotingPeriod": func(r *rand.Rand) interface{} {
return time.Duration(r.Intn(2*172800)) * time.Second
},
"TallyParams/Quorum": func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(334, 3)
},
"TallyParams/Threshold": func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(5, 1)
},
"TallyParams/Veto": func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(334, 3)
},
"UnbondingTime": func(r *rand.Rand) interface{} {
return time.Duration(RandIntBetween(r, 60, 60*60*24*3*2)) * time.Second
},
"MaxValidators": func(r *rand.Rand) interface{} {
return uint16(r.Intn(250) + 1)
},
"SignedBlocksWindow": func(r *rand.Rand) interface{} {
return int64(RandIntBetween(r, 10, 1000))
},
"MinSignedPerWindow": func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(int64(r.Intn(10)), 1)
},
"DowntimeJailDuration": func(r *rand.Rand) interface{} {
return time.Duration(RandIntBetween(r, 60, 60*60*24)) * time.Second
},
"SlashFractionDoubleSign": func(r *rand.Rand) interface{} {
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(50) + 1)))
},
"SlashFractionDowntime": func(r *rand.Rand) interface{} {
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(200) + 1)))
},
"InflationRateChange": func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(int64(r.Intn(99)), 2)
},
"InflationMax": func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(20, 2)
},
"InflationMin": func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(7, 2)
},
"GoalBonded": func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(67, 2)
},
}
)
// Simulation parameters