From aef1a2a06e7bb245cd707c029d23b066b857a6cf Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Tue, 28 Jan 2025 18:14:12 +0100 Subject: [PATCH] fix(x/tx): add an option to encode maps using amino json (ref #23513) (#23539) Co-authored-by: Alex | Interchain Labs --- x/tx/CHANGELOG.md | 8 ++++++ x/tx/signing/aminojson/json_marshal.go | 13 ++++++++- x/tx/signing/aminojson/json_marshal_test.go | 29 ++++++++++++++++++--- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/x/tx/CHANGELOG.md b/x/tx/CHANGELOG.md index 5ba2b8d3f04f..1c0ce9d4037d 100644 --- a/x/tx/CHANGELOG.md +++ b/x/tx/CHANGELOG.md @@ -33,6 +33,10 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos- ## [Unreleased] +## [v1.1.0](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v1.1.0) - 2025-01-28 + +* [#23513](https://github.com/cosmos/cosmos-sdk/pull/23513), [#23539](https://github.com/cosmos/cosmos-sdk/pull/23539) Add map marshalling support (as option) to Amino JSON encoder. + ## [v1.0.1](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v1.0.1) - 2025-01-17 * [#23324](https://github.com/cosmos/cosmos-sdk/pull/23324) Sign over unordered and timeout timestamp fields. @@ -57,6 +61,10 @@ Identical to v1.0.0-alpha.3. * [#21825](https://github.com/cosmos/cosmos-sdk/pull/21825) Fix decimal encoding and field ordering in Amino JSON encoder. * [#21850](https://github.com/cosmos/cosmos-sdk/pull/21850) Support bytes field as signer. +## [v0.13.7](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.7) - 2025-01-28 + +* [#23513](https://github.com/cosmos/cosmos-sdk/pull/23513), [#23539](https://github.com/cosmos/cosmos-sdk/pull/23539) Add map marshalling support (as option) to Amino JSON encoder. + ## [v0.13.6](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.6) - 2024-12-12 ### Bug Fixes diff --git a/x/tx/signing/aminojson/json_marshal.go b/x/tx/signing/aminojson/json_marshal.go index 45e08ffc0278..338ea9d88a61 100644 --- a/x/tx/signing/aminojson/json_marshal.go +++ b/x/tx/signing/aminojson/json_marshal.go @@ -242,7 +242,18 @@ func (enc Encoder) marshal(value protoreflect.Value, fd protoreflect.FieldDescri case protoreflect.Map: if enc.marshalMappings { - return jsonMarshal(writer, value) + if !val.IsValid() { + _, err := io.WriteString(writer, "null") + return err + } + + mapData := make(map[string]interface{}) + val.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { + mapData[k.String()] = v.Interface() + return true + }) + + return jsonMarshal(writer, mapData) } return errors.New("maps are not supported") diff --git a/x/tx/signing/aminojson/json_marshal_test.go b/x/tx/signing/aminojson/json_marshal_test.go index b2a4ddd77e42..108890debdb4 100644 --- a/x/tx/signing/aminojson/json_marshal_test.go +++ b/x/tx/signing/aminojson/json_marshal_test.go @@ -266,7 +266,6 @@ func TestIndent(t *testing.T) { bz, err := encoder.Marshal(msg) require.NoError(t, err) - fmt.Println(string(bz)) require.Equal(t, `{ "type": "ABitOfEverything", "value": { @@ -325,7 +324,6 @@ func TestEnumAsString(t *testing.T) { bz, err := encoder.Marshal(msg) require.NoError(t, err) - fmt.Println(string(bz)) require.Equal(t, `{ "type": "ABitOfEverything", "value": { @@ -384,7 +382,6 @@ func TestAminoNameAsTypeURL(t *testing.T) { bz, err := encoder.Marshal(msg) require.NoError(t, err) - fmt.Println(string(bz)) require.Equal(t, `{ "type": "/testpb.ABitOfEverything", "value": { @@ -416,6 +413,32 @@ func TestAminoNameAsTypeURL(t *testing.T) { }`, string(bz)) } +func TestMarshalMappings(t *testing.T) { + // valid + encoder := aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", MarshalMappings: true}) + + msg := &testpb.WithAMap{ + StrMap: map[string]string{ + "foo": "bar", + "baz": "qux", + }, + } + + bz, err := encoder.Marshal(msg) + require.NoError(t, err) + require.Equal(t, `{ + "str_map": { + "baz": "qux", + "foo": "bar" + } +}`, string(bz)) + + // invalid + encoder = aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", MarshalMappings: false}) + _, err = encoder.Marshal(msg) + require.Error(t, err) +} + func TestCustomBytesEncoder(t *testing.T) { cdc := amino.NewCodec() cdc.RegisterConcrete(&testpb.ABitOfEverything{}, "ABitOfEverything", nil)