diff --git a/x/committee/keeper/proposal.go b/x/committee/keeper/proposal.go index b36f4470..f2db48c5 100644 --- a/x/committee/keeper/proposal.go +++ b/x/committee/keeper/proposal.go @@ -78,7 +78,6 @@ func (k Keeper) AddVote(ctx sdk.Context, proposalID uint64, voter sdk.AccAddress } // GetProposalResult calculates if a proposal currently has enough votes to pass. -// TODO rename GetProposalTally? func (k Keeper) GetProposalResult(ctx sdk.Context, proposalID uint64) (bool, sdk.Error) { pr, found := k.GetProposal(ctx, proposalID) if !found { @@ -123,23 +122,23 @@ func (k Keeper) EnactProposal(ctx sdk.Context, proposalID uint64) sdk.Error { } // CloseExpiredProposals removes proposals (and associated votes) that have past their deadline. -// TODO rename to RemoveExpiredProposals? func (k Keeper) CloseExpiredProposals(ctx sdk.Context) { k.IterateProposals(ctx, func(proposal types.Proposal) bool { - if proposal.HasExpiredBy(ctx.BlockTime()) { - - k.DeleteProposalAndVotes(ctx, proposal.ID) - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeProposalClose, - sdk.NewAttribute(types.AttributeKeyCommitteeID, fmt.Sprintf("%d", proposal.CommitteeID)), - sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.ID)), - sdk.NewAttribute(types.AttributeKeyProposalCloseStatus, types.AttributeValueProposalTimeout), - ), - ) + if !proposal.HasExpiredBy(ctx.BlockTime()) { + return false } + + k.DeleteProposalAndVotes(ctx, proposal.ID) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeProposalClose, + sdk.NewAttribute(types.AttributeKeyCommitteeID, fmt.Sprintf("%d", proposal.CommitteeID)), + sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.ID)), + sdk.NewAttribute(types.AttributeKeyProposalCloseStatus, types.AttributeValueProposalTimeout), + ), + ) return false }) } diff --git a/x/committee/proposal_handler.go b/x/committee/proposal_handler.go index 749434bd..da5a049e 100644 --- a/x/committee/proposal_handler.go +++ b/x/committee/proposal_handler.go @@ -29,9 +29,10 @@ func handleCommitteeChangeProposal(ctx sdk.Context, k Keeper, committeeProposal // Remove all committee's ongoing proposals k.IterateProposals(ctx, func(p Proposal) bool { - if p.CommitteeID == committeeProposal.NewCommittee.ID { - k.DeleteProposalAndVotes(ctx, p.ID) + if p.CommitteeID != committeeProposal.NewCommittee.ID { + return false } + k.DeleteProposalAndVotes(ctx, p.ID) return false }) @@ -47,9 +48,10 @@ func handleCommitteeDeleteProposal(ctx sdk.Context, k Keeper, committeeProposal // Remove all committee's ongoing proposals k.IterateProposals(ctx, func(p Proposal) bool { - if p.CommitteeID == committeeProposal.CommitteeID { - k.DeleteProposalAndVotes(ctx, p.ID) + if p.CommitteeID != committeeProposal.CommitteeID { + return false } + k.DeleteProposalAndVotes(ctx, p.ID) return false }) diff --git a/x/committee/types/committee.go b/x/committee/types/committee.go index 4f705a22..fb22a196 100644 --- a/x/committee/types/committee.go +++ b/x/committee/types/committee.go @@ -21,8 +21,8 @@ type Committee struct { Description string `json:"description" yaml:"description"` Members []sdk.AccAddress `json:"members" yaml:"members"` Permissions []Permission `json:"permissions" yaml:"permissions"` - VoteThreshold sdk.Dec `json:"vote_threshold" yaml:"vote_threshold"` - ProposalDuration time.Duration `json:"proposal_duration" yaml:"proposal_duration"` + VoteThreshold sdk.Dec `json:"vote_threshold" yaml:"vote_threshold"` // Smallest percentage of members that must vote for a proposal to pass. + ProposalDuration time.Duration `json:"proposal_duration" yaml:"proposal_duration"` // The length of time a proposal remains active for. Proposals will close earlier if they get enough votes. } func NewCommittee(id uint64, description string, members []sdk.AccAddress, permissions []Permission, threshold sdk.Dec, duration time.Duration) Committee { @@ -80,22 +80,18 @@ func (c Committee) Validate() error { return fmt.Errorf("invalid description") } - if c.VoteThreshold.IsNil() || c.VoteThreshold.IsNegative() || c.VoteThreshold.GT(sdk.NewDec(1)) { + // threshold must be in the range (0,1] + if c.VoteThreshold.IsNil() || c.VoteThreshold.LTE(sdk.ZeroDec()) || c.VoteThreshold.GT(sdk.NewDec(1)) { return fmt.Errorf("invalid threshold") } if c.ProposalDuration < 0 { - return fmt.Errorf("invalid time") + return fmt.Errorf("invalid proposal duration") } return nil } -// Permission is anything with a method that validates whether a proposal is allowed by it or not. -type Permission interface { - Allows(PubProposal) bool -} - // ------------------------------------------ // Proposals // ------------------------------------------ diff --git a/x/committee/types/permissions.go b/x/committee/types/permissions.go index 77a66aa2..6608d9bd 100644 --- a/x/committee/types/permissions.go +++ b/x/committee/types/permissions.go @@ -13,6 +13,15 @@ func init() { gov.RegisterProposalTypeCodec(ParamChangePermission{}, "kava/ParamChangePermission") } +// Permission is anything with a method that validates whether a proposal is allowed by it or not. +type Permission interface { + Allows(PubProposal) bool +} + +// ------------------------------------------ +// GodPermission +// ------------------------------------------ + // GodPermission allows any governance proposal. It is used mainly for testing. type GodPermission struct{} @@ -29,6 +38,10 @@ func (GodPermission) MarshalYAML() (interface{}, error) { return valueToMarshal, nil } +// ------------------------------------------ +// ParamChangePermission +// ------------------------------------------ + // ParamChangeProposal only allows changes to certain params type ParamChangePermission struct { AllowedParams AllowedParams `json:"allowed_params" yaml:"allowed_params"` @@ -76,6 +89,10 @@ func (allowed AllowedParams) Contains(paramChange params.ParamChange) bool { return false } +// ------------------------------------------ +// TextPermission +// ------------------------------------------ + // TextPermission allows any text governance proposal. type TextPermission struct{}