diff --git a/CHANGELOG.md b/CHANGELOG.md index eced715b8929..58b074e11d50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -220,6 +220,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#11011](https://github.com/cosmos/cosmos-sdk/pull/11011) Remove burning of deposits when qourum is not reached on a governance proposal and when the deposit is not fully met. * [\#11019](https://github.com/cosmos/cosmos-sdk/pull/11019) Add `MsgCreatePermanentLockedAccount` and CLI method for creating permanent locked account * (x/feegrant) [\#10830](https://github.com/cosmos/cosmos-sdk/pull/10830) Expired allowances will be pruned from state. +* (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. ### Deprecated 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 30f472c01627..2d08f05f8cb3 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 Cosmos 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 4e5489042b8f..1f1603fc752c 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/migrations/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 50216e22e9c8..219969f34f36 100644 --- a/x/authz/module/module.go +++ b/x/authz/module/module.go @@ -52,7 +52,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 5216af3bc631..b2b530ad0f8a 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 abc025818595..b22a6f8b9b42 100644 --- a/x/authz/msgs_test.go +++ b/x/authz/msgs_test.go @@ -1,6 +1,7 @@ package authz_test import ( + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "testing" "time" @@ -8,6 +9,7 @@ import ( cdctypes "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/authz" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -120,3 +122,65 @@ func TestMsgGrantGetAuthorization(t *testing.T) { require.NoError(err) require.Equal(a, &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 39be98dac950..996345319b72 100644 --- a/x/authz/simulation/operations_test.go +++ b/x/authz/simulation/operations_test.go @@ -105,7 +105,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) @@ -142,7 +142,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 0e1d1df42be3..bf82ebcf0d3b 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 b44c6c295948..2246de692456 100644 --- a/x/feegrant/module/module.go +++ b/x/feegrant/module/module.go @@ -57,6 +57,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 703ceccef0ef..8cdc0f1962eb 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" @@ -73,7 +72,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 @@ -133,5 +132,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 402687274c86..f33849557c97 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 59554125a0aa..f958330d9810 100644 --- a/x/feegrant/simulation/operations_test.go +++ b/x/feegrant/simulation/operations_test.go @@ -113,7 +113,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) @@ -155,7 +155,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/gov/types/v1beta1/codec.go b/x/gov/types/v1beta1/codec.go index bb4daf87e9fc..721daecaa7f0 100644 --- a/x/gov/types/v1beta1/codec.go +++ b/x/gov/types/v1beta1/codec.go @@ -2,6 +2,7 @@ package v1beta1 import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" @@ -47,4 +48,8 @@ func RegisterProposalTypeCodec(o interface{}, name string) { func init() { RegisterLegacyAminoCodec(types.ModuleCdc.LegacyAmino) + + // 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/gov/types/v1beta2/codec.go b/x/gov/types/v1beta2/codec.go index c4b737f14aa0..a2403f8e5428 100644 --- a/x/gov/types/v1beta2/codec.go +++ b/x/gov/types/v1beta2/codec.go @@ -2,6 +2,7 @@ package v1beta2 import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" @@ -32,4 +33,8 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { func init() { RegisterLegacyAminoCodec(types.ModuleCdc.LegacyAmino) + + // 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/group/codec.go b/x/group/codec.go index 6e2cb6d40f32..2c1f36ba141c 100644 --- a/x/group/codec.go +++ b/x/group/codec.go @@ -2,6 +2,7 @@ package group import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" @@ -63,4 +64,8 @@ var ( 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/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) }