Add ADR 031 BaseApp and codec infrastructure (#7519)
* Refactor RegisterQueryServices -> RegisterServices * Cleaner proto files * Fix tests * Add MsgServer * Fix lint * Remove MsgServer from configurator for now * Remove useless file * Fix build * typo * Add router * Fix test * WIP * Add router * Remove test helper * Add beginning of test * Move test to simapp? * ServiceMsg implement sdk.Msg * Add handler by MsgServiceRouter * Correct signature * Add full test * use TxEncoder * Update baseapp/msg_service_router.go Co-authored-by: Aaron Craelius <aaron@regen.network> * Push changes * WIP on ServiceMsg unpacking * Make TestMsgService test pass * Fix tests * Tidying up * Tidying up * Tidying up * Add JSON test * Add comments * Tidying * Lint * Register MsgRequest interface * Rename * Fix tests * RegisterCustomTypeURL * Add changelog entries * Put in features * Update baseapp/msg_service_router.go Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> * Update baseapp/msg_service_router.go Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> * Update baseapp/msg_service_router.go Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> * Update baseapp/msg_service_router.go Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> * Update baseapp/msg_service_router.go Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> * Update baseapp/msg_service_router.go Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> * Update baseapp/msg_service_router.go Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> * Address review comments * Address nit * Fix lint * Update codec/types/interface_registry.go Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com> * godoc Co-authored-by: Aaron Craelius <aaronc@users.noreply.github.com> Co-authored-by: Aaron Craelius <aaron@regen.network> Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>
This commit is contained in:
parent
e6e4a94071
commit
55242a659c
|
@ -40,6 +40,15 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
|
||||
* (x/staking) [\#7499](https://github.com/cosmos/cosmos-sdk/pull/7499) `BondStatus` is now a protobuf `enum` instead of an `int32`, and JSON serialized using its protobuf name, so expect names like `BOND_STATUS_UNBONDING` as opposed to `Unbonding`.
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (AppModule) [\#7518](https://github.com/cosmos/cosmos-sdk/pull/7518) Rename `AppModule.RegisterQueryServices` to `AppModule.RegisterServices`, as this method now registers multiple services (the gRPC query service and the protobuf Msg service). A `Configurator` struct is used to hold the different services.
|
||||
|
||||
### Features
|
||||
|
||||
* (codec) [\#7519](https://github.com/cosmos/cosmos-sdk/pull/7519) `InterfaceRegistry` now inherits `jsonpb.AnyResolver`, and has a `RegisterCustomTypeURL` method to support ADR 031 packing of `Any`s. `AnyResolver` is now a required parameter to `RejectUnknownFields`.
|
||||
* (baseapp) [\#7519](https://github.com/cosmos/cosmos-sdk/pull/7519) Add `ServiceMsgRouter` to BaseApp to handle routing of protobuf service `Msg`s. The two new types defined in ADR 031, `sdk.ServiceMsg` and `sdk.MsgRequest` are introduced with this router.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (kvstore) [\#7415](https://github.com/cosmos/cosmos-sdk/pull/7415) Allow new stores to be registered during on-chain upgrades.
|
||||
|
|
|
@ -688,7 +688,7 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) abci.Res
|
|||
Result: res,
|
||||
}
|
||||
|
||||
bz, err := codec.ProtoMarshalJSON(simRes)
|
||||
bz, err := codec.ProtoMarshalJSON(simRes, app.interfaceRegistry)
|
||||
if err != nil {
|
||||
return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to JSON encode simulation response"))
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/snapshots"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
"github.com/cosmos/cosmos-sdk/store/rootmulti"
|
||||
|
@ -45,15 +46,17 @@ type (
|
|||
// BaseApp reflects the ABCI application implementation.
|
||||
type BaseApp struct { // nolint: maligned
|
||||
// initialized on creation
|
||||
logger log.Logger
|
||||
name string // application name from abci.Info
|
||||
db dbm.DB // common DB backend
|
||||
cms sdk.CommitMultiStore // Main (uncached) state
|
||||
storeLoader StoreLoader // function to handle store loading, may be overridden with SetStoreLoader()
|
||||
router sdk.Router // handle any kind of message
|
||||
queryRouter sdk.QueryRouter // router for redirecting query calls
|
||||
grpcQueryRouter *GRPCQueryRouter // router for redirecting gRPC query calls
|
||||
txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx
|
||||
logger log.Logger
|
||||
name string // application name from abci.Info
|
||||
db dbm.DB // common DB backend
|
||||
cms sdk.CommitMultiStore // Main (uncached) state
|
||||
storeLoader StoreLoader // function to handle store loading, may be overridden with SetStoreLoader()
|
||||
router sdk.Router // handle any kind of message
|
||||
queryRouter sdk.QueryRouter // router for redirecting query calls
|
||||
grpcQueryRouter *GRPCQueryRouter // router for redirecting gRPC query calls
|
||||
msgServiceRouter *MsgServiceRouter // router for redirecting Msg service messages
|
||||
interfaceRegistry types.InterfaceRegistry
|
||||
txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx
|
||||
|
||||
anteHandler sdk.AnteHandler // ante handler for fee and auth
|
||||
initChainer sdk.InitChainer // initialize state with validators and state blob
|
||||
|
@ -136,16 +139,17 @@ func NewBaseApp(
|
|||
name string, logger log.Logger, db dbm.DB, txDecoder sdk.TxDecoder, options ...func(*BaseApp),
|
||||
) *BaseApp {
|
||||
app := &BaseApp{
|
||||
logger: logger,
|
||||
name: name,
|
||||
db: db,
|
||||
cms: store.NewCommitMultiStore(db),
|
||||
storeLoader: DefaultStoreLoader,
|
||||
router: NewRouter(),
|
||||
queryRouter: NewQueryRouter(),
|
||||
grpcQueryRouter: NewGRPCQueryRouter(),
|
||||
txDecoder: txDecoder,
|
||||
fauxMerkleMode: false,
|
||||
logger: logger,
|
||||
name: name,
|
||||
db: db,
|
||||
cms: store.NewCommitMultiStore(db),
|
||||
storeLoader: DefaultStoreLoader,
|
||||
router: NewRouter(),
|
||||
queryRouter: NewQueryRouter(),
|
||||
grpcQueryRouter: NewGRPCQueryRouter(),
|
||||
msgServiceRouter: NewMsgServiceRouter(),
|
||||
txDecoder: txDecoder,
|
||||
fauxMerkleMode: false,
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
|
@ -176,6 +180,9 @@ func (app *BaseApp) Logger() log.Logger {
|
|||
return app.logger
|
||||
}
|
||||
|
||||
// MsgServiceRouter returns the MsgServiceRouter of a BaseApp.
|
||||
func (app *BaseApp) MsgServiceRouter() *MsgServiceRouter { return app.msgServiceRouter }
|
||||
|
||||
// MountStores mounts all IAVL or DB stores to the provided keys in the BaseApp
|
||||
// multistore.
|
||||
func (app *BaseApp) MountStores(keys ...sdk.StoreKey) {
|
||||
|
@ -682,20 +689,38 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s
|
|||
break
|
||||
}
|
||||
|
||||
msgRoute := msg.Route()
|
||||
handler := app.router.Route(ctx, msgRoute)
|
||||
var (
|
||||
msgEvents sdk.Events
|
||||
msgResult *sdk.Result
|
||||
msgFqName string
|
||||
err error
|
||||
)
|
||||
|
||||
if handler == nil {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message index: %d", msgRoute, i)
|
||||
if svcMsg, ok := msg.(sdk.ServiceMsg); ok {
|
||||
msgFqName = svcMsg.MethodName
|
||||
handler := app.msgServiceRouter.Handler(msgFqName)
|
||||
if handler == nil {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message service method: %s; message index: %d", msgFqName, i)
|
||||
}
|
||||
msgResult, err = handler(ctx, svcMsg.Request)
|
||||
} else {
|
||||
// legacy sdk.Msg routing
|
||||
msgRoute := msg.Route()
|
||||
msgFqName = msg.Type()
|
||||
handler := app.router.Route(ctx, msgRoute)
|
||||
if handler == nil {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message index: %d", msgRoute, i)
|
||||
}
|
||||
|
||||
msgResult, err = handler(ctx, msg)
|
||||
}
|
||||
|
||||
msgResult, err := handler(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "failed to execute message; message index: %d", i)
|
||||
}
|
||||
|
||||
msgEvents := sdk.Events{
|
||||
sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type())),
|
||||
msgEvents = sdk.Events{
|
||||
sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msgFqName)),
|
||||
}
|
||||
msgEvents = msgEvents.AppendEvents(msgResult.GetEvents())
|
||||
|
||||
|
|
|
@ -1692,9 +1692,9 @@ func TestQuery(t *testing.T) {
|
|||
|
||||
func TestGRPCQuery(t *testing.T) {
|
||||
grpcQueryOpt := func(bapp *BaseApp) {
|
||||
testdata.RegisterTestServiceServer(
|
||||
testdata.RegisterQueryServer(
|
||||
bapp.GRPCQueryRouter(),
|
||||
testdata.TestServiceImpl{},
|
||||
testdata.QueryImpl{},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1711,7 +1711,7 @@ func TestGRPCQuery(t *testing.T) {
|
|||
|
||||
reqQuery := abci.RequestQuery{
|
||||
Data: reqBz,
|
||||
Path: "/testdata.TestService/SayHello",
|
||||
Path: "/testdata.Query/SayHello",
|
||||
}
|
||||
|
||||
resQuery := app.Query(reqQuery)
|
||||
|
|
|
@ -4,12 +4,11 @@ import (
|
|||
gocontext "context"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
|
||||
gogogrpc "github.com/gogo/protobuf/grpc"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
|
@ -22,6 +21,11 @@ type QueryServiceTestHelper struct {
|
|||
ctx sdk.Context
|
||||
}
|
||||
|
||||
var (
|
||||
_ gogogrpc.Server = &QueryServiceTestHelper{}
|
||||
_ gogogrpc.ClientConn = &QueryServiceTestHelper{}
|
||||
)
|
||||
|
||||
// NewQueryServerTestHelper creates a new QueryServiceTestHelper that wraps
|
||||
// the provided sdk.Context
|
||||
func NewQueryServerTestHelper(ctx sdk.Context, interfaceRegistry types.InterfaceRegistry) *QueryServiceTestHelper {
|
||||
|
@ -62,6 +66,3 @@ func (q *QueryServiceTestHelper) Invoke(_ gocontext.Context, method string, args
|
|||
func (q *QueryServiceTestHelper) NewStream(gocontext.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
return nil, fmt.Errorf("not supported")
|
||||
}
|
||||
|
||||
var _ gogogrpc.Server = &QueryServiceTestHelper{}
|
||||
var _ gogogrpc.ClientConn = &QueryServiceTestHelper{}
|
||||
|
|
|
@ -15,12 +15,12 @@ func TestGRPCRouter(t *testing.T) {
|
|||
qr := NewGRPCQueryRouter()
|
||||
interfaceRegistry := testdata.NewTestInterfaceRegistry()
|
||||
qr.SetInterfaceRegistry(interfaceRegistry)
|
||||
testdata.RegisterTestServiceServer(qr, testdata.TestServiceImpl{})
|
||||
testdata.RegisterQueryServer(qr, testdata.QueryImpl{})
|
||||
helper := &QueryServiceTestHelper{
|
||||
GRPCQueryRouter: qr,
|
||||
ctx: sdk.Context{}.WithContext(context.Background()),
|
||||
}
|
||||
client := testdata.NewTestServiceClient(helper)
|
||||
client := testdata.NewQueryClient(helper)
|
||||
|
||||
res, err := client.Echo(context.Background(), &testdata.EchoRequest{Message: "hello"})
|
||||
require.Nil(t, err)
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package baseapp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
gogogrpc "github.com/gogo/protobuf/grpc"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// MsgServiceRouter routes fully-qualified Msg service methods to their handler.
|
||||
type MsgServiceRouter struct {
|
||||
interfaceRegistry codectypes.InterfaceRegistry
|
||||
routes map[string]MsgServiceHandler
|
||||
}
|
||||
|
||||
var _ gogogrpc.Server = &MsgServiceRouter{}
|
||||
|
||||
// NewMsgServiceRouter creates a new MsgServiceRouter.
|
||||
func NewMsgServiceRouter() *MsgServiceRouter {
|
||||
return &MsgServiceRouter{
|
||||
routes: map[string]MsgServiceHandler{},
|
||||
}
|
||||
}
|
||||
|
||||
// MsgServiceHandler defines a function type which handles Msg service message.
|
||||
type MsgServiceHandler = func(ctx sdk.Context, req sdk.MsgRequest) (*sdk.Result, error)
|
||||
|
||||
// Handler returns the MsgServiceHandler for a given query route path or nil
|
||||
// if not found.
|
||||
func (msr *MsgServiceRouter) Handler(methodName string) MsgServiceHandler {
|
||||
return msr.routes[methodName]
|
||||
}
|
||||
|
||||
// RegisterService implements the gRPC Server.RegisterService method. sd is a gRPC
|
||||
// service description, handler is an object which implements that gRPC service.
|
||||
func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler interface{}) {
|
||||
// Adds a top-level query handler based on the gRPC service name.
|
||||
for _, method := range sd.Methods {
|
||||
fqMethod := fmt.Sprintf("/%s/%s", sd.ServiceName, method.MethodName)
|
||||
methodHandler := method.Handler
|
||||
|
||||
// NOTE: This is how we pull the concrete request type for each handler for registering in the InterfaceRegistry.
|
||||
// This approach is maybe a bit hacky, but less hacky than reflecting on the handler object itself.
|
||||
// We use a no-op interceptor to avoid actually calling into the handler itself.
|
||||
_, _ = methodHandler(nil, context.Background(), func(i interface{}) error {
|
||||
msg, ok := i.(proto.Message)
|
||||
if !ok {
|
||||
// We panic here because there is no other alternative and the app cannot be initialized correctly
|
||||
// this should only happen if there is a problem with code generation in which case the app won't
|
||||
// work correctly anyway.
|
||||
panic(fmt.Errorf("can't register request type %T for service method %s", i, fqMethod))
|
||||
}
|
||||
|
||||
msr.interfaceRegistry.RegisterCustomTypeURL((*sdk.MsgRequest)(nil), fqMethod, msg)
|
||||
return nil
|
||||
}, func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
msr.routes[fqMethod] = func(ctx sdk.Context, req sdk.MsgRequest) (*sdk.Result, error) {
|
||||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
|
||||
// Call the method handler from the service description with the handler object.
|
||||
res, err := methodHandler(handler, sdk.WrapSDKContext(ctx), func(_ interface{}) error {
|
||||
// We don't do any decoding here because the decoding was already done.
|
||||
return nil
|
||||
}, func(goCtx context.Context, _ interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
goCtx = context.WithValue(goCtx, sdk.SdkContextKey, ctx)
|
||||
return handler(goCtx, req)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resMsg, ok := res.(proto.Message)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("can't proto encode %T", resMsg)
|
||||
}
|
||||
|
||||
return sdk.WrapServiceResult(ctx, resMsg, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetInterfaceRegistry sets the interface registry for the router.
|
||||
func (msr *MsgServiceRouter) SetInterfaceRegistry(interfaceRegistry codectypes.InterfaceRegistry) {
|
||||
msr.interfaceRegistry = interfaceRegistry
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package baseapp_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
func TestMsgService(t *testing.T) {
|
||||
priv, _, _ := testdata.KeyTestPubAddr()
|
||||
encCfg := simapp.MakeEncodingConfig()
|
||||
db := dbm.NewMemDB()
|
||||
app := baseapp.NewBaseApp("test", log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, encCfg.TxConfig.TxDecoder())
|
||||
app.SetInterfaceRegistry(encCfg.InterfaceRegistry)
|
||||
testdata.RegisterMsgServer(
|
||||
app.MsgServiceRouter(),
|
||||
testdata.MsgServerImpl{},
|
||||
)
|
||||
_ = app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: 1}})
|
||||
|
||||
msg := testdata.NewServiceMsgCreateDog(&testdata.MsgCreateDog{Dog: &testdata.Dog{Name: "Spot"}})
|
||||
txBuilder := encCfg.TxConfig.NewTxBuilder()
|
||||
txBuilder.SetFeeAmount(testdata.NewTestFeeAmount())
|
||||
txBuilder.SetGasLimit(testdata.NewTestGasLimit())
|
||||
err := txBuilder.SetMsgs(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
// First round: we gather all the signer infos. We use the "set empty
|
||||
// signature" hack to do that.
|
||||
sigV2 := signing.SignatureV2{
|
||||
PubKey: priv.PubKey(),
|
||||
Data: &signing.SingleSignatureData{
|
||||
SignMode: encCfg.TxConfig.SignModeHandler().DefaultMode(),
|
||||
Signature: nil,
|
||||
},
|
||||
Sequence: 0,
|
||||
}
|
||||
|
||||
err = txBuilder.SetSignatures(sigV2)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Second round: all signer infos are set, so each signer can sign.
|
||||
signerData := authsigning.SignerData{
|
||||
ChainID: "test",
|
||||
AccountNumber: 0,
|
||||
Sequence: 0,
|
||||
}
|
||||
sigV2, err = tx.SignWithPrivKey(
|
||||
encCfg.TxConfig.SignModeHandler().DefaultMode(), signerData,
|
||||
txBuilder, priv, encCfg.TxConfig, 0)
|
||||
require.NoError(t, err)
|
||||
err = txBuilder.SetSignatures(sigV2)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Send the tx to the app
|
||||
txBytes, err := encCfg.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||
require.NoError(t, err)
|
||||
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
||||
require.Equal(t, abci.CodeTypeOK, res.Code, "res=%+v", res)
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/snapshots"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -221,3 +222,10 @@ func (app *BaseApp) SetSnapshotKeepRecent(snapshotKeepRecent uint32) {
|
|||
}
|
||||
app.snapshotKeepRecent = snapshotKeepRecent
|
||||
}
|
||||
|
||||
// SetInterfaceRegistry sets the InterfaceRegistry.
|
||||
func (app *BaseApp) SetInterfaceRegistry(registry types.InterfaceRegistry) {
|
||||
app.interfaceRegistry = registry
|
||||
app.grpcQueryRouter.SetInterfaceRegistry(registry)
|
||||
app.msgServiceRouter.SetInterfaceRegistry(registry)
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ func TestCLIQueryConn(t *testing.T) {
|
|||
n := network.New(t, cfg)
|
||||
defer n.Cleanup()
|
||||
|
||||
testClient := testdata.NewTestServiceClient(n.Validators[0].ClientCtx)
|
||||
testClient := testdata.NewQueryClient(n.Validators[0].ClientCtx)
|
||||
res, err := testClient.Echo(context.Background(), &testdata.EchoRequest{Message: "hello"})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "hello", res.Message)
|
||||
|
|
|
@ -43,7 +43,7 @@ func (s *IntegrationTestSuite) TestGRPCQuery() {
|
|||
val0 := s.network.Validators[0]
|
||||
|
||||
// gRPC query to test service should work
|
||||
testClient := testdata.NewTestServiceClient(val0.ClientCtx)
|
||||
testClient := testdata.NewQueryClient(val0.ClientCtx)
|
||||
testRes, err := testClient.Echo(context.Background(), &testdata.EchoRequest{Message: "hello"})
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal("hello", testRes.Message)
|
||||
|
|
|
@ -11,10 +11,10 @@ import (
|
|||
|
||||
// ProtoMarshalJSON provides an auxiliary function to return Proto3 JSON encoded
|
||||
// bytes of a message.
|
||||
func ProtoMarshalJSON(msg proto.Message) ([]byte, error) {
|
||||
func ProtoMarshalJSON(msg proto.Message, resolver jsonpb.AnyResolver) ([]byte, error) {
|
||||
// We use the OrigName because camel casing fields just doesn't make sense.
|
||||
// EmitDefaults is also often the more expected behavior for CLI users
|
||||
jm := &jsonpb.Marshaler{OrigName: true, EmitDefaults: true}
|
||||
jm := &jsonpb.Marshaler{OrigName: true, EmitDefaults: true, AnyResolver: resolver}
|
||||
err := types.UnpackInterfaces(msg, types.ProtoJSONPacker{JSONPBMarshaler: jm})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -14,14 +14,14 @@ import (
|
|||
// ProtoCodec defines a codec that utilizes Protobuf for both binary and JSON
|
||||
// encoding.
|
||||
type ProtoCodec struct {
|
||||
anyUnpacker types.AnyUnpacker
|
||||
interfaceRegistry types.InterfaceRegistry
|
||||
}
|
||||
|
||||
var _ Marshaler = &ProtoCodec{}
|
||||
|
||||
// NewProtoCodec returns a reference to a new ProtoCodec
|
||||
func NewProtoCodec(anyUnpacker types.AnyUnpacker) *ProtoCodec {
|
||||
return &ProtoCodec{anyUnpacker: anyUnpacker}
|
||||
func NewProtoCodec(interfaceRegistry types.InterfaceRegistry) *ProtoCodec {
|
||||
return &ProtoCodec{interfaceRegistry: interfaceRegistry}
|
||||
}
|
||||
|
||||
// MarshalBinaryBare implements BinaryMarshaler.MarshalBinaryBare method.
|
||||
|
@ -67,7 +67,7 @@ func (pc *ProtoCodec) UnmarshalBinaryBare(bz []byte, ptr ProtoMarshaler) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.UnpackInterfaces(ptr, pc.anyUnpacker)
|
||||
err = types.UnpackInterfaces(ptr, pc.interfaceRegistry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ func (pc *ProtoCodec) MarshalJSON(o proto.Message) ([]byte, error) {
|
|||
return nil, fmt.Errorf("cannot protobuf JSON encode unsupported type: %T", o)
|
||||
}
|
||||
|
||||
return ProtoMarshalJSON(m)
|
||||
return ProtoMarshalJSON(m, pc.interfaceRegistry)
|
||||
}
|
||||
|
||||
// MustMarshalJSON implements JSONMarshaler.MustMarshalJSON method,
|
||||
|
@ -135,12 +135,13 @@ func (pc *ProtoCodec) UnmarshalJSON(bz []byte, ptr proto.Message) error {
|
|||
return fmt.Errorf("cannot protobuf JSON decode unsupported type: %T", ptr)
|
||||
}
|
||||
|
||||
err := jsonpb.Unmarshal(strings.NewReader(string(bz)), m)
|
||||
unmarshaler := jsonpb.Unmarshaler{AnyResolver: pc.interfaceRegistry}
|
||||
err := unmarshaler.Unmarshal(strings.NewReader(string(bz)), m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return types.UnpackInterfaces(ptr, pc.anyUnpacker)
|
||||
return types.UnpackInterfaces(ptr, pc.interfaceRegistry)
|
||||
}
|
||||
|
||||
// MustUnmarshalJSON implements JSONMarshaler.MustUnmarshalJSON method,
|
||||
|
@ -155,5 +156,9 @@ func (pc *ProtoCodec) MustUnmarshalJSON(bz []byte, ptr proto.Message) {
|
|||
// it unpacks the value in any to the interface pointer passed in as
|
||||
// iface.
|
||||
func (pc *ProtoCodec) UnpackAny(any *types.Any, iface interface{}) error {
|
||||
return pc.anyUnpacker.UnpackAny(any, iface)
|
||||
return pc.interfaceRegistry.UnpackAny(any, iface)
|
||||
}
|
||||
|
||||
func (pc *ProtoCodec) InterfaceRegistry() types.InterfaceRegistry {
|
||||
return pc.interfaceRegistry
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
|
@ -24,6 +26,7 @@ type AnyUnpacker interface {
|
|||
// implementations that can be safely unpacked from Any
|
||||
type InterfaceRegistry interface {
|
||||
AnyUnpacker
|
||||
jsonpb.AnyResolver
|
||||
|
||||
// RegisterInterface associates protoName as the public name for the
|
||||
// interface passed in as iface. This is to be used primarily to create
|
||||
|
@ -43,6 +46,17 @@ type InterfaceRegistry interface {
|
|||
// registry.RegisterImplementations((*sdk.Msg)(nil), &MsgSend{}, &MsgMultiSend{})
|
||||
RegisterImplementations(iface interface{}, impls ...proto.Message)
|
||||
|
||||
// RegisterCustomTypeURL allows a protobuf message to be registered as a
|
||||
// google.protobuf.Any with a custom typeURL (besides its own canonical
|
||||
// typeURL). iface should be an interface as type, as in RegisterInterface
|
||||
// and RegisterImplementations.
|
||||
//
|
||||
// Ex:
|
||||
// This will allow us to pack service methods in Any's using the full method name
|
||||
// as the type URL and the request body as the value, and allow us to unpack
|
||||
// such packed methods using the normal UnpackAny method for the interface iface.
|
||||
RegisterCustomTypeURL(iface interface{}, typeURL string, impl proto.Message)
|
||||
|
||||
// ListAllInterfaces list the type URLs of all registered interfaces.
|
||||
ListAllInterfaces() []string
|
||||
|
||||
|
@ -78,6 +92,7 @@ type UnpackInterfacesMessage interface {
|
|||
type interfaceRegistry struct {
|
||||
interfaceNames map[string]reflect.Type
|
||||
interfaceImpls map[reflect.Type]interfaceMap
|
||||
typeURLMap map[string]reflect.Type
|
||||
}
|
||||
|
||||
type interfaceMap = map[string]reflect.Type
|
||||
|
@ -87,6 +102,7 @@ func NewInterfaceRegistry() InterfaceRegistry {
|
|||
return &interfaceRegistry{
|
||||
interfaceNames: map[string]reflect.Type{},
|
||||
interfaceImpls: map[reflect.Type]interfaceMap{},
|
||||
typeURLMap: map[string]reflect.Type{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,21 +116,31 @@ func (registry *interfaceRegistry) RegisterInterface(protoName string, iface int
|
|||
}
|
||||
|
||||
func (registry *interfaceRegistry) RegisterImplementations(iface interface{}, impls ...proto.Message) {
|
||||
for _, impl := range impls {
|
||||
typeURL := "/" + proto.MessageName(impl)
|
||||
registry.registerImpl(iface, typeURL, impl)
|
||||
}
|
||||
}
|
||||
|
||||
func (registry *interfaceRegistry) RegisterCustomTypeURL(iface interface{}, typeURL string, impl proto.Message) {
|
||||
registry.registerImpl(iface, typeURL, impl)
|
||||
}
|
||||
|
||||
func (registry *interfaceRegistry) registerImpl(iface interface{}, typeURL string, impl proto.Message) {
|
||||
ityp := reflect.TypeOf(iface).Elem()
|
||||
imap, found := registry.interfaceImpls[ityp]
|
||||
if !found {
|
||||
imap = map[string]reflect.Type{}
|
||||
}
|
||||
|
||||
for _, impl := range impls {
|
||||
implType := reflect.TypeOf(impl)
|
||||
if !implType.AssignableTo(ityp) {
|
||||
panic(fmt.Errorf("type %T doesn't actually implement interface %+v", impl, ityp))
|
||||
}
|
||||
|
||||
imap["/"+proto.MessageName(impl)] = implType
|
||||
implType := reflect.TypeOf(impl)
|
||||
if !implType.AssignableTo(ityp) {
|
||||
panic(fmt.Errorf("type %T doesn't actually implement interface %+v", impl, ityp))
|
||||
}
|
||||
|
||||
imap[typeURL] = implType
|
||||
registry.typeURLMap[typeURL] = implType
|
||||
|
||||
registry.interfaceImpls[ityp] = imap
|
||||
}
|
||||
|
||||
|
@ -198,6 +224,23 @@ func (registry *interfaceRegistry) UnpackAny(any *Any, iface interface{}) error
|
|||
return nil
|
||||
}
|
||||
|
||||
// Resolve returns the proto message given its typeURL. It works with types
|
||||
// registered with RegisterInterface/RegisterImplementations, as well as those
|
||||
// registered with RegisterWithCustomTypeURL.
|
||||
func (registry *interfaceRegistry) Resolve(typeURL string) (proto.Message, error) {
|
||||
typ, found := registry.typeURLMap[typeURL]
|
||||
if !found {
|
||||
return nil, fmt.Errorf("unable to resolve type URL %s", typeURL)
|
||||
}
|
||||
|
||||
msg, ok := reflect.New(typ.Elem()).Interface().(proto.Message)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("can't resolve type URL %s", typeURL)
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// UnpackInterfaces is a convenience function that calls UnpackInterfaces
|
||||
// on x if x implements UnpackInterfacesMessage
|
||||
func UnpackInterfaces(x interface{}, unpacker AnyUnpacker) error {
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
package types_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/grpc"
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
grpc2 "google.golang.org/grpc"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
)
|
||||
|
||||
|
@ -153,3 +158,60 @@ func TestAny_ProtoJSON(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, spot, ha2.Animal.GetCachedValue())
|
||||
}
|
||||
|
||||
// this instance of grpc.ClientConn is used to test packing service method
|
||||
// requests into Any's
|
||||
type testAnyPackClient struct {
|
||||
any types.Any
|
||||
interfaceRegistry types.InterfaceRegistry
|
||||
}
|
||||
|
||||
var _ grpc.ClientConn = &testAnyPackClient{}
|
||||
|
||||
func (t *testAnyPackClient) Invoke(_ context.Context, method string, args, _ interface{}, _ ...grpc2.CallOption) error {
|
||||
reqMsg, ok := args.(proto.Message)
|
||||
if !ok {
|
||||
return fmt.Errorf("can't proto marshal %T", args)
|
||||
}
|
||||
|
||||
// registry the method request type with the interface registry
|
||||
t.interfaceRegistry.RegisterCustomTypeURL((*interface{})(nil), method, reqMsg)
|
||||
|
||||
bz, err := proto.Marshal(reqMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.any.TypeUrl = method
|
||||
t.any.Value = bz
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *testAnyPackClient) NewStream(context.Context, *grpc2.StreamDesc, string, ...grpc2.CallOption) (grpc2.ClientStream, error) {
|
||||
return nil, fmt.Errorf("not supported")
|
||||
}
|
||||
|
||||
func TestAny_ServiceRequestProtoJSON(t *testing.T) {
|
||||
interfaceRegistry := types.NewInterfaceRegistry()
|
||||
anyPacker := &testAnyPackClient{interfaceRegistry: interfaceRegistry}
|
||||
dogMsgClient := testdata.NewMsgClient(anyPacker)
|
||||
_, err := dogMsgClient.CreateDog(context.Background(), &testdata.MsgCreateDog{Dog: &testdata.Dog{
|
||||
Name: "spot",
|
||||
}})
|
||||
require.NoError(t, err)
|
||||
|
||||
// marshal JSON
|
||||
cdc := codec.NewProtoCodec(interfaceRegistry)
|
||||
bz, err := cdc.MarshalJSON(&anyPacker.any)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t,
|
||||
`{"@type":"/testdata.Msg/CreateDog","dog":{"size":"","name":"spot"}}`,
|
||||
string(bz))
|
||||
|
||||
// unmarshal JSON
|
||||
var any2 types.Any
|
||||
err = cdc.UnmarshalJSON(bz, &any2)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, anyPacker.any, any2)
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ func benchmarkRejectUnknownFields(b *testing.B, parallel bool) {
|
|||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
n1A := new(testdata.Nested1A)
|
||||
if err := unknownproto.RejectUnknownFieldsStrict(n1BBlob, n1A); err == nil {
|
||||
if err := unknownproto.RejectUnknownFieldsStrict(n1BBlob, n1A, unknownproto.DefaultAnyResolver{}); err == nil {
|
||||
b.Fatal("expected an error")
|
||||
}
|
||||
b.SetBytes(int64(len(n1BBlob)))
|
||||
|
@ -68,7 +68,7 @@ func benchmarkRejectUnknownFields(b *testing.B, parallel bool) {
|
|||
for pb.Next() {
|
||||
// To simulate the conditions of multiple transactions being processed in parallel.
|
||||
n1A := new(testdata.Nested1A)
|
||||
if err := unknownproto.RejectUnknownFieldsStrict(n1BBlob, n1A); err == nil {
|
||||
if err := unknownproto.RejectUnknownFieldsStrict(n1BBlob, n1A, unknownproto.DefaultAnyResolver{}); err == nil {
|
||||
b.Fatal("expected an error")
|
||||
}
|
||||
mu.Lock()
|
||||
|
|
|
@ -7,8 +7,10 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
|
@ -24,8 +26,9 @@ type descriptorIface interface {
|
|||
|
||||
// RejectUnknownFieldsStrict rejects any bytes bz with an error that has unknown fields for the provided proto.Message type.
|
||||
// This function traverses inside of messages nested via google.protobuf.Any. It does not do any deserialization of the proto.Message.
|
||||
func RejectUnknownFieldsStrict(bz []byte, msg proto.Message) error {
|
||||
_, err := RejectUnknownFields(bz, msg, false)
|
||||
// An AnyResolver must be provided for traversing inside google.protobuf.Any's.
|
||||
func RejectUnknownFieldsStrict(bz []byte, msg proto.Message, resolver jsonpb.AnyResolver) error {
|
||||
_, err := RejectUnknownFields(bz, msg, false, resolver)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -34,7 +37,8 @@ func RejectUnknownFieldsStrict(bz []byte, msg proto.Message) error {
|
|||
// hasUnknownNonCriticals will be set to true if non-critical fields were encountered during traversal. This flag can be
|
||||
// used to treat a message with non-critical field different in different security contexts (such as transaction signing).
|
||||
// This function traverses inside of messages nested via google.protobuf.Any. It does not do any deserialization of the proto.Message.
|
||||
func RejectUnknownFields(bz []byte, msg proto.Message, allowUnknownNonCriticals bool) (hasUnknownNonCriticals bool, err error) {
|
||||
// An AnyResolver must be provided for traversing inside google.protobuf.Any's.
|
||||
func RejectUnknownFields(bz []byte, msg proto.Message, allowUnknownNonCriticals bool, resolver jsonpb.AnyResolver) (hasUnknownNonCriticals bool, err error) {
|
||||
if len(bz) == 0 {
|
||||
return hasUnknownNonCriticals, nil
|
||||
}
|
||||
|
@ -115,9 +119,12 @@ func RejectUnknownFields(bz []byte, msg proto.Message, allowUnknownNonCriticals
|
|||
_, o := protowire.ConsumeVarint(fieldBytes)
|
||||
fieldBytes = fieldBytes[o:]
|
||||
|
||||
var msg proto.Message
|
||||
var err error
|
||||
|
||||
if protoMessageName == ".google.protobuf.Any" {
|
||||
// Firstly typecheck types.Any to ensure nothing snuck in.
|
||||
hasUnknownNonCriticalsChild, err := RejectUnknownFields(fieldBytes, (*types.Any)(nil), allowUnknownNonCriticals)
|
||||
hasUnknownNonCriticalsChild, err := RejectUnknownFields(fieldBytes, (*types.Any)(nil), allowUnknownNonCriticals, resolver)
|
||||
hasUnknownNonCriticals = hasUnknownNonCriticals || hasUnknownNonCriticalsChild
|
||||
if err != nil {
|
||||
return hasUnknownNonCriticals, err
|
||||
|
@ -129,14 +136,18 @@ func RejectUnknownFields(bz []byte, msg proto.Message, allowUnknownNonCriticals
|
|||
}
|
||||
protoMessageName = any.TypeUrl
|
||||
fieldBytes = any.Value
|
||||
msg, err = resolver.Resolve(protoMessageName)
|
||||
if err != nil {
|
||||
return hasUnknownNonCriticals, err
|
||||
}
|
||||
} else {
|
||||
msg, err = protoMessageForTypeName(protoMessageName[1:])
|
||||
if err != nil {
|
||||
return hasUnknownNonCriticals, err
|
||||
}
|
||||
}
|
||||
|
||||
msg, err := protoMessageForTypeName(protoMessageName[1:])
|
||||
if err != nil {
|
||||
return hasUnknownNonCriticals, err
|
||||
}
|
||||
|
||||
hasUnknownNonCriticalsChild, err := RejectUnknownFields(fieldBytes, msg, allowUnknownNonCriticals)
|
||||
hasUnknownNonCriticalsChild, err := RejectUnknownFields(fieldBytes, msg, allowUnknownNonCriticals, resolver)
|
||||
hasUnknownNonCriticals = hasUnknownNonCriticals || hasUnknownNonCriticalsChild
|
||||
if err != nil {
|
||||
return hasUnknownNonCriticals, err
|
||||
|
@ -401,3 +412,23 @@ func getDescriptorInfo(desc descriptorIface, msg proto.Message) (map[int32]*desc
|
|||
|
||||
return tagNumToTypeIndex, md, nil
|
||||
}
|
||||
|
||||
// DefaultAnyResolver is a default implementation of AnyResolver which uses
|
||||
// the default encoding of type URLs as specified by the protobuf specification.
|
||||
type DefaultAnyResolver struct{}
|
||||
|
||||
var _ jsonpb.AnyResolver = DefaultAnyResolver{}
|
||||
|
||||
// Resolve is the AnyResolver.Resolve method.
|
||||
func (d DefaultAnyResolver) Resolve(typeURL string) (proto.Message, error) {
|
||||
// Only the part of typeURL after the last slash is relevant.
|
||||
mname := typeURL
|
||||
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
|
||||
mname = mname[slash+1:]
|
||||
}
|
||||
mt := proto.MessageType(mname)
|
||||
if mt == nil {
|
||||
return nil, fmt.Errorf("unknown message type %q", mname)
|
||||
}
|
||||
return reflect.New(mt.Elem()).Interface().(proto.Message), nil
|
||||
}
|
||||
|
|
|
@ -230,7 +230,7 @@ func TestRejectUnknownFieldsRepeated(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hasUnknownNonCriticals, gotErr := RejectUnknownFields(protoBlob, tt.recv, tt.allowUnknownNonCriticals)
|
||||
hasUnknownNonCriticals, gotErr := RejectUnknownFields(protoBlob, tt.recv, tt.allowUnknownNonCriticals, DefaultAnyResolver{})
|
||||
require.Equal(t, tt.wantErr, gotErr)
|
||||
require.Equal(t, tt.hasUnknownNonCriticals, hasUnknownNonCriticals)
|
||||
})
|
||||
|
@ -289,7 +289,7 @@ func TestRejectUnknownFields_allowUnknownNonCriticals(t *testing.T) {
|
|||
}
|
||||
|
||||
c1 := new(testdata.Customer1)
|
||||
_, gotErr := RejectUnknownFields(blob, c1, tt.allowUnknownNonCriticals)
|
||||
_, gotErr := RejectUnknownFields(blob, c1, tt.allowUnknownNonCriticals, DefaultAnyResolver{})
|
||||
if !reflect.DeepEqual(gotErr, tt.wantErr) {
|
||||
t.Fatalf("Error mismatch\nGot:\n%s\n\nWant:\n%s", gotErr, tt.wantErr)
|
||||
}
|
||||
|
@ -490,7 +490,7 @@ func TestRejectUnknownFieldsNested(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gotErr := RejectUnknownFieldsStrict(protoBlob, tt.recv)
|
||||
gotErr := RejectUnknownFieldsStrict(protoBlob, tt.recv, DefaultAnyResolver{})
|
||||
if !reflect.DeepEqual(gotErr, tt.wantErr) {
|
||||
t.Fatalf("Error mismatch\nGot:\n%s\n\nWant:\n%s", gotErr, tt.wantErr)
|
||||
}
|
||||
|
@ -643,7 +643,7 @@ func TestRejectUnknownFieldsFlat(t *testing.T) {
|
|||
}
|
||||
|
||||
c1 := new(testdata.Customer1)
|
||||
gotErr := RejectUnknownFieldsStrict(blob, c1)
|
||||
gotErr := RejectUnknownFieldsStrict(blob, c1, DefaultAnyResolver{})
|
||||
if !reflect.DeepEqual(gotErr, tt.wantErr) {
|
||||
t.Fatalf("Error mismatch\nGot:\n%s\n\nWant:\n%s", gotErr, tt.wantErr)
|
||||
}
|
||||
|
@ -660,7 +660,7 @@ func TestPackedEncoding(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
unmarshalled := &testdata.TestRepeatedUints{}
|
||||
_, err = RejectUnknownFields(marshalled, unmarshalled, false)
|
||||
_, err = RejectUnknownFields(marshalled, unmarshalled, false, DefaultAnyResolver{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ done
|
|||
|
||||
# generate codec/testdata proto code
|
||||
protoc -I "proto" -I "third_party/proto" -I "testutil/testdata" --gocosmos_out=plugins=interfacetype+grpc,\
|
||||
Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. ./testutil/testdata/proto.proto
|
||||
Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. ./testutil/testdata/*.proto
|
||||
|
||||
# move proto files to the right places
|
||||
cp -r github.com/cosmos/cosmos-sdk/* ./
|
||||
|
|
|
@ -50,7 +50,7 @@ func (s *IntegrationTestSuite) TestGRPCServer() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// gRPC query to test service should work
|
||||
testClient := testdata.NewTestServiceClient(conn)
|
||||
testClient := testdata.NewQueryClient(conn)
|
||||
testRes, err := testClient.Echo(context.Background(), &testdata.EchoRequest{Message: "hello"})
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal("hello", testRes.Message)
|
||||
|
|
|
@ -114,6 +114,7 @@ var (
|
|||
upgrade.AppModuleBasic{},
|
||||
evidence.AppModuleBasic{},
|
||||
transfer.AppModuleBasic{},
|
||||
vesting.AppModuleBasic{},
|
||||
)
|
||||
|
||||
// module account permissions
|
||||
|
@ -202,7 +203,7 @@ func NewSimApp(
|
|||
bApp := baseapp.NewBaseApp(appName, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...)
|
||||
bApp.SetCommitMultiStoreTracer(traceStore)
|
||||
bApp.SetAppVersion(version.Version)
|
||||
bApp.GRPCQueryRouter().SetInterfaceRegistry(interfaceRegistry)
|
||||
bApp.SetInterfaceRegistry(interfaceRegistry)
|
||||
bApp.GRPCQueryRouter().RegisterSimulateService(bApp.Simulate, interfaceRegistry)
|
||||
|
||||
keys := sdk.NewKVStoreKeys(
|
||||
|
@ -362,7 +363,7 @@ func NewSimApp(
|
|||
app.mm.RegisterServices(module.NewConfigurator(app.GRPCQueryRouter()))
|
||||
|
||||
// add test gRPC service for testing gRPC queries in isolation
|
||||
testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{})
|
||||
testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{})
|
||||
|
||||
// create the simulation manager and define the order of the modules for deterministic simulations
|
||||
//
|
||||
|
|
|
@ -6,14 +6,12 @@ import (
|
|||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
|
||||
)
|
||||
|
||||
// RegisterLegacyAminoCodec registers types with the Amino codec.
|
||||
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
||||
sdk.RegisterLegacyAminoCodec(cdc)
|
||||
cryptocodec.RegisterCrypto(cdc)
|
||||
vesting.RegisterLegacyAminoCodec(cdc)
|
||||
}
|
||||
|
||||
// RegisterInterfaces registers Interfaces from sdk/types, vesting, crypto, tx.
|
||||
|
@ -21,5 +19,4 @@ func RegisterInterfaces(interfaceRegistry types.InterfaceRegistry) {
|
|||
sdk.RegisterInterfaces(interfaceRegistry)
|
||||
txtypes.RegisterInterfaces(interfaceRegistry)
|
||||
cryptocodec.RegisterInterfaces(interfaceRegistry)
|
||||
vesting.RegisterInterfaces(interfaceRegistry)
|
||||
}
|
||||
|
|
|
@ -4,10 +4,18 @@ import (
|
|||
amino "github.com/tendermint/go-amino"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func NewTestInterfaceRegistry() types.InterfaceRegistry {
|
||||
registry := types.NewInterfaceRegistry()
|
||||
RegisterInterfaces(registry)
|
||||
return registry
|
||||
}
|
||||
|
||||
func RegisterInterfaces(registry types.InterfaceRegistry) {
|
||||
registry.RegisterImplementations((*sdk.Msg)(nil), &TestMsg{})
|
||||
|
||||
registry.RegisterInterface("Animal", (*Animal)(nil))
|
||||
registry.RegisterImplementations(
|
||||
(*Animal)(nil),
|
||||
|
@ -22,7 +30,6 @@ func NewTestInterfaceRegistry() types.InterfaceRegistry {
|
|||
(*HasHasAnimalI)(nil),
|
||||
&HasHasAnimal{},
|
||||
)
|
||||
return registry
|
||||
}
|
||||
|
||||
func NewTestAmino() *amino.Codec {
|
|
@ -9,9 +9,11 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
)
|
||||
|
||||
type TestServiceImpl struct{}
|
||||
type QueryImpl struct{}
|
||||
|
||||
func (e TestServiceImpl) TestAny(_ context.Context, request *TestAnyRequest) (*TestAnyResponse, error) {
|
||||
var _ QueryServer = QueryImpl{}
|
||||
|
||||
func (e QueryImpl) TestAny(_ context.Context, request *TestAnyRequest) (*TestAnyResponse, error) {
|
||||
animal, ok := request.AnyAnimal.GetCachedValue().(Animal)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected Animal")
|
||||
|
@ -28,17 +30,15 @@ func (e TestServiceImpl) TestAny(_ context.Context, request *TestAnyRequest) (*T
|
|||
}}, nil
|
||||
}
|
||||
|
||||
func (e TestServiceImpl) Echo(_ context.Context, req *EchoRequest) (*EchoResponse, error) {
|
||||
func (e QueryImpl) Echo(_ context.Context, req *EchoRequest) (*EchoResponse, error) {
|
||||
return &EchoResponse{Message: req.Message}, nil
|
||||
}
|
||||
|
||||
func (e TestServiceImpl) SayHello(_ context.Context, request *SayHelloRequest) (*SayHelloResponse, error) {
|
||||
func (e QueryImpl) SayHello(_ context.Context, request *SayHelloRequest) (*SayHelloResponse, error) {
|
||||
greeting := fmt.Sprintf("Hello %s!", request.Name)
|
||||
return &SayHelloResponse{Greeting: greeting}, nil
|
||||
}
|
||||
|
||||
var _ TestServiceServer = TestServiceImpl{}
|
||||
|
||||
var _ types.UnpackInterfacesMessage = &TestAnyRequest{}
|
||||
|
||||
func (m *TestAnyRequest) UnpackInterfaces(unpacker types.AnyUnpacker) error {
|
|
@ -0,0 +1,16 @@
|
|||
package testdata
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type MsgServerImpl struct{}
|
||||
|
||||
var _ MsgServer = MsgServerImpl{}
|
||||
|
||||
// CreateDog implements the MsgServer interface.
|
||||
func (m MsgServerImpl) CreateDog(_ context.Context, msg *MsgCreateDog) (*MsgCreateDogResponse, error) {
|
||||
return &MsgCreateDogResponse{
|
||||
Name: msg.Dog.Name,
|
||||
}, nil
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,39 @@
|
|||
syntax = "proto3";
|
||||
package testdata;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "testdata.proto";
|
||||
|
||||
option go_package = "github.com/cosmos/cosmos-sdk/testutil/testdata";
|
||||
|
||||
// Query tests the protobuf Query service as defined in
|
||||
// https://github.com/cosmos/cosmos-sdk/issues/5921.
|
||||
service Query {
|
||||
rpc Echo(EchoRequest) returns (EchoResponse);
|
||||
rpc SayHello(SayHelloRequest) returns (SayHelloResponse);
|
||||
rpc TestAny(TestAnyRequest) returns (TestAnyResponse);
|
||||
}
|
||||
|
||||
message EchoRequest {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
message EchoResponse {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
message SayHelloRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message SayHelloResponse {
|
||||
string greeting = 1;
|
||||
}
|
||||
|
||||
message TestAnyRequest {
|
||||
google.protobuf.Any any_animal = 1;
|
||||
}
|
||||
|
||||
message TestAnyResponse {
|
||||
testdata.HasAnimal has_animal = 1;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,37 @@
|
|||
syntax = "proto3";
|
||||
package testdata;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
option go_package = "github.com/cosmos/cosmos-sdk/testutil/testdata";
|
||||
|
||||
message Dog {
|
||||
string size = 1;
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
message Cat {
|
||||
string moniker = 1;
|
||||
int32 lives = 2;
|
||||
}
|
||||
|
||||
message HasAnimal {
|
||||
google.protobuf.Any animal = 1;
|
||||
int64 x = 2;
|
||||
}
|
||||
|
||||
message HasHasAnimal {
|
||||
google.protobuf.Any has_animal = 1;
|
||||
}
|
||||
|
||||
message HasHasHasAnimal {
|
||||
google.protobuf.Any has_has_animal = 1;
|
||||
}
|
||||
|
||||
// bad MultiSignature with extra fields
|
||||
message BadMultiSignature {
|
||||
option (gogoproto.goproto_unrecognized) = true;
|
||||
repeated bytes signatures = 1;
|
||||
bytes malicious_field = 5;
|
||||
}
|
|
@ -65,3 +65,15 @@ func (msg *TestMsg) GetSigners() []sdk.AccAddress {
|
|||
return addrs
|
||||
}
|
||||
func (msg *TestMsg) ValidateBasic() error { return nil }
|
||||
|
||||
var _ sdk.MsgRequest = &MsgCreateDog{}
|
||||
|
||||
func (msg *MsgCreateDog) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{} }
|
||||
func (msg *MsgCreateDog) ValidateBasic() error { return nil }
|
||||
|
||||
func NewServiceMsgCreateDog(msg *MsgCreateDog) sdk.Msg {
|
||||
return sdk.ServiceMsg{
|
||||
MethodName: "/testdata.Msg/CreateDog",
|
||||
Request: msg,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,764 @@
|
|||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: tx.proto
|
||||
|
||||
package testdata
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
grpc1 "github.com/gogo/protobuf/grpc"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type MsgCreateDog struct {
|
||||
Dog *Dog `protobuf:"bytes,1,opt,name=dog,proto3" json:"dog,omitempty"`
|
||||
}
|
||||
|
||||
func (m *MsgCreateDog) Reset() { *m = MsgCreateDog{} }
|
||||
func (m *MsgCreateDog) String() string { return proto.CompactTextString(m) }
|
||||
func (*MsgCreateDog) ProtoMessage() {}
|
||||
func (*MsgCreateDog) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_0fd2153dc07d3b5c, []int{0}
|
||||
}
|
||||
func (m *MsgCreateDog) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *MsgCreateDog) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_MsgCreateDog.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *MsgCreateDog) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MsgCreateDog.Merge(m, src)
|
||||
}
|
||||
func (m *MsgCreateDog) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *MsgCreateDog) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MsgCreateDog.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MsgCreateDog proto.InternalMessageInfo
|
||||
|
||||
func (m *MsgCreateDog) GetDog() *Dog {
|
||||
if m != nil {
|
||||
return m.Dog
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type MsgCreateDogResponse struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (m *MsgCreateDogResponse) Reset() { *m = MsgCreateDogResponse{} }
|
||||
func (m *MsgCreateDogResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*MsgCreateDogResponse) ProtoMessage() {}
|
||||
func (*MsgCreateDogResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_0fd2153dc07d3b5c, []int{1}
|
||||
}
|
||||
func (m *MsgCreateDogResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *MsgCreateDogResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_MsgCreateDogResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *MsgCreateDogResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MsgCreateDogResponse.Merge(m, src)
|
||||
}
|
||||
func (m *MsgCreateDogResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *MsgCreateDogResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MsgCreateDogResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MsgCreateDogResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *MsgCreateDogResponse) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// TestMsg is msg type for testing protobuf message using any, as defined in
|
||||
// https://github.com/cosmos/cosmos-sdk/issues/6213.
|
||||
type TestMsg struct {
|
||||
Signers []string `protobuf:"bytes,1,rep,name=signers,proto3" json:"signers,omitempty"`
|
||||
}
|
||||
|
||||
func (m *TestMsg) Reset() { *m = TestMsg{} }
|
||||
func (m *TestMsg) String() string { return proto.CompactTextString(m) }
|
||||
func (*TestMsg) ProtoMessage() {}
|
||||
func (*TestMsg) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_0fd2153dc07d3b5c, []int{2}
|
||||
}
|
||||
func (m *TestMsg) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *TestMsg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_TestMsg.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *TestMsg) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_TestMsg.Merge(m, src)
|
||||
}
|
||||
func (m *TestMsg) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *TestMsg) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_TestMsg.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_TestMsg proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*MsgCreateDog)(nil), "testdata.MsgCreateDog")
|
||||
proto.RegisterType((*MsgCreateDogResponse)(nil), "testdata.MsgCreateDogResponse")
|
||||
proto.RegisterType((*TestMsg)(nil), "testdata.TestMsg")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("tx.proto", fileDescriptor_0fd2153dc07d3b5c) }
|
||||
|
||||
var fileDescriptor_0fd2153dc07d3b5c = []byte{
|
||||
// 258 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x28, 0xa9, 0xd0, 0x2b,
|
||||
0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x28, 0x49, 0x2d, 0x2e, 0x49, 0x49, 0x2c, 0x49, 0x94, 0x12,
|
||||
0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x0b, 0xea, 0x83, 0x58, 0x10, 0x79, 0x29, 0x3e, 0x98, 0x3c, 0x84,
|
||||
0xaf, 0xa4, 0xcf, 0xc5, 0xe3, 0x5b, 0x9c, 0xee, 0x5c, 0x94, 0x9a, 0x58, 0x92, 0xea, 0x92, 0x9f,
|
||||
0x2e, 0x24, 0xcf, 0xc5, 0x9c, 0x92, 0x9f, 0x2e, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x6d, 0xc4, 0xab,
|
||||
0x07, 0x57, 0xed, 0x92, 0x9f, 0x1e, 0x04, 0x92, 0x51, 0xd2, 0xe2, 0x12, 0x41, 0xd6, 0x10, 0x94,
|
||||
0x5a, 0x5c, 0x90, 0x9f, 0x57, 0x9c, 0x2a, 0x24, 0xc4, 0xc5, 0x92, 0x97, 0x98, 0x9b, 0x0a, 0xd6,
|
||||
0xc9, 0x19, 0x04, 0x66, 0x2b, 0x69, 0x72, 0xb1, 0x87, 0xa4, 0x16, 0x97, 0xf8, 0x16, 0xa7, 0x0b,
|
||||
0x49, 0x70, 0xb1, 0x17, 0x67, 0xa6, 0xe7, 0xa5, 0x16, 0x15, 0x4b, 0x30, 0x2a, 0x30, 0x6b, 0x70,
|
||||
0x06, 0xc1, 0xb8, 0x56, 0x2c, 0x1d, 0x0b, 0xe4, 0x19, 0x8c, 0xbc, 0xb8, 0x98, 0x41, 0xca, 0x9c,
|
||||
0xb9, 0x38, 0x11, 0x6e, 0x11, 0x43, 0x58, 0x8f, 0x6c, 0xa5, 0x94, 0x1c, 0x76, 0x71, 0x98, 0x53,
|
||||
0x9c, 0x3c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09,
|
||||
0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x2f, 0x3d, 0xb3,
|
||||
0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x3f, 0x39, 0xbf, 0x38, 0x37, 0xbf, 0x18, 0x4a,
|
||||
0xe9, 0x16, 0xa7, 0x64, 0xeb, 0x83, 0x4c, 0x2d, 0x2d, 0xc9, 0xcc, 0xd1, 0x87, 0x19, 0x9f, 0xc4,
|
||||
0x06, 0x0e, 0x24, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x15, 0x63, 0x9a, 0x1b, 0x60, 0x01,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// MsgClient is the client API for Msg service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type MsgClient interface {
|
||||
CreateDog(ctx context.Context, in *MsgCreateDog, opts ...grpc.CallOption) (*MsgCreateDogResponse, error)
|
||||
}
|
||||
|
||||
type msgClient struct {
|
||||
cc grpc1.ClientConn
|
||||
}
|
||||
|
||||
func NewMsgClient(cc grpc1.ClientConn) MsgClient {
|
||||
return &msgClient{cc}
|
||||
}
|
||||
|
||||
func (c *msgClient) CreateDog(ctx context.Context, in *MsgCreateDog, opts ...grpc.CallOption) (*MsgCreateDogResponse, error) {
|
||||
out := new(MsgCreateDogResponse)
|
||||
err := c.cc.Invoke(ctx, "/testdata.Msg/CreateDog", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MsgServer is the server API for Msg service.
|
||||
type MsgServer interface {
|
||||
CreateDog(context.Context, *MsgCreateDog) (*MsgCreateDogResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedMsgServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedMsgServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedMsgServer) CreateDog(ctx context.Context, req *MsgCreateDog) (*MsgCreateDogResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateDog not implemented")
|
||||
}
|
||||
|
||||
func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
|
||||
s.RegisterService(&_Msg_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Msg_CreateDog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(MsgCreateDog)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MsgServer).CreateDog(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/testdata.Msg/CreateDog",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MsgServer).CreateDog(ctx, req.(*MsgCreateDog))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Msg_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "testdata.Msg",
|
||||
HandlerType: (*MsgServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "CreateDog",
|
||||
Handler: _Msg_CreateDog_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "tx.proto",
|
||||
}
|
||||
|
||||
func (m *MsgCreateDog) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *MsgCreateDog) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *MsgCreateDog) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Dog != nil {
|
||||
{
|
||||
size, err := m.Dog.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintTx(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *MsgCreateDogResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *MsgCreateDogResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *MsgCreateDogResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Name) > 0 {
|
||||
i -= len(m.Name)
|
||||
copy(dAtA[i:], m.Name)
|
||||
i = encodeVarintTx(dAtA, i, uint64(len(m.Name)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *TestMsg) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *TestMsg) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *TestMsg) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Signers) > 0 {
|
||||
for iNdEx := len(m.Signers) - 1; iNdEx >= 0; iNdEx-- {
|
||||
i -= len(m.Signers[iNdEx])
|
||||
copy(dAtA[i:], m.Signers[iNdEx])
|
||||
i = encodeVarintTx(dAtA, i, uint64(len(m.Signers[iNdEx])))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintTx(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovTx(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *MsgCreateDog) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.Dog != nil {
|
||||
l = m.Dog.Size()
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *MsgCreateDogResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Name)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *TestMsg) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Signers) > 0 {
|
||||
for _, s := range m.Signers {
|
||||
l = len(s)
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovTx(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozTx(x uint64) (n int) {
|
||||
return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *MsgCreateDog) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: MsgCreateDog: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: MsgCreateDog: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Dog", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Dog == nil {
|
||||
m.Dog = &Dog{}
|
||||
}
|
||||
if err := m.Dog.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTx(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *MsgCreateDogResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: MsgCreateDogResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: MsgCreateDogResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Name = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTx(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *TestMsg) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: TestMsg: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: TestMsg: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Signers", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Signers = append(m.Signers, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTx(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipTx(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthTx
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupTx
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthTx
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowTx = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
|
@ -0,0 +1,28 @@
|
|||
syntax = "proto3";
|
||||
package testdata;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "testdata.proto";
|
||||
|
||||
option go_package = "github.com/cosmos/cosmos-sdk/testutil/testdata";
|
||||
|
||||
// Msg tests the Protobuf message service as defined in
|
||||
// https://github.com/cosmos/cosmos-sdk/issues/7500.
|
||||
service Msg {
|
||||
rpc CreateDog(MsgCreateDog) returns (MsgCreateDogResponse);
|
||||
}
|
||||
|
||||
message MsgCreateDog {
|
||||
testdata.Dog dog = 1;
|
||||
}
|
||||
|
||||
message MsgCreateDogResponse {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
// TestMsg is msg type for testing protobuf message using any, as defined in
|
||||
// https://github.com/cosmos/cosmos-sdk/issues/6213.
|
||||
message TestMsg {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
repeated string signers = 1;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -7,72 +7,6 @@ import "cosmos/tx/v1beta1/tx.proto";
|
|||
|
||||
option go_package = "github.com/cosmos/cosmos-sdk/testutil/testdata";
|
||||
|
||||
message Dog {
|
||||
string size = 1;
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
message Cat {
|
||||
string moniker = 1;
|
||||
int32 lives = 2;
|
||||
}
|
||||
|
||||
message HasAnimal {
|
||||
google.protobuf.Any animal = 1;
|
||||
int64 x = 2;
|
||||
}
|
||||
|
||||
message HasHasAnimal {
|
||||
google.protobuf.Any has_animal = 1;
|
||||
}
|
||||
|
||||
message HasHasHasAnimal {
|
||||
google.protobuf.Any has_has_animal = 1;
|
||||
}
|
||||
|
||||
service TestService {
|
||||
rpc Echo(EchoRequest) returns (EchoResponse);
|
||||
rpc SayHello(SayHelloRequest) returns (SayHelloResponse);
|
||||
rpc TestAny(TestAnyRequest) returns (TestAnyResponse);
|
||||
}
|
||||
|
||||
message EchoRequest {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
message EchoResponse {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
message SayHelloRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message SayHelloResponse {
|
||||
string greeting = 1;
|
||||
}
|
||||
|
||||
message TestAnyRequest {
|
||||
google.protobuf.Any any_animal = 1;
|
||||
}
|
||||
|
||||
message TestAnyResponse {
|
||||
HasAnimal has_animal = 1;
|
||||
}
|
||||
|
||||
// msg type for testing
|
||||
message TestMsg {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
repeated string signers = 1;
|
||||
}
|
||||
|
||||
// bad MultiSignature with extra fields
|
||||
message BadMultiSignature {
|
||||
option (gogoproto.goproto_unrecognized) = true;
|
||||
repeated bytes signatures = 1;
|
||||
bytes malicious_field = 5;
|
||||
}
|
||||
|
||||
message Customer1 {
|
||||
int32 id = 1;
|
||||
string name = 2;
|
|
@ -14,4 +14,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
|||
// RegisterInterfaces registers the sdk message type.
|
||||
func RegisterInterfaces(registry types.InterfaceRegistry) {
|
||||
registry.RegisterInterface("cosmos.base.v1beta1.Msg", (*Msg)(nil))
|
||||
// the interface name for MsgRequest is ServiceMsg because this is most useful for clients
|
||||
// to understand - it will be the way for clients to introspect on available Msg service methods
|
||||
registry.RegisterInterface("cosmos.base.v1beta1.ServiceMsg", (*MsgRequest)(nil))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
// MsgRequest is the interface a transaction message, defined as a proto
|
||||
// service method, must fulfill.
|
||||
type MsgRequest interface {
|
||||
proto.Message
|
||||
// ValidateBasic does a simple validation check that
|
||||
// doesn't require access to any other information.
|
||||
ValidateBasic() error
|
||||
// Signers returns the addrs of signers that must sign.
|
||||
// CONTRACT: All signatures must be present to be valid.
|
||||
// CONTRACT: Returns addrs in some deterministic order.
|
||||
GetSigners() []AccAddress
|
||||
}
|
||||
|
||||
// ServiceMsg is the struct into which an Any whose typeUrl matches a service
|
||||
// method format (ex. `/cosmos.gov.Msg/SubmitProposal`) unpacks.
|
||||
type ServiceMsg struct {
|
||||
// MethodName is the fully-qualified service method name.
|
||||
MethodName string
|
||||
// Request is the request payload.
|
||||
Request MsgRequest
|
||||
}
|
||||
|
||||
var _ Msg = ServiceMsg{}
|
||||
|
||||
func (msg ServiceMsg) ProtoMessage() {}
|
||||
func (msg ServiceMsg) Reset() {}
|
||||
func (msg ServiceMsg) String() string { return "ServiceMsg" }
|
||||
|
||||
// Route implements Msg.Route method.
|
||||
func (msg ServiceMsg) Route() string {
|
||||
return msg.MethodName
|
||||
}
|
||||
|
||||
// ValidateBasic implements Msg.ValidateBasic method.
|
||||
func (msg ServiceMsg) ValidateBasic() error {
|
||||
return msg.Request.ValidateBasic()
|
||||
}
|
||||
|
||||
// GetSignBytes implements Msg.GetSignBytes method.
|
||||
func (msg ServiceMsg) GetSignBytes() []byte {
|
||||
panic("ServiceMsg does not have a GetSignBytes method")
|
||||
}
|
||||
|
||||
// GetSigners implements Msg.GetSigners method.
|
||||
func (msg ServiceMsg) GetSigners() []AccAddress {
|
||||
return msg.Request.GetSigners()
|
||||
}
|
||||
|
||||
// Type implements Msg.Type method.
|
||||
func (msg ServiceMsg) Type() string {
|
||||
return msg.MethodName
|
||||
}
|
|
@ -5,6 +5,10 @@ package tx
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
|
||||
types "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
types1 "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -12,9 +16,6 @@ import (
|
|||
signing "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package tx
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
|
@ -26,7 +27,15 @@ func (t *Tx) GetMsgs() []sdk.Msg {
|
|||
anys := t.Body.Messages
|
||||
res := make([]sdk.Msg, len(anys))
|
||||
for i, any := range anys {
|
||||
msg := any.GetCachedValue().(sdk.Msg)
|
||||
var msg sdk.Msg
|
||||
if isServiceMsg(any.TypeUrl) {
|
||||
msg = sdk.ServiceMsg{
|
||||
MethodName: any.TypeUrl,
|
||||
Request: any.GetCachedValue().(sdk.MsgRequest),
|
||||
}
|
||||
} else {
|
||||
msg = any.GetCachedValue().(sdk.Msg)
|
||||
}
|
||||
res[i] = msg
|
||||
}
|
||||
return res
|
||||
|
@ -138,12 +147,23 @@ func (t *Tx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
|
|||
// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method
|
||||
func (m *TxBody) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
|
||||
for _, any := range m.Messages {
|
||||
var msg sdk.Msg
|
||||
err := unpacker.UnpackAny(any, &msg)
|
||||
if err != nil {
|
||||
return err
|
||||
// If the any's typeUrl contains 2 slashes, then we unpack the any into
|
||||
// a ServiceMsg struct as per ADR-031.
|
||||
if isServiceMsg(any.TypeUrl) {
|
||||
var req sdk.MsgRequest
|
||||
err := unpacker.UnpackAny(any, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
var msg sdk.Msg
|
||||
err := unpacker.UnpackAny(any, &msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -168,3 +188,9 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
|||
registry.RegisterInterface("cosmos.tx.v1beta1.Tx", (*sdk.Tx)(nil))
|
||||
registry.RegisterImplementations((*sdk.Tx)(nil), &Tx{})
|
||||
}
|
||||
|
||||
// isServiceMsg checks if a type URL corresponds to a service method name,
|
||||
// i.e. /cosmos.bank.Msg/Send vs /cosmos.bank.MsgSend
|
||||
func isServiceMsg(typeURL string) bool {
|
||||
return strings.Count(typeURL, "/") >= 2
|
||||
}
|
||||
|
|
|
@ -54,8 +54,9 @@ func (suite *AnteTestSuite) SetupTest(isCheckTx bool) {
|
|||
|
||||
// Set up TxConfig.
|
||||
encodingConfig := simapp.MakeEncodingConfig()
|
||||
// We're using TestMsg amino encoding in some tests, so register it here.
|
||||
// We're using TestMsg encoding in some tests, so register it here.
|
||||
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
|
||||
testdata.RegisterInterfaces(encodingConfig.InterfaceRegistry)
|
||||
|
||||
suite.clientCtx = client.Context{}.
|
||||
WithTxConfig(encodingConfig.TxConfig)
|
||||
|
|
|
@ -31,7 +31,7 @@ func TestParseQueryResponse(t *testing.T) {
|
|||
Result: &sdk.Result{Data: []byte("tx data"), Log: "log"},
|
||||
}
|
||||
|
||||
bz, err := codec.ProtoMarshalJSON(simRes)
|
||||
bz, err := codec.ProtoMarshalJSON(simRes, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := authclient.ParseQueryResponse(bz)
|
||||
|
|
|
@ -205,10 +205,27 @@ func (w *wrapper) SetMsgs(msgs ...sdk.Msg) error {
|
|||
|
||||
for i, msg := range msgs {
|
||||
var err error
|
||||
anys[i], err = codectypes.NewAnyWithValue(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
switch msg := msg.(type) {
|
||||
case sdk.ServiceMsg:
|
||||
{
|
||||
bz, err := proto.Marshal(msg.Request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
anys[i] = &codectypes.Any{
|
||||
TypeUrl: msg.MethodName,
|
||||
Value: bz,
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
anys[i], err = codectypes.NewAnyWithValue(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
w.tx.Body.Messages = anys
|
||||
|
|
|
@ -29,7 +29,7 @@ func NewTxConfig(protoCodec *codec.ProtoCodec, enabledSignModes []signingtypes.S
|
|||
decoder: DefaultTxDecoder(protoCodec),
|
||||
encoder: DefaultTxEncoder(),
|
||||
jsonDecoder: DefaultJSONTxDecoder(protoCodec),
|
||||
jsonEncoder: DefaultJSONTxEncoder(),
|
||||
jsonEncoder: DefaultJSONTxEncoder(protoCodec),
|
||||
protoCodec: protoCodec,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ func DefaultTxDecoder(cdc *codec.ProtoCodec) sdk.TxDecoder {
|
|||
var raw tx.TxRaw
|
||||
|
||||
// reject all unknown proto fields in the root TxRaw
|
||||
err := unknownproto.RejectUnknownFieldsStrict(txBytes, &raw)
|
||||
err := unknownproto.RejectUnknownFieldsStrict(txBytes, &raw, cdc.InterfaceRegistry())
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func DefaultTxDecoder(cdc *codec.ProtoCodec) sdk.TxDecoder {
|
|||
var body tx.TxBody
|
||||
|
||||
// allow non-critical unknown fields in TxBody
|
||||
txBodyHasUnknownNonCriticals, err := unknownproto.RejectUnknownFields(raw.BodyBytes, &body, true)
|
||||
txBodyHasUnknownNonCriticals, err := unknownproto.RejectUnknownFields(raw.BodyBytes, &body, true, cdc.InterfaceRegistry())
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ func DefaultTxDecoder(cdc *codec.ProtoCodec) sdk.TxDecoder {
|
|||
var authInfo tx.AuthInfo
|
||||
|
||||
// reject all unknown proto fields in AuthInfo
|
||||
err = unknownproto.RejectUnknownFieldsStrict(raw.AuthInfoBytes, &authInfo)
|
||||
err = unknownproto.RejectUnknownFieldsStrict(raw.AuthInfoBytes, &authInfo, cdc.InterfaceRegistry())
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func TestDefaultTxDecoderError(t *testing.T) {
|
||||
|
@ -32,9 +31,9 @@ func TestDefaultTxDecoderError(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
_, err = decoder(txBz)
|
||||
require.EqualError(t, err, "no registered implementations of type types.Msg: tx parse error")
|
||||
require.EqualError(t, err, "unable to resolve type URL /testdata.TestMsg: tx parse error")
|
||||
|
||||
registry.RegisterImplementations((*sdk.Msg)(nil), &testdata.TestMsg{})
|
||||
testdata.RegisterInterfaces(registry)
|
||||
_, err = decoder(txBz)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
|
|
@ -29,16 +29,16 @@ func DefaultTxEncoder() sdk.TxEncoder {
|
|||
}
|
||||
|
||||
// DefaultJSONTxEncoder returns a default protobuf JSON TxEncoder using the provided Marshaler.
|
||||
func DefaultJSONTxEncoder() sdk.TxEncoder {
|
||||
func DefaultJSONTxEncoder(cdc *codec.ProtoCodec) sdk.TxEncoder {
|
||||
return func(tx sdk.Tx) ([]byte, error) {
|
||||
txWrapper, ok := tx.(*wrapper)
|
||||
if ok {
|
||||
return codec.ProtoMarshalJSON(txWrapper.tx)
|
||||
return cdc.MarshalJSON(txWrapper.tx)
|
||||
}
|
||||
|
||||
protoTx, ok := tx.(*txtypes.Tx)
|
||||
if ok {
|
||||
return codec.ProtoMarshalJSON(protoTx)
|
||||
return cdc.MarshalJSON(protoTx)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("expected %T, got %T", &wrapper{}, tx)
|
||||
|
|
|
@ -125,7 +125,7 @@ func (g config) MarshalSignatureJSON(sigs []signing.SignatureV2) ([]byte, error)
|
|||
|
||||
toJSON := &signing.SignatureDescriptors{Signatures: descs}
|
||||
|
||||
return codec.ProtoMarshalJSON(toJSON)
|
||||
return codec.ProtoMarshalJSON(toJSON, nil)
|
||||
}
|
||||
|
||||
func (g config) UnmarshalSignatureJSON(bz []byte) ([]signing.SignatureV2, error) {
|
||||
|
|
|
@ -30,7 +30,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
|
|||
)
|
||||
|
||||
registry.RegisterInterface(
|
||||
"cosmos.auth.GenesisAccount",
|
||||
"cosmos.auth.v1beta1.GenesisAccount",
|
||||
(*GenesisAccount)(nil),
|
||||
&BaseAccount{},
|
||||
&ModuleAccount{},
|
||||
|
|
|
@ -31,6 +31,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
|
|||
|
||||
registry.RegisterImplementations(
|
||||
(*authtypes.AccountI)(nil),
|
||||
&BaseVestingAccount{},
|
||||
&DelayedVestingAccount{},
|
||||
&ContinuousVestingAccount{},
|
||||
&PeriodicVestingAccount{},
|
||||
|
@ -38,6 +39,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
|
|||
|
||||
registry.RegisterImplementations(
|
||||
(*authtypes.GenesisAccount)(nil),
|
||||
&BaseVestingAccount{},
|
||||
&DelayedVestingAccount{},
|
||||
&ContinuousVestingAccount{},
|
||||
&PeriodicVestingAccount{},
|
||||
|
|
|
@ -70,6 +70,7 @@ func (m *MsgSend) XXX_DiscardUnknown() {
|
|||
|
||||
var xxx_messageInfo_MsgSend proto.InternalMessageInfo
|
||||
|
||||
// MsgSendResponse defines the Msg/Send response type.
|
||||
type MsgSendResponse struct {
|
||||
}
|
||||
|
||||
|
@ -159,6 +160,7 @@ func (m *MsgMultiSend) GetOutputs() []Output {
|
|||
return nil
|
||||
}
|
||||
|
||||
// MsgMultiSendResponse defines the Msg/MultiSend response type.
|
||||
type MsgMultiSendResponse struct {
|
||||
}
|
||||
|
||||
|
@ -248,7 +250,9 @@ const _ = grpc.SupportPackageIsVersion4
|
|||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type MsgClient interface {
|
||||
// Send defines a method for sending coins from one account to another account.
|
||||
Send(ctx context.Context, in *MsgSend, opts ...grpc.CallOption) (*MsgSendResponse, error)
|
||||
// MultiSend defines a method for sending coins from some accounts to other accounts.
|
||||
MultiSend(ctx context.Context, in *MsgMultiSend, opts ...grpc.CallOption) (*MsgMultiSendResponse, error)
|
||||
}
|
||||
|
||||
|
@ -280,7 +284,9 @@ func (c *msgClient) MultiSend(ctx context.Context, in *MsgMultiSend, opts ...grp
|
|||
|
||||
// MsgServer is the server API for Msg service.
|
||||
type MsgServer interface {
|
||||
// Send defines a method for sending coins from one account to another account.
|
||||
Send(context.Context, *MsgSend) (*MsgSendResponse, error)
|
||||
// MultiSend defines a method for sending coins from some accounts to other accounts.
|
||||
MultiSend(context.Context, *MsgMultiSend) (*MsgMultiSendResponse, error)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue