Skip to content

Commit

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

Co-authored-by: Julien Robert <julien@rbrt.fr>
  • Loading branch information
mergify[bot] and julienrbrt committed Sep 18, 2024
1 parent f812291 commit 7ee3115
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 7 deletions.
6 changes: 6 additions & 0 deletions x/tx/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ 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
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 7ee3115

Please sign in to comment.