From b02d4faaed586415903814f6eb4b6852b1a9af56 Mon Sep 17 00:00:00 2001 From: vuong177 Date: Tue, 13 Sep 2022 16:18:06 +0700 Subject: [PATCH 1/3] cherry-pick fix authz amino encoding --- CHANGELOG.md | 1 + codec/legacy/codec.go | 3 +- docs/core/encoding.md | 18 +++++++ x/auth/types/codec.go | 5 ++ x/authz/codec.go | 18 +++++++ x/authz/module/module.go | 4 +- x/authz/msgs.go | 2 +- x/authz/msgs_test.go | 66 ++++++++++++++++++++++++ x/authz/simulation/operations_test.go | 6 +-- x/bank/types/codec.go | 6 +++ x/crisis/types/codec.go | 5 ++ x/distribution/types/codec.go | 5 ++ x/evidence/types/codec.go | 5 ++ x/feegrant/codec.go | 34 ++++++++++++ x/feegrant/module/module.go | 1 + x/feegrant/msgs.go | 5 +- x/feegrant/msgs_test.go | 29 +++++++++++ x/feegrant/simulation/operations_test.go | 4 +- x/slashing/types/codec.go | 5 ++ x/staking/types/codec.go | 10 ++++ 20 files changed, 220 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86e98df0e525..118bba48cfef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -171,6 +171,7 @@ empty coins slice before it is used to create `banktype.MsgSend`. * [\#9576](https://github.com/cosmos/cosmos-sdk/pull/9576) Add debug error message to query result when enabled * (types) [\#11200](https://github.com/cosmos/cosmos-sdk/pull/11200) Added `Min()` and `Max()` operations on sdk.Coins. * [#11267](https://github.com/cosmos/cosmos-sdk/pull/11267) Add hooks to allow app modules to add things to state-sync (backport #10961). +* (x/authz,x/feegrant) [\#11214](https://github.com/cosmos/cosmos-sdk/pull/11214) Fix Amino JSON encoding of authz and feegrant Msgs to be consistent with other modules. ## [v0.45.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.1) - 2022-02-03 diff --git a/codec/legacy/codec.go b/codec/legacy/codec.go index a4a963b6d211..d5d9a686c576 100644 --- a/codec/legacy/codec.go +++ b/codec/legacy/codec.go @@ -10,10 +10,9 @@ import ( // has all Tendermint crypto and evidence types registered. // // TODO: Deprecated - remove this global. -var Cdc *codec.LegacyAmino +var Cdc = codec.NewLegacyAmino() func init() { - Cdc = codec.NewLegacyAmino() cryptocodec.RegisterCrypto(Cdc) codec.RegisterEvidences(Cdc) } diff --git a/docs/core/encoding.md b/docs/core/encoding.md index 084cffadad20..355d631da972 100644 --- a/docs/core/encoding.md +++ b/docs/core/encoding.md @@ -67,6 +67,24 @@ Note, there are length-prefixed variants of the above functionality and this is typically used for when the data needs to be streamed or grouped together (e.g. `ResponseDeliverTx.Data`) +#### Authz authorizations + +Since the `MsgExec` message type can contain different messages instances, it is important that developers +add the following code inside the `init` method of their module's `codec.go` file: + +```go +import "github.com/cosmos/cosmos-sdk/codec/legacy" + +init() { + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize x/authz MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) +} +``` + +This will allow the `x/authz` module to properly serialize and de-serializes `MsgExec` instances using Amino, +which is required when signing this kind of messages using a Ledger. + ### Gogoproto Modules are encouraged to utilize Protobuf encoding for their respective types. In the SDK, we use the [Gogoproto](https://github.com/gogo/protobuf) specific implementation of the Protobuf spec that offers speed and DX improvements compared to the official [Google protobuf implementation](https://github.com/protocolbuffers/protobuf). diff --git a/x/auth/types/codec.go b/x/auth/types/codec.go index 629e2919d24d..1c91ee59a9c2 100644 --- a/x/auth/types/codec.go +++ b/x/auth/types/codec.go @@ -2,6 +2,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" @@ -45,4 +46,8 @@ var ( func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) + + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize x/authz MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) } diff --git a/x/authz/codec.go b/x/authz/codec.go index e9a490cea379..f7f4710bd0f5 100644 --- a/x/authz/codec.go +++ b/x/authz/codec.go @@ -1,11 +1,24 @@ package authz import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" types "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" ) +// RegisterLegacyAminoCodec registers the necessary x/authz interfaces and concrete types +// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgGrant{}, "cosmos-sdk/MsgGrant", nil) + cdc.RegisterConcrete(&MsgRevoke{}, "cosmos-sdk/MsgRevoke", nil) + cdc.RegisterConcrete(&MsgExec{}, "cosmos-sdk/MsgExec", nil) + + cdc.RegisterInterface((*Authorization)(nil), nil) + cdc.RegisterConcrete(&GenericAuthorization{}, "cosmos-sdk/GenericAuthorization", nil) +} + // RegisterInterfaces registers the interfaces types with the interface registry func RegisterInterfaces(registry types.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), @@ -22,3 +35,8 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { msgservice.RegisterMsgServiceDesc(registry, MsgServiceDesc()) } +func init() { + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) +} diff --git a/x/authz/module/module.go b/x/authz/module/module.go index 2c652e1d8fe7..f841b885b7cb 100644 --- a/x/authz/module/module.go +++ b/x/authz/module/module.go @@ -47,7 +47,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { } // RegisterLegacyAminoCodec registers the authz module's types for the given codec. -func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {} +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + authz.RegisterLegacyAminoCodec(cdc) +} // RegisterInterfaces registers the authz module's interface types func (AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { diff --git a/x/authz/msgs.go b/x/authz/msgs.go index 0cf0a312759c..43b1a67fb4f9 100644 --- a/x/authz/msgs.go +++ b/x/authz/msgs.go @@ -1,11 +1,11 @@ package authz import ( + "github.com/cosmos/cosmos-sdk/codec/legacy" "time" "github.com/gogo/protobuf/proto" - "github.com/cosmos/cosmos-sdk/codec/legacy" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" diff --git a/x/authz/msgs_test.go b/x/authz/msgs_test.go index 9e7ef83bca64..cbbdd57c715c 100644 --- a/x/authz/msgs_test.go +++ b/x/authz/msgs_test.go @@ -4,10 +4,14 @@ import ( "testing" "time" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/require" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" + "github.com/cosmos/cosmos-sdk/x/authz" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -116,3 +120,65 @@ func TestMsgGrantGetAuthorization(t *testing.T) { m.SetAuthorization(&g) require.Equal(m.GetAuthorization(), &g) } + +func TestAminoJSON(t *testing.T) { + tx := legacytx.StdTx{} + var msg legacytx.LegacyMsg + someDate := time.Date(1, 1, 1, 1, 1, 1, 1, time.UTC) + msgSend := banktypes.MsgSend{FromAddress: "cosmos1ghi", ToAddress: "cosmos1jkl"} + typeURL := sdk.MsgTypeURL(&msgSend) + msgSendAny, err := cdctypes.NewAnyWithValue(&msgSend) + require.NoError(t, err) + grant, err := authz.NewGrant(someDate, authz.NewGenericAuthorization(typeURL), someDate.Add(time.Hour)) + require.NoError(t, err) + sendGrant, err := authz.NewGrant(someDate, banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000)))), someDate.Add(time.Hour)) + require.NoError(t, err) + valAddr, err := sdk.ValAddressFromBech32("cosmosvaloper1xcy3els9ua75kdm783c3qu0rfa2eples6eavqq") + require.NoError(t, err) + stakingAuth, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{valAddr}, nil, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &sdk.Coin{Denom: "stake", Amount: sdk.NewInt(1000)}) + require.NoError(t, err) + delegateGrant, err := authz.NewGrant(someDate, stakingAuth, someDate.Add(time.Hour)) + require.NoError(t, err) + + // Amino JSON encoding has changed in authz since v0.46. + // Before, it was outputting something like: + // `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"grant":{"authorization":{"msg":"/cosmos.bank.v1beta1.MsgSend"},"expiration":"0001-01-01T02:01:01.000000001Z"},"grantee":"cosmos1def","granter":"cosmos1abc"}],"sequence":"1","timeout_height":"1"}` + // + // This was a bug. Now, it's as below, See how there's `type` & `value` fields. + // ref: https://github.com/cosmos/cosmos-sdk/issues/11190 + // ref: https://github.com/cosmos/cosmjs/issues/1026 + msg = &authz.MsgGrant{Granter: "cosmos1abc", Grantee: "cosmos1def", Grant: grant} + tx.Msgs = []sdk.Msg{msg} + require.Equal(t, + `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgGrant","value":{"grant":{"authorization":{"type":"cosmos-sdk/GenericAuthorization","value":{"msg":"/cosmos.bank.v1beta1.MsgSend"}},"expiration":"0001-01-01T02:01:01.000000001Z"},"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + ) + + msg = &authz.MsgGrant{Granter: "cosmos1abc", Grantee: "cosmos1def", Grant: sendGrant} + tx.Msgs = []sdk.Msg{msg} + require.Equal(t, + `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgGrant","value":{"grant":{"authorization":{"type":"cosmos-sdk/SendAuthorization","value":{"spend_limit":[{"amount":"1000","denom":"stake"}]}},"expiration":"0001-01-01T02:01:01.000000001Z"},"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + ) + + msg = &authz.MsgGrant{Granter: "cosmos1abc", Grantee: "cosmos1def", Grant: delegateGrant} + tx.Msgs = []sdk.Msg{msg} + require.Equal(t, + `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgGrant","value":{"grant":{"authorization":{"type":"cosmos-sdk/StakeAuthorization","value":{"Validators":{"type":"cosmos-sdk/StakeAuthorization/AllowList","value":{"allow_list":{"address":["cosmosvaloper1xcy3els9ua75kdm783c3qu0rfa2eples6eavqq"]}}},"authorization_type":1,"max_tokens":{"amount":"1000","denom":"stake"}}},"expiration":"0001-01-01T02:01:01.000000001Z"},"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + ) + + msg = &authz.MsgRevoke{Granter: "cosmos1abc", Grantee: "cosmos1def", MsgTypeUrl: typeURL} + tx.Msgs = []sdk.Msg{msg} + require.Equal(t, + `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgRevoke","value":{"grantee":"cosmos1def","granter":"cosmos1abc","msg_type_url":"/cosmos.bank.v1beta1.MsgSend"}}],"sequence":"1","timeout_height":"1"}`, + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + ) + + msg = &authz.MsgExec{Grantee: "cosmos1def", Msgs: []*cdctypes.Any{msgSendAny}} + tx.Msgs = []sdk.Msg{msg} + require.Equal(t, + `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgExec","value":{"grantee":"cosmos1def","msgs":[{"type":"cosmos-sdk/MsgSend","value":{"amount":[],"from_address":"cosmos1ghi","to_address":"cosmos1jkl"}}]}}],"sequence":"1","timeout_height":"1"}`, + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + ) +} diff --git a/x/authz/simulation/operations_test.go b/x/authz/simulation/operations_test.go index 8db963be733f..728819057589 100644 --- a/x/authz/simulation/operations_test.go +++ b/x/authz/simulation/operations_test.go @@ -106,7 +106,7 @@ func (suite *SimTestSuite) TestSimulateGrant() { suite.Require().NoError(err) var msg authz.MsgGrant - suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + suite.app.LegacyAmino().UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().True(operationMsg.OK) suite.Require().Equal(granter.Address.String(), msg.Granter) suite.Require().Equal(grantee.Address.String(), msg.Grantee) @@ -143,7 +143,7 @@ func (suite *SimTestSuite) TestSimulateRevoke() { suite.Require().NoError(err) var msg authz.MsgRevoke - suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + suite.app.LegacyAmino().UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().True(operationMsg.OK) suite.Require().Equal(granter.Address.String(), msg.Granter) @@ -178,7 +178,7 @@ func (suite *SimTestSuite) TestSimulateExec() { var msg authz.MsgExec - suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + suite.app.LegacyAmino().UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().True(operationMsg.OK) suite.Require().Equal(grantee.Address.String(), msg.Grantee) diff --git a/x/bank/types/codec.go b/x/bank/types/codec.go index 07859ceab603..62e6b4fe1568 100644 --- a/x/bank/types/codec.go +++ b/x/bank/types/codec.go @@ -2,6 +2,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -14,6 +15,7 @@ import ( func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgSend{}, "cosmos-sdk/MsgSend", nil) cdc.RegisterConcrete(&MsgMultiSend{}, "cosmos-sdk/MsgMultiSend", nil) + cdc.RegisterConcrete(&SendAuthorization{}, "cosmos-sdk/SendAuthorization", nil) } func RegisterInterfaces(registry types.InterfaceRegistry) { @@ -45,4 +47,8 @@ func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) amino.Seal() + + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize x/authz MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) } diff --git a/x/crisis/types/codec.go b/x/crisis/types/codec.go index ac02c54630cb..67e32f4cee53 100644 --- a/x/crisis/types/codec.go +++ b/x/crisis/types/codec.go @@ -2,6 +2,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -38,4 +39,8 @@ func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) amino.Seal() + + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize x/authz MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) } diff --git a/x/distribution/types/codec.go b/x/distribution/types/codec.go index 73aca45060e6..a4a5d480d1d8 100644 --- a/x/distribution/types/codec.go +++ b/x/distribution/types/codec.go @@ -2,6 +2,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -51,4 +52,8 @@ func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) amino.Seal() + + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize x/authz MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) } diff --git a/x/evidence/types/codec.go b/x/evidence/types/codec.go index 9de2743e38ef..45644588b43b 100644 --- a/x/evidence/types/codec.go +++ b/x/evidence/types/codec.go @@ -2,6 +2,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -44,4 +45,8 @@ func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) amino.Seal() + + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize x/authz MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) } diff --git a/x/feegrant/codec.go b/x/feegrant/codec.go index 7e307f42197d..aebd654399d2 100644 --- a/x/feegrant/codec.go +++ b/x/feegrant/codec.go @@ -1,11 +1,25 @@ package feegrant import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" ) +// RegisterLegacyAminoCodec registers the necessary x/feegrant interfaces and concrete types +// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgGrantAllowance{}, "cosmos-sdk/MsgGrantAllowance", nil) + cdc.RegisterConcrete(&MsgRevokeAllowance{}, "cosmos-sdk/MsgRevokeAllowance", nil) + + cdc.RegisterInterface((*FeeAllowanceI)(nil), nil) + cdc.RegisterConcrete(&BasicAllowance{}, "cosmos-sdk/BasicAllowance", nil) + cdc.RegisterConcrete(&PeriodicAllowance{}, "cosmos-sdk/PeriodicAllowance", nil) + cdc.RegisterConcrete(&AllowedMsgAllowance{}, "cosmos-sdk/AllowedMsgAllowance", nil) +} + // RegisterInterfaces registers the interfaces types with the interface registry func RegisterInterfaces(registry types.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), @@ -23,3 +37,23 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } + +var ( + amino = codec.NewLegacyAmino() + + // ModuleCdc references the global x/feegrant module codec. Note, the codec should + // ONLY be used in certain instances of tests and for JSON encoding as Amino is + // still used for that purpose. + // + // The actual codec used for serialization should be provided to x/feegrant and + // defined at the application level. + ModuleCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize x/authz MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) +} diff --git a/x/feegrant/module/module.go b/x/feegrant/module/module.go index 421ecfca186b..196d66dabf85 100644 --- a/x/feegrant/module/module.go +++ b/x/feegrant/module/module.go @@ -53,6 +53,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { // RegisterLegacyAminoCodec registers the feegrant module's types for the given codec. func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + feegrant.RegisterLegacyAminoCodec(cdc) } // RegisterInterfaces registers the feegrant module's interface types diff --git a/x/feegrant/msgs.go b/x/feegrant/msgs.go index 340007f8da1f..8100a438372b 100644 --- a/x/feegrant/msgs.go +++ b/x/feegrant/msgs.go @@ -3,7 +3,6 @@ package feegrant import ( "github.com/gogo/protobuf/proto" - "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -78,7 +77,7 @@ func (msg MsgGrantAllowance) Route() string { // GetSignBytes implements the LegacyMsg.GetSignBytes method. func (msg MsgGrantAllowance) GetSignBytes() []byte { - return sdk.MustSortJSON(legacy.Cdc.MustMarshalJSON(&msg)) + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) } // GetFeeAllowanceI returns unpacked FeeAllowance @@ -142,5 +141,5 @@ func (msg MsgRevokeAllowance) Route() string { // GetSignBytes implements the LegacyMsg.GetSignBytes method. func (msg MsgRevokeAllowance) GetSignBytes() []byte { - return sdk.MustSortJSON(legacy.Cdc.MustMarshalJSON(&msg)) + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) } diff --git a/x/feegrant/msgs_test.go b/x/feegrant/msgs_test.go index c5eceb3b6bd3..3e5dea79e424 100644 --- a/x/feegrant/msgs_test.go +++ b/x/feegrant/msgs_test.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" "github.com/cosmos/cosmos-sdk/x/feegrant" ) @@ -132,3 +133,31 @@ func TestMsgRevokeAllowance(t *testing.T) { } } } + +func TestAminoJSON(t *testing.T) { + tx := legacytx.StdTx{} + var msg legacytx.LegacyMsg + allowanceAny, err := codectypes.NewAnyWithValue(&feegrant.BasicAllowance{SpendLimit: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(100)))}) + require.NoError(t, err) + + // Amino JSON encoding has changed in feegrant since v0.46. + // Before, it was outputting something like: + // `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"allowance":{"spend_limit":[{"amount":"100","denom":"foo"}]},"grantee":"cosmos1def","granter":"cosmos1abc"}],"sequence":"1","timeout_height":"1"}` + // + // This was a bug. Now, it's as below, See how there's `type` & `value` fields. + // ref: https://github.com/cosmos/cosmos-sdk/issues/11190 + // ref: https://github.com/cosmos/cosmjs/issues/1026 + msg = &feegrant.MsgGrantAllowance{Granter: "cosmos1abc", Grantee: "cosmos1def", Allowance: allowanceAny} + tx.Msgs = []sdk.Msg{msg} + require.Equal(t, + `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgGrantAllowance","value":{"allowance":{"type":"cosmos-sdk/BasicAllowance","value":{"spend_limit":[{"amount":"100","denom":"foo"}]}},"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + ) + + msg = &feegrant.MsgRevokeAllowance{Granter: "cosmos1abc", Grantee: "cosmos1def"} + tx.Msgs = []sdk.Msg{msg} + require.Equal(t, + `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgRevokeAllowance","value":{"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + ) +} diff --git a/x/feegrant/simulation/operations_test.go b/x/feegrant/simulation/operations_test.go index c78db36d168e..0376d340e4ea 100644 --- a/x/feegrant/simulation/operations_test.go +++ b/x/feegrant/simulation/operations_test.go @@ -112,7 +112,7 @@ func (suite *SimTestSuite) TestSimulateMsgGrantAllowance() { require.NoError(err) var msg feegrant.MsgGrantAllowance - suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + suite.app.LegacyAmino().UnmarshalJSON(operationMsg.Msg, &msg) require.True(operationMsg.OK) require.Equal(accounts[2].Address.String(), msg.Granter) @@ -154,7 +154,7 @@ func (suite *SimTestSuite) TestSimulateMsgRevokeAllowance() { require.NoError(err) var msg feegrant.MsgRevokeAllowance - suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + suite.app.LegacyAmino().UnmarshalJSON(operationMsg.Msg, &msg) require.True(operationMsg.OK) require.Equal(granter.Address.String(), msg.Granter) diff --git a/x/slashing/types/codec.go b/x/slashing/types/codec.go index bc89862f1b46..d56869d38088 100644 --- a/x/slashing/types/codec.go +++ b/x/slashing/types/codec.go @@ -2,6 +2,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -37,4 +38,8 @@ func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) amino.Seal() + + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize x/authz MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) } diff --git a/x/staking/types/codec.go b/x/staking/types/codec.go index 485549077bd0..5b95b543650e 100644 --- a/x/staking/types/codec.go +++ b/x/staking/types/codec.go @@ -2,6 +2,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -17,6 +18,11 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgDelegate{}, "cosmos-sdk/MsgDelegate", nil) cdc.RegisterConcrete(&MsgUndelegate{}, "cosmos-sdk/MsgUndelegate", nil) cdc.RegisterConcrete(&MsgBeginRedelegate{}, "cosmos-sdk/MsgBeginRedelegate", nil) + + cdc.RegisterInterface((*isStakeAuthorization_Validators)(nil), nil) + cdc.RegisterConcrete(&StakeAuthorization_AllowList{}, "cosmos-sdk/StakeAuthorization/AllowList", nil) + cdc.RegisterConcrete(&StakeAuthorization_DenyList{}, "cosmos-sdk/StakeAuthorization/DenyList", nil) + cdc.RegisterConcrete(&StakeAuthorization{}, "cosmos-sdk/StakeAuthorization", nil) } // RegisterInterfaces registers the x/staking interfaces types with the interface registry @@ -52,4 +58,8 @@ func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) amino.Seal() + + // Register all Amino interfaces and concrete types on the global Amino codec so that this can later be + // used to properly serialize x/authz MsgExec instances + RegisterLegacyAminoCodec(legacy.Cdc) } From 8196d5e7fb8ab5a31d55e2631b5ea2a5b8bda1e6 Mon Sep 17 00:00:00 2001 From: vuong177 Date: Tue, 13 Sep 2022 16:18:24 +0700 Subject: [PATCH 2/3] fix msg_test.go --- x/authz/msgs_test.go | 16 ++++++++-------- x/feegrant/msgs_test.go | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/x/authz/msgs_test.go b/x/authz/msgs_test.go index cbbdd57c715c..be40c705da2e 100644 --- a/x/authz/msgs_test.go +++ b/x/authz/msgs_test.go @@ -129,15 +129,15 @@ func TestAminoJSON(t *testing.T) { typeURL := sdk.MsgTypeURL(&msgSend) msgSendAny, err := cdctypes.NewAnyWithValue(&msgSend) require.NoError(t, err) - grant, err := authz.NewGrant(someDate, authz.NewGenericAuthorization(typeURL), someDate.Add(time.Hour)) + grant, err := authz.NewGrant(authz.NewGenericAuthorization(typeURL), someDate.Add(time.Hour)) require.NoError(t, err) - sendGrant, err := authz.NewGrant(someDate, banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000)))), someDate.Add(time.Hour)) + sendGrant, err := authz.NewGrant(banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000)))), someDate.Add(time.Hour)) require.NoError(t, err) valAddr, err := sdk.ValAddressFromBech32("cosmosvaloper1xcy3els9ua75kdm783c3qu0rfa2eples6eavqq") require.NoError(t, err) stakingAuth, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{valAddr}, nil, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &sdk.Coin{Denom: "stake", Amount: sdk.NewInt(1000)}) require.NoError(t, err) - delegateGrant, err := authz.NewGrant(someDate, stakingAuth, someDate.Add(time.Hour)) + delegateGrant, err := authz.NewGrant(stakingAuth, someDate.Add(time.Hour)) require.NoError(t, err) // Amino JSON encoding has changed in authz since v0.46. @@ -151,34 +151,34 @@ func TestAminoJSON(t *testing.T) { tx.Msgs = []sdk.Msg{msg} require.Equal(t, `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgGrant","value":{"grant":{"authorization":{"type":"cosmos-sdk/GenericAuthorization","value":{"msg":"/cosmos.bank.v1beta1.MsgSend"}},"expiration":"0001-01-01T02:01:01.000000001Z"},"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, - string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo")), ) msg = &authz.MsgGrant{Granter: "cosmos1abc", Grantee: "cosmos1def", Grant: sendGrant} tx.Msgs = []sdk.Msg{msg} require.Equal(t, `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgGrant","value":{"grant":{"authorization":{"type":"cosmos-sdk/SendAuthorization","value":{"spend_limit":[{"amount":"1000","denom":"stake"}]}},"expiration":"0001-01-01T02:01:01.000000001Z"},"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, - string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo")), ) msg = &authz.MsgGrant{Granter: "cosmos1abc", Grantee: "cosmos1def", Grant: delegateGrant} tx.Msgs = []sdk.Msg{msg} require.Equal(t, `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgGrant","value":{"grant":{"authorization":{"type":"cosmos-sdk/StakeAuthorization","value":{"Validators":{"type":"cosmos-sdk/StakeAuthorization/AllowList","value":{"allow_list":{"address":["cosmosvaloper1xcy3els9ua75kdm783c3qu0rfa2eples6eavqq"]}}},"authorization_type":1,"max_tokens":{"amount":"1000","denom":"stake"}}},"expiration":"0001-01-01T02:01:01.000000001Z"},"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, - string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo")), ) msg = &authz.MsgRevoke{Granter: "cosmos1abc", Grantee: "cosmos1def", MsgTypeUrl: typeURL} tx.Msgs = []sdk.Msg{msg} require.Equal(t, `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgRevoke","value":{"grantee":"cosmos1def","granter":"cosmos1abc","msg_type_url":"/cosmos.bank.v1beta1.MsgSend"}}],"sequence":"1","timeout_height":"1"}`, - string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo")), ) msg = &authz.MsgExec{Grantee: "cosmos1def", Msgs: []*cdctypes.Any{msgSendAny}} tx.Msgs = []sdk.Msg{msg} require.Equal(t, `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgExec","value":{"grantee":"cosmos1def","msgs":[{"type":"cosmos-sdk/MsgSend","value":{"amount":[],"from_address":"cosmos1ghi","to_address":"cosmos1jkl"}}]}}],"sequence":"1","timeout_height":"1"}`, - string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo")), ) } diff --git a/x/feegrant/msgs_test.go b/x/feegrant/msgs_test.go index 3e5dea79e424..fc3e28185c7d 100644 --- a/x/feegrant/msgs_test.go +++ b/x/feegrant/msgs_test.go @@ -9,7 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/feegrant" ) @@ -151,13 +151,13 @@ func TestAminoJSON(t *testing.T) { tx.Msgs = []sdk.Msg{msg} require.Equal(t, `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgGrantAllowance","value":{"allowance":{"type":"cosmos-sdk/BasicAllowance","value":{"spend_limit":[{"amount":"100","denom":"foo"}]}},"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, - string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo")), ) msg = &feegrant.MsgRevokeAllowance{Granter: "cosmos1abc", Grantee: "cosmos1def"} tx.Msgs = []sdk.Msg{msg} require.Equal(t, `{"account_number":"1","chain_id":"foo","fee":{"amount":[],"gas":"0"},"memo":"memo","msgs":[{"type":"cosmos-sdk/MsgRevokeAllowance","value":{"grantee":"cosmos1def","granter":"cosmos1abc"}}],"sequence":"1","timeout_height":"1"}`, - string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo", nil)), + string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{msg}, "memo")), ) } From 482e316d7b1416c389c122a9607eb95188412aa4 Mon Sep 17 00:00:00 2001 From: vuong177 Date: Tue, 13 Sep 2022 16:30:48 +0700 Subject: [PATCH 3/3] fix: implement Amino serialization for x/authz and x/feegrant (#11224) * fix: Add RegisterLegacyAminoCodec for authz/feegrant * add module name * Fix GetSignByes, add tests * removed module names from registered messages to match other modules * added interfaces and concrete types registration * unseal amino instances to allow external grant and authorization registration * fixed messages tests * allow to register external types into authz modulecdc * use legacy.Cdc instead of ModuleCdc inside x/authz * move the legacy.Cdc initialization outside init function * added serialization docs * Update docs/core/encoding.md Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> * added the Ledger specification * fixed tests Co-authored-by: Amaury M <1293565+amaurym@users.noreply.github.com>