mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 08:15:19 +00:00
add genesis init/export/validation
This commit is contained in:
parent
62da823314
commit
18dfcd2a3d
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/kava-labs/kava/x/committee/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitGenesis initializes the store state from a genesis state.
|
// InitGenesis initializes the store state from a genesis state.
|
||||||
@ -14,11 +15,44 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, gs GenesisState) {
|
|||||||
|
|
||||||
keeper.SetNextProposalID(ctx, gs.NextProposalID)
|
keeper.SetNextProposalID(ctx, gs.NextProposalID)
|
||||||
|
|
||||||
// TODO set votes, committee, proposals
|
for _, com := range gs.Committees {
|
||||||
|
keeper.SetCommittee(ctx, com)
|
||||||
|
}
|
||||||
|
for _, p := range gs.Proposals {
|
||||||
|
keeper.SetProposal(ctx, p)
|
||||||
|
}
|
||||||
|
for _, v := range gs.Votes {
|
||||||
|
keeper.SetVote(ctx, v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportGenesis returns a GenesisState for a given context and keeper.
|
// ExportGenesis returns a GenesisState for a given context and keeper.
|
||||||
func ExportGenesis(ctx sdk.Context, keeper Keeper) GenesisState {
|
func ExportGenesis(ctx sdk.Context, keeper Keeper) GenesisState {
|
||||||
// TODO
|
|
||||||
return GenesisState{}
|
nextID, err := keeper.GetNextProposalID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
committees := []types.Committee{}
|
||||||
|
keeper.IterateCommittees(ctx, func(com types.Committee) bool {
|
||||||
|
committees = append(committees, com)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
proposals := []types.Proposal{}
|
||||||
|
votes := []types.Vote{}
|
||||||
|
keeper.IterateProposals(ctx, func(p types.Proposal) bool {
|
||||||
|
proposals = append(proposals, p)
|
||||||
|
keeper.IterateVotes(ctx, p.ID, func(v types.Vote) bool {
|
||||||
|
votes = append(votes, v)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
return types.NewGenesisState(
|
||||||
|
nextID,
|
||||||
|
committees,
|
||||||
|
proposals,
|
||||||
|
votes,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
75
x/committee/genesis_test.go
Normal file
75
x/committee/genesis_test.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package committee_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
|
"github.com/kava-labs/kava/app"
|
||||||
|
"github.com/kava-labs/kava/x/committee"
|
||||||
|
"github.com/kava-labs/kava/x/committee/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GenesisTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
|
||||||
|
app app.TestApp
|
||||||
|
ctx sdk.Context
|
||||||
|
keeper committee.Keeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *GenesisTestSuite) TestGenesis() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
genState types.GenesisState
|
||||||
|
expectPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "normal",
|
||||||
|
genState: types.DefaultGenesisState(),
|
||||||
|
expectPass: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid",
|
||||||
|
genState: types.NewGenesisState(
|
||||||
|
2,
|
||||||
|
[]types.Committee{},
|
||||||
|
[]types.Proposal{{ID: 1, CommitteeID: 57}},
|
||||||
|
[]types.Vote{},
|
||||||
|
),
|
||||||
|
expectPass: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
// Setup (note: suite.SetupTest is not run before every suite.Run)
|
||||||
|
suite.app = app.NewTestApp()
|
||||||
|
suite.keeper = suite.app.GetCommitteeKeeper()
|
||||||
|
suite.ctx = suite.app.NewContext(true, abci.Header{})
|
||||||
|
|
||||||
|
// Run
|
||||||
|
var exportedGenState types.GenesisState
|
||||||
|
run := func() {
|
||||||
|
committee.InitGenesis(suite.ctx, suite.keeper, tc.genState)
|
||||||
|
exportedGenState = committee.ExportGenesis(suite.ctx, suite.keeper)
|
||||||
|
}
|
||||||
|
if tc.expectPass {
|
||||||
|
suite.NotPanics(run)
|
||||||
|
} else {
|
||||||
|
suite.Panics(run)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check
|
||||||
|
if tc.expectPass {
|
||||||
|
suite.Equal(tc.genState, exportedGenState)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenesisTestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(GenesisTestSuite))
|
||||||
|
}
|
@ -2,6 +2,7 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultNextProposalID is the starting poiint for proposal IDs.
|
// DefaultNextProposalID is the starting poiint for proposal IDs.
|
||||||
@ -10,18 +11,18 @@ const DefaultNextProposalID uint64 = 1
|
|||||||
// GenesisState is state that must be provided at chain genesis.
|
// GenesisState is state that must be provided at chain genesis.
|
||||||
type GenesisState struct {
|
type GenesisState struct {
|
||||||
NextProposalID uint64
|
NextProposalID uint64
|
||||||
Votes []Vote
|
|
||||||
Proposals []Proposal
|
|
||||||
Committees []Committee
|
Committees []Committee
|
||||||
|
Proposals []Proposal
|
||||||
|
Votes []Vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGenesisState returns a new genesis state object for the module.
|
// NewGenesisState returns a new genesis state object for the module.
|
||||||
func NewGenesisState(nextProposalID uint64, votes []Vote, proposals []Proposal, committees []Committee) GenesisState {
|
func NewGenesisState(nextProposalID uint64, committees []Committee, proposals []Proposal, votes []Vote) GenesisState {
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
NextProposalID: nextProposalID,
|
NextProposalID: nextProposalID,
|
||||||
Votes: votes,
|
|
||||||
Proposals: proposals,
|
|
||||||
Committees: committees,
|
Committees: committees,
|
||||||
|
Proposals: proposals,
|
||||||
|
Votes: votes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,9 +30,9 @@ func NewGenesisState(nextProposalID uint64, votes []Vote, proposals []Proposal,
|
|||||||
func DefaultGenesisState() GenesisState {
|
func DefaultGenesisState() GenesisState {
|
||||||
return NewGenesisState(
|
return NewGenesisState(
|
||||||
DefaultNextProposalID,
|
DefaultNextProposalID,
|
||||||
[]Vote{},
|
|
||||||
[]Proposal{},
|
|
||||||
[]Committee{},
|
[]Committee{},
|
||||||
|
[]Proposal{},
|
||||||
|
[]Vote{},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,4 +49,62 @@ func (data GenesisState) IsEmpty() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate performs basic validation of genesis data.
|
// Validate performs basic validation of genesis data.
|
||||||
func (gs GenesisState) Validate() error { return nil }
|
func (gs GenesisState) Validate() error {
|
||||||
|
// validate committees
|
||||||
|
committeeMap := make(map[uint64]bool, len(gs.Committees))
|
||||||
|
for _, com := range gs.Committees {
|
||||||
|
// check there are no duplicate IDs
|
||||||
|
if _, ok := committeeMap[com.ID]; ok {
|
||||||
|
return fmt.Errorf("duplicate committee ID found in genesis state; id: %d", com.ID)
|
||||||
|
}
|
||||||
|
committeeMap[com.ID] = true
|
||||||
|
|
||||||
|
// validate committee
|
||||||
|
if len(com.Members) == 0 {
|
||||||
|
return fmt.Errorf("committee %d invalid: cannot have zero members", com.ID)
|
||||||
|
}
|
||||||
|
for _, m := range com.Members {
|
||||||
|
if m.Empty() {
|
||||||
|
return fmt.Errorf("committee %d invalid: found empty member address", com.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate proposals - pp.Val, no duplicate IDs, no ids >= nextID, committee needs to exist
|
||||||
|
proposalMap := make(map[uint64]bool, len(gs.Proposals))
|
||||||
|
for _, p := range gs.Proposals {
|
||||||
|
// check there are no duplicate IDs
|
||||||
|
if _, ok := proposalMap[p.ID]; ok {
|
||||||
|
return fmt.Errorf("duplicate proposal ID found in genesis state; id: %d", p.ID)
|
||||||
|
}
|
||||||
|
proposalMap[p.ID] = true
|
||||||
|
|
||||||
|
// validate next proposal ID
|
||||||
|
if p.ID >= gs.NextProposalID {
|
||||||
|
return fmt.Errorf("NextProposalID is not greater than all proposal IDs; id: %d", p.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check committee exists
|
||||||
|
if !committeeMap[p.CommitteeID] {
|
||||||
|
return fmt.Errorf("proposal refers to non existant committee; proposal: %+v", p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate pubProposal
|
||||||
|
if err := p.PubProposal.ValidateBasic(); err != nil {
|
||||||
|
return fmt.Errorf("proposal %d invalid: %w", p.ID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate votes
|
||||||
|
for _, v := range gs.Votes {
|
||||||
|
// check proposal exists
|
||||||
|
if !proposalMap[v.ProposalID] {
|
||||||
|
return fmt.Errorf("vote refers to non existant proposal; vote: %+v", v)
|
||||||
|
}
|
||||||
|
// validate address
|
||||||
|
if v.Voter.Empty() {
|
||||||
|
return fmt.Errorf("found empty voter address; vote: %+v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
36
x/committee/types/genesis_test.go
Normal file
36
x/committee/types/genesis_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGenesisState_Validate(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
genState GenesisState
|
||||||
|
expectPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "normal",
|
||||||
|
genState: DefaultGenesisState(),
|
||||||
|
expectPass: true,
|
||||||
|
},
|
||||||
|
// TODO test failure cases
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
|
||||||
|
err := tc.genState.Validate()
|
||||||
|
|
||||||
|
if tc.expectPass {
|
||||||
|
require.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user