Skip to content

Commit

Permalink
feat(gov): handle panics when executing x/gov proposals (backport #17780
Browse files Browse the repository at this point in the history
) (#17790)

Co-authored-by: Robert Zaremba <robert@zaremba.ch>
Co-authored-by: Julien Robert <julien@rbrt.fr>
  • Loading branch information
3 people authored Sep 18, 2023
1 parent 2196eda commit 87ba5a6
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Improvments

* (x/gov) [#17780](https://github.com/cosmos/cosmos-sdk/pull/17780) Recover panics and turn them into errors when executing x/gov proposals.
* (types/module) [#17554](https://github.com/cosmos/cosmos-sdk/pull/17554) Introduce `HasABCIGenesis` which is implemented by a module only when a validatorset update needs to be returned.
* (baseapp) [#17667](https://github.com/cosmos/cosmos-sdk/pull/17667) Close databases opened by SDK in `baseApp.Close()`.

Expand Down
16 changes: 14 additions & 2 deletions x/gov/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"cosmossdk.io/collections"

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/keeper"
Expand Down Expand Up @@ -133,9 +134,8 @@ func EndBlocker(ctx sdk.Context, keeper *keeper.Keeper) error {
// execute all messages
for idx, msg = range messages {
handler := keeper.Router().Handler(msg)

var res *sdk.Result
res, err = handler(cacheCtx, msg)
res, err = safeExecuteHandler(cacheCtx, msg, handler)
if err != nil {
break
}
Expand Down Expand Up @@ -223,3 +223,15 @@ func EndBlocker(ctx sdk.Context, keeper *keeper.Keeper) error {
}
return nil
}

// executes handle(msg) and recovers from panic.
func safeExecuteHandler(ctx sdk.Context, msg sdk.Msg, handler baseapp.MsgServiceHandler,
) (res *sdk.Result, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("handling x/gov proposal msg [%s] PANICKED: %v", msg, r)
}
}()
res, err = handler(ctx, msg)
return
}
32 changes: 32 additions & 0 deletions x/gov/abci_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package gov

import (
"testing"

"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
)

func failingHandler(_ sdk.Context, _ sdk.Msg) (*sdk.Result, error) {
panic("test-fail")
}

func okHandler(_ sdk.Context, _ sdk.Msg) (*sdk.Result, error) {
return new(sdk.Result), nil
}

func TestSafeExecuteHandler(t *testing.T) {
t.Parallel()

require := require.New(t)
var ctx sdk.Context

r, err := safeExecuteHandler(ctx, nil, failingHandler)
require.ErrorContains(err, "test-fail")
require.Nil(r)

r, err = safeExecuteHandler(ctx, nil, okHandler)
require.Nil(err)
require.NotNil(r)
}

0 comments on commit 87ba5a6

Please sign in to comment.