feat(gov): handle panics when executing x/gov proposals (backport #17780) (#17790)

Co-authored-by: Robert Zaremba <robert@zaremba.ch>
Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
mergify[bot] 2023-09-18 15:33:57 +00:00 committed by GitHub
parent 2196edacb9
commit 87ba5a6a13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 2 deletions

View File

@ -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()`.

View File

@ -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"
@ -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
}
@ -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
}

View File

@ -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)
}