Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions sei-cosmos/x/gov/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import (

var logger = seilog.NewLogger("cosmos", "x", "gov")

// EndBlocker called every block, process inflation, update validator set.
// MaxVotesProcessedPerBlock is the governance vote-record budget shared by tallying and cleanup.
const MaxVotesProcessedPerBlock = 1000

// EndBlocker expires governance proposals and advances bounded vote tally work.
func EndBlocker(ctx sdk.Context, keeper keeper.Keeper) {
endBlockerStart := time.Now()
defer func() {
Expand Down Expand Up @@ -50,11 +53,17 @@ func EndBlocker(ctx sdk.Context, keeper keeper.Keeper) {
return false
})

remainingVotes := MaxVotesProcessedPerBlock

// fetch active proposals whose voting periods have ended (are passed the block time)
keeper.IterateActiveProposalsQueue(ctx, ctx.BlockHeader().Time, func(proposal types.Proposal) bool {
var tagValue, logMsg string

passes, burnDeposits, tallyResults := keeper.Tally(ctx, proposal)
complete, processed, passes, burnDeposits, tallyResults := keeper.TallyIncremental(ctx, proposal, remainingVotes)
remainingVotes -= processed
if !complete {
return true
}

// If an expedited proposal fails, we do not want to update
// the deposit at this point since the proposal is converted to regular.
Expand Down Expand Up @@ -141,6 +150,8 @@ func EndBlocker(ctx sdk.Context, keeper keeper.Keeper) {
sdk.NewAttribute(types.AttributeKeyProposalResult, tagValue),
),
)
return false
return remainingVotes == 0
})

keeper.CleanupTallyVotes(ctx, remainingVotes)
}
50 changes: 50 additions & 0 deletions sei-cosmos/x/gov/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gov_test

import (
"context"
"encoding/binary"
"testing"
"time"

Expand Down Expand Up @@ -606,6 +607,55 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) {
gov.EndBlocker(ctx, app.GovKeeper)
}

func TestEndBlockerBoundsVoteTallyAndCleanupWork(t *testing.T) {
app := seiapp.Setup(t, false, false, false)
ctx := app.BaseApp.NewContext(false, tmproto.Header{})

proposal, err := app.GovKeeper.SubmitProposal(ctx, TestProposal)
require.NoError(t, err)
app.GovKeeper.ActivateVotingPeriod(ctx, proposal)
proposal, found := app.GovKeeper.GetProposal(ctx, proposal.ProposalId)
require.True(t, found)

for i := 0; i < gov.MaxVotesProcessedPerBlock+1; i++ {
addr := make(sdk.AccAddress, 20)
binary.BigEndian.PutUint64(addr[12:], uint64(i+1))
require.NoError(t, app.GovKeeper.AddVote(
ctx,
proposal.ProposalId,
addr,
types.NewNonSplitVoteOption(types.OptionYes),
))
}

ctx = ctx.WithBlockTime(proposal.VotingEndTime)
gov.EndBlocker(ctx, app.GovKeeper)

proposal, found = app.GovKeeper.GetProposal(ctx, proposal.ProposalId)
require.True(t, found)
require.Equal(t, types.StatusVotingPeriod, proposal.Status)
require.True(t, app.GovKeeper.IsTallying(ctx, proposal.ProposalId))
require.Len(t, app.GovKeeper.GetVotes(ctx, proposal.ProposalId), 1)
require.Len(t, app.GovKeeper.GetArchivedTallyVotes(ctx, proposal.ProposalId, false), gov.MaxVotesProcessedPerBlock)

newVoter := make(sdk.AccAddress, 20)
binary.BigEndian.PutUint64(newVoter[12:], uint64(gov.MaxVotesProcessedPerBlock+2))
err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, newVoter, types.NewNonSplitVoteOption(types.OptionNo))
require.ErrorIs(t, err, types.ErrInactiveProposal)

gov.EndBlocker(ctx, app.GovKeeper)

proposal, found = app.GovKeeper.GetProposal(ctx, proposal.ProposalId)
require.True(t, found)
require.Equal(t, types.StatusRejected, proposal.Status)
require.False(t, app.GovKeeper.IsTallying(ctx, proposal.ProposalId))
require.Empty(t, app.GovKeeper.GetVotes(ctx, proposal.ProposalId))
require.Len(t, app.GovKeeper.GetArchivedTallyVotes(ctx, proposal.ProposalId, false), 2)

gov.EndBlocker(ctx, app.GovKeeper)
require.Empty(t, app.GovKeeper.GetArchivedTallyVotes(ctx, proposal.ProposalId, false))
}

// With expedited proposal's minimum deposit set higher than the default deposit, we must
// initialize and deposit an amount depositMultiplier times larger
// than the regular min deposit amount.
Expand Down
4 changes: 4 additions & 0 deletions sei-cosmos/x/gov/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
deposits := k.GetDeposits(ctx, proposal.ProposalId)
proposalsDeposits = append(proposalsDeposits, deposits...)

if k.IsTallying(ctx, proposal.ProposalId) {
archivedVotes := k.GetArchivedTallyVotes(ctx, proposal.ProposalId, proposal.IsExpedited)
proposalsVotes = append(proposalsVotes, archivedVotes...)
}
votes := k.GetVotes(ctx, proposal.ProposalId)
proposalsVotes = append(proposalsVotes, votes...)
}
Expand Down
30 changes: 30 additions & 0 deletions sei-cosmos/x/gov/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gov_test

import (
"context"
"encoding/binary"
"encoding/json"
"testing"

Expand Down Expand Up @@ -168,3 +169,32 @@ func TestEqualProposals(t *testing.T) {
require.Equal(t, state1, state2)
require.True(t, state1.Equal(state2))
}

func TestExportGenesisIncludesVotesFromUnfinishedTally(t *testing.T) {
app := seiapp.Setup(t, false, false, false)
ctx := app.BaseApp.NewContext(false, tmproto.Header{})

proposal, err := app.GovKeeper.SubmitProposal(ctx, TestProposal)
require.NoError(t, err)
app.GovKeeper.ActivateVotingPeriod(ctx, proposal)
proposal, found := app.GovKeeper.GetProposal(ctx, proposal.ProposalId)
require.True(t, found)

for i := 0; i < 3; i++ {
addr := make(sdk.AccAddress, 20)
binary.BigEndian.PutUint64(addr[12:], uint64(i+1))
require.NoError(t, app.GovKeeper.AddVote(
ctx,
proposal.ProposalId,
addr,
types.NewNonSplitVoteOption(types.OptionYes),
))
}

complete, processed, _, _, _ := app.GovKeeper.TallyIncremental(ctx, proposal, 1)
require.False(t, complete)
require.Equal(t, 1, processed)

genesis := gov.ExportGenesis(ctx, app.GovKeeper)
require.Len(t, genesis.Votes, 3)
}
Loading
Loading