Skip to content

Commit

Permalink
Merge PR #4244: Param Proposal Simulation Messages; Minting Params Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbez authored May 2, 2019
1 parent 38f9312 commit 29ed730
Show file tree
Hide file tree
Showing 9 changed files with 322 additions and 95 deletions.
1 change: 1 addition & 0 deletions .pending/improvements/sdk/4235-Add-parameter-c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#4235 Add parameter change proposal messages to simulation.
2 changes: 2 additions & 0 deletions .pending/improvements/sdk/4235-Update-the-mint
Original file line number Diff line number Diff line change
@@ -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.
86 changes: 46 additions & 40 deletions cmd/gaia/app/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)},
Expand Down
2 changes: 1 addition & 1 deletion x/gov/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
62 changes: 30 additions & 32 deletions x/gov/simulation/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand All @@ -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()
Expand All @@ -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())
}
Expand Down
28 changes: 6 additions & 22 deletions x/mint/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
28 changes: 28 additions & 0 deletions x/mint/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {

Expand Down Expand Up @@ -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},
}
}
Loading

0 comments on commit 29ed730

Please sign in to comment.