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: add module name to message server #14352

Closed
wants to merge 4 commits into from
Closed
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
13 changes: 5 additions & 8 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ func (app *BaseApp) SetMsgServiceRouter(msgServiceRouter *MsgServiceRouter) {
// MountStores mounts all IAVL or DB stores to the provided keys in the BaseApp
// multistore.
func (app *BaseApp) MountStores(keys ...storetypes.StoreKey) {
app.msgServiceRouter.SetModuleName(keys)

for _, key := range keys {
switch key.(type) {
case *storetypes.KVStoreKey:
Expand Down Expand Up @@ -796,7 +798,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s
}

// create message events
msgEvents := createEvents(msg).AppendEvents(msgResult.GetEvents())
msgEvents := createEvents(msg, app.msgServiceRouter.moduleNames[msg.String()]).AppendEvents(msgResult.GetEvents())

// append message events, data and logs
//
Expand Down Expand Up @@ -838,7 +840,7 @@ func makeABCIData(msgResponses []*codectypes.Any) ([]byte, error) {
return proto.Marshal(&sdk.TxMsgData{MsgResponses: msgResponses})
}

func createEvents(msg sdk.Msg) sdk.Events {
func createEvents(msg sdk.Msg, name string) sdk.Events {
eventMsgName := sdk.MsgTypeURL(msg)
msgEvent := sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, eventMsgName))

Expand All @@ -847,12 +849,7 @@ func createEvents(msg sdk.Msg) sdk.Events {
msgEvent = msgEvent.AppendAttributes(sdk.NewAttribute(sdk.AttributeKeySender, msg.GetSigners()[0].String()))
}

// here we assume that routes module name is the second element of the route
// e.g. "cosmos.bank.v1beta1.MsgSend" => "bank"
moduleName := strings.Split(eventMsgName, ".")
if len(moduleName) > 1 {
msgEvent = msgEvent.AppendAttributes(sdk.NewAttribute(sdk.AttributeKeyModule, moduleName[1]))
}
msgEvent = msgEvent.AppendAttributes(sdk.NewAttribute(sdk.AttributeKeyModule, name))

return sdk.Events{msgEvent}
}
Expand Down
39 changes: 37 additions & 2 deletions baseapp/msg_service_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package baseapp
import (
"context"
"fmt"
"strings"

gogogrpc "github.com/cosmos/gogoproto/grpc"
"github.com/cosmos/gogoproto/proto"
"google.golang.org/grpc"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
Expand All @@ -17,20 +19,34 @@ import (
type MsgServiceRouter struct {
interfaceRegistry codectypes.InterfaceRegistry
routes map[string]MsgServiceHandler

// map of module names associated with each Msg service msgURL/moduleName, to be used for events and error wrapping
moduleNames map[string]string // map of module names associated with each Msg service msgURL/moduleName
names map[string]struct{} // map of module names set when keys are set in the store. Assumption is module name == storekey and the message url contains the module name
}

var _ gogogrpc.Server = &MsgServiceRouter{}

// NewMsgServiceRouter creates a new MsgServiceRouter.
func NewMsgServiceRouter() *MsgServiceRouter {
return &MsgServiceRouter{
routes: map[string]MsgServiceHandler{},
routes: map[string]MsgServiceHandler{},
moduleNames: map[string]string{},
}
}

// MsgServiceHandler defines a function type which handles Msg service message.
type MsgServiceHandler = func(ctx sdk.Context, req sdk.Msg) (*sdk.Result, error)

// SetModuleName sets a module name used
func (msr *MsgServiceRouter) SetModuleName(names []storetypes.StoreKey) {
msr.names = make(map[string]struct{})

for _, e := range names {
msr.names[e.Name()] = struct{}{}
}
}

// 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)]
Expand All @@ -54,9 +70,13 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter
for _, method := range sd.Methods {
fqMethod := fmt.Sprintf("/%s/%s", sd.ServiceName, method.MethodName)
methodHandler := method.Handler

var requestTypeName string

// check if the new map contains the service name, if not add it
// add the module name from the moduleNames map associated with the service name

// fmt.Println(msr.moduleNames, "msr.moduleName", sd.ServiceName)

// NOTE: This is how we pull the concrete request type for each handler for registering in the InterfaceRegistry.
// This approach is maybe a bit hacky, but less hacky than reflecting on the handler object itself.
// We use a no-op interceptor to avoid actually calling into the handler itself.
Expand All @@ -73,6 +93,7 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter
return nil
}, noopInterceptor)

msr.RegisterModuleNames(requestTypeName)
// Check that the service Msg fully-qualified method name has already
// been registered (via RegisterInterfaces). If the user registers a
// service without registering according service Msg type, there might be
Expand Down Expand Up @@ -138,6 +159,20 @@ func (msr *MsgServiceRouter) SetInterfaceRegistry(interfaceRegistry codectypes.I
msr.interfaceRegistry = interfaceRegistry
}

// RegisterModuleNames adds the module name to the message url
func (msr *MsgServiceRouter) RegisterModuleNames(msgUrl string) {
// assign a module name to the message url
if _, ok := msr.moduleNames[msgUrl]; !ok {
for k := range msr.names {
if strings.Contains(msgUrl, k) {
if !strings.Contains(k, ":") { // avoid setting moduleurl to storekeys like transient:params
msr.moduleNames[msgUrl] = k // put the module name on the message url
}
}
}
Comment on lines +166 to +172

Check failure

Code scanning / gosec

the value in the range statement should be _ unless copying a map: want: for key := range m

got *ast.IfStmt; expected exactly 1 statement (either append or delete) in a range with a map
Comment on lines +166 to +172

Check warning

Code scanning / CodeQL

Iteration over map

Iteration over map may be a possible source of non-determinism
}
}

func noopDecoder(_ interface{}) error { return nil }
func noopInterceptor(_ context.Context, _ interface{}, _ *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (interface{}, error) {
return nil, nil
Expand Down
13 changes: 13 additions & 0 deletions baseapp/msg_service_router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import (
dbm "github.com/tendermint/tm-db"

"cosmossdk.io/depinject"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/runtime"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
Expand Down Expand Up @@ -143,3 +145,14 @@ func TestMsgService(t *testing.T) {
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.Equal(t, abci.CodeTypeOK, res.Code, "res=%+v", res)
}

func TestSetModuleName(t *testing.T) {
modules := []storetypes.StoreKey{storetypes.NewKVStoreKey("staking"), storetypes.NewKVStoreKey("transient:staking")}

msgServer := baseapp.NewMsgServiceRouter()
msgServer.SetModuleName(modules)
msgUrls := []string{"/cosmos.slashing.v1beta1.MsgUnjail", "/cosmos.slashing.v1beta1.MsgUpdateParams", "/cosmos.staking.v1beta1.MsgCreateValidator", "/cosmos.staking.v1beta1.MsgEditValidator", "/cosmos.staking.v1beta1.MsgDelegate", "/cosmos.staking.v1beta1.MsgBeginRedelegate", "/cosmos.staking.v1beta1.MsgUndelegate", "/cosmos.staking.v1beta1.MsgCancelUnbondingDelegation", "/cosmos.staking.v1beta1.MsgUpdateParams"}
for _, url := range msgUrls {
msgServer.RegisterModuleNames(url)
}
}
20 changes: 10 additions & 10 deletions x/bank/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ type AppModule struct {

var _ appmodule.AppModule = AppModule{}

// NewAppModule creates a new AppModule object
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper, ss exported.Subspace) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{cdc: cdc},
keeper: keeper,
accountKeeper: accountKeeper,
legacySubspace: ss,
}
}

// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
func (am AppModule) IsOnePerModuleType() {}

Expand All @@ -132,16 +142,6 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
}
}

// NewAppModule creates a new AppModule object
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper, ss exported.Subspace) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{cdc: cdc},
keeper: keeper,
accountKeeper: accountKeeper,
legacySubspace: ss,
}
}

// Name returns the bank module's name.
func (AppModule) Name() string { return types.ModuleName }

Expand Down