mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-27 00:35:18 +00:00
23a5c7b969
* first pass at genesis and msgs * add proposal generation * add permission generation * add decoder * add invariants * add committee change proposal generator * improve committee change proposal generation * fix error formatting * update sims to v0.38 * Update x/committee/keeper/invariants.go Co-Authored-By: Denali Marsh <denali@kava.io> * Update x/committee/keeper/invariants.go Co-Authored-By: Denali Marsh <denali@kava.io> * tidy up comments * tidy up random helpers * add committee to ImportExport test * add member check to vote invariant * fix comment wording Co-authored-by: Kevin Davis <karzak@users.noreply.github.com> Co-authored-by: Denali Marsh <denali@kava.io> Co-authored-by: Kevin Davis <karzak@users.noreply.github.com>
146 lines
3.8 KiB
Go
146 lines
3.8 KiB
Go
package keeper
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
"github.com/kava-labs/kava/x/committee/types"
|
|
)
|
|
|
|
// RegisterInvariants registers all committee invariants
|
|
func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) {
|
|
|
|
ir.RegisterRoute(types.ModuleName, "valid-committees",
|
|
ValidCommitteesInvariant(k))
|
|
ir.RegisterRoute(types.ModuleName, "valid-proposals",
|
|
ValidProposalsInvariant(k))
|
|
ir.RegisterRoute(types.ModuleName, "valid-votes",
|
|
ValidVotesInvariant(k))
|
|
}
|
|
|
|
// ValidCommitteesInvariant verifies that all committees in the store are independently valid
|
|
func ValidCommitteesInvariant(k Keeper) sdk.Invariant {
|
|
return func(ctx sdk.Context) (string, bool) {
|
|
|
|
var validationErr error
|
|
var invalidCommittee types.Committee
|
|
k.IterateCommittees(ctx, func(com types.Committee) bool {
|
|
|
|
if err := com.Validate(); err != nil {
|
|
validationErr = err
|
|
invalidCommittee = com
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
|
|
broken := validationErr != nil
|
|
invariantMessage := sdk.FormatInvariant(
|
|
types.ModuleName,
|
|
"valid committees",
|
|
fmt.Sprintf(
|
|
"\tfound invalid committee, reason: %s\n"+
|
|
"\tcommittee:\n\t%+v\n",
|
|
validationErr, invalidCommittee),
|
|
)
|
|
return invariantMessage, broken
|
|
}
|
|
}
|
|
|
|
// ValidProposalsInvariant verifies that all proposals in the store are valid
|
|
func ValidProposalsInvariant(k Keeper) sdk.Invariant {
|
|
return func(ctx sdk.Context) (string, bool) {
|
|
|
|
var validationErr error
|
|
var invalidProposal types.Proposal
|
|
k.IterateProposals(ctx, func(proposal types.Proposal) bool {
|
|
invalidProposal = proposal
|
|
|
|
if err := proposal.PubProposal.ValidateBasic(); err != nil {
|
|
validationErr = err
|
|
return true
|
|
}
|
|
|
|
currentTime := ctx.BlockTime()
|
|
if !currentTime.Equal(time.Time{}) { // this avoids a simulator bug where app.InitGenesis is called with blockTime=0 instead of the correct time
|
|
if proposal.Deadline.Before(currentTime) {
|
|
validationErr = fmt.Errorf("deadline after current block time %s", currentTime)
|
|
return true
|
|
}
|
|
}
|
|
|
|
com, found := k.GetCommittee(ctx, proposal.CommitteeID)
|
|
if !found {
|
|
validationErr = fmt.Errorf("proposal has no committee %d", proposal.CommitteeID)
|
|
return true
|
|
}
|
|
|
|
if !com.HasPermissionsFor(proposal.PubProposal) {
|
|
validationErr = fmt.Errorf("proposal not permitted for committee %+v", com)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
})
|
|
|
|
broken := validationErr != nil
|
|
invariantMessage := sdk.FormatInvariant(
|
|
types.ModuleName,
|
|
"valid proposals",
|
|
fmt.Sprintf(
|
|
"\tfound invalid proposal, reason: %s\n"+
|
|
"\tproposal:\n\t%s\n",
|
|
validationErr, invalidProposal),
|
|
)
|
|
return invariantMessage, broken
|
|
}
|
|
}
|
|
|
|
// ValidVotesInvariant verifies that all votes in the store are valid
|
|
func ValidVotesInvariant(k Keeper) sdk.Invariant {
|
|
return func(ctx sdk.Context) (string, bool) {
|
|
|
|
var validationErr error
|
|
var invalidVote types.Vote
|
|
k.IterateVotes(ctx, func(vote types.Vote) bool {
|
|
invalidVote = vote
|
|
|
|
if vote.Voter.Empty() {
|
|
validationErr = fmt.Errorf("empty voter address")
|
|
return true
|
|
}
|
|
|
|
proposal, found := k.GetProposal(ctx, vote.ProposalID)
|
|
if !found {
|
|
validationErr = fmt.Errorf("vote has no proposal %d", vote.ProposalID)
|
|
return true
|
|
}
|
|
|
|
com, found := k.GetCommittee(ctx, proposal.CommitteeID)
|
|
if !found {
|
|
validationErr = fmt.Errorf("vote's proposal has no committee %d", proposal.CommitteeID)
|
|
return true
|
|
}
|
|
if !com.HasMember(vote.Voter) {
|
|
validationErr = fmt.Errorf("voter is not a member of committee %+v", com)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
})
|
|
|
|
broken := validationErr != nil
|
|
invariantMessage := sdk.FormatInvariant(
|
|
types.ModuleName,
|
|
"valid votes",
|
|
fmt.Sprintf(
|
|
"\tfound invalid vote, reason: %s\n"+
|
|
"\tvote:\n\t%+v\n",
|
|
validationErr, invalidVote),
|
|
)
|
|
return invariantMessage, broken
|
|
}
|
|
}
|