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

feat: custom proposal-based voting periods #1

Merged
merged 1 commit into from
Jun 15, 2022
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
21 changes: 20 additions & 1 deletion docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@
- [Deposit](#cosmos.gov.v1beta1.Deposit)
- [DepositParams](#cosmos.gov.v1beta1.DepositParams)
- [Proposal](#cosmos.gov.v1beta1.Proposal)
- [ProposalVotingPeriod](#cosmos.gov.v1beta1.ProposalVotingPeriod)
- [TallyParams](#cosmos.gov.v1beta1.TallyParams)
- [TallyResult](#cosmos.gov.v1beta1.TallyResult)
- [TextProposal](#cosmos.gov.v1beta1.TextProposal)
Expand Down Expand Up @@ -5115,6 +5116,23 @@ Proposal defines the core field members of a governance proposal.



<a name="cosmos.gov.v1beta1.ProposalVotingPeriod"></a>

### ProposalVotingPeriod
ProposalVotingPeriod defines custom voting periods for a unique governance
proposal type.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `proposal_type` | [string](#string) | | e.g. "cosmos.params.v1beta1.ParameterChangeProposal" |
| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | |






<a name="cosmos.gov.v1beta1.TallyParams"></a>

### TallyParams
Expand Down Expand Up @@ -5194,7 +5212,8 @@ VotingParams defines the params for voting on governance proposals.

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. |
| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | voting_period defines the length of the voting period. |
| `proposal_voting_periods` | [ProposalVotingPeriod](#cosmos.gov.v1beta1.ProposalVotingPeriod) | repeated | proposal_voting_periods defines custom voting periods for proposal types. |



Expand Down
17 changes: 16 additions & 1 deletion proto/cosmos/gov/v1beta1/gov.proto
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,16 @@ message DepositParams {

// VotingParams defines the params for voting on governance proposals.
message VotingParams {
// Length of the voting period.
// voting_period defines the length of the voting period.
google.protobuf.Duration voting_period = 1 [
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
(gogoproto.jsontag) = "voting_period,omitempty",
(gogoproto.moretags) = "yaml:\"voting_period\""
];

// proposal_voting_periods defines custom voting periods for proposal types.
repeated ProposalVotingPeriod proposal_voting_periods = 2 [(gogoproto.nullable) = false];
}

// TallyParams defines the params for tallying votes on governance proposals.
Expand Down Expand Up @@ -198,3 +201,15 @@ message TallyParams {
(gogoproto.moretags) = "yaml:\"veto_threshold\""
];
}

// ProposalVotingPeriod defines custom voting periods for a unique governance
// proposal type.
message ProposalVotingPeriod {
string proposal_type = 1; // e.g. "cosmos.params.v1beta1.ParameterChangeProposal"
google.protobuf.Duration voting_period = 2 [
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
(gogoproto.jsontag) = "voting_period,omitempty",
(gogoproto.moretags) = "yaml:\"voting_period\""
];
}
3 changes: 2 additions & 1 deletion x/gov/client/testutil/cli_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build norace
// +build norace

package testutil
Expand All @@ -21,7 +22,7 @@ func TestIntegrationTestSuite(t *testing.T) {

genesisState := types.DefaultGenesisState()
genesisState.DepositParams = types.NewDepositParams(sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, types.DefaultMinDepositTokens)), time.Duration(15)*time.Second)
genesisState.VotingParams = types.NewVotingParams(time.Duration(5) * time.Second)
genesisState.VotingParams = types.NewVotingParams(time.Duration(5)*time.Second, []types.ProposalVotingPeriod{})
bz, err := cfg.Codec.MarshalJSON(genesisState)
require.NoError(t, err)
cfg.GenesisState["gov"] = bz
Expand Down
5 changes: 3 additions & 2 deletions x/gov/client/testutil/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (s *IntegrationTestSuite) TestCmdParams() {
{
"json output",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
`{"voting_params":{"voting_period":"172800000000000"},"tally_params":{"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000"},"deposit_params":{"min_deposit":[{"denom":"stake","amount":"10000000"}],"max_deposit_period":"172800000000000"}}`,
`{"voting_params":{"voting_period":"172800000000000","proposal_voting_periods":null},"tally_params":{"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000"},"deposit_params":{"min_deposit":[{"denom":"stake","amount":"10000000"}],"max_deposit_period":"172800000000000"}}`,
},
{
"text output",
Expand All @@ -104,6 +104,7 @@ tally_params:
threshold: "0.500000000000000000"
veto_threshold: "0.334000000000000000"
voting_params:
proposal_voting_periods: null
voting_period: "172800000000000"
`,
},
Expand Down Expand Up @@ -137,7 +138,7 @@ func (s *IntegrationTestSuite) TestCmdParam() {
"voting",
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
`{"voting_period":"172800000000000"}`,
`{"voting_period":"172800000000000","proposal_voting_periods":null}`,
},
{
"tally params",
Expand Down
2 changes: 1 addition & 1 deletion x/gov/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryParams() {
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().Equal(expRes.GetDepositParams(), params.GetDepositParams())
suite.Require().Equal(expRes.GetVotingParams(), params.GetVotingParams())
suite.Require().True(expRes.GetVotingParams().Equal(params.GetVotingParams()))
suite.Require().Equal(expRes.GetTallyParams(), params.GetTallyParams())
} else {
suite.Require().Error(err)
Expand Down
5 changes: 5 additions & 0 deletions x/gov/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ func (keeper Keeper) GetDepositParams(ctx sdk.Context) types.DepositParams {
func (keeper Keeper) GetVotingParams(ctx sdk.Context) types.VotingParams {
var votingParams types.VotingParams
keeper.paramSpace.Get(ctx, types.ParamStoreKeyVotingParams, &votingParams)

if votingParams.ProposalVotingPeriods == nil {
votingParams.ProposalVotingPeriods = []types.ProposalVotingPeriod{}
}

return votingParams
}

Expand Down
32 changes: 30 additions & 2 deletions x/gov/keeper/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package keeper

import (
"fmt"
"github.com/gogo/protobuf/proto"
"strings"
"time"

"github.com/cosmos/cosmos-sdk/client"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -183,17 +186,42 @@ func (keeper Keeper) SetProposalID(ctx sdk.Context, proposalID uint64) {
store.Set(types.ProposalIDKey, types.GetProposalIDBytes(proposalID))
}

// ActivateVotingPeriod moves the governance proposal from the deposit stage to
// the voting stage, given that enough deposits have been submitted. It is
// removed from the inactive proposal queue and moved into the active queue.
// Note, if the proposal's contents has a custom voting period registered, that
// voting period is used instead of the base voting period.
func (keeper Keeper) ActivateVotingPeriod(ctx sdk.Context, proposal types.Proposal) {
proposal.VotingStartTime = ctx.BlockHeader().Time
votingPeriod := keeper.GetVotingParams(ctx).VotingPeriod
proposal.VotingEndTime = proposal.VotingStartTime.Add(votingPeriod)
proposal.Status = types.StatusVotingPeriod

votingPeriod := keeper.GetVotingPeriod(ctx, proposal.GetContent())
proposal.VotingEndTime = proposal.VotingStartTime.Add(votingPeriod)

keeper.SetProposal(ctx, proposal)

keeper.RemoveFromInactiveProposalQueue(ctx, proposal.ProposalId, proposal.DepositEndTime)
keeper.InsertActiveProposalQueue(ctx, proposal.ProposalId, proposal.VotingEndTime)
}

// GetVotingPeriod returns the voting period for the given proposal Content. If
// the proposal type has a custom voting period registered, we return that.
// Otherwise, we use the default voting period.
func (keeper Keeper) GetVotingPeriod(ctx sdk.Context, content types.Content) time.Duration {
vpParams := keeper.GetVotingParams(ctx)

// Check if there exists a registered custom voting period for the proposal
// type.
for _, pvp := range vpParams.ProposalVotingPeriods {
contentProto, ok := content.(proto.Message)
if ok && strings.EqualFold(pvp.ProposalType, proto.MessageName(contentProto)) {
return pvp.VotingPeriod
}
}

return vpParams.VotingPeriod
}

func (keeper Keeper) MarshalProposal(proposal types.Proposal) ([]byte, error) {
bz, err := keeper.cdc.Marshal(&proposal)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions x/gov/legacy/v040/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ func TestMigrate(t *testing.T) {
},
"votes": [],
"voting_params": {
"proposal_voting_periods": [],
"voting_period": "0s"
}
}`
Expand Down
1 change: 1 addition & 0 deletions x/gov/legacy/v043/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func TestMigrateJSON(t *testing.T) {
}
],
"voting_params": {
"proposal_voting_periods": [],
"voting_period": "0s"
}
}`
Expand Down
17 changes: 16 additions & 1 deletion x/gov/simulation/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,25 @@ func RandomizedGenState(simState *module.SimulationState) {
func(r *rand.Rand) { veto = GenTallyParamsVeto(r) },
)

proposalVotingPeriods := []types.ProposalVotingPeriod{
{
ProposalType: "cosmos.params.v1beta1.ParameterChangeProposal",
},
}
for _, pvp := range proposalVotingPeriods {
var pvpDuration time.Duration
simState.AppParams.GetOrGenerate(
simState.Cdc, VotingParamsVotingPeriod, &pvpDuration, simState.Rand,
func(r *rand.Rand) { pvpDuration = GenVotingParamsVotingPeriod(r) },
)

pvp.VotingPeriod = pvpDuration
}

govGenesis := types.NewGenesisState(
startingProposalID,
types.NewDepositParams(minDeposit, depositPeriod),
types.NewVotingParams(votingPeriod),
types.NewVotingParams(votingPeriod, proposalVotingPeriods),
types.NewTallyParams(quorum, threshold, veto),
)

Expand Down
Loading