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

refactor(x/gov)!: let hooks return an error #18173

Merged
merged 2 commits into from
Oct 19, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* (x/gov) [#18173](https://github.com/cosmos/cosmos-sdk/pull/18173) Gov Hooks now returns error and are "blocking" if they fail. Expect for `AfterProposalFailedMinDeposit` and `AfterProposalVotingPeriodEnded` that will log the error and continue.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something to be explained when this is done: #10453

* (x/gov/testutil) [#17986](https://github.com/cosmos/cosmos-sdk/pull/18036) `MsgDeposit` has been removed because of AutoCLI migration.
* (x/staking/testutil) [#17986](https://github.com/cosmos/cosmos-sdk/pull/17986) `MsgRedelegateExec`, `MsgUnbondExec` has been removed because of AutoCLI migration.
* (x/bank/testutil) [#17868](https://github.com/cosmos/cosmos-sdk/pull/17868) `MsgSendExec` has been removed because of AutoCLI migration.
Expand Down
16 changes: 14 additions & 2 deletions x/gov/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ func EndBlocker(ctx sdk.Context, keeper *keeper.Keeper) error {
}

// 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 @@ -228,7 +234,13 @@ func EndBlocker(ctx sdk.Context, keeper *keeper.Keeper) error {
}

// 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 @@ -115,7 +115,10 @@ func (keeper Keeper) AddDeposit(ctx context.Context, proposalID uint64, deposito
}

// 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
}

sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.EventManager().EmitEvent(
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 @@ -27,24 +27,29 @@ type MockGovHooksReceiver struct {
AfterProposalVotingPeriodEndedValid bool
}

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

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

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

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

func (h *MockGovHooksReceiver) AfterProposalVotingPeriodEnded(ctx context.Context, proposalID uint64) {
func (h *MockGovHooksReceiver) AfterProposalVotingPeriodEnded(ctx context.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 @@ -114,7 +114,10 @@ func (keeper Keeper) SubmitProposal(ctx context.Context, messages []sdk.Msg, met
}

// 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
}

sdkCtx.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 @@ -42,7 +42,10 @@ func (keeper Keeper) AddVote(ctx context.Context, proposalID uint64, voterAddr s
}

// 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
}

sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.EventManager().EmitEvent(
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 @@ -61,11 +61,11 @@ type PoolKeeper interface {

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

type GovHooksWrapper struct{ GovHooks }
Expand Down
32 changes: 22 additions & 10 deletions x/gov/types/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

import (
"context"
"errors"

sdk "github.com/cosmos/cosmos-sdk/types"
)
Expand All @@ -15,32 +16,43 @@ func NewMultiGovHooks(hooks ...GovHooks) MultiGovHooks {
return hooks
}

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

return errs
}

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

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

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

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