Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(x/gov): Backport of pull request #18173 to feature/v.0.47.x-ics-lsm branch #19305

Merged
Merged
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
16 changes: 14 additions & 2 deletions x/gov/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ func EndBlocker(ctx sdk.Context, keeper *keeper.Keeper) {
}

// called when proposal become inactive
keeper.Hooks().AfterProposalFailedMinDeposit(ctx, proposal.Id)
cacheCtx, writeCache := ctx.CacheContext()
err := keeper.Hooks().AfterProposalFailedMinDeposit(cacheCtx, proposal.Id)
if err == nil { // purposely ignoring the error here not to halt the chain if the hook fails
writeCache()
} else {
keeper.Logger(ctx).Error("failed to execute AfterProposalFailedMinDeposit hook", "error", err)
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
Expand Down Expand Up @@ -118,7 +124,13 @@ func EndBlocker(ctx sdk.Context, keeper *keeper.Keeper) {
keeper.RemoveFromActiveProposalQueue(ctx, proposal.Id, *proposal.VotingEndTime)

// when proposal become active
keeper.Hooks().AfterProposalVotingPeriodEnded(ctx, proposal.Id)
cacheCtx, writeCache := ctx.CacheContext()
err := keeper.Hooks().AfterProposalVotingPeriodEnded(cacheCtx, proposal.Id)
if err == nil { // purposely ignoring the error here not to halt the chain if the hook fails
writeCache()
} else {
keeper.Logger(ctx).Error("failed to execute AfterProposalVotingPeriodEnded hook", "error", err)
}

logger.Info(
"proposal tallied",
Expand Down
5 changes: 4 additions & 1 deletion x/gov/keeper/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAdd
}

// called when deposit has been added to a proposal, however the proposal may not be active
keeper.Hooks().AfterProposalDeposit(ctx, proposalID, depositorAddr)
err = keeper.Hooks().AfterProposalDeposit(ctx, proposalID, depositorAddr)
if err != nil {
return false, err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
Expand Down
15 changes: 10 additions & 5 deletions x/gov/keeper/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,29 @@ type MockGovHooksReceiver struct {
AfterProposalVotingPeriodEndedValid bool
}

func (h *MockGovHooksReceiver) AfterProposalSubmission(ctx sdk.Context, proposalID uint64) {
func (h *MockGovHooksReceiver) AfterProposalSubmission(ctx sdk.Context, proposalID uint64) error {
h.AfterProposalSubmissionValid = true
return nil
}

func (h *MockGovHooksReceiver) AfterProposalDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) {
func (h *MockGovHooksReceiver) AfterProposalDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) error {
h.AfterProposalDepositValid = true
return nil
}

func (h *MockGovHooksReceiver) AfterProposalVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) {
func (h *MockGovHooksReceiver) AfterProposalVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) error {
h.AfterProposalVoteValid = true
return nil
}

func (h *MockGovHooksReceiver) AfterProposalFailedMinDeposit(ctx sdk.Context, proposalID uint64) {
func (h *MockGovHooksReceiver) AfterProposalFailedMinDeposit(ctx sdk.Context, proposalID uint64) error {
h.AfterProposalFailedMinDepositValid = true
return nil
}

func (h *MockGovHooksReceiver) AfterProposalVotingPeriodEnded(ctx sdk.Context, proposalID uint64) {
func (h *MockGovHooksReceiver) AfterProposalVotingPeriodEnded(ctx sdk.Context, proposalID uint64) error {
h.AfterProposalVotingPeriodEndedValid = true
return nil
}

func TestHooks(t *testing.T) {
Expand Down
5 changes: 4 additions & 1 deletion x/gov/keeper/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ func (keeper Keeper) SubmitProposal(ctx sdk.Context, messages []sdk.Msg, metadat
keeper.SetProposalID(ctx, proposalID+1)

// called right after a proposal is submitted
keeper.Hooks().AfterProposalSubmission(ctx, proposalID)
err = keeper.Hooks().AfterProposalSubmission(ctx, proposalID)
if err != nil {
return v1.Proposal{}, err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
Expand Down
5 changes: 4 additions & 1 deletion x/gov/keeper/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.A
keeper.SetVote(ctx, vote)

// called after a vote on a proposal is cast
keeper.Hooks().AfterProposalVote(ctx, proposalID, voterAddr)
err = keeper.Hooks().AfterProposalVote(ctx, proposalID, voterAddr)
if err != nil {
return err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
Expand Down
10 changes: 5 additions & 5 deletions x/gov/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ type BankKeeper interface {

// GovHooks event hooks for governance proposal object (noalias)
type GovHooks interface {
AfterProposalSubmission(ctx sdk.Context, proposalID uint64) // Must be called after proposal is submitted
AfterProposalDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) // Must be called after a deposit is made
AfterProposalVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) // Must be called after a vote on a proposal is cast
AfterProposalFailedMinDeposit(ctx sdk.Context, proposalID uint64) // Must be called when proposal fails to reach min deposit
AfterProposalVotingPeriodEnded(ctx sdk.Context, proposalID uint64) // Must be called when proposal's finishes it's voting period
AfterProposalSubmission(ctx sdk.Context, proposalID uint64) error // Must be called after proposal is submitted
AfterProposalDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) error // Must be called after a deposit is made
AfterProposalVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) error // Must be called after a vote on a proposal is cast
AfterProposalFailedMinDeposit(ctx sdk.Context, proposalID uint64) error // Must be called when proposal fails to reach min deposit
AfterProposalVotingPeriodEnded(ctx sdk.Context, proposalID uint64) error // Must be called when proposal's finishes it's voting period
}

type GovHooksWrapper struct{ GovHooks }
Expand Down
67 changes: 57 additions & 10 deletions x/gov/types/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,79 @@ func NewMultiGovHooks(hooks ...GovHooks) MultiGovHooks {
return hooks
}

func (h MultiGovHooks) AfterProposalSubmission(ctx sdk.Context, proposalID uint64) {
func (h MultiGovHooks) AfterProposalSubmission(ctx sdk.Context, proposalID uint64) error {
var errs error
for i := range h {
h[i].AfterProposalSubmission(ctx, proposalID)
errs = JoinErrors(errs, h[i].AfterProposalSubmission(ctx, proposalID))
}
return errs
}

func (h MultiGovHooks) AfterProposalDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) {
func (h MultiGovHooks) AfterProposalDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) error {
var errs error
for i := range h {
h[i].AfterProposalDeposit(ctx, proposalID, depositorAddr)
errs = JoinErrors(errs, h[i].AfterProposalDeposit(ctx, proposalID, depositorAddr))
}
return errs
}

func (h MultiGovHooks) AfterProposalVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) {
func (h MultiGovHooks) AfterProposalVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) error {
var errs error
for i := range h {
h[i].AfterProposalVote(ctx, proposalID, voterAddr)
errs = JoinErrors(errs, h[i].AfterProposalVote(ctx, proposalID, voterAddr))
}
return errs
}

func (h MultiGovHooks) AfterProposalFailedMinDeposit(ctx sdk.Context, proposalID uint64) {
func (h MultiGovHooks) AfterProposalFailedMinDeposit(ctx sdk.Context, proposalID uint64) error {
var errs error
for i := range h {
h[i].AfterProposalFailedMinDeposit(ctx, proposalID)
errs = JoinErrors(errs, h[i].AfterProposalFailedMinDeposit(ctx, proposalID))
}
return errs
}

func (h MultiGovHooks) AfterProposalVotingPeriodEnded(ctx sdk.Context, proposalID uint64) {
func (h MultiGovHooks) AfterProposalVotingPeriodEnded(ctx sdk.Context, proposalID uint64) error {
var errs error
for i := range h {
h[i].AfterProposalVotingPeriodEnded(ctx, proposalID)
errs = JoinErrors(errs, h[i].AfterProposalVotingPeriodEnded(ctx, proposalID))
}
return errs
}

// implementation of errors.Join() in Go 1.20, until we upgrade to that version
func JoinErrors(errs ...error) error {
n := 0
for _, err := range errs {
if err != nil {
n++
}
}
if n == 0 {
return nil
}
e := &joinError{
errs: make([]error, 0, n),
}
for _, err := range errs {
if err != nil {
e.errs = append(e.errs, err)
}
}
return e
}

type joinError struct {
errs []error
}

func (e *joinError) Error() string {
var b []byte
for i, err := range e.errs {
if i > 0 {
b = append(b, '\n')
}
b = append(b, err.Error()...)
}
return string(b)
}
Loading