diff --git a/core/router/service.go b/core/router/service.go index 50b1865e6800..95c65f851e0c 100644 --- a/core/router/service.go +++ b/core/router/service.go @@ -11,8 +11,6 @@ import ( type Service interface { // CanInvoke returns an error if the given request cannot be invoked. CanInvoke(ctx context.Context, typeURL string) error - // InvokeTyped execute a message or query. It should be used when the called knows the type of the response. - InvokeTyped(ctx context.Context, req, res transaction.Msg) error - // InvokeUntyped execute a Msg or query. It should be used when the called doesn't know the type of the response. - InvokeUntyped(ctx context.Context, req transaction.Msg) (res transaction.Msg, err error) + // Invoke execute a message or query. The response should be type casted by the caller to the expected response. + Invoke(ctx context.Context, req transaction.Msg) (res transaction.Msg, err error) } diff --git a/docs/rfc/rfc-006-handlers.md b/docs/rfc/rfc-006-handlers.md index 479b2006300f..a22992ccdb0c 100644 --- a/docs/rfc/rfc-006-handlers.md +++ b/docs/rfc/rfc-006-handlers.md @@ -79,11 +79,11 @@ import ( type PreMsgHandlerRouter interface { // RegisterGlobalPreMsgHandler will register a pre msg handler that hooks before any message executes. // Handler will be called before ANY message executes. - RegisterGlobalPreMsgHandler(handler func(ctx context.Context, msg protoiface.MessageV1) error) + RegisterGlobalPreMsgHandler(handler func(ctx context.Context, msg transaction.Msg) error) // RegisterPreMsgHandler will register a pre msg handler that hooks before the provided message // with the given message name executes. Handler will be called before the message is executed // by the module. - RegisterPreMsgHandler(msgName string, handler func(ctx context.Context, msg protoiface.MessageV1) error) + RegisterPreMsgHandler(msgName string, handler func(ctx context.Context, msg transaction.Msg) error) } type HasPreMsgHandler interface { @@ -105,11 +105,11 @@ import ( type PostMsgHandlerRouter interface { // RegisterGlobalPostMsgHandler will register a post msg handler that hooks after any message executes. // Handler will be called after ANY message executes, alongside the response. - RegisterGlobalPostMsgHandler(handler func(ctx context.Context, msg, msgResp protoiface.MessageV1) error) + RegisterGlobalPostMsgHandler(handler func(ctx context.Context, msg, msgResp transaction.Msg) error) // RegisterPostMsgHandler will register a pre msg handler that hooks after the provided message // with the given message name executes. Handler will be called after the message is executed // by the module, alongside the response returned by the module. - RegisterPostMsgHandler(msgName string, handler func(ctx context.Context, msg, msgResp protoiface.MessageV1) error) + RegisterPostMsgHandler(msgName string, handler func(ctx context.Context, msg, msgResp transaction.Msg) error) } type HasPostMsgHandler interface { @@ -142,7 +142,7 @@ import ( ) type MsgHandlerRouter interface { - RegisterMsgHandler(msgName string, handler func(ctx context.Context, msg protoiface.MessageV1) (msgResp protoiface.MessageV1, err error)) + RegisterMsgHandler(msgName string, handler func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error)) } type HasMsgHandler interface { @@ -150,7 +150,7 @@ type HasMsgHandler interface { } // RegisterMsgHandler is a helper function to retain type safety when creating handlers, so we do not need to cast messages. -func RegisterMsgHandler[Req, Resp protoiface.MessageV1](router MsgHandlerRouter, handler func(ctx context.Context, req Req) (resp Resp, err error)) { +func RegisterMsgHandler[Req, Resp transaction.Msg](router MsgHandlerRouter, handler func(ctx context.Context, req Req) (resp Resp, err error)) { // impl detail } ``` @@ -186,7 +186,7 @@ import ( ) type QueryHandlerRouter interface { - RegisterQueryHandler(msgName string, handler func(ctx context.Context, req protoiface.MessageV1) (resp protoiface.MessageV1, err error)) + RegisterQueryHandler(msgName string, handler func(ctx context.Context, req transaction.Msg) (resp transaction.Msg, err error)) } type HasQueryHandler interface { @@ -194,7 +194,7 @@ type HasQueryHandler interface { } // RegisterQueryHandler is a helper function to retain type safety when creating handlers, so we do not need to cast messages. -func RegisterQueryHandler[Req, Resp protoiface.MessageV1](router QueryHandlerRouter, handler func(ctx context.Context, req Req) (resp Resp, err error)) { +func RegisterQueryHandler[Req, Resp transaction.Msg](router QueryHandlerRouter, handler func(ctx context.Context, req Req) (resp Resp, err error)) { // impl detail } diff --git a/runtime/router.go b/runtime/router.go index 8c30f2a27929..86ba89289d47 100644 --- a/runtime/router.go +++ b/runtime/router.go @@ -45,21 +45,8 @@ func (m *msgRouterService) CanInvoke(ctx context.Context, typeURL string) error return nil } -// InvokeTyped execute a message and fill-in a response. -// The response must be known and passed as a parameter. -// Use InvokeUntyped if the response type is not known. -func (m *msgRouterService) InvokeTyped(ctx context.Context, msg, resp gogoproto.Message) error { - messageName := msgTypeURL(msg) - handler := m.router.HybridHandlerByMsgName(messageName) - if handler == nil { - return fmt.Errorf("unknown message: %s", messageName) - } - - return handler(ctx, msg, resp) -} - -// InvokeUntyped execute a message and returns a response. -func (m *msgRouterService) InvokeUntyped(ctx context.Context, msg gogoproto.Message) (gogoproto.Message, error) { +// Invoke execute a message and returns a response. +func (m *msgRouterService) Invoke(ctx context.Context, msg gogoproto.Message) (gogoproto.Message, error) { messageName := msgTypeURL(msg) respName := m.router.ResponseNameByMsgName(messageName) if respName == "" { @@ -76,7 +63,16 @@ func (m *msgRouterService) InvokeUntyped(ctx context.Context, msg gogoproto.Mess return nil, fmt.Errorf("could not create response message %s", respName) } - return msgResp, m.InvokeTyped(ctx, msg, msgResp) + handler := m.router.HybridHandlerByMsgName(messageName) + if handler == nil { + return nil, fmt.Errorf("unknown message: %s", messageName) + } + + if err := handler(ctx, msg, msgResp); err != nil { + return nil, err + } + + return msgResp, nil } // NewQueryRouterService implements router.Service. @@ -110,27 +106,12 @@ func (m *queryRouterService) CanInvoke(ctx context.Context, typeURL string) erro return nil } -// InvokeTyped execute a message and fill-in a response. -// The response must be known and passed as a parameter. -// Use InvokeUntyped if the response type is not known. -func (m *queryRouterService) InvokeTyped(ctx context.Context, req, resp gogoproto.Message) error { - reqName := msgTypeURL(req) - handlers := m.router.HybridHandlerByRequestName(reqName) - if len(handlers) == 0 { - return fmt.Errorf("unknown request: %s", reqName) - } else if len(handlers) > 1 { - return fmt.Errorf("ambiguous request, query have multiple handlers: %s", reqName) - } - - return handlers[0](ctx, req, resp) -} - -// InvokeUntyped execute a message and returns a response. -func (m *queryRouterService) InvokeUntyped(ctx context.Context, req gogoproto.Message) (gogoproto.Message, error) { +// Invoke execute a message and returns a response. +func (m *queryRouterService) Invoke(ctx context.Context, req gogoproto.Message) (gogoproto.Message, error) { reqName := msgTypeURL(req) respName := m.router.ResponseNameByRequestName(reqName) if respName == "" { - return nil, fmt.Errorf("could not find response type for request %s (%T)", reqName, req) + return nil, fmt.Errorf("unknown request: could not find response type for request %s (%T)", reqName, req) } // get response type @@ -143,7 +124,18 @@ func (m *queryRouterService) InvokeUntyped(ctx context.Context, req gogoproto.Me return nil, fmt.Errorf("could not create response request %s", respName) } - return reqResp, m.InvokeTyped(ctx, req, reqResp) + handlers := m.router.HybridHandlerByRequestName(reqName) + if len(handlers) == 0 { + return nil, fmt.Errorf("unknown request: %s", reqName) + } else if len(handlers) > 1 { + return nil, fmt.Errorf("ambiguous request, query have multiple handlers: %s", reqName) + } + + if err := handlers[0](ctx, req, reqResp); err != nil { + return nil, err + } + + return reqResp, nil } // msgTypeURL returns the TypeURL of a proto message. diff --git a/runtime/router_test.go b/runtime/router_test.go index 2eec2197a4db..00e20ccdd091 100644 --- a/runtime/router_test.go +++ b/runtime/router_test.go @@ -6,7 +6,6 @@ import ( "github.com/stretchr/testify/require" bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" - counterv1 "cosmossdk.io/api/cosmos/counter/v1" coretesting "cosmossdk.io/core/testing" storetypes "cosmossdk.io/store/types" @@ -38,12 +37,12 @@ func TestRouterService(t *testing.T) { // Messages t.Run("invalid msg", func(t *testing.T) { - _, err := messageRouterService.InvokeUntyped(testCtx.Ctx, &bankv1beta1.MsgSend{}) + _, err := messageRouterService.Invoke(testCtx.Ctx, &bankv1beta1.MsgSend{}) require.ErrorContains(t, err, "could not find response type for message cosmos.bank.v1beta1.MsgSend") }) - t.Run("invoke untyped: valid msg (proto v1)", func(t *testing.T) { - resp, err := messageRouterService.InvokeUntyped(testCtx.Ctx, &countertypes.MsgIncreaseCounter{ + t.Run("invoke: valid msg (proto v1)", func(t *testing.T) { + resp, err := messageRouterService.Invoke(testCtx.Ctx, &countertypes.MsgIncreaseCounter{ Signer: "cosmos1", Count: 42, }) @@ -51,57 +50,17 @@ func TestRouterService(t *testing.T) { require.NotNil(t, resp) }) - t.Run("invoke typed: valid msg (proto v1)", func(t *testing.T) { - resp := &countertypes.MsgIncreaseCountResponse{} - err := messageRouterService.InvokeTyped(testCtx.Ctx, &countertypes.MsgIncreaseCounter{ - Signer: "cosmos1", - Count: 42, - }, resp) - require.NoError(t, err) - require.NotNil(t, resp) - }) - - t.Run("invoke typed: valid msg (proto v2)", func(t *testing.T) { - resp := &counterv1.MsgIncreaseCountResponse{} - err := messageRouterService.InvokeTyped(testCtx.Ctx, &counterv1.MsgIncreaseCounter{ - Signer: "cosmos1", - Count: 42, - }, resp) - require.NoError(t, err) - require.NotNil(t, resp) - }) - // Queries t.Run("invalid query", func(t *testing.T) { - err := queryRouterService.InvokeTyped(testCtx.Ctx, &bankv1beta1.QueryBalanceRequest{}, &bankv1beta1.QueryBalanceResponse{}) - require.ErrorContains(t, err, "unknown request: cosmos.bank.v1beta1.QueryBalanceRequest") - }) - - t.Run("invoke typed: valid query (proto v1)", func(t *testing.T) { - _ = counterKeeper.CountStore.Set(testCtx.Ctx, 42) - - resp := &countertypes.QueryGetCountResponse{} - err := queryRouterService.InvokeTyped(testCtx.Ctx, &countertypes.QueryGetCountRequest{}, resp) - require.NoError(t, err) - require.NotNil(t, resp) - require.Equal(t, int64(42), resp.TotalCount) - }) - - t.Run("invoke typed: valid query (proto v2)", func(t *testing.T) { - _ = counterKeeper.CountStore.Set(testCtx.Ctx, 42) - - resp := &counterv1.QueryGetCountResponse{} - err := queryRouterService.InvokeTyped(testCtx.Ctx, &counterv1.QueryGetCountRequest{}, resp) - require.NoError(t, err) - require.NotNil(t, resp) - require.Equal(t, int64(42), resp.TotalCount) + _, err := queryRouterService.Invoke(testCtx.Ctx, &bankv1beta1.QueryBalanceRequest{}) + require.ErrorContains(t, err, "could not find response type for request cosmos.bank.v1beta1.QueryBalanceRequest") }) - t.Run("invoke untyped: valid query (proto v1)", func(t *testing.T) { + t.Run("invoke: valid query (proto v1)", func(t *testing.T) { _ = counterKeeper.CountStore.Set(testCtx.Ctx, 42) - resp, err := queryRouterService.InvokeUntyped(testCtx.Ctx, &countertypes.QueryGetCountRequest{}) + resp, err := queryRouterService.Invoke(testCtx.Ctx, &countertypes.QueryGetCountRequest{}) require.NoError(t, err) require.NotNil(t, resp) respVal, ok := resp.(*countertypes.QueryGetCountResponse) diff --git a/schema/appdata/batch_test.go b/schema/appdata/batch_test.go index 557079e225c4..0f43f07ba063 100644 --- a/schema/appdata/batch_test.go +++ b/schema/appdata/batch_test.go @@ -28,7 +28,7 @@ var testBatch = PacketBatch{ } func batchListener() (Listener, *PacketBatch) { - var got = new(PacketBatch) + got := new(PacketBatch) l := Listener{ InitializeModuleData: func(m ModuleInitializationData) error { *got = append(*got, m) diff --git a/schema/diff/diff_test.go b/schema/diff/diff_test.go index ac7563a5b6ad..159d85c3500c 100644 --- a/schema/diff/diff_test.go +++ b/schema/diff/diff_test.go @@ -290,7 +290,8 @@ func TestCompareModuleSchemas(t *testing.T) { { Name: "foo", KeyFields: []schema.Field{{Name: "key1", Kind: schema.EnumKind, EnumType: schema.EnumType{Name: "bar", Values: []string{"a"}}}}, - }}, + }, + }, AddedObjectTypes: []schema.ObjectType{ { Name: "bar", diff --git a/scripts/mockgen.sh b/scripts/mockgen.sh index eef0730c881a..f13f02349663 100755 --- a/scripts/mockgen.sh +++ b/scripts/mockgen.sh @@ -13,7 +13,7 @@ $mockgen_cmd -source=x/nft/expected_keepers.go -package testutil -destination x/ $mockgen_cmd -source=x/feegrant/expected_keepers.go -package testutil -destination x/feegrant/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/mint/types/expected_keepers.go -package testutil -destination x/mint/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/auth/tx/config/expected_keepers.go -package testutil -destination x/auth/tx/testutil/expected_keepers_mocks.go -$mockgen_cmd -source=x/auth/types/expected_keepers.go -package testutil -destination x/auth/testutil/expected_keepers_mocks.go +# $mockgen_cmd -source=x/auth/types/expected_keepers.go -package testutil -destination x/auth/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/auth/ante/expected_keepers.go -package testutil -destination x/auth/ante/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/authz/expected_keepers.go -package testutil -destination x/authz/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/bank/types/expected_keepers.go -package testutil -destination x/bank/testutil/expected_keepers_mocks.go @@ -24,5 +24,5 @@ $mockgen_cmd -source=x/slashing/types/expected_keepers.go -package testutil -des $mockgen_cmd -source=x/genutil/types/expected_keepers.go -package testutil -destination x/genutil/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/gov/testutil/expected_keepers.go -package testutil -destination x/gov/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/staking/types/expected_keepers.go -package testutil -destination x/staking/testutil/expected_keepers_mocks.go -$mockgen_cmd -source=x/auth/vesting/types/expected_keepers.go -package testutil -destination x/auth/vesting/testutil/expected_keepers_mocks.go +# $mockgen_cmd -source=x/auth/vesting/types/expected_keepers.go -package testutil -destination x/auth/vesting/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/protocolpool/types/expected_keepers.go -package testutil -destination x/protocolpool/testutil/expected_keepers_mocks.go diff --git a/server/v2/stf/core_router_service.go b/server/v2/stf/core_router_service.go index 4d0115d148e3..e3a3f95940a6 100644 --- a/server/v2/stf/core_router_service.go +++ b/server/v2/stf/core_router_service.go @@ -31,26 +31,14 @@ func (m msgRouterService) CanInvoke(ctx context.Context, typeURL string) error { return exCtx.msgRouter.CanInvoke(ctx, typeURL) } -// InvokeTyped execute a message and fill-in a response. -// The response must be known and passed as a parameter. -// Use InvokeUntyped if the response type is not known. -func (m msgRouterService) InvokeTyped(ctx context.Context, msg, resp transaction.Msg) error { - exCtx, err := getExecutionCtxFromContext(ctx) - if err != nil { - return err - } - - return exCtx.msgRouter.InvokeTyped(ctx, msg, resp) -} - -// InvokeUntyped execute a message and returns a response. -func (m msgRouterService) InvokeUntyped(ctx context.Context, msg transaction.Msg) (transaction.Msg, error) { +// Invoke execute a message and returns a response. +func (m msgRouterService) Invoke(ctx context.Context, msg transaction.Msg) (transaction.Msg, error) { exCtx, err := getExecutionCtxFromContext(ctx) if err != nil { return nil, err } - return exCtx.msgRouter.InvokeUntyped(ctx, msg) + return exCtx.msgRouter.Invoke(ctx, msg) } // NewQueryRouterService implements router.Service. @@ -72,23 +60,8 @@ func (m queryRouterService) CanInvoke(ctx context.Context, typeURL string) error return exCtx.queryRouter.CanInvoke(ctx, typeURL) } -// InvokeTyped execute a message and fill-in a response. -// The response must be known and passed as a parameter. -// Use InvokeUntyped if the response type is not known. -func (m queryRouterService) InvokeTyped( - ctx context.Context, - req, resp transaction.Msg, -) error { - exCtx, err := getExecutionCtxFromContext(ctx) - if err != nil { - return err - } - - return exCtx.queryRouter.InvokeTyped(ctx, req, resp) -} - // InvokeUntyped execute a message and returns a response. -func (m queryRouterService) InvokeUntyped( +func (m queryRouterService) Invoke( ctx context.Context, req transaction.Msg, ) (transaction.Msg, error) { @@ -97,5 +70,5 @@ func (m queryRouterService) InvokeUntyped( return nil, err } - return exCtx.queryRouter.InvokeUntyped(ctx, req) + return exCtx.queryRouter.Invoke(ctx, req) } diff --git a/server/v2/stf/stf.go b/server/v2/stf/stf.go index 1ef5a50eae16..43fa6bcf9c3f 100644 --- a/server/v2/stf/stf.go +++ b/server/v2/stf/stf.go @@ -321,7 +321,7 @@ func (s STF[T]) runTxMsgs( execCtx.setGasLimit(gasLimit) for i, msg := range msgs { execCtx.sender = txSenders[i] - resp, err := s.msgRouter.InvokeUntyped(execCtx, msg) + resp, err := s.msgRouter.Invoke(execCtx, msg) if err != nil { return nil, 0, nil, fmt.Errorf("message execution at index %d failed: %w", i, err) } @@ -457,7 +457,7 @@ func (s STF[T]) Query( queryCtx := s.makeContext(ctx, nil, queryState, internal.ExecModeSimulate) queryCtx.setHeaderInfo(hi) queryCtx.setGasLimit(gasLimit) - return s.queryRouter.InvokeUntyped(queryCtx, req) + return s.queryRouter.Invoke(queryCtx, req) } // RunWithCtx is made to support genesis, if genesis was just the execution of messages instead diff --git a/server/v2/stf/stf_router.go b/server/v2/stf/stf_router.go index 06abb61fb735..0593dddf71b4 100644 --- a/server/v2/stf/stf_router.go +++ b/server/v2/stf/stf_router.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "reflect" "strings" gogoproto "github.com/cosmos/gogoproto/proto" @@ -160,54 +159,12 @@ func (r coreRouterImpl) CanInvoke(_ context.Context, typeURL string) error { return nil } -func (r coreRouterImpl) InvokeTyped(ctx context.Context, req, resp transaction.Msg) error { - handlerResp, err := r.InvokeUntyped(ctx, req) - if err != nil { - return err - } - return merge(handlerResp, resp) -} - -func (r coreRouterImpl) InvokeUntyped(ctx context.Context, req transaction.Msg) (res transaction.Msg, err error) { +func (r coreRouterImpl) Invoke(ctx context.Context, req transaction.Msg) (res transaction.Msg, err error) { typeName := msgTypeURL(req) handler, exists := r.handlers[typeName] if !exists { return nil, fmt.Errorf("%w: %s", ErrNoHandler, typeName) } - return handler(ctx, req) -} - -// merge merges together two protobuf messages by setting the pointer -// to src in dst. Used internally. -func merge(src, dst gogoproto.Message) error { - if src == nil { - return fmt.Errorf("source message is nil") - } - if dst == nil { - return fmt.Errorf("destination message is nil") - } - srcVal := reflect.ValueOf(src) - dstVal := reflect.ValueOf(dst) - - if srcVal.Kind() == reflect.Interface { - srcVal = srcVal.Elem() - } - if dstVal.Kind() == reflect.Interface { - dstVal = dstVal.Elem() - } - - if srcVal.Kind() != reflect.Ptr || dstVal.Kind() != reflect.Ptr { - return fmt.Errorf("both source and destination must be pointers") - } - - srcElem := srcVal.Elem() - dstElem := dstVal.Elem() - - if !srcElem.Type().AssignableTo(dstElem.Type()) { - return fmt.Errorf("incompatible types: cannot merge %v into %v", srcElem.Type(), dstElem.Type()) - } - - dstElem.Set(srcElem) - return nil + return handler(ctx, req) } diff --git a/server/v2/stf/stf_router_test.go b/server/v2/stf/stf_router_test.go index 3f6e9ef68809..91d6c9417176 100644 --- a/server/v2/stf/stf_router_test.go +++ b/server/v2/stf/stf_router_test.go @@ -6,7 +6,6 @@ import ( gogoproto "github.com/cosmos/gogoproto/proto" gogotypes "github.com/cosmos/gogoproto/types" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "cosmossdk.io/core/appmodule/v2" @@ -41,68 +40,9 @@ func TestRouter(t *testing.T) { require.Error(t, err) }) - t.Run("invoke untyped", func(t *testing.T) { - gotResp, err := router.InvokeUntyped(context.Background(), expectedMsg) + t.Run("invoke", func(t *testing.T) { + gotResp, err := router.Invoke(context.Background(), expectedMsg) require.NoError(t, err) require.Equal(t, expectedResp, gotResp) }) - - t.Run("invoked typed", func(t *testing.T) { - gotResp := new(gogotypes.StringValue) - err := router.InvokeTyped(context.Background(), expectedMsg, gotResp) - require.NoError(t, err) - require.Equal(t, expectedResp, gotResp) - }) -} - -func TestMerge(t *testing.T) { - tests := []struct { - name string - src transaction.Msg - dst transaction.Msg - expected transaction.Msg - wantErr bool - }{ - { - name: "success", - src: &gogotypes.BoolValue{Value: true}, - dst: &gogotypes.BoolValue{}, - expected: &gogotypes.BoolValue{Value: true}, - wantErr: false, - }, - { - name: "nil src", - src: nil, - dst: &gogotypes.StringValue{}, - expected: &gogotypes.StringValue{}, - wantErr: true, - }, - { - name: "nil dst", - src: &gogotypes.StringValue{Value: "hello"}, - dst: nil, - expected: nil, - wantErr: true, - }, - { - name: "incompatible types", - src: &gogotypes.StringValue{Value: "hello"}, - dst: &gogotypes.BoolValue{}, - expected: &gogotypes.BoolValue{}, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := merge(tt.src, tt.dst) - - if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tt.expected, tt.dst) - } - }) - } } diff --git a/simapp/mint_fn.go b/simapp/mint_fn.go index dcb9f96c7ff6..1ed53166b345 100644 --- a/simapp/mint_fn.go +++ b/simapp/mint_fn.go @@ -3,6 +3,7 @@ package simapp import ( "context" "encoding/binary" + "fmt" "cosmossdk.io/core/appmodule" "cosmossdk.io/core/event" @@ -29,31 +30,45 @@ func ProvideExampleMintFn(bankKeeper MintBankKeeper) minttypes.MintFn { return nil } - var stakingParams stakingtypes.QueryParamsResponse - err := env.QueryRouterService.InvokeTyped(ctx, &stakingtypes.QueryParamsRequest{}, &stakingParams) + resp, err := env.QueryRouterService.Invoke(ctx, &stakingtypes.QueryParamsRequest{}) if err != nil { return err } + stakingParams, ok := resp.(*stakingtypes.QueryParamsResponse) + if !ok { + return fmt.Errorf("unexpected response type: %T", resp) + } - var bankSupply banktypes.QuerySupplyOfResponse - err = env.QueryRouterService.InvokeTyped(ctx, &banktypes.QuerySupplyOfRequest{Denom: stakingParams.Params.BondDenom}, &bankSupply) + resp, err = env.QueryRouterService.Invoke(ctx, &banktypes.QuerySupplyOfRequest{Denom: stakingParams.Params.BondDenom}) if err != nil { return err } + bankSupply, ok := resp.(*banktypes.QuerySupplyOfResponse) + if !ok { + return fmt.Errorf("unexpected response type: %T", resp) + } + stakingTokenSupply := bankSupply.Amount - var mintParams minttypes.QueryParamsResponse - err = env.QueryRouterService.InvokeTyped(ctx, &minttypes.QueryParamsRequest{}, &mintParams) + resp, err = env.QueryRouterService.Invoke(ctx, &minttypes.QueryParamsRequest{}) if err != nil { return err } + mintParams, ok := resp.(*minttypes.QueryParamsResponse) + if !ok { + return fmt.Errorf("unexpected response type: %T", resp) + } - var stakingPool stakingtypes.QueryPoolResponse - err = env.QueryRouterService.InvokeTyped(ctx, &stakingtypes.QueryPoolRequest{}, &stakingPool) + resp, err = env.QueryRouterService.Invoke(ctx, &stakingtypes.QueryPoolRequest{}) if err != nil { return err } + stakingPool, ok := resp.(*stakingtypes.QueryPoolResponse) + if !ok { + return fmt.Errorf("unexpected response type: %T", resp) + } + // bondedRatio bondedRatio := math.LegacyNewDecFromInt(stakingPool.Pool.BondedTokens).QuoInt(stakingTokenSupply.Amount) minter.Inflation = minter.NextInflationRate(mintParams.Params, bondedRatio) diff --git a/tests/e2e/accounts/lockup/utils.go b/tests/e2e/accounts/lockup/utils.go index b1a90d7ece72..69606d58d743 100644 --- a/tests/e2e/accounts/lockup/utils.go +++ b/tests/e2e/accounts/lockup/utils.go @@ -5,8 +5,8 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - "google.golang.org/protobuf/runtime/protoiface" + "cosmossdk.io/core/transaction" "cosmossdk.io/simapp" "cosmossdk.io/x/accounts/defaults/lockup/types" "cosmossdk.io/x/bank/testutil" @@ -15,8 +15,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -type ProtoMsg = protoiface.MessageV1 - var ( ownerAddr = secp256k1.GenPrivKey().PubKey().Address() accOwner = sdk.AccAddress(ownerAddr) @@ -52,7 +50,7 @@ func (s *E2ETestSuite) executeTx(ctx sdk.Context, msg sdk.Msg, app *simapp.SimAp return err } -func (s *E2ETestSuite) queryAcc(ctx sdk.Context, req sdk.Msg, app *simapp.SimApp, accAddr []byte) (ProtoMsg, error) { +func (s *E2ETestSuite) queryAcc(ctx sdk.Context, req sdk.Msg, app *simapp.SimApp, accAddr []byte) (transaction.Msg, error) { resp, err := app.AccountsKeeper.Query(ctx, accAddr, req) return resp, err } diff --git a/tests/e2e/accounts/multisig/test_suite.go b/tests/e2e/accounts/multisig/test_suite.go index 1f333cf2a0c7..3aa23f147d25 100644 --- a/tests/e2e/accounts/multisig/test_suite.go +++ b/tests/e2e/accounts/multisig/test_suite.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - "google.golang.org/protobuf/runtime/protoiface" + "cosmossdk.io/core/transaction" "cosmossdk.io/math" "cosmossdk.io/simapp" multisigaccount "cosmossdk.io/x/accounts/defaults/multisig" @@ -19,8 +19,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -type ProtoMsg = protoiface.MessageV1 - type E2ETestSuite struct { suite.Suite @@ -59,7 +57,7 @@ func (s *E2ETestSuite) executeTx(ctx context.Context, msg sdk.Msg, accAddr, send return err } -func (s *E2ETestSuite) queryAcc(ctx context.Context, req sdk.Msg, accAddr []byte) (ProtoMsg, error) { +func (s *E2ETestSuite) queryAcc(ctx context.Context, req sdk.Msg, accAddr []byte) (transaction.Msg, error) { resp, err := s.app.AccountsKeeper.Query(ctx, accAddr, req) return resp, err } diff --git a/testutil/mock/types_module_module.go b/testutil/mock/types_module_module.go index 6e8832ec9cfc..be1de62e6626 100644 --- a/testutil/mock/types_module_module.go +++ b/testutil/mock/types_module_module.go @@ -14,6 +14,7 @@ import ( module "github.com/cosmos/cosmos-sdk/types/module" gomock "github.com/golang/mock/gomock" runtime "github.com/grpc-ecosystem/grpc-gateway/runtime" + grpc "google.golang.org/grpc" ) // MockAppModuleBasic is a mock of AppModuleBasic interface. @@ -264,6 +265,67 @@ func (mr *MockHasServicesMockRecorder) RegisterServices(arg0 interface{}) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterServices", reflect.TypeOf((*MockHasServices)(nil).RegisterServices), arg0) } +// MockhasServicesV1 is a mock of hasServicesV1 interface. +type MockhasServicesV1 struct { + ctrl *gomock.Controller + recorder *MockhasServicesV1MockRecorder +} + +// MockhasServicesV1MockRecorder is the mock recorder for MockhasServicesV1. +type MockhasServicesV1MockRecorder struct { + mock *MockhasServicesV1 +} + +// NewMockhasServicesV1 creates a new mock instance. +func NewMockhasServicesV1(ctrl *gomock.Controller) *MockhasServicesV1 { + mock := &MockhasServicesV1{ctrl: ctrl} + mock.recorder = &MockhasServicesV1MockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockhasServicesV1) EXPECT() *MockhasServicesV1MockRecorder { + return m.recorder +} + +// IsAppModule mocks base method. +func (m *MockhasServicesV1) IsAppModule() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "IsAppModule") +} + +// IsAppModule indicates an expected call of IsAppModule. +func (mr *MockhasServicesV1MockRecorder) IsAppModule() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAppModule", reflect.TypeOf((*MockhasServicesV1)(nil).IsAppModule)) +} + +// IsOnePerModuleType mocks base method. +func (m *MockhasServicesV1) IsOnePerModuleType() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "IsOnePerModuleType") +} + +// IsOnePerModuleType indicates an expected call of IsOnePerModuleType. +func (mr *MockhasServicesV1MockRecorder) IsOnePerModuleType() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsOnePerModuleType", reflect.TypeOf((*MockhasServicesV1)(nil).IsOnePerModuleType)) +} + +// RegisterServices mocks base method. +func (m *MockhasServicesV1) RegisterServices(arg0 grpc.ServiceRegistrar) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RegisterServices", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// RegisterServices indicates an expected call of RegisterServices. +func (mr *MockhasServicesV1MockRecorder) RegisterServices(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterServices", reflect.TypeOf((*MockhasServicesV1)(nil).RegisterServices), arg0) +} + // MockHasABCIEndBlock is a mock of HasABCIEndBlock interface. type MockHasABCIEndBlock struct { ctrl *gomock.Controller diff --git a/tools/cosmovisor/cmd/cosmovisor/version_test.go b/tools/cosmovisor/cmd/cosmovisor/version_test.go index 47dcb06cc74b..8f51ea47dafb 100644 --- a/tools/cosmovisor/cmd/cosmovisor/version_test.go +++ b/tools/cosmovisor/cmd/cosmovisor/version_test.go @@ -20,7 +20,7 @@ func TestVersionCommand_Error(t *testing.T) { rootCmd.SetOut(out) rootCmd.SetErr(out) - ctx := context.WithValue(context.Background(), log.ContextKey, logger) //nolint:staticcheck // SA1029: temporary issue in dependency + ctx := context.WithValue(context.Background(), log.ContextKey, logger) require.Error(t, rootCmd.ExecuteContext(ctx)) require.Contains(t, out.String(), "DAEMON_NAME is not set") diff --git a/types/module/module.go b/types/module/module.go index e24bc4f64f30..7d06c7ce2109 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -97,7 +97,7 @@ type HasServices interface { // hasServicesV1 is the interface for registering service in baseapp Cosmos SDK. // This API is part of core/appmodule but commented out for dependencies. type hasServicesV1 interface { - appmodule.AppModule + appmodulev2.AppModule RegisterServices(grpc.ServiceRegistrar) error } diff --git a/x/accounts/account_test.go b/x/accounts/account_test.go index 6d6834b90fa7..f5b7b8117125 100644 --- a/x/accounts/account_test.go +++ b/x/accounts/account_test.go @@ -2,15 +2,18 @@ package accounts import ( "context" + "fmt" "strconv" "github.com/cosmos/gogoproto/types" - bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" - basev1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" "cosmossdk.io/collections" + "cosmossdk.io/math" "cosmossdk.io/x/accounts/accountstd" "cosmossdk.io/x/accounts/internal/implementation" + banktypes "cosmossdk.io/x/bank/types" + + sdk "github.com/cosmos/cosmos-sdk/types" ) var _ implementation.Account = (*TestAccount)(nil) @@ -28,7 +31,7 @@ type TestAccount struct { func (t TestAccount) RegisterInitHandler(builder *implementation.InitBuilder) { implementation.RegisterInitHandler(builder, func(ctx context.Context, _ *types.Empty) (*types.Empty, error) { // we also force a module call here to test things work as expected. - _, err := implementation.QueryModule[bankv1beta1.QueryBalanceResponse](ctx, &bankv1beta1.QueryBalanceRequest{ + _, err := implementation.QueryModule(ctx, &banktypes.QueryBalanceRequest{ Address: string(implementation.Whoami(ctx)), Denom: "atom", }) @@ -52,15 +55,10 @@ func (t TestAccount) RegisterExecuteHandlers(builder *implementation.ExecuteBuil // this is for intermodule comms testing, we simulate a bank send implementation.RegisterExecuteHandler(builder, func(ctx context.Context, req *types.Int64Value) (*types.Empty, error) { - resp, err := implementation.ExecModule[bankv1beta1.MsgSendResponse](ctx, &bankv1beta1.MsgSend{ + resp, err := implementation.ExecModule(ctx, &banktypes.MsgSend{ FromAddress: string(implementation.Whoami(ctx)), ToAddress: "recipient", - Amount: []*basev1beta1.Coin{ - { - Denom: "test", - Amount: strconv.FormatInt(req.Value, 10), - }, - }, + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(req.Value))), }) if err != nil { return nil, err @@ -90,7 +88,7 @@ func (t TestAccount) RegisterQueryHandlers(builder *implementation.QueryBuilder) // test intermodule comms, we simulate someone is sending the account a request for the accounts balance // of a given denom. implementation.RegisterQueryHandler(builder, func(ctx context.Context, req *types.StringValue) (*types.Int64Value, error) { - resp, err := implementation.QueryModule[bankv1beta1.QueryBalanceResponse](ctx, &bankv1beta1.QueryBalanceRequest{ + resp, err := implementation.QueryModule(ctx, &banktypes.QueryBalanceRequest{ Address: string(implementation.Whoami(ctx)), Denom: req.Value, }) @@ -98,11 +96,12 @@ func (t TestAccount) RegisterQueryHandlers(builder *implementation.QueryBuilder) return nil, err } - amt, err := strconv.ParseInt(resp.Balance.Amount, 10, 64) - if err != nil { - return nil, err + r, ok := resp.(*banktypes.QueryBalanceResponse) + if !ok { + panic(fmt.Sprintf("unexpected response type: %T", resp)) } - return &types.Int64Value{Value: amt}, nil + + return &types.Int64Value{Value: r.Balance.Amount.Int64()}, nil }) // genesis testing; DoubleValue does not make sense as a request type for this query, but empty is already taken diff --git a/x/accounts/accountstd/exports.go b/x/accounts/accountstd/exports.go index ea181db0a6b0..24ffc17c1e98 100644 --- a/x/accounts/accountstd/exports.go +++ b/x/accounts/accountstd/exports.go @@ -6,6 +6,7 @@ import ( "context" "fmt" + "cosmossdk.io/core/transaction" "cosmossdk.io/x/accounts/internal/implementation" sdk "github.com/cosmos/cosmos-sdk/types" @@ -90,18 +91,13 @@ func SenderIsAccountsModule(ctx context.Context) bool { // returns nil. func Funds(ctx context.Context) sdk.Coins { return implementation.Funds(ctx) } -// ExecModule can be used to execute a message towards a module. -func ExecModule[Resp any, RespProto implementation.ProtoMsgG[Resp], Req any, ReqProto implementation.ProtoMsgG[Req]](ctx context.Context, msg ReqProto) (RespProto, error) { - return implementation.ExecModule[Resp, RespProto, Req, ReqProto](ctx, msg) -} - -func ExecModuleUntyped(ctx context.Context, msg implementation.ProtoMsg) (implementation.ProtoMsg, error) { - return implementation.ExecModuleUntyped(ctx, msg) +func ExecModule(ctx context.Context, msg transaction.Msg) (transaction.Msg, error) { + return implementation.ExecModule(ctx, msg) } // QueryModule can be used by an account to execute a module query. -func QueryModule[Resp any, RespProto implementation.ProtoMsgG[Resp], Req any, ReqProto implementation.ProtoMsgG[Req]](ctx context.Context, req ReqProto) (RespProto, error) { - return implementation.QueryModule[Resp, RespProto, Req, ReqProto](ctx, req) +func QueryModule(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { + return implementation.QueryModule(ctx, req) } // UnpackAny unpacks a protobuf Any message generically. @@ -110,7 +106,7 @@ func UnpackAny[Msg any, ProtoMsg implementation.ProtoMsgG[Msg]](any *implementat } // PackAny packs a protobuf Any message generically. -func PackAny(msg implementation.ProtoMsg) (*implementation.Any, error) { +func PackAny(msg transaction.Msg) (*implementation.Any, error) { return implementation.PackAny(msg) } @@ -124,7 +120,7 @@ func ExecModuleAnys(ctx context.Context, msgs []*implementation.Any) ([]*impleme if err != nil { return nil, fmt.Errorf("error unpacking message %d: %w", i, err) } - resp, err := ExecModuleUntyped(ctx, concreteMessage) + resp, err := ExecModule(ctx, concreteMessage) if err != nil { return nil, fmt.Errorf("error executing message %d: %w", i, err) } diff --git a/x/accounts/accountstd/test_util.go b/x/accounts/accountstd/test_util.go index 0ab912868820..6188c265a972 100644 --- a/x/accounts/accountstd/test_util.go +++ b/x/accounts/accountstd/test_util.go @@ -4,7 +4,7 @@ import ( "context" "cosmossdk.io/core/store" - "cosmossdk.io/core/testing" + coretesting "cosmossdk.io/core/testing" "cosmossdk.io/x/accounts/internal/implementation" sdk "github.com/cosmos/cosmos-sdk/types" @@ -16,14 +16,13 @@ func NewMockContext( sender []byte, funds sdk.Coins, moduleExec implementation.ModuleExecFunc, - moduleExecUntyped implementation.ModuleExecUntypedFunc, moduleQuery implementation.ModuleQueryFunc, ) (context.Context, store.KVStoreService) { ctx := coretesting.Context() ss := coretesting.KVStoreService(ctx, "test") return implementation.MakeAccountContext( - ctx, ss, accNumber, accountAddr, sender, funds, moduleExec, moduleExecUntyped, moduleQuery, + ctx, ss, accNumber, accountAddr, sender, funds, moduleExec, moduleQuery, ), ss } diff --git a/x/accounts/coin_transfer.go b/x/accounts/coin_transfer.go index 3f0c852bb39d..096498867da1 100644 --- a/x/accounts/coin_transfer.go +++ b/x/accounts/coin_transfer.go @@ -1,12 +1,9 @@ package accounts import ( - "google.golang.org/protobuf/proto" - - bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" - v1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" "cosmossdk.io/core/address" - "cosmossdk.io/x/accounts/internal/implementation" + "cosmossdk.io/core/transaction" + banktypes "cosmossdk.io/x/bank/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -14,49 +11,22 @@ import ( // coinsTransferMsgFunc defines a function that creates a message to send coins from one // address to the other, and also a message that parses such response. // This in most cases will be implemented as a bank.MsgSend creator, but we keep x/accounts independent of bank. -type coinsTransferMsgFunc = func(from, to []byte, coins sdk.Coins) (implementation.ProtoMsg, implementation.ProtoMsg, error) - -type gogoProtoPlusV2 interface { - proto.Message - implementation.ProtoMsg -} - -// protoV2GogoWrapper is a wrapper of a protov2 message into a gogo message. -// this is exceptionally allowed to enable accounts to be decoupled from -// the SDK, since x/accounts can support only protov1 in its APIs. -// But in order to keep it decoupled from the SDK we need to use the API module. -// This is a hack to make an API module type work in x/accounts. Once the SDK -// has protov2 support, we can migrate internal/implementation/encoding.go to -// work with protov2. -type protoV2GogoWrapper struct { - gogoProtoPlusV2 -} - -func (h protoV2GogoWrapper) XXX_MessageName() string { - return string(proto.MessageName(h.gogoProtoPlusV2)) -} +type coinsTransferMsgFunc = func(from, to []byte, coins sdk.Coins) (transaction.Msg, error) func defaultCoinsTransferMsgFunc(addrCdc address.Codec) coinsTransferMsgFunc { - return func(from, to []byte, coins sdk.Coins) (implementation.ProtoMsg, implementation.ProtoMsg, error) { + return func(from, to []byte, coins sdk.Coins) (transaction.Msg, error) { fromAddr, err := addrCdc.BytesToString(from) if err != nil { - return nil, nil, err + return nil, err } toAddr, err := addrCdc.BytesToString(to) if err != nil { - return nil, nil, err - } - v2Coins := make([]*v1beta1.Coin, len(coins)) - for i, coin := range coins { - v2Coins[i] = &v1beta1.Coin{ - Denom: coin.Denom, - Amount: coin.Amount.String(), - } + return nil, err } - return protoV2GogoWrapper{&bankv1beta1.MsgSend{ + return &banktypes.MsgSend{ FromAddress: fromAddr, ToAddress: toAddr, - Amount: v2Coins, - }}, new(bankv1beta1.MsgSendResponse), nil + Amount: coins, + }, nil } } diff --git a/x/accounts/defaults/base/account.go b/x/accounts/defaults/base/account.go index 731658db403d..550227599f36 100644 --- a/x/accounts/defaults/base/account.go +++ b/x/accounts/defaults/base/account.go @@ -163,12 +163,17 @@ func (a Account) computeSignerData(ctx context.Context) (secp256k1.PubKey, signi } func (a Account) getNumber(ctx context.Context, addrStr string) (uint64, error) { - accNum, err := accountstd.QueryModule[accountsv1.AccountNumberResponse](ctx, &accountsv1.AccountNumberRequest{Address: addrStr}) + accNum, err := accountstd.QueryModule(ctx, &accountsv1.AccountNumberRequest{Address: addrStr}) if err != nil { return 0, err } - return accNum.Number, nil + resp, ok := accNum.(*accountsv1.AccountNumberResponse) + if !ok { + return 0, fmt.Errorf("unexpected response type: %T", accNum) + } + + return resp.Number, nil } func (a Account) getTxData(msg *aa_interface_v1.MsgAuthenticate) (signing.TxData, error) { diff --git a/x/accounts/defaults/base/utils_test.go b/x/accounts/defaults/base/utils_test.go index 90c2c9deb5a2..1be354d04358 100644 --- a/x/accounts/defaults/base/utils_test.go +++ b/x/accounts/defaults/base/utils_test.go @@ -5,8 +5,6 @@ import ( "testing" gogoproto "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/runtime/protoiface" signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" "cosmossdk.io/collections" @@ -14,6 +12,7 @@ import ( "cosmossdk.io/core/event" "cosmossdk.io/core/header" "cosmossdk.io/core/store" + "cosmossdk.io/core/transaction" "cosmossdk.io/x/accounts/accountstd" accountsv1 "cosmossdk.io/x/accounts/v1" "cosmossdk.io/x/tx/signing" @@ -24,8 +23,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx" ) -type ProtoMsg = protoiface.MessageV1 - // mock statecodec type mockStateCodec struct { codec.Codec @@ -58,17 +55,13 @@ func (a addressCodec) BytesToString(bz []byte) (string, error) { return string func newMockContext(t *testing.T) (context.Context, store.KVStoreService) { t.Helper() return accountstd.NewMockContext( - 0, []byte("mock_base_account"), []byte("sender"), nil, func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error { - return nil - }, func(ctx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) { + 0, []byte("mock_base_account"), []byte("sender"), nil, + func(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { return nil, nil - }, func(ctx context.Context, req, resp ProtoMsg) error { - _, ok := req.(*accountsv1.AccountNumberRequest) - require.True(t, ok) - gogoproto.Merge(resp.(gogoproto.Message), &accountsv1.AccountNumberResponse{ + }, func(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { + return &accountsv1.AccountNumberResponse{ Number: 1, - }) - return nil + }, nil }, ) } diff --git a/x/accounts/defaults/lockup/go.mod b/x/accounts/defaults/lockup/go.mod index ee2d13730e77..b32b9874285e 100644 --- a/x/accounts/defaults/lockup/go.mod +++ b/x/accounts/defaults/lockup/go.mod @@ -13,30 +13,20 @@ require ( github.com/cosmos/gogoproto v1.7.0 ) -require cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect +require github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect - cosmossdk.io/depinject v1.0.0 // indirect - github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect - github.com/cosmos/crypto v0.1.2 // indirect - github.com/dgraph-io/badger/v4 v4.2.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/flatbuffers v2.0.8+incompatible // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/supranational/blst v0.3.12 // indirect - go.opencensus.io v0.24.0 // indirect -) - -require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/api v0.7.5 // indirect + cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -53,9 +43,11 @@ require ( github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft v1.0.0-rc1 // indirect github.com/cometbft/cometbft-db v0.12.0 // indirect + github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.0.2 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 + github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/iavl v1.2.1-0.20240725141113-7adc688cf179 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect @@ -63,6 +55,7 @@ require ( github.com/danieljoos/wincred v1.2.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/dgraph-io/badger/v4 v4.2.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect @@ -75,9 +68,10 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.2.1 // indirect - github.com/golang/protobuf v1.5.4 + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect + github.com/google/flatbuffers v2.0.8+incompatible // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect @@ -100,6 +94,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/petermattis/goid v0.0.0-20240327183114-c42a807a84ba // indirect @@ -123,6 +118,7 @@ require ( github.com/spf13/viper v1.19.0 // indirect github.com/stretchr/testify v1.9.0 github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.12 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/tidwall/btree v1.7.0 // indirect @@ -131,6 +127,7 @@ require ( gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect + go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.26.0 // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect diff --git a/x/accounts/defaults/lockup/lockup.go b/x/accounts/defaults/lockup/lockup.go index 060e656aa273..826f51c5a9a3 100644 --- a/x/accounts/defaults/lockup/lockup.go +++ b/x/accounts/defaults/lockup/lockup.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "errors" + "fmt" "time" "github.com/cosmos/gogoproto/proto" @@ -386,7 +387,7 @@ func (bva *BaseLockup) checkSender(ctx context.Context, sender string) error { } func sendMessage(ctx context.Context, msg proto.Message) ([]*codectypes.Any, error) { - response, err := accountstd.ExecModuleUntyped(ctx, msg) + response, err := accountstd.ExecModule(ctx, msg) if err != nil { return nil, err } @@ -401,13 +402,16 @@ func sendMessage(ctx context.Context, msg proto.Message) ([]*codectypes.Any, err func getStakingDenom(ctx context.Context) (string, error) { // Query account balance for the sent denom - paramsQueryReq := &stakingtypes.QueryParamsRequest{} - resp, err := accountstd.QueryModule[stakingtypes.QueryParamsResponse](ctx, paramsQueryReq) + resp, err := accountstd.QueryModule(ctx, &stakingtypes.QueryParamsRequest{}) if err != nil { return "", err } + res, ok := resp.(*stakingtypes.QueryParamsResponse) + if !ok { + return "", fmt.Errorf("unexpected response type: %T", resp) + } - return resp.Params.BondDenom, nil + return res.Params.BondDenom, nil } // TrackDelegation tracks a delegation amount for any given lockup account type @@ -532,13 +536,17 @@ func (bva *BaseLockup) TrackUndelegation(ctx context.Context, amount sdk.Coins) func (bva BaseLockup) getBalance(ctx context.Context, sender, denom string) (*sdk.Coin, error) { // Query account balance for the sent denom - balanceQueryReq := &banktypes.QueryBalanceRequest{Address: sender, Denom: denom} - resp, err := accountstd.QueryModule[banktypes.QueryBalanceResponse](ctx, balanceQueryReq) + resp, err := accountstd.QueryModule(ctx, &banktypes.QueryBalanceRequest{Address: sender, Denom: denom}) if err != nil { return nil, err } - return resp.Balance, nil + res, ok := resp.(*banktypes.QueryBalanceResponse) + if !ok { + return nil, fmt.Errorf("unexpected response type: %T", resp) + } + + return res.Balance, nil } func (bva BaseLockup) checkTokensSendable(ctx context.Context, sender string, amount, lockedCoins sdk.Coins) error { diff --git a/x/accounts/defaults/lockup/utils_test.go b/x/accounts/defaults/lockup/utils_test.go index a7032ceedeb3..79104e356fc1 100644 --- a/x/accounts/defaults/lockup/utils_test.go +++ b/x/accounts/defaults/lockup/utils_test.go @@ -6,14 +6,13 @@ import ( "testing" gogoproto "github.com/cosmos/gogoproto/proto" - "github.com/golang/protobuf/proto" // nolint: staticcheck // needed because gogoproto.Merge does not work consistently. See NOTE: comments. "github.com/stretchr/testify/require" - "google.golang.org/protobuf/runtime/protoiface" "cosmossdk.io/collections" "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/header" "cosmossdk.io/core/store" + "cosmossdk.io/core/transaction" "cosmossdk.io/math" "cosmossdk.io/x/accounts/accountstd" banktypes "cosmossdk.io/x/bank/types" @@ -24,8 +23,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -type ProtoMsg = protoiface.MessageV1 - var TestFunds = sdk.NewCoins(sdk.NewCoin("test", math.NewInt(10))) // mock statecodec @@ -52,9 +49,9 @@ func (c mockStateCodec) Unmarshal(bz []byte, ptr gogoproto.Message) error { } type ( - ModuleExecUntypedFunc = func(ctx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) - ModuleExecFunc = func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error - ModuleQueryFunc = func(ctx context.Context, queryReq, queryResp ProtoMsg) error + ModuleExecUntypedFunc = func(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) + ModuleExecFunc = func(ctx context.Context, sender []byte, msg, msgResp transaction.Msg) error + ModuleQueryFunc = func(ctx context.Context, queryReq, queryResp transaction.Msg) error ) // mock address codec @@ -73,9 +70,8 @@ func (h headerService) HeaderInfo(ctx context.Context) header.Info { func newMockContext(t *testing.T) (context.Context, store.KVStoreService) { t.Helper() return accountstd.NewMockContext( - 0, []byte("lockup_account"), []byte("sender"), TestFunds, func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error { - return nil - }, func(ctx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) { + 0, []byte("lockup_account"), []byte("sender"), TestFunds, + func(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { typeUrl := sdk.MsgTypeURL(msg) switch typeUrl { case "/cosmos.staking.v1beta1.MsgDelegate": @@ -89,28 +85,24 @@ func newMockContext(t *testing.T) (context.Context, store.KVStoreService) { default: return nil, errors.New("unrecognized request type") } - }, func(ctx context.Context, req, resp ProtoMsg) error { + }, func(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { _, ok := req.(*banktypes.QueryBalanceRequest) if !ok { _, ok = req.(*stakingtypes.QueryParamsRequest) require.True(t, ok) - gogoproto.Merge(resp.(gogoproto.Message), &stakingtypes.QueryParamsResponse{ + return &stakingtypes.QueryParamsResponse{ Params: stakingtypes.Params{ BondDenom: "test", }, - }) - } else { - // NOTE: using gogoproto.Merge will fail for some reason unknown to me, but - // using proto.Merge with gogo messages seems to work fine. - proto.Merge(resp.(gogoproto.Message), &banktypes.QueryBalanceResponse{ - Balance: &(sdk.Coin{ - Denom: "test", - Amount: TestFunds.AmountOf("test"), - }), - }) + }, nil } - return nil + return &banktypes.QueryBalanceResponse{ + Balance: &(sdk.Coin{ + Denom: "test", + Amount: TestFunds.AmountOf("test"), + }), + }, nil }, ) } diff --git a/x/accounts/defaults/multisig/account_test.go b/x/accounts/defaults/multisig/account_test.go index 58d3e11a4457..a53b57f6884f 100644 --- a/x/accounts/defaults/multisig/account_test.go +++ b/x/accounts/defaults/multisig/account_test.go @@ -10,12 +10,13 @@ import ( "github.com/stretchr/testify/require" "cosmossdk.io/core/store" + "cosmossdk.io/core/transaction" "cosmossdk.io/x/accounts/accountstd" v1 "cosmossdk.io/x/accounts/defaults/multisig/v1" accountsv1 "cosmossdk.io/x/accounts/v1" ) -func setup(t *testing.T, ctx context.Context, ss store.KVStoreService, timefn func() time.Time) *Account { +func setup(t *testing.T, _ context.Context, ss store.KVStoreService, timefn func() time.Time) *Account { t.Helper() deps := makeMockDependencies(ss, timefn) @@ -442,15 +443,13 @@ func TestProposal_NotPassing(t *testing.T) { } ctx, ss := accountstd.NewMockContext( - 0, []byte("multisig_acc"), []byte("addr1"), TestFunds, func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error { - return nil - }, func(ctx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) { + 0, []byte("multisig_acc"), []byte("addr1"), TestFunds, func(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { if _, ok := msg.(*v1.MsgUpdateConfig); ok { return &v1.MsgUpdateConfigResponse{}, nil } return nil, nil - }, func(ctx context.Context, req, resp ProtoMsg) error { - return nil + }, func(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { + return nil, nil }, ) @@ -565,9 +564,8 @@ func TestProposalPassing(t *testing.T) { var ctx context.Context var ss store.KVStoreService ctx, ss = accountstd.NewMockContext( - 0, []byte("multisig_acc"), []byte("addr1"), TestFunds, func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error { - return nil - }, func(ictx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) { + 0, []byte("multisig_acc"), []byte("addr1"), TestFunds, + func(ictx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { if execmsg, ok := msg.(*accountsv1.MsgExecute); ok { updateCfg, err := accountstd.UnpackAny[v1.MsgUpdateConfig](execmsg.GetMessage()) if err != nil { @@ -578,8 +576,8 @@ func TestProposalPassing(t *testing.T) { return acc.UpdateConfig(ctx, updateCfg) } return nil, nil - }, func(ctx context.Context, req, resp ProtoMsg) error { - return nil + }, func(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { + return nil, nil }, ) diff --git a/x/accounts/defaults/multisig/utils_test.go b/x/accounts/defaults/multisig/utils_test.go index 47f185fef1cd..86f6c62551d6 100644 --- a/x/accounts/defaults/multisig/utils_test.go +++ b/x/accounts/defaults/multisig/utils_test.go @@ -9,13 +9,13 @@ import ( types "github.com/cosmos/gogoproto/types/any" "github.com/stretchr/testify/require" "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/runtime/protoiface" "cosmossdk.io/collections" "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/event" "cosmossdk.io/core/header" "cosmossdk.io/core/store" + "cosmossdk.io/core/transaction" "cosmossdk.io/math" "cosmossdk.io/x/accounts/accountstd" banktypes "cosmossdk.io/x/bank/types" @@ -26,8 +26,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -type ProtoMsg = protoiface.MessageV1 - var TestFunds = sdk.NewCoins(sdk.NewCoin("test", math.NewInt(10))) // mock statecodec @@ -149,9 +147,9 @@ func (c mockStateCodec) Unmarshal(bz []byte, ptr gogoproto.Message) error { } type ( - ModuleExecUntypedFunc = func(ctx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) - ModuleExecFunc = func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error - ModuleQueryFunc = func(ctx context.Context, queryReq, queryResp ProtoMsg) error + ModuleExecUntypedFunc = func(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) + ModuleExecFunc = func(ctx context.Context, sender []byte, msg, msgResp transaction.Msg) error + ModuleQueryFunc = func(ctx context.Context, queryReq, queryResp transaction.Msg) error ) // mock address codec @@ -163,20 +161,19 @@ func (a addressCodec) BytesToString(bz []byte) (string, error) { return string func newMockContext(t *testing.T) (context.Context, store.KVStoreService) { t.Helper() return accountstd.NewMockContext( - 0, []byte("mock_multisig_account"), []byte("sender"), TestFunds, func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error { - return nil - }, func(ctx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) { + 0, []byte("mock_multisig_account"), []byte("sender"), TestFunds, func(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { return nil, nil - }, func(ctx context.Context, req, resp ProtoMsg) error { + }, func(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { + var resp transaction.Msg _, ok := req.(*banktypes.QueryBalanceRequest) require.True(t, ok) - gogoproto.Merge(resp.(gogoproto.Message), &banktypes.QueryBalanceResponse{ + gogoproto.Merge(resp, &banktypes.QueryBalanceResponse{ Balance: &sdk.Coin{ Denom: "test", Amount: math.NewInt(5), }, }) - return nil + return resp, nil }, ) } diff --git a/x/accounts/go.mod b/x/accounts/go.mod index 0e4eaed60faa..3ad22c807c61 100644 --- a/x/accounts/go.mod +++ b/x/accounts/go.mod @@ -20,23 +20,18 @@ require ( google.golang.org/protobuf v1.34.2 ) -require github.com/golang/mock v1.6.0 // indirect - -require ( - cosmossdk.io/schema v0.1.1 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect -) - require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/x/distribution v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -85,6 +80,7 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect @@ -123,6 +119,7 @@ require ( github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect github.com/oklog/run v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect @@ -184,6 +181,7 @@ replace ( cosmossdk.io/collections => ../../collections cosmossdk.io/core => ../../core cosmossdk.io/core/testing => ../../core/testing + cosmossdk.io/x/accounts/defaults/lockup => ./defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ./defaults/multisig cosmossdk.io/x/auth => ../auth cosmossdk.io/x/bank => ../bank diff --git a/x/accounts/go.sum b/x/accounts/go.sum index 48811cc15181..855f0b8066b9 100644 --- a/x/accounts/go.sum +++ b/x/accounts/go.sum @@ -16,8 +16,6 @@ cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= -cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 h1:eb0kcGyaYHSS0do7+MIWg7UKlskSH01biRNENbm/zDA= -cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5/go.mod h1:drzY4oVisyWvSgpsM7ccQ7IX3efMuVIvd9Eij1Gm/6o= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= diff --git a/x/accounts/internal/implementation/api_builder.go b/x/accounts/internal/implementation/api_builder.go index bd6e408215ea..fd554dad6e75 100644 --- a/x/accounts/internal/implementation/api_builder.go +++ b/x/accounts/internal/implementation/api_builder.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + + "cosmossdk.io/core/transaction" ) var ( @@ -22,7 +24,7 @@ type InitBuilder struct { // handler is the handler function that will be called when the smart account is initialized. // Although the function here is defined to take an any, the smart account will work // with a typed version of it. - handler func(ctx context.Context, initRequest ProtoMsg) (initResponse ProtoMsg, err error) + handler func(ctx context.Context, initRequest transaction.Msg) (initResponse transaction.Msg, err error) // schema is the schema of the message that will be passed to the handler function. schema HandlerSchema @@ -30,7 +32,7 @@ type InitBuilder struct { // makeHandler returns the handler function that will be called when the smart account is initialized. // It returns an error if no handler was registered. -func (i *InitBuilder) makeHandler() (func(ctx context.Context, initRequest ProtoMsg) (initResponse ProtoMsg, err error), error) { +func (i *InitBuilder) makeHandler() (func(ctx context.Context, initRequest transaction.Msg) (initResponse transaction.Msg, err error), error) { if i.handler == nil { return nil, errNoInitHandler } @@ -40,7 +42,7 @@ func (i *InitBuilder) makeHandler() (func(ctx context.Context, initRequest Proto // NewExecuteBuilder creates a new ExecuteBuilder instance. func NewExecuteBuilder() *ExecuteBuilder { return &ExecuteBuilder{ - handlers: make(map[string]func(ctx context.Context, executeRequest ProtoMsg) (executeResponse ProtoMsg, err error)), + handlers: make(map[string]func(ctx context.Context, executeRequest transaction.Msg) (executeResponse transaction.Msg, err error)), handlersSchema: make(map[string]HandlerSchema), } } @@ -49,7 +51,7 @@ func NewExecuteBuilder() *ExecuteBuilder { // to a handler function for a specific account. type ExecuteBuilder struct { // handlers is a map of handler functions that will be called when the smart account is executed. - handlers map[string]func(ctx context.Context, executeRequest ProtoMsg) (executeResponse ProtoMsg, err error) + handlers map[string]func(ctx context.Context, executeRequest transaction.Msg) (executeResponse transaction.Msg, err error) // handlersSchema is a map of schemas for the messages that will be passed to the handler functions // and the messages that will be returned by the handler functions. @@ -59,10 +61,10 @@ type ExecuteBuilder struct { err error } -func (r *ExecuteBuilder) makeHandler() (func(ctx context.Context, executeRequest ProtoMsg) (executeResponse ProtoMsg, err error), error) { +func (r *ExecuteBuilder) makeHandler() (func(ctx context.Context, executeRequest transaction.Msg) (executeResponse transaction.Msg, err error), error) { // if no handler is registered it's fine, it means the account will not be accepting execution or query messages. if len(r.handlers) == 0 { - return func(ctx context.Context, _ ProtoMsg) (_ ProtoMsg, err error) { + return func(ctx context.Context, _ transaction.Msg) (_ transaction.Msg, err error) { return nil, errNoExecuteHandler }, nil } @@ -72,7 +74,7 @@ func (r *ExecuteBuilder) makeHandler() (func(ctx context.Context, executeRequest } // build the real execution handler - return func(ctx context.Context, executeRequest ProtoMsg) (executeResponse ProtoMsg, err error) { + return func(ctx context.Context, executeRequest transaction.Msg) (executeResponse transaction.Msg, err error) { messageName := MessageName(executeRequest) handler, ok := r.handlers[messageName] if !ok { @@ -96,7 +98,7 @@ type QueryBuilder struct { er *ExecuteBuilder } -func (r *QueryBuilder) makeHandler() (func(ctx context.Context, queryRequest ProtoMsg) (queryResponse ProtoMsg, err error), error) { +func (r *QueryBuilder) makeHandler() (func(ctx context.Context, queryRequest transaction.Msg) (queryResponse transaction.Msg, err error), error) { return r.er.makeHandler() } diff --git a/x/accounts/internal/implementation/context.go b/x/accounts/internal/implementation/context.go index 64ba2820d6cd..8a24ea7cd034 100644 --- a/x/accounts/internal/implementation/context.go +++ b/x/accounts/internal/implementation/context.go @@ -6,6 +6,7 @@ import ( "cosmossdk.io/collections" "cosmossdk.io/core/store" + "cosmossdk.io/core/transaction" "cosmossdk.io/x/accounts/internal/prefixstore" sdk "github.com/cosmos/cosmos-sdk/types" @@ -14,22 +15,20 @@ import ( var AccountStatePrefix = collections.NewPrefix(255) type ( - ModuleExecUntypedFunc = func(ctx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) - ModuleExecFunc = func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error - ModuleQueryFunc = func(ctx context.Context, queryReq, queryResp ProtoMsg) error + ModuleExecFunc = func(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) + ModuleQueryFunc = func(ctx context.Context, queryReq transaction.Msg) (transaction.Msg, error) ) type contextKey struct{} type contextValue struct { - store store.KVStore // store is the prefixed store for the account. - sender []byte // sender is the address of the entity invoking the account action. - whoami []byte // whoami is the address of the account being invoked. - funds sdk.Coins // funds reports the coins sent alongside the request. - parentContext context.Context // parentContext that was used to build the account context. - moduleExec ModuleExecFunc // moduleExec is a function that executes a module message, when the resp type is known. - moduleExecUntyped ModuleExecUntypedFunc // moduleExecUntyped is a function that executes a module message, when the resp type is unknown. - moduleQuery ModuleQueryFunc // moduleQuery is a function that queries a module. + store store.KVStore // store is the prefixed store for the account. + sender []byte // sender is the address of the entity invoking the account action. + whoami []byte // whoami is the address of the account being invoked. + funds sdk.Coins // funds reports the coins sent alongside the request. + parentContext context.Context // parentContext that was used to build the account context. + moduleExec ModuleExecFunc // moduleExec is a function that executes a module message, when the resp type is unknown. + moduleQuery ModuleQueryFunc // moduleQuery is a function that queries a module. } func addCtx(ctx context.Context, value contextValue) context.Context { @@ -55,18 +54,16 @@ func MakeAccountContext( sender []byte, funds sdk.Coins, moduleExec ModuleExecFunc, - moduleExecUntyped ModuleExecUntypedFunc, moduleQuery ModuleQueryFunc, ) context.Context { return addCtx(ctx, contextValue{ - store: makeAccountStore(ctx, storeSvc, accNumber), - sender: sender, - whoami: accountAddr, - funds: funds, - parentContext: ctx, - moduleExec: moduleExec, - moduleExecUntyped: moduleExecUntyped, - moduleQuery: moduleQuery, + store: makeAccountStore(ctx, storeSvc, accNumber), + sender: sender, + whoami: accountAddr, + funds: funds, + parentContext: ctx, + moduleExec: moduleExec, + moduleQuery: moduleQuery, }) } @@ -85,27 +82,12 @@ func makeAccountStore(ctx context.Context, storeSvc store.KVStoreService, accNum return prefixstore.New(storeSvc.OpenKVStore(ctx), append(AccountStatePrefix, prefix...)) } -// ExecModuleUntyped can be used to execute a message towards a module, when the response type is unknown. -func ExecModuleUntyped(ctx context.Context, msg ProtoMsg) (ProtoMsg, error) { +// ExecModule can be used to execute a message towards a module, when the response type is unknown. +func ExecModule(ctx context.Context, msg transaction.Msg) (transaction.Msg, error) { // get sender v := getCtx(ctx) - resp, err := v.moduleExecUntyped(v.parentContext, v.whoami, msg) - if err != nil { - return nil, err - } - - return resp, nil -} - -// ExecModule can be used to execute a message towards a module. -func ExecModule[Resp any, RespProto ProtoMsgG[Resp], Req any, ReqProto ProtoMsgG[Req]](ctx context.Context, msg ReqProto) (RespProto, error) { - // get sender - v := getCtx(ctx) - - // execute module, unwrapping the original context. - resp := RespProto(new(Resp)) - err := v.moduleExec(v.parentContext, v.whoami, msg, resp) + resp, err := v.moduleExec(v.parentContext, v.whoami, msg) if err != nil { return nil, err } @@ -114,12 +96,11 @@ func ExecModule[Resp any, RespProto ProtoMsgG[Resp], Req any, ReqProto ProtoMsgG } // QueryModule can be used by an account to execute a module query. -func QueryModule[Resp any, RespProto ProtoMsgG[Resp], Req any, ReqProto ProtoMsgG[Req]](ctx context.Context, req ReqProto) (RespProto, error) { +func QueryModule(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { // we do not need to check the sender in a query because it is not a state transition. // we also unwrap the original context. v := getCtx(ctx) - resp := RespProto(new(Resp)) - err := v.moduleQuery(v.parentContext, req, resp) + resp, err := v.moduleQuery(v.parentContext, req) if err != nil { return nil, err } diff --git a/x/accounts/internal/implementation/context_test.go b/x/accounts/internal/implementation/context_test.go index ff47b50c89ef..9cf1108401aa 100644 --- a/x/accounts/internal/implementation/context_test.go +++ b/x/accounts/internal/implementation/context_test.go @@ -9,7 +9,8 @@ import ( "github.com/stretchr/testify/require" "cosmossdk.io/collections" - "cosmossdk.io/core/testing" + coretesting "cosmossdk.io/core/testing" + "cosmossdk.io/core/transaction" ) func TestMakeAccountContext(t *testing.T) { @@ -19,7 +20,7 @@ func TestMakeAccountContext(t *testing.T) { sender := []byte("sender") sb := collections.NewSchemaBuilderFromAccessor(openKVStore) - accountCtx := MakeAccountContext(originalContext, storeService, 1, accountAddr, sender, nil, nil, nil, nil) + accountCtx := MakeAccountContext(originalContext, storeService, 1, accountAddr, sender, nil, nil, nil) // ensure whoami require.Equal(t, accountAddr, Whoami(accountCtx)) @@ -43,38 +44,24 @@ func TestMakeAccountContext(t *testing.T) { value, err := store.Get(append(AccountStatePrefix, append(binary.BigEndian.AppendUint64(nil, 1), itemPrefix...)...)) require.NoError(t, err) require.Equal(t, []byte{0, 0, 0, 0, 0, 0, 3, 232}, value) - - // ensure calling ExecModule works - accountCtx = MakeAccountContext(originalContext, storeService, 1, []byte("legit-exec-module"), []byte("invoker"), nil, func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error { - // ensure we unwrapped the context when invoking a module call - require.Equal(t, originalContext, ctx) - Merge(msgResp, &types.StringValue{Value: "module exec was called"}) - return nil - }, nil, nil) - - resp, err := ExecModule[types.StringValue](accountCtx, &types.UInt64Value{Value: 1000}) - require.NoError(t, err) - require.True(t, Equal(&types.StringValue{Value: "module exec was called"}, resp)) - // ensure calling ExecModuleUntyped works - accountCtx = MakeAccountContext(originalContext, storeService, 1, []byte("legit-exec-module-untyped"), []byte("invoker"), nil, nil, func(ctx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) { + accountCtx = MakeAccountContext(originalContext, storeService, 1, []byte("legit-exec-module-untyped"), []byte("invoker"), nil, func(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { require.Equal(t, originalContext, ctx) return &types.StringValue{Value: "module exec untyped was called"}, nil }, nil) - respUntyped, err := ExecModuleUntyped(accountCtx, &types.UInt64Value{Value: 1000}) + respUntyped, err := ExecModule(accountCtx, &types.UInt64Value{Value: 1000}) require.NoError(t, err) require.True(t, Equal(&types.StringValue{Value: "module exec untyped was called"}, respUntyped)) // ensure calling QueryModule works, also by setting everything else communication related to nil // we can guarantee that exec paths do not impact query paths. - accountCtx = MakeAccountContext(originalContext, storeService, 1, nil, nil, nil, nil, nil, func(ctx context.Context, req, resp ProtoMsg) error { + accountCtx = MakeAccountContext(originalContext, storeService, 1, nil, nil, nil, nil, func(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { require.Equal(t, originalContext, ctx) - Merge(resp, &types.StringValue{Value: "module query was called"}) - return nil + return &types.StringValue{Value: "module query was called"}, nil }) - resp, err = QueryModule[types.StringValue](accountCtx, &types.UInt64Value{Value: 1000}) + resp, err := QueryModule(accountCtx, &types.UInt64Value{Value: 1000}) require.NoError(t, err) require.True(t, Equal(&types.StringValue{Value: "module query was called"}, resp)) } diff --git a/x/accounts/internal/implementation/encoding.go b/x/accounts/internal/implementation/encoding.go index 167ecb38aa9e..9b08d00bf862 100644 --- a/x/accounts/internal/implementation/encoding.go +++ b/x/accounts/internal/implementation/encoding.go @@ -6,35 +6,34 @@ import ( "strings" "github.com/cosmos/gogoproto/proto" - "google.golang.org/protobuf/runtime/protoiface" + + "cosmossdk.io/core/transaction" codectypes "github.com/cosmos/cosmos-sdk/codec/types" ) -type ProtoMsg = protoiface.MessageV1 - // ProtoMsgG is a generic interface for protobuf messages. type ProtoMsgG[T any] interface { *T - protoiface.MessageV1 + transaction.Msg } type Any = codectypes.Any -func FindMessageByName(name string) (ProtoMsg, error) { +func FindMessageByName(name string) (transaction.Msg, error) { typ := proto.MessageType(name) if typ == nil { return nil, fmt.Errorf("no message type found for %s", name) } - return reflect.New(typ.Elem()).Interface().(ProtoMsg), nil + return reflect.New(typ.Elem()).Interface().(transaction.Msg), nil } -func MessageName(msg ProtoMsg) string { +func MessageName(msg transaction.Msg) string { return proto.MessageName(msg) } // PackAny packs a proto message into an anypb.Any. -func PackAny(msg ProtoMsg) (*Any, error) { +func PackAny(msg transaction.Msg) (*Any, error) { return codectypes.NewAnyWithValue(msg) } @@ -44,7 +43,7 @@ func UnpackAny[T any, PT ProtoMsgG[T]](anyPB *Any) (PT, error) { return to, UnpackAnyTo(anyPB, PT(to)) } -func UnpackAnyTo(anyPB *Any, to ProtoMsg) error { +func UnpackAnyTo(anyPB *Any, to transaction.Msg) error { return proto.Unmarshal(anyPB.Value, to) } @@ -59,10 +58,10 @@ func UnpackAnyRaw(anyPB *Any) (proto.Message, error) { return to, UnpackAnyTo(anyPB, to) } -func Merge(a, b ProtoMsg) { +func Merge(a, b transaction.Msg) { proto.Merge(a, b) } -func Equal(a, b ProtoMsg) bool { +func Equal(a, b transaction.Msg) bool { return proto.Equal(a, b) } diff --git a/x/accounts/internal/implementation/implementation.go b/x/accounts/internal/implementation/implementation.go index 47457af718d1..6ee1edc39927 100644 --- a/x/accounts/internal/implementation/implementation.go +++ b/x/accounts/internal/implementation/implementation.go @@ -9,6 +9,7 @@ import ( "cosmossdk.io/collections" "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" + "cosmossdk.io/core/transaction" "github.com/cosmos/cosmos-sdk/codec" ) @@ -107,11 +108,11 @@ func newImplementation(schemaBuilder *collections.SchemaBuilder, account Account // and non-generic implementation usable by the x/accounts module. type Implementation struct { // Init defines the initialisation handler for the smart account. - Init func(ctx context.Context, msg ProtoMsg) (resp ProtoMsg, err error) + Init func(ctx context.Context, msg transaction.Msg) (resp transaction.Msg, err error) // Execute defines the execution handler for the smart account. - Execute func(ctx context.Context, msg ProtoMsg) (resp ProtoMsg, err error) + Execute func(ctx context.Context, msg transaction.Msg) (resp transaction.Msg, err error) // Query defines the query handler for the smart account. - Query func(ctx context.Context, msg ProtoMsg) (resp ProtoMsg, err error) + Query func(ctx context.Context, msg transaction.Msg) (resp transaction.Msg, err error) // CollectionsSchema represents the state schema. CollectionsSchema collections.Schema // InitHandlerSchema represents the init handler schema. @@ -123,19 +124,19 @@ type Implementation struct { } // HasExec returns true if the account can execute the given msg. -func (i Implementation) HasExec(m ProtoMsg) bool { +func (i Implementation) HasExec(m transaction.Msg) bool { _, ok := i.ExecuteHandlersSchema[MessageName(m)] return ok } // HasQuery returns true if the account can execute the given request. -func (i Implementation) HasQuery(m ProtoMsg) bool { +func (i Implementation) HasQuery(m transaction.Msg) bool { _, ok := i.QueryHandlersSchema[MessageName(m)] return ok } // HasInit returns true if the account uses the provided init message. -func (i Implementation) HasInit(m ProtoMsg) bool { +func (i Implementation) HasInit(m transaction.Msg) bool { return i.InitHandlerSchema.RequestSchema.Name == MessageName(m) } @@ -145,7 +146,7 @@ type MessageSchema struct { // Name identifies the message name, this must be queryable from some reflection service. Name string // New is used to create a new message instance for the schema. - New func() ProtoMsg + New func() transaction.Msg } // HandlerSchema defines the schema of a handler. diff --git a/x/accounts/internal/implementation/protoaccount.go b/x/accounts/internal/implementation/protoaccount.go index 122ec1168827..e17c793316f2 100644 --- a/x/accounts/internal/implementation/protoaccount.go +++ b/x/accounts/internal/implementation/protoaccount.go @@ -5,6 +5,8 @@ import ( "fmt" "google.golang.org/protobuf/proto" + + "cosmossdk.io/core/transaction" ) // RegisterInitHandler registers an initialisation handler for a smart account that uses protobuf. @@ -14,7 +16,7 @@ func RegisterInitHandler[ ) { reqName := MessageName(ProtoReq(new(Req))) - router.handler = func(ctx context.Context, initRequest ProtoMsg) (initResponse ProtoMsg, err error) { + router.handler = func(ctx context.Context, initRequest transaction.Msg) (initResponse transaction.Msg, err error) { concrete, ok := initRequest.(ProtoReq) if !ok { return nil, fmt.Errorf("%w: wanted %s, got %T", errInvalidMessage, reqName, initRequest) @@ -40,7 +42,7 @@ func RegisterExecuteHandler[ return } - router.handlers[reqName] = func(ctx context.Context, executeRequest ProtoMsg) (executeResponse ProtoMsg, err error) { + router.handlers[reqName] = func(ctx context.Context, executeRequest transaction.Msg) (executeResponse transaction.Msg, err error) { concrete, ok := executeRequest.(ProtoReq) if !ok { return nil, fmt.Errorf("%w: wanted %s, got %T", errInvalidMessage, reqName, executeRequest) @@ -69,7 +71,7 @@ func NewProtoMessageSchema[T any, PT ProtoMsgG[T]]() *MessageSchema { } return &MessageSchema{ Name: MessageName(msg), - New: func() ProtoMsg { + New: func() transaction.Msg { return PT(new(T)) }, } diff --git a/x/accounts/keeper.go b/x/accounts/keeper.go index 91ef5d707c82..fee356a7736f 100644 --- a/x/accounts/keeper.go +++ b/x/accounts/keeper.go @@ -13,6 +13,7 @@ import ( "cosmossdk.io/collections" "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" + "cosmossdk.io/core/transaction" "cosmossdk.io/x/accounts/accountstd" "cosmossdk.io/x/accounts/internal/implementation" v1 "cosmossdk.io/x/accounts/v1" @@ -137,9 +138,9 @@ func (k Keeper) Init( ctx context.Context, accountType string, creator []byte, - initRequest implementation.ProtoMsg, + initRequest transaction.Msg, funds sdk.Coins, -) (implementation.ProtoMsg, []byte, error) { +) (transaction.Msg, []byte, error) { // get the next account number num, err := k.AccountNumber.Next(ctx) if err != nil { @@ -158,7 +159,7 @@ func (k Keeper) Init( } // initFromMsg is a helper which inits an account given a v1.MsgInit. -func (k Keeper) initFromMsg(ctx context.Context, initMsg *v1.MsgInit) (implementation.ProtoMsg, []byte, error) { +func (k Keeper) initFromMsg(ctx context.Context, initMsg *v1.MsgInit) (transaction.Msg, []byte, error) { creator, err := k.addressCodec.StringToBytes(initMsg.Sender) if err != nil { return nil, nil, err @@ -182,9 +183,9 @@ func (k Keeper) init( creator []byte, accountNum uint64, accountAddr []byte, - initRequest implementation.ProtoMsg, + initRequest transaction.Msg, funds sdk.Coins, -) (implementation.ProtoMsg, error) { +) (transaction.Msg, error) { impl, ok := k.accounts[accountType] if !ok { return nil, fmt.Errorf("%w: not found %s", errAccountTypeNotFound, accountType) @@ -223,8 +224,8 @@ func (k Keeper) MigrateLegacyAccount( addr []byte, // The current address of the account accNum uint64, // The current account number accType string, // The account type to migrate to - msg implementation.ProtoMsg, // The init msg of the account type we're migrating to -) (implementation.ProtoMsg, error) { + msg transaction.Msg, // The init msg of the account type we're migrating to +) (transaction.Msg, error) { return k.init(ctx, accType, addr, accNum, addr, msg, nil) } @@ -233,9 +234,9 @@ func (k Keeper) Execute( ctx context.Context, accountAddr []byte, sender []byte, - execRequest implementation.ProtoMsg, + execRequest transaction.Msg, funds sdk.Coins, -) (implementation.ProtoMsg, error) { +) (transaction.Msg, error) { // get account implementation impl, err := k.getImplementation(ctx, accountAddr) if err != nil { @@ -265,8 +266,8 @@ func (k Keeper) Execute( func (k Keeper) Query( ctx context.Context, accountAddr []byte, - queryRequest implementation.ProtoMsg, -) (implementation.ProtoMsg, error) { + queryRequest transaction.Msg, +) (transaction.Msg, error) { // get account implementation impl, err := k.getImplementation(ctx, accountAddr) if err != nil { @@ -315,8 +316,7 @@ func (k Keeper) makeAccountContext(ctx context.Context, accountNumber uint64, ac accountAddr, sender, funds, - k.sendModuleMessage, - k.SendModuleMessageUntyped, + k.SendModuleMessage, k.queryModule, ) } @@ -330,10 +330,7 @@ func (k Keeper) makeAccountContext(ctx context.Context, accountNumber uint64, ac accountAddr, nil, nil, - func(ctx context.Context, sender []byte, msg, msgResp implementation.ProtoMsg) error { - return errors.New("cannot execute in query context") - }, - func(ctx context.Context, sender []byte, msg implementation.ProtoMsg) (implementation.ProtoMsg, error) { + func(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { return nil, errors.New("cannot execute in query context") }, k.queryModule, @@ -350,7 +347,7 @@ func (k Keeper) sendAnyMessages(ctx context.Context, sender []byte, anyMessages if err != nil { return nil, err } - resp, err := k.SendModuleMessageUntyped(ctx, sender, msg) + resp, err := k.SendModuleMessage(ctx, sender, msg) if err != nil { return nil, fmt.Errorf("failed to execute message %d: %s", i, err.Error()) } @@ -363,9 +360,9 @@ func (k Keeper) sendAnyMessages(ctx context.Context, sender []byte, anyMessages return anyResponses, nil } -// SendModuleMessageUntyped can be used to send a message towards a module. +// SendModuleMessage can be used to send a message towards a module. // It should be used when the response type is not known by the caller. -func (k Keeper) SendModuleMessageUntyped(ctx context.Context, sender []byte, msg implementation.ProtoMsg) (implementation.ProtoMsg, error) { +func (k Keeper) SendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { // do sender assertions. wantSenders, _, err := k.codec.GetMsgSigners(msg) if err != nil { @@ -377,7 +374,7 @@ func (k Keeper) SendModuleMessageUntyped(ctx context.Context, sender []byte, msg if !bytes.Equal(sender, wantSenders[0]) { return nil, fmt.Errorf("%w: sender does not match expected sender", ErrUnauthorized) } - resp, err := k.MsgRouterService.InvokeUntyped(ctx, msg) + resp, err := k.MsgRouterService.Invoke(ctx, msg) if err != nil { return nil, err } @@ -388,26 +385,27 @@ func (k Keeper) SendModuleMessageUntyped(ctx context.Context, sender []byte, msg // sendModuleMessage can be used to send a message towards a module. It expects the // response type to be known by the caller. It will also assert the sender has the right // is not trying to impersonate another account. -func (k Keeper) sendModuleMessage(ctx context.Context, sender []byte, msg, msgResp implementation.ProtoMsg) error { +func (k Keeper) sendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { // do sender assertions. wantSenders, _, err := k.codec.GetMsgSigners(msg) if err != nil { - return fmt.Errorf("cannot get signers: %w", err) + return nil, fmt.Errorf("cannot get signers: %w", err) } if len(wantSenders) != 1 { - return fmt.Errorf("expected only one signer, got %d", len(wantSenders)) + return nil, fmt.Errorf("expected only one signer, got %d", len(wantSenders)) } if !bytes.Equal(sender, wantSenders[0]) { - return fmt.Errorf("%w: sender does not match expected sender", ErrUnauthorized) + return nil, fmt.Errorf("%w: sender does not match expected sender", ErrUnauthorized) } - return k.MsgRouterService.InvokeTyped(ctx, msg, msgResp) + + return k.MsgRouterService.Invoke(ctx, msg) } // queryModule is the entrypoint for an account to query a module. // It will try to find the query handler for the given query and execute it. // If multiple query handlers are found, it will return an error. -func (k Keeper) queryModule(ctx context.Context, queryReq, queryResp implementation.ProtoMsg) error { - return k.QueryRouterService.InvokeTyped(ctx, queryReq, queryResp) +func (k Keeper) queryModule(ctx context.Context, queryReq transaction.Msg) (transaction.Msg, error) { + return k.QueryRouterService.Invoke(ctx, queryReq) } // maybeSendFunds will send the provided coins between the provided addresses, if amt @@ -417,23 +415,24 @@ func (k Keeper) maybeSendFunds(ctx context.Context, from, to []byte, amt sdk.Coi return nil } - msg, msgResp, err := k.makeSendCoinsMsg(from, to, amt) + msg, err := k.makeSendCoinsMsg(from, to, amt) if err != nil { return err } // send module message ensures that "from" cannot impersonate. - err = k.sendModuleMessage(ctx, from, msg, msgResp) + _, err = k.sendModuleMessage(ctx, from, msg) if err != nil { return err } + return nil } const msgInterfaceName = "cosmos.accounts.v1.MsgInterface" // creates a new interface type which is an alias of the proto message interface to avoid conflicts with sdk.Msg -type msgInterface implementation.ProtoMsg +type msgInterface transaction.Msg var msgInterfaceType = (*msgInterface)(nil) diff --git a/x/auth/ante/setup.go b/x/auth/ante/setup.go index f048bb139324..e81a7cba5051 100644 --- a/x/auth/ante/setup.go +++ b/x/auth/ante/setup.go @@ -46,11 +46,16 @@ func (sud SetUpContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, newCtx = SetGasMeter(ctx, gasTx.GetGas()) // TODO: possibly cache the result of this query for other antehandlers to use - var res consensusv1.QueryParamsResponse - if err := sud.env.QueryRouterService.InvokeTyped(ctx, &consensusv1.QueryParamsRequest{}, &res); err != nil { + resp, err := sud.env.QueryRouterService.Invoke(ctx, &consensusv1.QueryParamsRequest{}) + if err != nil { return newCtx, err } + res, ok := resp.(*consensusv1.QueryParamsResponse) + if !ok { + return newCtx, fmt.Errorf("unexpected response type: %T", resp) + } + if res.Params.Block != nil { // If there exists a maximum block gas limit, we must ensure that the tx // does not exceed it. diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index d98cae0ca1e8..497cc50d8850 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -29,7 +29,7 @@ import ( // GetMultiSignCommand returns the multi-sign command func GetMultiSignCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "multi-sign [...]", + Use: "multi-sign [...]", Aliases: []string{"multisign"}, Short: "Generate multisig signatures for transactions generated offline", Long: strings.TrimSpace( diff --git a/x/auth/keeper/keeper.go b/x/auth/keeper/keeper.go index 00240e8f9a65..5a8c35fda61f 100644 --- a/x/auth/keeper/keeper.go +++ b/x/auth/keeper/keeper.go @@ -315,7 +315,7 @@ func (ak AccountKeeper) NonAtomicMsgsExec(ctx context.Context, signer sdk.AccAdd } if err := ak.BranchService.Execute(ctx, func(ctx context.Context) error { - result, err := ak.AccountsModKeeper.SendModuleMessageUntyped(ctx, signer, msg) + result, err := ak.AccountsModKeeper.SendModuleMessage(ctx, signer, msg) if err != nil { // If an error occurs during message execution, append error response response := &types.NonAtomicExecResult{Resp: nil, Error: err.Error()} diff --git a/x/auth/keeper/msg_server_test.go b/x/auth/keeper/msg_server_test.go index 43a17bc13bc0..b6789421ed18 100644 --- a/x/auth/keeper/msg_server_test.go +++ b/x/auth/keeper/msg_server_test.go @@ -185,7 +185,7 @@ func (s *KeeperTestSuite) TestNonAtomicExec() { }, } - s.acctsModKeeper.EXPECT().SendModuleMessageUntyped(gomock.Any(), gomock.Any(), gomock.Any()). + s.acctsModKeeper.EXPECT().SendModuleMessage(gomock.Any(), gomock.Any(), gomock.Any()). DoAndReturn(func(_ context.Context, sender []byte, msg proto.Message) (protoiface.MessageV1, error) { return msg, nil }).AnyTimes() diff --git a/x/auth/testutil/expected_keepers_mocks.go b/x/auth/testutil/expected_keepers_mocks.go index a53fb9b61b85..348a1740378a 100644 --- a/x/auth/testutil/expected_keepers_mocks.go +++ b/x/auth/testutil/expected_keepers_mocks.go @@ -8,9 +8,9 @@ import ( context "context" reflect "reflect" + transaction "cosmossdk.io/core/transaction" types "github.com/cosmos/cosmos-sdk/types" gomock "github.com/golang/mock/gomock" - protoiface "google.golang.org/protobuf/runtime/protoiface" ) // MockBankKeeper is a mock of BankKeeper interface. @@ -149,17 +149,17 @@ func (mr *MockAccountsModKeeperMockRecorder) NextAccountNumber(ctx interface{}) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NextAccountNumber", reflect.TypeOf((*MockAccountsModKeeper)(nil).NextAccountNumber), ctx) } -// SendModuleMessageUntyped mocks base method. -func (m *MockAccountsModKeeper) SendModuleMessageUntyped(ctx context.Context, sender []byte, msg protoiface.MessageV1) (protoiface.MessageV1, error) { +// SendModuleMessage mocks base method. +func (m *MockAccountsModKeeper) SendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SendModuleMessageUntyped", ctx, sender, msg) - ret0, _ := ret[0].(protoiface.MessageV1) + ret := m.ctrl.Call(m, "SendModuleMessage", ctx, sender, msg) + ret0, _ := ret[0].(transaction.Msg) ret1, _ := ret[1].(error) return ret0, ret1 } -// SendModuleMessageUntyped indicates an expected call of SendModuleMessageUntyped. -func (mr *MockAccountsModKeeperMockRecorder) SendModuleMessageUntyped(ctx, sender, msg interface{}) *gomock.Call { +// SendModuleMessage indicates an expected call of SendModuleMessage. +func (mr *MockAccountsModKeeperMockRecorder) SendModuleMessage(ctx, sender, msg interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendModuleMessageUntyped", reflect.TypeOf((*MockAccountsModKeeper)(nil).SendModuleMessageUntyped), ctx, sender, msg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendModuleMessage", reflect.TypeOf((*MockAccountsModKeeper)(nil).SendModuleMessage), ctx, sender, msg) } diff --git a/x/auth/types/expected_keepers.go b/x/auth/types/expected_keepers.go index 401988a7d00d..7fb82e89ed8a 100644 --- a/x/auth/types/expected_keepers.go +++ b/x/auth/types/expected_keepers.go @@ -3,7 +3,7 @@ package types import ( "context" - "google.golang.org/protobuf/runtime/protoiface" + "cosmossdk.io/core/transaction" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -17,7 +17,7 @@ type BankKeeper interface { // AccountsModKeeper defines the contract for x/accounts APIs type AccountsModKeeper interface { - SendModuleMessageUntyped(ctx context.Context, sender []byte, msg protoiface.MessageV1) (protoiface.MessageV1, error) + SendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) IsAccountsModuleAccount(ctx context.Context, accountAddr []byte) bool NextAccountNumber(ctx context.Context) (accNum uint64, err error) diff --git a/x/auth/vesting/testutil/expected_keepers_mocks.go b/x/auth/vesting/testutil/expected_keepers_mocks.go index 3446770eceae..7612d81e200b 100644 --- a/x/auth/vesting/testutil/expected_keepers_mocks.go +++ b/x/auth/vesting/testutil/expected_keepers_mocks.go @@ -8,9 +8,9 @@ import ( context "context" reflect "reflect" + transaction "cosmossdk.io/core/transaction" types "github.com/cosmos/cosmos-sdk/types" gomock "github.com/golang/mock/gomock" - protoiface "google.golang.org/protobuf/runtime/protoiface" ) // MockBankKeeper is a mock of BankKeeper interface. @@ -149,17 +149,17 @@ func (mr *MockAccountsModKeeperMockRecorder) NextAccountNumber(ctx interface{}) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NextAccountNumber", reflect.TypeOf((*MockAccountsModKeeper)(nil).NextAccountNumber), ctx) } -// SendModuleMessageUntyped mocks base method. -func (m *MockAccountsModKeeper) SendModuleMessageUntyped(ctx context.Context, sender []byte, msg protoiface.MessageV1) (protoiface.MessageV1, error) { +// SendModuleMessage mocks base method. +func (m *MockAccountsModKeeper) SendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SendModuleMessageUntyped", ctx, sender, msg) - ret0, _ := ret[0].(protoiface.MessageV1) + ret := m.ctrl.Call(m, "SendModuleMessage", ctx, sender, msg) + ret0, _ := ret[0].(transaction.Msg) ret1, _ := ret[1].(error) return ret0, ret1 } -// SendModuleMessageUntyped indicates an expected call of SendModuleMessageUntyped. -func (mr *MockAccountsModKeeperMockRecorder) SendModuleMessageUntyped(ctx, sender, msg interface{}) *gomock.Call { +// SendModuleMessage indicates an expected call of SendModuleMessage. +func (mr *MockAccountsModKeeperMockRecorder) SendModuleMessage(ctx, sender, msg interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendModuleMessageUntyped", reflect.TypeOf((*MockAccountsModKeeper)(nil).SendModuleMessageUntyped), ctx, sender, msg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendModuleMessage", reflect.TypeOf((*MockAccountsModKeeper)(nil).SendModuleMessage), ctx, sender, msg) } diff --git a/x/authz/client/cli/tx.go b/x/authz/client/cli/tx.go index f8cc4b26a165..515efb5aa95a 100644 --- a/x/authz/client/cli/tx.go +++ b/x/authz/client/cli/tx.go @@ -58,8 +58,8 @@ func GetTxCmd() *cobra.Command { // but it will be removed in future versions. func NewCmdExecAuthorization() *cobra.Command { cmd := &cobra.Command{ - Use: "legacy-exec --from ", - Short: "Execute tx on behalf of granter account. Deprecated, use exec instead.", + Use: "legacy-exec --from ", + Short: "Execute tx on behalf of granter account. Deprecated, use exec instead.", Example: fmt.Sprintf("$ %s tx authz exec tx.json --from grantee\n $ %[1]s tx bank send [granter] [recipient] [amount] --generate-only tx.json && %[1]s tx authz exec tx.json --from grantee", version.AppName), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go index e2708a55ff31..8e24fff495c4 100644 --- a/x/authz/keeper/keeper.go +++ b/x/authz/keeper/keeper.go @@ -146,7 +146,7 @@ func (k Keeper) DispatchActions(ctx context.Context, grantee sdk.AccAddress, msg } // no need to use the branch service here, as if the transaction fails, the transaction will be reverted - resp, err := k.MsgRouterService.InvokeUntyped(ctx, msg) + resp, err := k.MsgRouterService.Invoke(ctx, msg) if err != nil { return nil, fmt.Errorf("failed to execute message %d; message %v: %w", i, msg, err) } diff --git a/x/evidence/keeper/infraction.go b/x/evidence/keeper/infraction.go index 713d21ad62b8..ac417aa6c664 100644 --- a/x/evidence/keeper/infraction.go +++ b/x/evidence/keeper/infraction.go @@ -73,10 +73,15 @@ func (k Keeper) handleEquivocationEvidence(ctx context.Context, evidence *types. // Reject evidence if the double-sign is too old. Evidence is considered stale // if the difference in time and number of blocks is greater than the allowed // parameters defined. - var res consensusv1.QueryParamsResponse - if err := k.QueryRouterService.InvokeTyped(ctx, &consensusv1.QueryParamsRequest{}, &res); err != nil { + resp, err := k.QueryRouterService.Invoke(ctx, &consensusv1.QueryParamsRequest{}) + if err != nil { return fmt.Errorf("failed to query consensus params: %w", err) } + res, ok := resp.(*consensusv1.QueryParamsResponse) + if !ok { + return fmt.Errorf("unexpected response type: %T", resp) + } + if res.Params.Evidence != nil { if ageDuration > res.Params.Evidence.MaxAgeDuration && ageBlocks > res.Params.Evidence.MaxAgeNumBlocks { k.Logger.Info( diff --git a/x/gov/keeper/abci.go b/x/gov/keeper/abci.go index f45c3d4c0a66..c0e4120528ab 100644 --- a/x/gov/keeper/abci.go +++ b/x/gov/keeper/abci.go @@ -288,7 +288,7 @@ func safeExecuteHandler(ctx context.Context, msg sdk.Msg, router router.Service) } }() - res, err = router.InvokeUntyped(ctx, msg) + res, err = router.Invoke(ctx, msg) return } diff --git a/x/gov/keeper/abci_internal_test.go b/x/gov/keeper/abci_internal_test.go index 47a6a197a0f9..fc1315dc73cf 100644 --- a/x/gov/keeper/abci_internal_test.go +++ b/x/gov/keeper/abci_internal_test.go @@ -16,7 +16,7 @@ type mockRouterService struct { panic bool } -func (m *mockRouterService) InvokeUntyped(ctx context.Context, req gogoproto.Message) (res gogoproto.Message, err error) { +func (m *mockRouterService) Invoke(ctx context.Context, req gogoproto.Message) (res gogoproto.Message, err error) { if m.panic { panic("test-fail") } diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index 5c7b623f045f..8dca8c094fe1 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -5,10 +5,9 @@ import ( "encoding/json" "fmt" - "google.golang.org/protobuf/runtime/protoiface" - corecontext "cosmossdk.io/core/context" "cosmossdk.io/core/event" + "cosmossdk.io/core/transaction" "cosmossdk.io/errors" "cosmossdk.io/math" govtypes "cosmossdk.io/x/gov/types" @@ -379,14 +378,14 @@ func (k msgServer) SudoExec(ctx context.Context, msg *v1.MsgSudoExec) (*v1.MsgSu } } - var msgResp protoiface.MessageV1 + var msgResp transaction.Msg if err := k.BranchService.Execute(ctx, func(ctx context.Context) error { // TODO add route check here if err := k.MsgRouterService.CanInvoke(ctx, sdk.MsgTypeURL(sudoedMsg)); err != nil { return errors.Wrap(govtypes.ErrInvalidProposal, err.Error()) } - msgResp, err = k.MsgRouterService.InvokeUntyped(ctx, sudoedMsg) + msgResp, err = k.MsgRouterService.Invoke(ctx, sudoedMsg) if err != nil { return errors.Wrapf(err, "failed to execute sudo-ed message; message %v", sudoedMsg) } diff --git a/x/group/go.mod b/x/group/go.mod index 5ce3087809e9..4d54911cc3ab 100644 --- a/x/group/go.mod +++ b/x/group/go.mod @@ -45,6 +45,7 @@ require ( cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/x/distribution v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -189,6 +190,7 @@ replace ( cosmossdk.io/core => ../../core cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/x/accounts => ../accounts + cosmossdk.io/x/accounts/defaults/lockup => ../accounts/defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ../accounts/defaults/multisig cosmossdk.io/x/auth => ../auth cosmossdk.io/x/authz => ../authz diff --git a/x/group/go.sum b/x/group/go.sum index 2badce6b5501..8b8baf8c1c8f 100644 --- a/x/group/go.sum +++ b/x/group/go.sum @@ -16,8 +16,6 @@ cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= -cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 h1:eb0kcGyaYHSS0do7+MIWg7UKlskSH01biRNENbm/zDA= -cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5/go.mod h1:drzY4oVisyWvSgpsM7ccQ7IX3efMuVIvd9Eij1Gm/6o= cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 h1:GuBrfHsK3RD5vlD4DuBz3DXslR6VlnzrYmHOC3L679Q= cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337/go.mod h1:PhLn1pMBilyRC4GfRkoYhm+XVAYhF4adVrzut8AdpJI= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/group/keeper/proposal_executor.go b/x/group/keeper/proposal_executor.go index ffa9f4657ea1..4ecef52d1927 100644 --- a/x/group/keeper/proposal_executor.go +++ b/x/group/keeper/proposal_executor.go @@ -45,7 +45,7 @@ func (k Keeper) doExecuteMsgs(ctx context.Context, proposal group.Proposal, grou } for i, msg := range msgs { - if _, err := k.MsgRouterService.InvokeUntyped(ctx, msg); err != nil { + if _, err := k.MsgRouterService.Invoke(ctx, msg); err != nil { return errorsmod.Wrapf(err, "message %s at position %d", sdk.MsgTypeURL(msg), i) } } diff --git a/x/staking/keeper/msg_server.go b/x/staking/keeper/msg_server.go index 166f5a1ef62b..cd8fc499c012 100644 --- a/x/staking/keeper/msg_server.go +++ b/x/staking/keeper/msg_server.go @@ -69,10 +69,15 @@ func (k msgServer) CreateValidator(ctx context.Context, msg *types.MsgCreateVali return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "Expecting cryptotypes.PubKey, got %T", msg.Pubkey.GetCachedValue()) } - res := consensusv1.QueryParamsResponse{} - if err := k.QueryRouterService.InvokeTyped(ctx, &consensusv1.QueryParamsRequest{}, &res); err != nil { + resp, err := k.QueryRouterService.Invoke(ctx, &consensusv1.QueryParamsRequest{}) + if err != nil { return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "failed to query consensus params: %s", err) } + res, ok := resp.(*consensusv1.QueryParamsResponse) + if !ok { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "unexpected response type: %T", resp) + } + if res.Params.Validator != nil { pkType := pk.Type() if !slices.Contains(res.Params.Validator.PubKeyTypes, pkType) { @@ -652,10 +657,15 @@ func (k msgServer) RotateConsPubKey(ctx context.Context, msg *types.MsgRotateCon } // check if the new public key type is valid - paramsRes := consensusv1.QueryParamsResponse{} - if err := k.QueryRouterService.InvokeTyped(ctx, &consensusv1.QueryParamsRequest{}, ¶msRes); err != nil { + resp, err := k.QueryRouterService.Invoke(ctx, &consensusv1.QueryParamsRequest{}) + if err != nil { return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "failed to query consensus params: %s", err) } + paramsRes, ok := resp.(*consensusv1.QueryParamsResponse) + if !ok { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "unexpected response type: %T", resp) + } + if paramsRes.Params.Validator != nil { pkType := pk.Type() if !slices.Contains(paramsRes.Params.Validator.PubKeyTypes, pkType) { diff --git a/x/upgrade/keeper/abci.go b/x/upgrade/keeper/abci.go index e6bed2f5e6ae..926dd4afec09 100644 --- a/x/upgrade/keeper/abci.go +++ b/x/upgrade/keeper/abci.go @@ -45,10 +45,16 @@ func (k Keeper) PreBlocker(ctx context.Context) error { if lastAppliedPlan != "" && !k.HasHandler(lastAppliedPlan) { var appVersion uint64 - var res consensusv1.QueryParamsResponse - if err := k.QueryRouterService.InvokeTyped(ctx, &consensusv1.QueryParamsRequest{}, &res); err != nil { + resp, err := k.QueryRouterService.Invoke(ctx, &consensusv1.QueryParamsRequest{}) + if err != nil { return errors.New("failed to query consensus params") } + + res, ok := resp.(*consensusv1.QueryParamsResponse) + if !ok { + return fmt.Errorf("unexpected response type: %T", resp) + } + if res.Params.Version != nil { appVersion = res.Params.Version.App }