Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Param Proposal Simulation Messages; Minting Params Fix #4244

Merged
merged 9 commits into from
May 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, slashing has no such function. Separate PR.

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 {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

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"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this differs with the module name (?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed. I didn't write this module -- it should be changed. Separate PR though.

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{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be cool to use params.NewParamSetPairs here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need New* constructor for slice literals, but certainly their contents.

{KeyMintDenom, &p.MintDenom},
{KeyInflationRateChange, &p.InflationRateChange},
{KeyInflationMax, &p.InflationMax},
{KeyInflationMin, &p.InflationMin},
{KeyGoalBonded, &p.GoalBonded},
{KeyBlocksPerYear, &p.BlocksPerYear},
}
}
Loading