refactor begin blocker

This commit is contained in:
rhuairahrighairigh 2020-04-24 23:15:51 +01:00
parent 73dc488239
commit 5c280696fb
5 changed files with 128 additions and 30 deletions

View File

@ -1,32 +1,12 @@
package committee
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/kava-labs/kava/x/committee/types"
)
// BeginBlocker runs at the start of every block.
func BeginBlocker(ctx sdk.Context, _ abci.RequestBeginBlock, k Keeper) {
// Close all expired proposals
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),
),
)
}
return false
})
k.CloseExpiredProposals(ctx)
}

View File

@ -0,0 +1,21 @@
package keeper_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/committee/types"
)
// proposalVoteMap collects up votes into a map indexed by proposalID
func getProposalVoteMap(k keeper.Keeper, ctx sdk.Context) map[uint64]([]types.Vote) {
proposalVoteMap = map[uint64]([]types.Vote){}
keeper.IterateProposals(suite.ctx, func(p types.Proposal) bool {
keeper.IterateVotes(suite.ctx, p.ID, func(v types.Vote) bool {
proposalVoteMap[p.ID] = append(proposalVoteMap[p.ID], v)
return false
})
return false
})
return proposalVoteMap
}

View File

@ -125,6 +125,27 @@ func (k Keeper) EnactProposal(ctx sdk.Context, proposalID uint64) sdk.Error {
return nil
}
// CloseExpiredProposals removes proposals (and associated votes) that have past their deadline.
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),
),
)
}
return false
})
}
// ValidatePubProposal checks if a pubproposal is valid.
func (k Keeper) ValidatePubProposal(ctx sdk.Context, pubProposal types.PubProposal) sdk.Error {
if pubProposal == nil {

View File

@ -322,3 +322,87 @@ func (suite *KeeperTestSuite) TestValidatePubProposal() {
})
}
}
func (suite *KeeperTestSuite) TestCloseExpiredProposals() {
// Setup test state
firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC)
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: firstBlockTime.Add(7 * 24 * time.Hour),
},
{
ID: 2,
CommitteeID: 1,
PubProposal: gov.NewTextProposal("Another Title", "A description of this other proposal."),
Deadline: firstBlockTime.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, testGenesis),
)
// close proposals
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: firstBlockTime})
suite.keeper.CloseExpiredProposals(ctx)
// check
for _, p := range testGenesis.Proposals {
_, found := k.GetProposal(ctx, p.ID)
votes := getProposalVoteMap(suite.keeper, ctx)
if ctx.BlockTime().After(p.Deadline) {
suite.False(found)
suite.Empty(votes[p.ID])
} else {
suite.True(found)
suite.NotEmpty(votes[p.ID])
}
}
// close (later time)
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: firstBlockTime.Add(7 * 24 * time.Hour)})
suite.keeper.CloseExpiredProposals(ctx)
// check
for _, p := range testGenesis.Proposals {
_, found := k.GetProposal(ctx, p.ID)
votes := getProposalVoteMap(suite.keeper, ctx)
if ctx.BlockTime().After(p.Deadline) {
suite.False(found)
suite.Empty(votes[p.ID])
} else {
suite.True(found)
suite.NotEmpty(votes[p.ID])
}
}
}

View File

@ -84,15 +84,7 @@ func (suite *QuerierTestSuite) SetupTest() {
NewCommitteeGenesisState(suite.cdc, suite.testGenesis),
)
// 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 {
suite.votes[p.ID] = append(suite.votes[p.ID], v)
return false
})
return false
})
suite.votes = getProposalVoteMap(suite.keeper, suite.ctx)
}
func (suite *QuerierTestSuite) TestQueryCommittees() {