mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 15:25:18 +00:00
add mre fields to committee type
This commit is contained in:
parent
77553ed299
commit
57f4ca7c9a
@ -14,6 +14,8 @@ import (
|
||||
"github.com/kava-labs/kava/x/committee"
|
||||
)
|
||||
|
||||
func d(s string) sdk.Dec { return sdk.MustNewDecFromStr(s) }
|
||||
|
||||
type ModuleTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
@ -35,9 +37,11 @@ func (suite *ModuleTestSuite) TestBeginBlock() {
|
||||
suite.app.InitializeFromGenesisStates()
|
||||
// TODO replace below with genesis state
|
||||
normalCom := committee.Committee{
|
||||
ID: 12,
|
||||
Members: suite.addresses[:2],
|
||||
Permissions: []committee.Permission{committee.GodPermission{}},
|
||||
ID: 12,
|
||||
Members: suite.addresses[:2],
|
||||
Permissions: []committee.Permission{committee.GodPermission{}},
|
||||
VoteThreshold: d("0.8"),
|
||||
MaxProposalDuration: time.Hour * 24 * 7,
|
||||
}
|
||||
suite.keeper.SetCommittee(suite.ctx, normalCom)
|
||||
|
||||
@ -51,7 +55,7 @@ func (suite *ModuleTestSuite) TestBeginBlock() {
|
||||
suite.NoError(err)
|
||||
|
||||
// Run BeginBlocker
|
||||
proposalDurationLaterCtx := suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(committee.MaxProposalDuration))
|
||||
proposalDurationLaterCtx := suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(normalCom.MaxProposalDuration))
|
||||
suite.NotPanics(func() {
|
||||
committee.BeginBlocker(proposalDurationLaterCtx, abci.RequestBeginBlock{}, suite.keeper)
|
||||
})
|
||||
|
@ -14,6 +14,7 @@ const (
|
||||
DefaultNextProposalID = types.DefaultNextProposalID
|
||||
DefaultParamspace = types.DefaultParamspace
|
||||
EventTypeSubmitProposal = types.EventTypeSubmitProposal
|
||||
MaxDescriptionLength = types.MaxDescriptionLength
|
||||
ModuleName = types.ModuleName
|
||||
ProposalTypeCommitteeChange = types.ProposalTypeCommitteeChange
|
||||
ProposalTypeCommitteeDelete = types.ProposalTypeCommitteeDelete
|
||||
@ -53,14 +54,12 @@ var (
|
||||
Uint64FromBytes = types.Uint64FromBytes
|
||||
|
||||
// variable aliases
|
||||
ProposalHandler = client.ProposalHandler
|
||||
CommitteeKeyPrefix = types.CommitteeKeyPrefix
|
||||
MaxProposalDuration = types.MaxProposalDuration
|
||||
ModuleCdc = types.ModuleCdc
|
||||
NextProposalIDKey = types.NextProposalIDKey
|
||||
ProposalKeyPrefix = types.ProposalKeyPrefix
|
||||
VoteKeyPrefix = types.VoteKeyPrefix
|
||||
VoteThreshold = types.VoteThreshold
|
||||
ProposalHandler = client.ProposalHandler
|
||||
CommitteeKeyPrefix = types.CommitteeKeyPrefix
|
||||
ModuleCdc = types.ModuleCdc
|
||||
NextProposalIDKey = types.NextProposalIDKey
|
||||
ProposalKeyPrefix = types.ProposalKeyPrefix
|
||||
VoteKeyPrefix = types.VoteKeyPrefix
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@ -189,8 +190,15 @@ func mustGetExampleCommitteeChangeProposal(cdc *codec.Codec) string {
|
||||
"A description of this proposal.",
|
||||
types.NewCommittee(
|
||||
1,
|
||||
"The description of this committee.",
|
||||
[]sdk.AccAddress{sdk.AccAddress(crypto.AddressHash([]byte("exampleAddres")))},
|
||||
[]types.Permission{}, // TODO permissions
|
||||
[]types.Permission{
|
||||
types.ParamChangePermission{
|
||||
AllowedParams: types.AllowedParams{{Subspace: "cdp", Key: "CircuitBreaker"}},
|
||||
},
|
||||
},
|
||||
sdk.MustNewDecFromStr("0.8"),
|
||||
time.Hour*24*7,
|
||||
),
|
||||
)
|
||||
exampleChangeProposalBz, err := cdc.MarshalJSONIndent(exampleChangeProposal, "", " ")
|
||||
|
@ -2,10 +2,12 @@ package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
@ -13,6 +15,8 @@ import (
|
||||
"github.com/kava-labs/kava/x/committee/types"
|
||||
)
|
||||
|
||||
func d(s string) sdk.Dec { return sdk.MustNewDecFromStr(s) }
|
||||
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
@ -33,8 +37,12 @@ func (suite *KeeperTestSuite) SetupTest() {
|
||||
func (suite *KeeperTestSuite) TestGetSetDeleteCommittee() {
|
||||
// setup test
|
||||
com := types.Committee{
|
||||
ID: 12,
|
||||
// TODO other fields
|
||||
ID: 12,
|
||||
Description: "This committee is for testing.",
|
||||
Members: suite.addresses,
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
VoteThreshold: d("0.667"),
|
||||
MaxProposalDuration: time.Hour * 24 * 7,
|
||||
}
|
||||
|
||||
// write and read from store
|
||||
@ -56,8 +64,10 @@ func (suite *KeeperTestSuite) TestGetSetDeleteCommittee() {
|
||||
func (suite *KeeperTestSuite) TestGetSetProposal() {
|
||||
// test setup
|
||||
prop := types.Proposal{
|
||||
ID: 12,
|
||||
// TODO other fields
|
||||
ID: 12,
|
||||
CommitteeID: 0,
|
||||
PubProposal: gov.NewTextProposal("A Title", "A description of this proposal."),
|
||||
Deadline: time.Date(1998, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
}
|
||||
|
||||
// write and read from store
|
||||
@ -81,7 +91,6 @@ func (suite *KeeperTestSuite) TestGetSetVote() {
|
||||
vote := types.Vote{
|
||||
ProposalID: 12,
|
||||
Voter: suite.addresses[0],
|
||||
// TODO other fields
|
||||
}
|
||||
|
||||
// write and read from store
|
||||
|
@ -30,7 +30,7 @@ func (k Keeper) SubmitProposal(ctx sdk.Context, proposer sdk.AccAddress, committ
|
||||
}
|
||||
|
||||
// Get a new ID and store the proposal
|
||||
deadline := ctx.BlockTime().Add(types.MaxProposalDuration)
|
||||
deadline := ctx.BlockTime().Add(com.MaxProposalDuration)
|
||||
proposalID, err := k.StoreNewProposal(ctx, pubProposal, committeeID, deadline)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -82,7 +82,7 @@ func (k Keeper) GetProposalResult(ctx sdk.Context, proposalID uint64) (bool, sdk
|
||||
|
||||
numVotes := k.TallyVotes(ctx, proposalID)
|
||||
|
||||
proposalResult := sdk.NewDec(numVotes).GTE(types.VoteThreshold.MulInt64(int64(len(com.Members))))
|
||||
proposalResult := sdk.NewDec(numVotes).GTE(com.VoteThreshold.MulInt64(int64(len(com.Members))))
|
||||
|
||||
return proposalResult, nil
|
||||
}
|
||||
|
@ -16,15 +16,15 @@ import (
|
||||
|
||||
func (suite *KeeperTestSuite) TestSubmitProposal() {
|
||||
normalCom := types.Committee{
|
||||
ID: 12,
|
||||
Members: suite.addresses[:2],
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
}
|
||||
noPermissionsCom := types.Committee{
|
||||
ID: 12,
|
||||
Members: suite.addresses[:2],
|
||||
Permissions: []types.Permission{},
|
||||
ID: 12,
|
||||
Description: "This committee is for testing.",
|
||||
Members: suite.addresses[:2],
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
VoteThreshold: d("0.667"),
|
||||
MaxProposalDuration: time.Hour * 24 * 7,
|
||||
}
|
||||
noPermissionsCom := normalCom
|
||||
noPermissionsCom.Permissions = []types.Permission{}
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
@ -96,7 +96,7 @@ func (suite *KeeperTestSuite) TestSubmitProposal() {
|
||||
pr, found := keeper.GetProposal(ctx, id)
|
||||
suite.True(found)
|
||||
suite.Equal(tc.committeeID, pr.CommitteeID)
|
||||
suite.Equal(ctx.BlockTime().Add(types.MaxProposalDuration), pr.Deadline)
|
||||
suite.Equal(ctx.BlockTime().Add(tc.committee.MaxProposalDuration), pr.Deadline)
|
||||
} else {
|
||||
suite.NotNil(err)
|
||||
}
|
||||
@ -141,7 +141,7 @@ func (suite *KeeperTestSuite) TestAddVote() {
|
||||
name: "proposal expired",
|
||||
proposalID: types.DefaultNextProposalID,
|
||||
voter: normalCom.Members[0],
|
||||
voteTime: firstBlockTime.Add(types.MaxProposalDuration),
|
||||
voteTime: firstBlockTime.Add(normalCom.MaxProposalDuration),
|
||||
expectPass: false,
|
||||
},
|
||||
}
|
||||
@ -174,6 +174,14 @@ func (suite *KeeperTestSuite) TestAddVote() {
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGetProposalResult() {
|
||||
normalCom := types.Committee{
|
||||
ID: 12,
|
||||
Description: "This committee is for testing.",
|
||||
Members: suite.addresses[:5],
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
VoteThreshold: d("0.667"),
|
||||
MaxProposalDuration: time.Hour * 24 * 7,
|
||||
}
|
||||
var defaultID uint64 = 1
|
||||
firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC)
|
||||
|
||||
@ -185,12 +193,8 @@ func (suite *KeeperTestSuite) TestGetProposalResult() {
|
||||
expectPass bool
|
||||
}{
|
||||
{
|
||||
name: "enough votes",
|
||||
committee: types.Committee{
|
||||
ID: 12,
|
||||
Members: suite.addresses[:5],
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
},
|
||||
name: "enough votes",
|
||||
committee: normalCom,
|
||||
votes: []types.Vote{
|
||||
{ProposalID: defaultID, Voter: suite.addresses[0]},
|
||||
{ProposalID: defaultID, Voter: suite.addresses[1]},
|
||||
@ -201,12 +205,8 @@ func (suite *KeeperTestSuite) TestGetProposalResult() {
|
||||
expectPass: true,
|
||||
},
|
||||
{
|
||||
name: "not enough votes",
|
||||
committee: types.Committee{
|
||||
ID: 12,
|
||||
Members: suite.addresses[:5],
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
},
|
||||
name: "not enough votes",
|
||||
committee: normalCom,
|
||||
votes: []types.Vote{
|
||||
{ProposalID: defaultID, Voter: suite.addresses[0]},
|
||||
},
|
||||
|
@ -3,6 +3,7 @@ package keeper_test
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
@ -12,6 +13,7 @@ import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
"github.com/kava-labs/kava/x/committee"
|
||||
"github.com/kava-labs/kava/x/committee/keeper"
|
||||
"github.com/kava-labs/kava/x/committee/types"
|
||||
)
|
||||
@ -20,6 +22,12 @@ const (
|
||||
custom = "custom"
|
||||
)
|
||||
|
||||
var testTime time.Time = time.Date(1998, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
func NewCommitteeGenesisState(cdc *codec.Codec, gs committee.GenesisState) app.GenesisState {
|
||||
return app.GenesisState{committee.ModuleName: cdc.MustMarshalJSON(gs)}
|
||||
}
|
||||
|
||||
type QuerierTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
@ -30,10 +38,9 @@ type QuerierTestSuite struct {
|
||||
|
||||
querier sdk.Querier
|
||||
|
||||
addresses []sdk.AccAddress
|
||||
committees []types.Committee
|
||||
proposals []types.Proposal
|
||||
votes map[uint64]([]types.Vote)
|
||||
addresses []sdk.AccAddress
|
||||
testGenesis types.GenesisState
|
||||
votes map[uint64]([]types.Vote)
|
||||
}
|
||||
|
||||
func (suite *QuerierTestSuite) SetupTest() {
|
||||
@ -44,37 +51,40 @@ func (suite *QuerierTestSuite) SetupTest() {
|
||||
suite.querier = keeper.NewQuerier(suite.keeper)
|
||||
|
||||
_, suite.addresses = app.GeneratePrivKeyAddressPairs(5)
|
||||
suite.app.InitializeFromGenesisStates()
|
||||
// TODO replace below with genesis state
|
||||
normalCom := types.Committee{
|
||||
ID: 12,
|
||||
Members: suite.addresses[:2],
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
}
|
||||
suite.keeper.SetCommittee(suite.ctx, normalCom)
|
||||
suite.testGenesis = types.NewGenesisState(
|
||||
3,
|
||||
[]types.Committee{
|
||||
{
|
||||
ID: 1,
|
||||
Description: "This committee is for testing.",
|
||||
Members: suite.addresses[:3],
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
VoteThreshold: d("0.667"),
|
||||
MaxProposalDuration: time.Hour * 24 * 7,
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Members: suite.addresses[2:],
|
||||
Permissions: nil,
|
||||
VoteThreshold: d("0.667"),
|
||||
MaxProposalDuration: time.Hour * 24 * 7,
|
||||
},
|
||||
},
|
||||
[]types.Proposal{
|
||||
{ID: 1, CommitteeID: 1, PubProposal: gov.NewTextProposal("A Title", "A description of this proposal."), Deadline: testTime.Add(7 * 24 * time.Hour)},
|
||||
{ID: 2, CommitteeID: 1, PubProposal: gov.NewTextProposal("Another Title", "A description of this other proposal."), Deadline: testTime.Add(21 * 24 * time.Hour)},
|
||||
},
|
||||
[]types.Vote{
|
||||
{ProposalID: 1, Voter: suite.addresses[0]},
|
||||
{ProposalID: 1, Voter: suite.addresses[1]},
|
||||
{ProposalID: 2, Voter: suite.addresses[2]},
|
||||
},
|
||||
)
|
||||
suite.app.InitializeFromGenesisStates(
|
||||
NewCommitteeGenesisState(suite.cdc, suite.testGenesis),
|
||||
)
|
||||
|
||||
pprop1 := gov.NewTextProposal("1A Title", "A description of this proposal.")
|
||||
id1, err := suite.keeper.SubmitProposal(suite.ctx, normalCom.Members[0], normalCom.ID, pprop1)
|
||||
suite.NoError(err)
|
||||
|
||||
pprop2 := gov.NewTextProposal("2A Title", "A description of this proposal.")
|
||||
id2, err := suite.keeper.SubmitProposal(suite.ctx, normalCom.Members[0], normalCom.ID, pprop2)
|
||||
suite.NoError(err)
|
||||
|
||||
err = suite.keeper.AddVote(suite.ctx, id1, normalCom.Members[0])
|
||||
suite.NoError(err)
|
||||
err = suite.keeper.AddVote(suite.ctx, id1, normalCom.Members[1])
|
||||
suite.NoError(err)
|
||||
err = suite.keeper.AddVote(suite.ctx, id2, normalCom.Members[1])
|
||||
suite.NoError(err)
|
||||
|
||||
suite.committees = []types.Committee{}
|
||||
suite.committees = []types.Committee{normalCom} // TODO
|
||||
suite.proposals = []types.Proposal{}
|
||||
suite.keeper.IterateProposals(suite.ctx, func(p types.Proposal) bool {
|
||||
suite.proposals = append(suite.proposals, p)
|
||||
return false
|
||||
})
|
||||
// Collect up votes into a map indexed by proposalID for convenience
|
||||
suite.votes = map[uint64]([]types.Vote){}
|
||||
suite.keeper.IterateProposals(suite.ctx, func(p types.Proposal) bool {
|
||||
suite.keeper.IterateVotes(suite.ctx, p.ID, func(v types.Vote) bool {
|
||||
@ -102,7 +112,7 @@ func (suite *QuerierTestSuite) TestQueryCommittees() {
|
||||
suite.NoError(suite.cdc.UnmarshalJSON(bz, &committees))
|
||||
|
||||
// Check
|
||||
suite.Equal(suite.committees, committees)
|
||||
suite.Equal(suite.testGenesis.Committees, committees)
|
||||
}
|
||||
|
||||
func (suite *QuerierTestSuite) TestQueryCommittee() {
|
||||
@ -110,7 +120,7 @@ func (suite *QuerierTestSuite) TestQueryCommittee() {
|
||||
// Set up request query
|
||||
query := abci.RequestQuery{
|
||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryCommittee}, "/"),
|
||||
Data: suite.cdc.MustMarshalJSON(types.NewQueryCommitteeParams(suite.committees[0].ID)),
|
||||
Data: suite.cdc.MustMarshalJSON(types.NewQueryCommitteeParams(suite.testGenesis.Committees[0].ID)),
|
||||
}
|
||||
|
||||
// Execute query and check the []byte result
|
||||
@ -123,13 +133,13 @@ func (suite *QuerierTestSuite) TestQueryCommittee() {
|
||||
suite.NoError(suite.cdc.UnmarshalJSON(bz, &committee))
|
||||
|
||||
// Check
|
||||
suite.Equal(suite.committees[0], committee)
|
||||
suite.Equal(suite.testGenesis.Committees[0], committee)
|
||||
}
|
||||
|
||||
func (suite *QuerierTestSuite) TestQueryProposals() {
|
||||
ctx := suite.ctx.WithIsCheckTx(false)
|
||||
// Set up request query
|
||||
comID := suite.proposals[0].CommitteeID
|
||||
comID := suite.testGenesis.Proposals[0].CommitteeID
|
||||
query := abci.RequestQuery{
|
||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryProposals}, "/"),
|
||||
Data: suite.cdc.MustMarshalJSON(types.NewQueryCommitteeParams(comID)),
|
||||
@ -146,7 +156,7 @@ func (suite *QuerierTestSuite) TestQueryProposals() {
|
||||
|
||||
// Check
|
||||
expectedProposals := []types.Proposal{}
|
||||
for _, p := range suite.proposals {
|
||||
for _, p := range suite.testGenesis.Proposals {
|
||||
if p.CommitteeID == comID {
|
||||
expectedProposals = append(expectedProposals, p)
|
||||
}
|
||||
@ -159,7 +169,7 @@ func (suite *QuerierTestSuite) TestQueryProposal() {
|
||||
// Set up request query
|
||||
query := abci.RequestQuery{
|
||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryProposal}, "/"),
|
||||
Data: suite.cdc.MustMarshalJSON(types.NewQueryProposalParams(suite.proposals[0].ID)),
|
||||
Data: suite.cdc.MustMarshalJSON(types.NewQueryProposalParams(suite.testGenesis.Proposals[0].ID)),
|
||||
}
|
||||
|
||||
// Execute query and check the []byte result
|
||||
@ -172,13 +182,13 @@ func (suite *QuerierTestSuite) TestQueryProposal() {
|
||||
suite.NoError(suite.cdc.UnmarshalJSON(bz, &proposal))
|
||||
|
||||
// Check
|
||||
suite.Equal(suite.proposals[0], proposal)
|
||||
suite.Equal(suite.testGenesis.Proposals[0], proposal)
|
||||
}
|
||||
|
||||
func (suite *QuerierTestSuite) TestQueryVotes() {
|
||||
ctx := suite.ctx.WithIsCheckTx(false)
|
||||
// Set up request query
|
||||
propID := suite.proposals[0].ID
|
||||
propID := suite.testGenesis.Proposals[0].ID
|
||||
query := abci.RequestQuery{
|
||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryVotes}, "/"),
|
||||
Data: suite.cdc.MustMarshalJSON(types.NewQueryProposalParams(propID)),
|
||||
@ -200,7 +210,7 @@ func (suite *QuerierTestSuite) TestQueryVotes() {
|
||||
func (suite *QuerierTestSuite) TestQueryVote() {
|
||||
ctx := suite.ctx.WithIsCheckTx(false) // ?
|
||||
// Set up request query
|
||||
propID := suite.proposals[0].ID
|
||||
propID := suite.testGenesis.Proposals[0].ID
|
||||
query := abci.RequestQuery{
|
||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryVote}, "/"),
|
||||
Data: suite.cdc.MustMarshalJSON(types.NewQueryVoteParams(propID, suite.votes[propID][0].Voter)),
|
||||
@ -222,7 +232,7 @@ func (suite *QuerierTestSuite) TestQueryVote() {
|
||||
func (suite *QuerierTestSuite) TestQueryTally() {
|
||||
ctx := suite.ctx.WithIsCheckTx(false) // ?
|
||||
// Set up request query
|
||||
propID := suite.proposals[0].ID
|
||||
propID := suite.testGenesis.Proposals[0].ID
|
||||
query := abci.RequestQuery{
|
||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryTally}, "/"),
|
||||
Data: suite.cdc.MustMarshalJSON(types.NewQueryProposalParams(propID)),
|
||||
|
@ -38,14 +38,19 @@ func (suite *ProposalHandlerTestSuite) SetupTest() {
|
||||
2,
|
||||
[]committee.Committee{
|
||||
{
|
||||
ID: 1,
|
||||
Members: suite.addresses[:3],
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
ID: 1,
|
||||
Description: "This committee is for testing.",
|
||||
Members: suite.addresses[:3],
|
||||
Permissions: []types.Permission{types.GodPermission{}},
|
||||
VoteThreshold: d("0.667"),
|
||||
MaxProposalDuration: time.Hour * 24 * 7,
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Members: suite.addresses[2:],
|
||||
Permissions: nil,
|
||||
ID: 2,
|
||||
Members: suite.addresses[2:],
|
||||
Permissions: nil,
|
||||
VoteThreshold: d("0.667"),
|
||||
MaxProposalDuration: time.Hour * 24 * 7,
|
||||
},
|
||||
},
|
||||
[]committee.Proposal{
|
||||
@ -69,8 +74,10 @@ func (suite *ProposalHandlerTestSuite) TestProposalHandler_ChangeCommittee() {
|
||||
"A Title",
|
||||
"A proposal description.",
|
||||
committee.Committee{
|
||||
ID: 34,
|
||||
Members: suite.addresses[:1],
|
||||
ID: 34,
|
||||
Members: suite.addresses[:1],
|
||||
VoteThreshold: d("1"),
|
||||
MaxProposalDuration: time.Hour * 24,
|
||||
},
|
||||
),
|
||||
expectPass: true,
|
||||
@ -81,9 +88,11 @@ func (suite *ProposalHandlerTestSuite) TestProposalHandler_ChangeCommittee() {
|
||||
"A Title",
|
||||
"A proposal description.",
|
||||
committee.Committee{
|
||||
ID: 1,
|
||||
Members: suite.addresses,
|
||||
Permissions: suite.testGenesis.Committees[0].Permissions,
|
||||
ID: suite.testGenesis.Committees[0].ID,
|
||||
Members: suite.addresses, // add new members
|
||||
Permissions: suite.testGenesis.Committees[0].Permissions,
|
||||
VoteThreshold: suite.testGenesis.Committees[0].VoteThreshold,
|
||||
MaxProposalDuration: suite.testGenesis.Committees[0].MaxProposalDuration,
|
||||
},
|
||||
),
|
||||
expectPass: true,
|
||||
@ -93,9 +102,7 @@ func (suite *ProposalHandlerTestSuite) TestProposalHandler_ChangeCommittee() {
|
||||
proposal: committee.NewCommitteeChangeProposal(
|
||||
"A Title That Is Much Too Long And Really Quite Unreasonable Given That It Is Trying To Fullfill The Roll Of An Acceptable Governance Proposal Title That Should Succinctly Communicate The Goal And Contents Of The Proposed Proposal To All Parties Involved",
|
||||
"A proposal description.",
|
||||
committee.Committee{
|
||||
ID: 34,
|
||||
},
|
||||
suite.testGenesis.Committees[0],
|
||||
),
|
||||
expectPass: false,
|
||||
},
|
||||
@ -105,9 +112,11 @@ func (suite *ProposalHandlerTestSuite) TestProposalHandler_ChangeCommittee() {
|
||||
"A Title",
|
||||
"A proposal description.",
|
||||
committee.Committee{
|
||||
ID: 1,
|
||||
Members: append(suite.addresses, suite.addresses[0]), // duplicate address
|
||||
Permissions: suite.testGenesis.Committees[0].Permissions,
|
||||
ID: suite.testGenesis.Committees[0].ID,
|
||||
Members: append(suite.addresses, suite.addresses[0]), // duplicate address
|
||||
Permissions: suite.testGenesis.Committees[0].Permissions,
|
||||
VoteThreshold: suite.testGenesis.Committees[0].VoteThreshold,
|
||||
MaxProposalDuration: suite.testGenesis.Committees[0].MaxProposalDuration,
|
||||
},
|
||||
),
|
||||
expectPass: false,
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
)
|
||||
|
||||
func d(s string) sdk.Dec { return sdk.MustNewDecFromStr(s) }
|
||||
func TestGenesisState_Validate(t *testing.T) {
|
||||
testTime := time.Date(1998, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||
addresses := []sdk.AccAddress{
|
||||
@ -24,14 +25,20 @@ func TestGenesisState_Validate(t *testing.T) {
|
||||
NextProposalID: 2,
|
||||
Committees: []Committee{
|
||||
{
|
||||
ID: 1,
|
||||
Members: addresses[:3],
|
||||
Permissions: []Permission{GodPermission{}},
|
||||
ID: 1,
|
||||
Description: "This committee is for testing.",
|
||||
Members: addresses[:3],
|
||||
Permissions: []Permission{GodPermission{}},
|
||||
VoteThreshold: d("0.667"),
|
||||
MaxProposalDuration: time.Hour * 24 * 7,
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Members: addresses[2:],
|
||||
Permissions: nil,
|
||||
ID: 2,
|
||||
Description: "This committee is also for testing.",
|
||||
Members: addresses[2:],
|
||||
Permissions: nil,
|
||||
VoteThreshold: d("0.8"),
|
||||
MaxProposalDuration: time.Hour * 24 * 21,
|
||||
},
|
||||
},
|
||||
Proposals: []Proposal{
|
||||
|
@ -16,6 +16,7 @@ func init() {
|
||||
}
|
||||
|
||||
// GodPermission allows any governance proposal. It is used mainly for testing.
|
||||
// TODO better name?
|
||||
type GodPermission struct{}
|
||||
|
||||
var _ Permission = GodPermission{}
|
||||
|
@ -9,29 +9,28 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
)
|
||||
|
||||
// TODO move these into params
|
||||
var (
|
||||
VoteThreshold sdk.Dec = sdk.MustNewDecFromStr("0.75")
|
||||
MaxProposalDuration time.Duration = time.Hour * 24 * 7
|
||||
)
|
||||
const MaxCommitteeDescriptionLength int = 5000
|
||||
|
||||
// -------- Committees --------
|
||||
|
||||
// A Committee is a collection of addresses that are allowed to vote and enact any governance proposal that passes their permissions.
|
||||
type Committee struct {
|
||||
ID uint64 `json:"id" yaml:"id"`
|
||||
//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"`
|
||||
// MaxProposalDuration time.Duration `json:"max_proposal_duration" yaml:"max_proposal_duration"`
|
||||
ID uint64 `json:"id" yaml:"id"`
|
||||
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"`
|
||||
MaxProposalDuration time.Duration `json:"max_proposal_duration" yaml:"max_proposal_duration"`
|
||||
}
|
||||
|
||||
func NewCommittee(id uint64, members []sdk.AccAddress, permissions []Permission) Committee {
|
||||
func NewCommittee(id uint64, description string, members []sdk.AccAddress, permissions []Permission, threshold sdk.Dec, duration time.Duration) Committee {
|
||||
return Committee{
|
||||
ID: id,
|
||||
Members: members,
|
||||
Permissions: permissions,
|
||||
ID: id,
|
||||
Description: description,
|
||||
Members: members,
|
||||
Permissions: permissions,
|
||||
VoteThreshold: threshold,
|
||||
MaxProposalDuration: duration,
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,6 +73,19 @@ func (c Committee) Validate() error {
|
||||
if len(c.Members) == 0 {
|
||||
return fmt.Errorf("committee %d invalid: cannot have zero members", c.ID)
|
||||
}
|
||||
|
||||
if len(c.Description) > MaxCommitteeDescriptionLength {
|
||||
return fmt.Errorf("invalid description")
|
||||
}
|
||||
|
||||
if c.VoteThreshold.IsNil() || c.VoteThreshold.IsNegative() || c.VoteThreshold.GT(sdk.NewDec(1)) {
|
||||
return fmt.Errorf("invalid threshold")
|
||||
}
|
||||
|
||||
if c.MaxProposalDuration < 0 {
|
||||
return fmt.Errorf("invalid time")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -118,5 +130,4 @@ func (p Proposal) String() string {
|
||||
type Vote struct {
|
||||
ProposalID uint64 `json:"proposal_id" yaml:"proposal_id"`
|
||||
Voter sdk.AccAddress `json:"voter" yaml:"voter"`
|
||||
// Option byte // TODO for now don't need more than just a yes as options
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user