add nicer keeper get methods

This commit is contained in:
rhuairahrighairigh 2020-04-27 15:04:47 +01:00
parent 20c02a6a54
commit c17de631d2
8 changed files with 110 additions and 131 deletions

View File

@ -33,21 +33,9 @@ func ExportGenesis(ctx sdk.Context, keeper Keeper) GenesisState {
if err != nil { if err != nil {
panic(err) panic(err)
} }
committees := []types.Committee{} committees := keeper.GetCommittees(ctx)
keeper.IterateCommittees(ctx, func(com types.Committee) bool { proposals := keeper.GetProposals(ctx)
committees = append(committees, com) votes := keeper.GetVotes(ctx)
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( return types.NewGenesisState(
nextID, nextID,

View File

@ -89,6 +89,7 @@ func (suite *HandlerTestSuite) TestSubmitProposalMsg_Valid() {
} }
func (suite *HandlerTestSuite) TestSubmitProposalMsg_Invalid() { func (suite *HandlerTestSuite) TestSubmitProposalMsg_Invalid() {
var committeeID uint64 = 1
msg := types.NewMsgSubmitProposal( msg := types.NewMsgSubmitProposal(
params.NewParameterChangeProposal( params.NewParameterChangeProposal(
"A Title", "A Title",
@ -100,32 +101,34 @@ func (suite *HandlerTestSuite) TestSubmitProposalMsg_Invalid() {
}}, }},
), ),
suite.addresses[0], suite.addresses[0],
1, committeeID,
) )
res := suite.handler(suite.ctx, msg) res := suite.handler(suite.ctx, msg)
suite.False(res.IsOK()) suite.False(res.IsOK())
suite.keeper.IterateProposals(suite.ctx, func(p types.Proposal) bool { suite.Empty(
suite.Fail("proposal found when none should exist") suite.keeper.GetProposalsByCommittee(suite.ctx, committeeID),
return true "proposal found when none should exist",
}) )
} }
func (suite *HandlerTestSuite) TestSubmitProposalMsg_Unregistered() { func (suite *HandlerTestSuite) TestSubmitProposalMsg_Unregistered() {
var committeeID uint64 = 1
msg := types.NewMsgSubmitProposal( msg := types.NewMsgSubmitProposal(
UnregisteredPubProposal{}, UnregisteredPubProposal{},
suite.addresses[0], suite.addresses[0],
1, committeeID,
) )
res := suite.handler(suite.ctx, msg) res := suite.handler(suite.ctx, msg)
suite.False(res.IsOK()) suite.False(res.IsOK())
suite.keeper.IterateProposals(suite.ctx, func(p types.Proposal) bool { suite.Empty(
suite.Fail("proposal found when none should exist") suite.keeper.GetProposalsByCommittee(suite.ctx, committeeID),
return true "proposal found when none should exist",
}) )
} }
func (suite *HandlerTestSuite) TestMsgAddVote_ProposalPass() { func (suite *HandlerTestSuite) TestMsgAddVote_ProposalPass() {
@ -159,10 +162,10 @@ func (suite *HandlerTestSuite) TestMsgAddVote_ProposalPass() {
// Check proposal and votes are gone // Check proposal and votes are gone
_, found := suite.keeper.GetProposal(suite.ctx, proposalID) _, found := suite.keeper.GetProposal(suite.ctx, proposalID)
suite.False(found) suite.False(found)
suite.keeper.IterateVotes(suite.ctx, proposalID, func(v types.Vote) bool { suite.Empty(
suite.Fail("vote found when there should be none") suite.keeper.GetVotesByProposal(suite.ctx, proposalID),
return true "vote found when there should be none",
}) )
} }
func (suite *HandlerTestSuite) TestMsgAddVote_ProposalFail() { func (suite *HandlerTestSuite) TestMsgAddVote_ProposalFail() {
@ -196,10 +199,10 @@ func (suite *HandlerTestSuite) TestMsgAddVote_ProposalFail() {
// Check proposal and votes are gone // Check proposal and votes are gone
_, found := suite.keeper.GetProposal(suite.ctx, proposalID) _, found := suite.keeper.GetProposal(suite.ctx, proposalID)
suite.False(found) suite.False(found)
suite.keeper.IterateVotes(suite.ctx, proposalID, func(v types.Vote) bool { suite.Empty(
suite.Fail("vote found when there should be none") suite.keeper.GetVotesByProposal(suite.ctx, proposalID),
return true "vote found when there should be none",
}) )
} }
func TestHandlerTestSuite(t *testing.T) { func TestHandlerTestSuite(t *testing.T) {

View File

@ -16,16 +16,13 @@ func d(str string) sdk.Dec { return sdk.MustNewDecFromStr(str)
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) } func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
// proposalVoteMap collects up votes into a map indexed by proposalID // getProposalVoteMap collects up votes into a map indexed by proposalID
func getProposalVoteMap(k keeper.Keeper, ctx sdk.Context) map[uint64]([]types.Vote) { func getProposalVoteMap(k keeper.Keeper, ctx sdk.Context) map[uint64]([]types.Vote) {
proposalVoteMap := map[uint64]([]types.Vote){} proposalVoteMap := map[uint64]([]types.Vote){}
k.IterateProposals(ctx, func(p types.Proposal) bool { k.IterateProposals(ctx, func(p types.Proposal) bool {
k.IterateVotes(ctx, p.ID, func(v types.Vote) bool { proposalVoteMap[p.ID] = k.GetVotesByProposal(ctx, p.ID)
proposalVoteMap[p.ID] = append(proposalVoteMap[p.ID], v)
return false
})
return false return false
}) })
return proposalVoteMap return proposalVoteMap

View File

@ -78,6 +78,16 @@ func (k Keeper) IterateCommittees(ctx sdk.Context, cb func(committee types.Commi
} }
} }
// GetCommittees returns all stored committees.
func (k Keeper) GetCommittees(ctx sdk.Context) []types.Committee {
results := []types.Committee{}
k.IterateCommittees(ctx, func(com types.Committee) bool {
results = append(results, com)
return false
})
return results
}
// ------------------------------------------ // ------------------------------------------
// Proposals // Proposals
// ------------------------------------------ // ------------------------------------------
@ -171,6 +181,39 @@ func (k Keeper) IterateProposals(ctx sdk.Context, cb func(proposal types.Proposa
} }
} }
// GetProposals returns all stored proposals.
func (k Keeper) GetProposals(ctx sdk.Context) []types.Proposal {
results := []types.Proposal{}
k.IterateProposals(ctx, func(prop types.Proposal) bool {
results = append(results, prop)
return false
})
return results
}
// GetProposalsByCommittee returns all proposals for one committee.
func (k Keeper) GetProposalsByCommittee(ctx sdk.Context, committeeID uint64) []types.Proposal {
results := []types.Proposal{}
k.IterateProposals(ctx, func(prop types.Proposal) bool {
if prop.CommitteeID == committeeID {
results = append(results, prop)
}
return false
})
return results
}
// DeleteProposalAndVotes removes a proposal and its associated votes.
func (k Keeper) DeleteProposalAndVotes(ctx sdk.Context, proposalID uint64) {
votes := k.GetVotesByProposal(ctx, proposalID)
k.DeleteProposal(ctx, proposalID)
for _, v := range votes {
k.DeleteVote(ctx, v.ProposalID, v.Voter)
}
}
// ------------------------------------------ // ------------------------------------------
// Votes // Votes
// ------------------------------------------ // ------------------------------------------
@ -200,11 +243,10 @@ func (k Keeper) DeleteVote(ctx sdk.Context, proposalID uint64, voter sdk.AccAddr
store.Delete(types.GetVoteKey(proposalID, voter)) store.Delete(types.GetVoteKey(proposalID, voter))
} }
// IterateVotes provides an iterator over all stored votes for a given proposal. // IterateVotes provides an iterator over all stored votes.
// For each vote, cb will be called. If cb returns true, the iterator will close and stop. // For each vote, cb will be called. If cb returns true, the iterator will close and stop.
func (k Keeper) IterateVotes(ctx sdk.Context, proposalID uint64, cb func(vote types.Vote) (stop bool)) { func (k Keeper) IterateVotes(ctx sdk.Context, cb func(vote types.Vote) (stop bool)) {
// iterate over the section of the votes store that has all votes for a particular proposal iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), types.VoteKeyPrefix)
iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), append(types.VoteKeyPrefix, types.GetKeyFromID(proposalID)...))
defer iterator.Close() defer iterator.Close()
for ; iterator.Valid(); iterator.Next() { for ; iterator.Valid(); iterator.Next() {
@ -216,3 +258,25 @@ func (k Keeper) IterateVotes(ctx sdk.Context, proposalID uint64, cb func(vote ty
} }
} }
} }
// GetVotes returns all stored votes.
func (k Keeper) GetVotes(ctx sdk.Context) []types.Vote {
results := []types.Vote{}
k.IterateVotes(ctx, func(vote types.Vote) bool {
results = append(results, vote)
return false
})
return results
}
// GetVotesByProposal returns all votes for one proposal.
func (k Keeper) GetVotesByProposal(ctx sdk.Context, proposalID uint64) []types.Vote {
results := []types.Vote{}
k.IterateVotes(ctx, func(vote types.Vote) bool {
if vote.ProposalID == proposalID {
results = append(results, vote)
}
return false
})
return results
}

View File

@ -99,11 +99,7 @@ func (k Keeper) GetProposalResult(ctx sdk.Context, proposalID uint64) (bool, sdk
// TallyVotes counts all the votes on a proposal // TallyVotes counts all the votes on a proposal
func (k Keeper) TallyVotes(ctx sdk.Context, proposalID uint64) int64 { func (k Keeper) TallyVotes(ctx sdk.Context, proposalID uint64) int64 {
var votes []types.Vote votes := k.GetVotesByProposal(ctx, proposalID)
k.IterateVotes(ctx, proposalID, func(vote types.Vote) bool {
votes = append(votes, vote)
return false
})
return int64(len(votes)) return int64(len(votes))
} }
@ -180,18 +176,3 @@ func (k Keeper) ValidatePubProposal(ctx sdk.Context, pubProposal types.PubPropos
} }
return nil return nil
} }
// DeleteProposalAndVotes removes a proposal and its associated votes.
// TODO move to keeper.go
func (k Keeper) DeleteProposalAndVotes(ctx sdk.Context, proposalID uint64) {
var votes []types.Vote
k.IterateVotes(ctx, proposalID, func(vote types.Vote) bool {
votes = append(votes, vote)
return false
})
k.DeleteProposal(ctx, proposalID)
for _, v := range votes {
k.DeleteVote(ctx, v.ProposalID, v.Voter)
}
}

View File

@ -42,11 +42,7 @@ func NewQuerier(keeper Keeper) sdk.Querier {
func queryCommittees(ctx sdk.Context, path []string, _ abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { func queryCommittees(ctx sdk.Context, path []string, _ abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
committees := []types.Committee{} committees := keeper.GetCommittees(ctx)
keeper.IterateCommittees(ctx, func(com types.Committee) bool {
committees = append(committees, com)
return false
})
bz, err := codec.MarshalJSONIndent(keeper.cdc, committees) bz, err := codec.MarshalJSONIndent(keeper.cdc, committees)
if err != nil { if err != nil {
@ -85,13 +81,7 @@ func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keepe
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
} }
proposals := []types.Proposal{} proposals := keeper.GetProposalsByCommittee(ctx, params.CommitteeID)
keeper.IterateProposals(ctx, func(p types.Proposal) bool {
if p.CommitteeID == params.CommitteeID {
proposals = append(proposals, p)
}
return false
})
bz, err := codec.MarshalJSONIndent(keeper.cdc, proposals) bz, err := codec.MarshalJSONIndent(keeper.cdc, proposals)
if err != nil { if err != nil {
@ -131,11 +121,7 @@ func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
} }
votes := []types.Vote{} votes := keeper.GetVotesByProposal(ctx, params.ProposalID)
keeper.IterateVotes(ctx, params.ProposalID, func(v types.Vote) bool {
votes = append(votes, v)
return false
})
bz, err := codec.MarshalJSONIndent(keeper.cdc, votes) bz, err := codec.MarshalJSONIndent(keeper.cdc, votes)
if err != nil { if err != nil {

View File

@ -28,16 +28,12 @@ func handleCommitteeChangeProposal(ctx sdk.Context, k Keeper, committeeProposal
} }
// Remove all committee's ongoing proposals // Remove all committee's ongoing proposals
var proposals []Proposal
k.IterateProposals(ctx, func(p Proposal) bool { k.IterateProposals(ctx, func(p Proposal) bool {
if p.CommitteeID == committeeProposal.NewCommittee.ID { if p.CommitteeID == committeeProposal.NewCommittee.ID {
proposals = append(proposals, p) k.DeleteProposalAndVotes(ctx, p.ID)
} }
return false return false
}) })
for _, p := range proposals { // split loops to avoid updating the db while iterating
k.DeleteProposalAndVotes(ctx, p.ID)
}
// update/create the committee // update/create the committee
k.SetCommittee(ctx, committeeProposal.NewCommittee) k.SetCommittee(ctx, committeeProposal.NewCommittee)
@ -50,16 +46,12 @@ func handleCommitteeDeleteProposal(ctx sdk.Context, k Keeper, committeeProposal
} }
// Remove all committee's ongoing proposals // Remove all committee's ongoing proposals
var proposals []Proposal
k.IterateProposals(ctx, func(p Proposal) bool { k.IterateProposals(ctx, func(p Proposal) bool {
if p.CommitteeID == committeeProposal.CommitteeID { if p.CommitteeID == committeeProposal.CommitteeID {
proposals = append(proposals, p) k.DeleteProposalAndVotes(ctx, p.ID)
} }
return false return false
}) })
for _, p := range proposals { // split loops to avoid updating the db while iterating
k.DeleteProposalAndVotes(ctx, p.ID)
}
k.DeleteCommittee(ctx, committeeProposal.CommitteeID) k.DeleteCommittee(ctx, committeeProposal.CommitteeID)
return nil return nil

View File

@ -133,19 +133,7 @@ func (suite *ProposalHandlerTestSuite) TestProposalHandler_ChangeCommittee() {
suite.ctx = suite.app.NewContext(true, abci.Header{Height: 1, Time: testTime}) suite.ctx = suite.app.NewContext(true, abci.Header{Height: 1, Time: testTime})
handler := committee.NewProposalHandler(suite.keeper) handler := committee.NewProposalHandler(suite.keeper)
// get proposals and votes for target committee oldProposals := suite.keeper.GetProposalsByCommittee(suite.ctx, tc.proposal.NewCommittee.ID)
var proposals []committee.Proposal
var votes []committee.Vote
suite.keeper.IterateProposals(suite.ctx, func(p committee.Proposal) bool {
if p.CommitteeID == tc.proposal.NewCommittee.ID {
proposals = append(proposals, p)
suite.keeper.IterateVotes(suite.ctx, p.ID, func(v committee.Vote) bool {
votes = append(votes, v)
return false
})
}
return false
})
// Run // Run
err := handler(suite.ctx, tc.proposal) err := handler(suite.ctx, tc.proposal)
@ -153,19 +141,15 @@ func (suite *ProposalHandlerTestSuite) TestProposalHandler_ChangeCommittee() {
// Check // Check
if tc.expectPass { if tc.expectPass {
suite.NoError(err) suite.NoError(err)
// check proposal is accurate // check committee is accurate
actualCom, found := suite.keeper.GetCommittee(suite.ctx, tc.proposal.NewCommittee.ID) actualCom, found := suite.keeper.GetCommittee(suite.ctx, tc.proposal.NewCommittee.ID)
suite.True(found) suite.True(found)
suite.Equal(tc.proposal.NewCommittee, actualCom) suite.Equal(tc.proposal.NewCommittee, actualCom)
// check proposals and votes for this committee have been removed // check proposals and votes for this committee have been removed
for _, p := range proposals { suite.Empty(suite.keeper.GetProposalsByCommittee(suite.ctx, tc.proposal.NewCommittee.ID))
_, found := suite.keeper.GetProposal(suite.ctx, p.ID) for _, p := range oldProposals {
suite.False(found) suite.Empty(suite.keeper.GetVotesByProposal(suite.ctx, p.ID))
}
for _, v := range votes {
_, found := suite.keeper.GetVote(suite.ctx, v.ProposalID, v.Voter)
suite.False(found)
} }
} else { } else {
suite.Error(err) suite.Error(err)
@ -211,19 +195,7 @@ func (suite *ProposalHandlerTestSuite) TestProposalHandler_DeleteCommittee() {
suite.ctx = suite.app.NewContext(true, abci.Header{Height: 1, Time: testTime}) suite.ctx = suite.app.NewContext(true, abci.Header{Height: 1, Time: testTime})
handler := committee.NewProposalHandler(suite.keeper) handler := committee.NewProposalHandler(suite.keeper)
// get proposals and votes for target committee oldProposals := suite.keeper.GetProposalsByCommittee(suite.ctx, tc.proposal.CommitteeID)
var proposals []committee.Proposal
var votes []committee.Vote
suite.keeper.IterateProposals(suite.ctx, func(p committee.Proposal) bool {
if p.CommitteeID == tc.proposal.CommitteeID {
proposals = append(proposals, p)
suite.keeper.IterateVotes(suite.ctx, p.ID, func(v committee.Vote) bool {
votes = append(votes, v)
return false
})
}
return false
})
// Run // Run
err := handler(suite.ctx, tc.proposal) err := handler(suite.ctx, tc.proposal)
@ -231,18 +203,14 @@ func (suite *ProposalHandlerTestSuite) TestProposalHandler_DeleteCommittee() {
// Check // Check
if tc.expectPass { if tc.expectPass {
suite.NoError(err) suite.NoError(err)
// check proposal is accurate // check committee has been removed
_, found := suite.keeper.GetCommittee(suite.ctx, tc.proposal.CommitteeID) _, found := suite.keeper.GetCommittee(suite.ctx, tc.proposal.CommitteeID)
suite.False(found) suite.False(found)
// check proposals and votes for this committee have been removed // check proposals and votes for this committee have been removed
for _, p := range proposals { suite.Empty(suite.keeper.GetProposalsByCommittee(suite.ctx, tc.proposal.CommitteeID))
_, found := suite.keeper.GetProposal(suite.ctx, p.ID) for _, p := range oldProposals {
suite.False(found) suite.Empty(suite.keeper.GetVotesByProposal(suite.ctx, p.ID))
}
for _, v := range votes {
_, found := suite.keeper.GetVote(suite.ctx, v.ProposalID, v.Voter)
suite.False(found)
} }
} else { } else {
suite.Error(err) suite.Error(err)