From 1d869f7d2c0fb0fe06183cf97e994e1f8889d410 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Wed, 18 Sep 2024 11:48:39 +0200 Subject: [PATCH 1/3] feat(x/tx): add `aminoNameAsTypeURL` option in aminojson encoder (#21712) Co-authored-by: Matt Kocubinski (cherry picked from commit 0c8ad9d2c64bf53b56bedc9ec864e66f6204cec3) # Conflicts: # client/v2/CHANGELOG.md # x/tx/CHANGELOG.md --- client/v2/CHANGELOG.md | 17 ++++++ client/v2/autocli/query.go | 11 ++-- x/tx/CHANGELOG.md | 5 ++ x/tx/signing/aminojson/json_marshal.go | 26 ++++++--- x/tx/signing/aminojson/json_marshal_test.go | 59 +++++++++++++++++++++ x/tx/signing/aminojson/options.go | 6 ++- 6 files changed, 112 insertions(+), 12 deletions(-) diff --git a/client/v2/CHANGELOG.md b/client/v2/CHANGELOG.md index ed2ef30195a8..9554c3213a25 100644 --- a/client/v2/CHANGELOG.md +++ b/client/v2/CHANGELOG.md @@ -36,7 +36,24 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +<<<<<<< HEAD ## [v2.0.0-beta.4] - 2024-07-16 +======= + + +### Features + +* [#18626](https://github.com/cosmos/cosmos-sdk/pull/18626) Support for off-chain signing and verification of a file. +* [#18461](https://github.com/cosmos/cosmos-sdk/pull/18461) Support governance proposals. + +### Improvements + +* [#21712](https://github.com/cosmos/cosmos-sdk/pull/21712) Marshal `type` field as proto message url in queries instead of amino name. + +### API Breaking Changes + +* [#17709](https://github.com/cosmos/cosmos-sdk/pull/17709) Address codecs have been removed from `autocli.AppOptions` and `flag.Builder`. Instead client/v2 uses the address codecs present in the context (introduced in [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503)). +>>>>>>> 0c8ad9d2c (feat(x/tx): add `aminoNameAsTypeURL` option in aminojson encoder (#21712)) ### Bug Fixes diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index 95bfbca78bca..7e0f4cbc3185 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -118,11 +118,12 @@ func (b *Builder) BuildQueryMethodCommand(ctx context.Context, descriptor protor methodName := fmt.Sprintf("/%s/%s", serviceDescriptor.FullName(), descriptor.Name()) outputType := util.ResolveMessageType(b.TypeResolver, descriptor.Output()) encoderOptions := aminojson.EncoderOptions{ - Indent: " ", - EnumAsString: true, - DoNotSortFields: true, - TypeResolver: b.TypeResolver, - FileResolver: b.FileResolver, + Indent: " ", + EnumAsString: true, + DoNotSortFields: true, + AminoNameAsTypeURL: true, + TypeResolver: b.TypeResolver, + FileResolver: b.FileResolver, } cmd, err := b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error { diff --git a/x/tx/CHANGELOG.md b/x/tx/CHANGELOG.md index bbdc0456a835..23e604cc3caf 100644 --- a/x/tx/CHANGELOG.md +++ b/x/tx/CHANGELOG.md @@ -37,7 +37,12 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos- ### Improvements +<<<<<<< HEAD * [#21073](https://github.com/cosmos/cosmos-sdk/pull/21073) In Context use sync.Map `getSignersFuncs` map from concurrent writes, we also call Validate when creating the Context. +======= +* [#21712](https://github.com/cosmos/cosmos-sdk/pull/21712) Add `AminoNameAsTypeURL` option to Amino JSON encoder. +* [#21073](https://github.com/cosmos/cosmos-sdk/pull/21073) In Context use sync.Map `getSignersFuncs` map from concurrent writes, we also need to call Validate when using the legacy app. +>>>>>>> 0c8ad9d2c (feat(x/tx): add `aminoNameAsTypeURL` option in aminojson encoder (#21712)) ## [v0.13.3](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.3) - 2024-04-22 diff --git a/x/tx/signing/aminojson/json_marshal.go b/x/tx/signing/aminojson/json_marshal.go index f276cb39d23e..52defcca6357 100644 --- a/x/tx/signing/aminojson/json_marshal.go +++ b/x/tx/signing/aminojson/json_marshal.go @@ -32,6 +32,10 @@ type EncoderOptions struct { // EnumAsString when set will encode enums as strings instead of integers. // Caution: Enabling this option produce different sign bytes. EnumAsString bool + // AminoNameAsTypeURL when set will use the amino name as the type URL in the JSON output. + // It is useful when using the Amino JSON encoder for non Amino purposes, + // such as JSON RPC. + AminoNameAsTypeURL bool // TypeResolver is used to resolve protobuf message types by TypeURL when marshaling any packed messages. TypeResolver signing.TypeResolver // FileResolver is used to resolve protobuf file descriptors TypeURL when TypeResolver fails. @@ -50,6 +54,7 @@ type Encoder struct { doNotSortFields bool indent string enumsAsString bool + aminoNameAsTypeURL bool } // NewEncoder returns a new Encoder capable of serializing protobuf messages to JSON using the Amino JSON encoding @@ -80,11 +85,12 @@ func NewEncoder(options EncoderOptions) Encoder { "google.protobuf.Duration": marshalDuration, "google.protobuf.Any": marshalAny, }, - fileResolver: options.FileResolver, - typeResolver: options.TypeResolver, - doNotSortFields: options.DoNotSortFields, - indent: options.Indent, - enumsAsString: options.EnumAsString, + fileResolver: options.FileResolver, + typeResolver: options.TypeResolver, + doNotSortFields: options.DoNotSortFields, + indent: options.Indent, + enumsAsString: options.EnumAsString, + aminoNameAsTypeURL: options.AminoNameAsTypeURL, } return enc } @@ -187,9 +193,17 @@ func (enc Encoder) beginMarshal(msg protoreflect.Message, writer io.Writer, isAn ) if isAny { - name, named = getMessageAminoNameAny(msg), true + if enc.aminoNameAsTypeURL { + name, named = getMessageTypeURL(msg), true + } else { + name, named = getMessageAminoNameAny(msg), true + } } else { name, named = getMessageAminoName(msg) + if enc.aminoNameAsTypeURL { + // do not override named + name = getMessageTypeURL(msg) + } } if named { diff --git a/x/tx/signing/aminojson/json_marshal_test.go b/x/tx/signing/aminojson/json_marshal_test.go index a51b83bb49da..29d2f8cf8f59 100644 --- a/x/tx/signing/aminojson/json_marshal_test.go +++ b/x/tx/signing/aminojson/json_marshal_test.go @@ -355,3 +355,62 @@ func TestEnumAsString(t *testing.T) { } }`, string(bz)) } + +func TestAminoNameAsTypeURL(t *testing.T) { + encoder := aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", AminoNameAsTypeURL: true}) + + msg := &testpb.ABitOfEverything{ + Message: &testpb.NestedMessage{ + Foo: "test", + Bar: 0, // this is the default value and should be omitted from output + }, + Enum: testpb.AnEnum_ONE, + Repeated: []int32{3, -7, 2, 6, 4}, + Str: `abcxyz"foo"def`, + Bool: true, + Bytes: []byte{0, 1, 2, 3}, + I32: -15, + F32: 1001, + U32: 1200, + Si32: -376, + Sf32: -1000, + I64: 14578294827584932, + F64: 9572348124213523654, + U64: 4759492485, + Si64: -59268425823934, + Sf64: -659101379604211154, + } + + bz, err := encoder.Marshal(msg) + require.NoError(t, err) + fmt.Println(string(bz)) + require.Equal(t, `{ + "type": "/testpb.ABitOfEverything", + "value": { + "bool": true, + "bytes": "AAECAw==", + "enum": 1, + "f32": 1001, + "f64": "9572348124213523654", + "i32": -15, + "i64": "14578294827584932", + "message": { + "foo": "test" + }, + "repeated": [ + 3, + -7, + 2, + 6, + 4 + ], + "sf32": -1000, + "sf64": "-659101379604211154", + "si32": -376, + "si64": "-59268425823934", + "str": "abcxyz\"foo\"def", + "u32": 1200, + "u64": "4759492485" + } +}`, string(bz)) +} diff --git a/x/tx/signing/aminojson/options.go b/x/tx/signing/aminojson/options.go index 0eecedb88731..cf9110aef3ae 100644 --- a/x/tx/signing/aminojson/options.go +++ b/x/tx/signing/aminojson/options.go @@ -25,7 +25,6 @@ func getMessageAminoName(msg protoreflect.Message) (string, bool) { // 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) { @@ -33,6 +32,11 @@ func getMessageAminoNameAny(msg protoreflect.Message) string { return name.(string) } + return getMessageTypeURL(msg) +} + +// getMessageTypeURL returns the msg url. +func getMessageTypeURL(msg protoreflect.Message) string { msgURL := "/" + string(msg.Descriptor().FullName()) if msgURL != "/" { return msgURL From 5dc0256cdf08a1b387dc7a5d13402c31401030c0 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Wed, 18 Sep 2024 12:31:46 +0200 Subject: [PATCH 2/3] fix x/tx changelog and revert client/v2 changes --- client/v2/CHANGELOG.md | 17 ----------------- client/v2/autocli/query.go | 11 +++++------ 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/client/v2/CHANGELOG.md b/client/v2/CHANGELOG.md index 9554c3213a25..ed2ef30195a8 100644 --- a/client/v2/CHANGELOG.md +++ b/client/v2/CHANGELOG.md @@ -36,24 +36,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] -<<<<<<< HEAD ## [v2.0.0-beta.4] - 2024-07-16 -======= - - -### Features - -* [#18626](https://github.com/cosmos/cosmos-sdk/pull/18626) Support for off-chain signing and verification of a file. -* [#18461](https://github.com/cosmos/cosmos-sdk/pull/18461) Support governance proposals. - -### Improvements - -* [#21712](https://github.com/cosmos/cosmos-sdk/pull/21712) Marshal `type` field as proto message url in queries instead of amino name. - -### API Breaking Changes - -* [#17709](https://github.com/cosmos/cosmos-sdk/pull/17709) Address codecs have been removed from `autocli.AppOptions` and `flag.Builder`. Instead client/v2 uses the address codecs present in the context (introduced in [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503)). ->>>>>>> 0c8ad9d2c (feat(x/tx): add `aminoNameAsTypeURL` option in aminojson encoder (#21712)) ### Bug Fixes diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index 7e0f4cbc3185..95bfbca78bca 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -118,12 +118,11 @@ func (b *Builder) BuildQueryMethodCommand(ctx context.Context, descriptor protor methodName := fmt.Sprintf("/%s/%s", serviceDescriptor.FullName(), descriptor.Name()) outputType := util.ResolveMessageType(b.TypeResolver, descriptor.Output()) encoderOptions := aminojson.EncoderOptions{ - Indent: " ", - EnumAsString: true, - DoNotSortFields: true, - AminoNameAsTypeURL: true, - TypeResolver: b.TypeResolver, - FileResolver: b.FileResolver, + Indent: " ", + EnumAsString: true, + DoNotSortFields: true, + TypeResolver: b.TypeResolver, + FileResolver: b.FileResolver, } cmd, err := b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error { From c3b5d8b3672e0203c6fde3891283d21443121a3e Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Wed, 18 Sep 2024 12:31:54 +0200 Subject: [PATCH 3/3] cl --- x/tx/CHANGELOG.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/x/tx/CHANGELOG.md b/x/tx/CHANGELOG.md index 23e604cc3caf..058b9b7d99a2 100644 --- a/x/tx/CHANGELOG.md +++ b/x/tx/CHANGELOG.md @@ -33,16 +33,17 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos- ## [Unreleased] +## [v0.13.5](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.5) - 2024-09-18 + +### Improvements + +* [#21712](https://github.com/cosmos/cosmos-sdk/pull/21712) Add `AminoNameAsTypeURL` option to Amino JSON encoder. + ## [v0.13.4](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.4) - 2024-08-02 ### Improvements -<<<<<<< HEAD * [#21073](https://github.com/cosmos/cosmos-sdk/pull/21073) In Context use sync.Map `getSignersFuncs` map from concurrent writes, we also call Validate when creating the Context. -======= -* [#21712](https://github.com/cosmos/cosmos-sdk/pull/21712) Add `AminoNameAsTypeURL` option to Amino JSON encoder. -* [#21073](https://github.com/cosmos/cosmos-sdk/pull/21073) In Context use sync.Map `getSignersFuncs` map from concurrent writes, we also need to call Validate when using the legacy app. ->>>>>>> 0c8ad9d2c (feat(x/tx): add `aminoNameAsTypeURL` option in aminojson encoder (#21712)) ## [v0.13.3](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.3) - 2024-04-22