Skip to content

Commit

Permalink
feat(x/tx): add aminoNameAsTypeURL option in aminojson encoder (#21712
Browse files Browse the repository at this point in the history
)

Co-authored-by: Matt Kocubinski <mkocubinski@gmail.com>
  • Loading branch information
julienrbrt and kocubinski committed Sep 18, 2024
1 parent 870cab5 commit 0c8ad9d
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 12 deletions.
4 changes: 4 additions & 0 deletions client/v2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [#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)).
Expand Down
11 changes: 6 additions & 5 deletions client/v2/autocli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,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 {
Expand Down
1 change: 1 addition & 0 deletions x/tx/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos-

### Improvements

* [#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.

## [v0.13.3](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.3) - 2024-04-22
Expand Down
26 changes: 20 additions & 6 deletions x/tx/signing/aminojson/json_marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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 {
Expand Down
59 changes: 59 additions & 0 deletions x/tx/signing/aminojson/json_marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
6 changes: 5 additions & 1 deletion x/tx/signing/aminojson/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@ 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) {
name := proto.GetExtension(messageOptions, amino.E_Name)
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
Expand Down

0 comments on commit 0c8ad9d

Please sign in to comment.