From d33c0cff58fa25716a21c9eb699d384aab8ca774 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Thu, 25 May 2023 14:22:54 +0200 Subject: [PATCH 1/3] add base app setter for circuit breaker --- baseapp/baseapp.go | 6 ++++++ baseapp/circuit.go | 10 ++++++++++ baseapp/msg_service_router.go | 12 ++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 baseapp/circuit.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index ca2fe852af6e..2cd1d577f410 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -229,6 +229,12 @@ func (app *BaseApp) SetMsgServiceRouter(msgServiceRouter *MsgServiceRouter) { app.msgServiceRouter = msgServiceRouter } +// SetCircuitBreaker sets the circuit breaker for the BaseApp. +// The circuit breaker is checked on every message execution to verify if a transaction should be executed or not. +func (app *BaseApp) SetCircuitBreaker(cb CircuitBreaker) { + app.msgServiceRouter.SetCircuit(cb) +} + // MountStores mounts all IAVL or DB stores to the provided keys in the BaseApp // multistore. func (app *BaseApp) MountStores(keys ...storetypes.StoreKey) { diff --git a/baseapp/circuit.go b/baseapp/circuit.go new file mode 100644 index 000000000000..022ee6632c2e --- /dev/null +++ b/baseapp/circuit.go @@ -0,0 +1,10 @@ +package baseapp + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// CircuitBreaker is an interface that defines the methods for a circuit breaker. +type CircuitBreaker interface { + IsAllowed(ctx sdk.Context, typeURL string) bool +} diff --git a/baseapp/msg_service_router.go b/baseapp/msg_service_router.go index b42fc282ec31..a6494eebc6d1 100644 --- a/baseapp/msg_service_router.go +++ b/baseapp/msg_service_router.go @@ -17,6 +17,7 @@ import ( type MsgServiceRouter struct { interfaceRegistry codectypes.InterfaceRegistry routes map[string]MsgServiceHandler + circuitBreaker CircuitBreaker } var _ gogogrpc.Server = &MsgServiceRouter{} @@ -31,6 +32,10 @@ func NewMsgServiceRouter() *MsgServiceRouter { // MsgServiceHandler defines a function type which handles Msg service message. type MsgServiceHandler = func(ctx sdk.Context, req sdk.Msg) (*sdk.Result, error) +func (msr *MsgServiceRouter) SetCircuit(cb CircuitBreaker) { + msr.circuitBreaker = cb +} + // Handler returns the MsgServiceHandler for a given msg or nil if not found. func (msr *MsgServiceRouter) Handler(msg sdk.Msg) MsgServiceHandler { return msr.routes[sdk.MsgTypeURL(msg)] @@ -120,6 +125,13 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter } else { return nil, err } + + if msr.circuitBreaker != nil { + msgURL := sdk.MsgTypeURL(req) + if !msr.circuitBreaker.IsAllowed(ctx, msgURL) { + return nil, fmt.Errorf("circuit breaker disables execution of this message: %s", msgURL) + } + } } // Call the method handler from the service description with the handler object. // We don't do any decoding here because the decoding was already done. From 17a7571102c704da547aa39e9b5b4be0129eaa3f Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 26 May 2023 14:50:27 +0200 Subject: [PATCH 2/3] add changelog and kick ci --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e1f20107ec2..838540ea883b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Features +* (baseapp) [#16290](https://github.com/cosmos/cosmos-sdk/pull/16290) Add circuit breaker setter in baseapp. * [#16060](https://github.com/cosmos/cosmos-sdk/pull/16060) Support saving restoring snapshot locally. ### Improvements From d87e919389412302a2e7dc3f49ab1b599389036a Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 26 May 2023 14:51:47 +0200 Subject: [PATCH 3/3] add nil check --- baseapp/baseapp.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 2cd1d577f410..b42a56efca68 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -232,6 +232,9 @@ func (app *BaseApp) SetMsgServiceRouter(msgServiceRouter *MsgServiceRouter) { // SetCircuitBreaker sets the circuit breaker for the BaseApp. // The circuit breaker is checked on every message execution to verify if a transaction should be executed or not. func (app *BaseApp) SetCircuitBreaker(cb CircuitBreaker) { + if app.msgServiceRouter == nil { + panic("cannot set circuit breaker with no msg service router set") + } app.msgServiceRouter.SetCircuit(cb) }