diff --git a/client/debug/main.go b/client/debug/main.go index d3552880688a..06ee00cb8b13 100644 --- a/client/debug/main.go +++ b/client/debug/main.go @@ -43,6 +43,64 @@ func Cmd() *cobra.Command { return cmd } +<<<<<<< HEAD +======= +// CodecCmd creates and returns a new codec debug cmd. +func CodecCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "codec", + Short: "Tool for helping with debugging your application codec", + RunE: client.ValidateCmd, + } + + cmd.AddCommand(getCodecInterfaces()) + cmd.AddCommand(getCodecInterfaceImpls()) + + return cmd +} + +// getCodecInterfaces creates and returns a new cmd used for listing all registered interfaces on the application codec. +func getCodecInterfaces() *cobra.Command { + return &cobra.Command{ + Use: "list-interfaces", + Short: "List all registered interface type URLs", + Long: "List all registered interface type URLs using the application codec", + Example: fmt.Sprintf("%s debug codec list-interfaces", version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + iFaces := clientCtx.Codec.InterfaceRegistry().ListAllInterfaces() + + slices.Sort(iFaces) + for _, iFace := range iFaces { + cmd.Println(iFace) + } + return nil + }, + } +} + +// getCodecInterfaceImpls creates and returns a new cmd used for listing all registered implemenations of a given interface on the application codec. +func getCodecInterfaceImpls() *cobra.Command { + return &cobra.Command{ + Use: "list-implementations [interface]", + Short: "List the registered type URLs for the provided interface", + Long: "List the registered type URLs that can be used for the provided interface name using the application codec", + Example: fmt.Sprintf("%s debug codec list-implementations cosmos.crypto.PubKey", version.AppName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + impls := clientCtx.Codec.InterfaceRegistry().ListImplementations(args[0]) + + slices.Sort(impls) + for _, imp := range impls { + cmd.Println(imp) + } + return nil + }, + } +} + +>>>>>>> 2caf00deb (fix(client/v2): fix marshalling of queries with any (#18309)) // getPubKeyFromString decodes SDK PubKey using JSON marshaler. func getPubKeyFromString(ctx client.Context, pkstr string) (cryptotypes.PubKey, error) { var pk cryptotypes.PubKey diff --git a/client/v2/autocli/app.go b/client/v2/autocli/app.go index e726ee385a88..83459d061eb6 100644 --- a/client/v2/autocli/app.go +++ b/client/v2/autocli/app.go @@ -1,7 +1,6 @@ package autocli import ( - "github.com/cosmos/gogoproto/proto" "github.com/spf13/cobra" "google.golang.org/grpc" "google.golang.org/protobuf/reflect/protoregistry" @@ -73,10 +72,14 @@ func (appOptions AppOptions) EnhanceRootCommand(rootCmd *cobra.Command) error { builder := &Builder{ Builder: flag.Builder{ TypeResolver: protoregistry.GlobalTypes, +<<<<<<< HEAD FileResolver: proto.HybridResolver, AddressCodec: appOptions.AddressCodec, ValidatorAddressCodec: appOptions.ValidatorAddressCodec, ConsensusAddressCodec: appOptions.ConsensusAddressCodec, +======= + FileResolver: appOptions.ClientCtx.InterfaceRegistry, +>>>>>>> 2caf00deb (fix(client/v2): fix marshalling of queries with any (#18309)) Keyring: appOptions.Keyring, }, ClientCtx: appOptions.ClientCtx, diff --git a/client/v2/go.mod b/client/v2/go.mod index d7863f9a00c3..17ba13509720 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -9,8 +9,12 @@ require ( cosmossdk.io/x/tx v0.11.0 github.com/cockroachdb/errors v1.11.1 github.com/cosmos/cosmos-proto v1.0.0-beta.3 +<<<<<<< HEAD github.com/cosmos/cosmos-sdk v0.50.0-rc.1.0.20231011110545-0863b5c5001c github.com/cosmos/gogoproto v1.4.11 +======= + github.com/cosmos/cosmos-sdk v0.51.0 +>>>>>>> 2caf00deb (fix(client/v2): fix marshalling of queries with any (#18309)) github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 google.golang.org/grpc v1.59.0 @@ -45,6 +49,7 @@ require ( github.com/cosmos/cosmos-db v1.0.0 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect + github.com/cosmos/gogoproto v1.4.11 // indirect github.com/cosmos/iavl v1.0.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect diff --git a/x/tx/CHANGELOG.md b/x/tx/CHANGELOG.md index 742122009eb3..e42ea7c88aaf 100644 --- a/x/tx/CHANGELOG.md +++ b/x/tx/CHANGELOG.md @@ -31,6 +31,46 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +<<<<<<< HEAD +======= +## v0.12.0 + +### Improvements + +* [#18309](https://github.com/cosmos/cosmos-sdk/pull/18309) Update encoder so that amino types default to msg type url. + +## v0.11.0 + +### Improvements + +* [#17787](https://github.com/cosmos/cosmos-sdk/pull/17787) Drop tip support. + +## v0.10.0 + +### Features + +* [#17681](https://github.com/cosmos/cosmos-sdk/pull/17681) Add encoder `DefineTypeEncoding` method for defining custom type encodings. +* [#17600](https://github.com/cosmos/cosmos-sdk/pull/17600) Add encoder `DefineScalarEncoding` method for defining custom scalar encodings. +* [#17600](https://github.com/cosmos/cosmos-sdk/pull/17600) Add indent option to encoder. + +## v0.9.1 + +### Improvements + +* [#16936](https://github.com/cosmos/cosmos-sdk/pull/16936) Remove extra whitespace when marshalling module accounts. + +## v0.9.0 + +### Bug Fixes + +* [#16681](https://github.com/cosmos/cosmos-sdk/pull/16681): Catch and fix `(*Decoder).Decode` crash from invalid length prefix in Tx bytes. + +### Improvements + +* [#16846](https://github.com/cosmos/cosmos-sdk/pull/16846): Harmonize interface `signing.TypeResolver` with the rest of the codebase (orm and client/v2). +* [#16684](https://github.com/cosmos/cosmos-sdk/pull/16684): Use `io.WriteString`+`fmt.Fprintf` to remove unnecessary `string`->`[]byte` roundtrip. + +>>>>>>> 2caf00deb (fix(client/v2): fix marshalling of queries with any (#18309)) ## v0.8.0 ### Improvements diff --git a/x/tx/go.mod b/x/tx/go.mod index 04c2f20d708e..5ee5f2c33770 100644 --- a/x/tx/go.mod +++ b/x/tx/go.mod @@ -8,6 +8,7 @@ require ( cosmossdk.io/errors v1.0.0-beta.7 cosmossdk.io/math v1.1.3-rc.1 github.com/cosmos/cosmos-proto v1.0.0-beta.3 + github.com/cosmos/gogoproto v1.4.11 github.com/google/go-cmp v0.6.0 github.com/iancoleman/strcase v0.2.0 github.com/pkg/errors v0.9.1 @@ -19,7 +20,6 @@ require ( ) require ( - github.com/cosmos/gogoproto v1.4.11 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/x/tx/signing/aminojson/any.go b/x/tx/signing/aminojson/any.go index 6898f50ce15f..df4a970a2b1d 100644 --- a/x/tx/signing/aminojson/any.go +++ b/x/tx/signing/aminojson/any.go @@ -50,13 +50,7 @@ func (enc Encoder) marshalAny(message protoreflect.Message, writer io.Writer) er protoMessage = valueMsg.ProtoReflect() } - _, named := getMessageAminoName(protoMessage.Descriptor().Options()) - if !named { - return fmt.Errorf("message %s is packed into an any field, so requires an amino.name annotation", - anyMsg.TypeUrl) - } - - return enc.beginMarshal(protoMessage, writer) + return enc.beginMarshal(protoMessage, writer, true) } const ( @@ -73,17 +67,11 @@ func (enc Encoder) marshalDynamic(message protoreflect.Message, writer io.Writer return errors.Wrapf(err, "can't resolve type URL %s", msgName) } - _, named := getMessageAminoName(desc.Options()) - if !named { - return fmt.Errorf("message %s is packed into an any field, so requires an amino.name annotation", - msgName) - } - valueMsg := dynamicpb.NewMessageType(desc.(protoreflect.MessageDescriptor)).New().Interface() err = proto.Unmarshal(msgBytes, valueMsg) if err != nil { return err } - return enc.beginMarshal(valueMsg.ProtoReflect(), writer) + return enc.beginMarshal(valueMsg.ProtoReflect(), writer, true) } diff --git a/x/tx/signing/aminojson/json_marshal.go b/x/tx/signing/aminojson/json_marshal.go index 4afb432329d6..b5ad75f75917 100644 --- a/x/tx/signing/aminojson/json_marshal.go +++ b/x/tx/signing/aminojson/json_marshal.go @@ -112,12 +112,36 @@ func (enc Encoder) DefineFieldEncoding(name string, encoder FieldEncoder) Encode // Marshal serializes a protobuf message to JSON. func (enc Encoder) Marshal(message proto.Message) ([]byte, error) { buf := &bytes.Buffer{} +<<<<<<< HEAD err := enc.beginMarshal(message.ProtoReflect(), buf) +======= + err := enc.beginMarshal(message.ProtoReflect(), buf, false) + + if enc.indent != "" { + indentBuf := &bytes.Buffer{} + if err := json.Indent(indentBuf, buf.Bytes(), "", enc.indent); err != nil { + return nil, err + } + + return indentBuf.Bytes(), err + } + +>>>>>>> 2caf00deb (fix(client/v2): fix marshalling of queries with any (#18309)) return buf.Bytes(), err } -func (enc Encoder) beginMarshal(msg protoreflect.Message, writer io.Writer) error { - name, named := getMessageAminoName(msg.Descriptor().Options()) +func (enc Encoder) beginMarshal(msg protoreflect.Message, writer io.Writer, isAny bool) error { + var ( + name string + named bool + ) + + if isAny { + name, named = getMessageAminoNameAny(msg), true + } else { + name, named = getMessageAminoName(msg) + } + if named { _, err := writer.Write([]byte(fmt.Sprintf(`{"type":"%s","value":`, name))) if err != nil { diff --git a/x/tx/signing/aminojson/options.go b/x/tx/signing/aminojson/options.go index f8b8991d04db..07d407bd2cc3 100644 --- a/x/tx/signing/aminojson/options.go +++ b/x/tx/signing/aminojson/options.go @@ -2,6 +2,7 @@ package aminojson import ( cosmos_proto "github.com/cosmos/cosmos-proto" + gogoproto "github.com/cosmos/gogoproto/proto" "github.com/iancoleman/strcase" "github.com/pkg/errors" "google.golang.org/protobuf/proto" @@ -12,14 +13,38 @@ import ( // getMessageAminoName returns the amino name of a message if it has been set by the `amino.name` option. // If the message does not have an amino name, then the function returns false. -func getMessageAminoName(messageOptions proto.Message) (string, bool) { +func getMessageAminoName(msg protoreflect.Message) (string, bool) { + messageOptions := msg.Descriptor().Options() if proto.HasExtension(messageOptions, amino.E_Name) { name := proto.GetExtension(messageOptions, amino.E_Name) return name.(string), true } + return "", false } +// getMessageAminoName returns the amino name of a message if it has been set by the `amino.name` option. +// If the message does not have an amino name, then it returns the msg url. +// If it cannot get the msg url, then it returns false. +func getMessageAminoNameAny(msg protoreflect.Message) string { + messageOptions := msg.Descriptor().Options() + if proto.HasExtension(messageOptions, amino.E_Name) { + name := proto.GetExtension(messageOptions, amino.E_Name) + return name.(string) + } + + msgURL := "/" + string(msg.Descriptor().FullName()) + if msgURL != "/" { + return msgURL + } + + if m, ok := msg.(gogoproto.Message); ok { + return "/" + gogoproto.MessageName(m) + } + + return "" +} + // omitEmpty returns true if the field should be omitted if empty. Empty field omission is the default behavior. func omitEmpty(field protoreflect.FieldDescriptor) bool { opts := field.Options() diff --git a/x/tx/signing/aminojson/options_test.go b/x/tx/signing/aminojson/options_test.go new file mode 100644 index 000000000000..8038827f0f7f --- /dev/null +++ b/x/tx/signing/aminojson/options_test.go @@ -0,0 +1,30 @@ +package aminojson + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "cosmossdk.io/x/tx/signing/aminojson/internal/testpb" +) + +func Test_getMessageAminoName(t *testing.T) { + msg := &testpb.ABitOfEverything{} + name, ok := getMessageAminoName(msg.ProtoReflect()) + require.True(t, ok) + require.Equal(t, "ABitOfEverything", name) + + secondMsg := &testpb.Duration{} + _, ok = getMessageAminoName(secondMsg.ProtoReflect()) + require.False(t, ok) +} + +func Test_getMessageAminoNameAny(t *testing.T) { + msg := &testpb.ABitOfEverything{} + name := getMessageAminoNameAny(msg.ProtoReflect()) + require.Equal(t, "ABitOfEverything", name) + + secondMsg := &testpb.Duration{} + name = getMessageAminoNameAny(secondMsg.ProtoReflect()) + require.Equal(t, "/testpb.Duration", name) +}