From d24e73d1eefa27c2a434f0f217fa13b366c4098b Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 6 May 2022 10:57:43 -0400 Subject: [PATCH 1/3] fix: remove time.now check from authz #11129 --- x/authz/authorization_grant.go | 12 ++--- x/authz/authorization_grant_test.go | 10 ++--- x/authz/client/cli/tx.go | 2 +- x/authz/client/rest/grpc_query_test.go | 5 ++- x/authz/client/testutil/query.go | 4 +- x/authz/client/testutil/test_helpers.go | 2 +- x/authz/client/testutil/tx.go | 31 +++++++------ x/authz/keeper/keeper.go | 8 +++- x/authz/keeper/keeper_test.go | 18 +++----- x/authz/msgs_test.go | 2 +- x/authz/simulation/decoder_test.go | 3 +- x/authz/simulation/genesis.go | 6 ++- x/authz/simulation/operations.go | 60 ++++++++++++------------- x/authz/simulation/operations_test.go | 4 +- 14 files changed, 85 insertions(+), 82 deletions(-) diff --git a/x/authz/authorization_grant.go b/x/authz/authorization_grant.go index a873499b621b..30bc1eec467d 100644 --- a/x/authz/authorization_grant.go +++ b/x/authz/authorization_grant.go @@ -9,12 +9,12 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// NewGrant returns new Grant -func NewGrant( /*blockTime time.Time, */ a Authorization, expiration time.Time) (Grant, error) { - // TODO: add this for 0.45 - // if !expiration.After(blockTime) { - // return Grant{}, sdkerrors.ErrInvalidRequest.Wrapf("expiration must be after the current block time (%v), got %v", blockTime.Format(time.RFC3339), expiration.Format(time.RFC3339)) - // } +// NewGrant returns new Grant. It returns an error if the expiration is before +// the current block time, which is passed into the `blockTime` arg. +func NewGrant(blockTime time.Time, a Authorization, expiration time.Time) (Grant, error) { + if !expiration.After(blockTime) { + return Grant{}, sdkerrors.ErrInvalidRequest.Wrapf("expiration must be after the current block time (%v), got %v", blockTime.Format(time.RFC3339), expiration.Format(time.RFC3339)) + } g := Grant{ Expiration: expiration, } diff --git a/x/authz/authorization_grant_test.go b/x/authz/authorization_grant_test.go index 9f9f00108c73..849b48d32ac8 100644 --- a/x/authz/authorization_grant_test.go +++ b/x/authz/authorization_grant_test.go @@ -4,7 +4,6 @@ import ( "testing" "time" - // banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/stretchr/testify/require" ) @@ -18,7 +17,6 @@ func expecError(r *require.Assertions, expected string, received error) { } func TestNewGrant(t *testing.T) { - // ba := banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewInt64Coin("foo", 123))) a := NewGenericAuthorization("some-type") var tcs = []struct { title string @@ -27,16 +25,16 @@ func TestNewGrant(t *testing.T) { expire time.Time err string }{ - // {"wrong expire time (1)", a, time.Unix(10, 0), time.Unix(8, 0), "expiration must be after"}, - // {"wrong expire time (2)", a, time.Unix(10, 0), time.Unix(10, 0), "expiration must be after"}, + {"wrong expire time (1)", a, time.Unix(10, 0), time.Unix(8, 0), "expiration must be after"}, + {"wrong expire time (2)", a, time.Unix(10, 0), time.Unix(10, 0), "expiration must be after"}, {"good expire time (1)", a, time.Unix(10, 0), time.Unix(10, 1), ""}, {"good expire time (2)", a, time.Unix(10, 0), time.Unix(11, 0), ""}, } for _, tc := range tcs { + tc := tc t.Run(tc.title, func(t *testing.T) { - // _, err := NewGrant(tc.blockTime, tc.a, tc.expire) - _, err := NewGrant(tc.a, tc.expire) + _, err := NewGrant(tc.blockTime, tc.a, tc.expire) expecError(require.New(t), tc.err, err) }) } diff --git a/x/authz/client/cli/tx.go b/x/authz/client/cli/tx.go index f4117ee1c740..0200e615e03f 100644 --- a/x/authz/client/cli/tx.go +++ b/x/authz/client/cli/tx.go @@ -56,7 +56,7 @@ func NewCmdGrantAuthorization() *cobra.Command { Use: "grant --from ", Short: "Grant authorization to an address", Long: strings.TrimSpace( - fmt.Sprintf(`grant authorization to an address to execute a transaction on your behalf: + fmt.Sprintf(`create a new grant authorization to an address to execute a transaction on your behalf: Examples: $ %s tx %s grant cosmos1skjw.. send %s --spend-limit=1000stake --from=cosmos1skl.. diff --git a/x/authz/client/rest/grpc_query_test.go b/x/authz/client/rest/grpc_query_test.go index 614e283a15ed..0a1bb8d11380 100644 --- a/x/authz/client/rest/grpc_query_test.go +++ b/x/authz/client/rest/grpc_query_test.go @@ -1,3 +1,4 @@ +//go:build norace // +build norace package rest_test @@ -61,7 +62,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().Contains(out.String(), `"code":0`) // grant authorization - out, err = authztestutil.ExecGrant(val, []string{ + out, err = authztestutil.CreateGrant(val, []string{ newAddr.String(), "send", fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), @@ -177,7 +178,7 @@ func (s *IntegrationTestSuite) TestQueryGrantsGRPC() { false, "", func() { - _, err := authztestutil.ExecGrant(val, []string{ + _, err := authztestutil.CreateGrant(val, []string{ s.grantee.String(), "generic", fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), diff --git a/x/authz/client/testutil/query.go b/x/authz/client/testutil/query.go index 529939a7019c..a91362fa1b07 100644 --- a/x/authz/client/testutil/query.go +++ b/x/authz/client/testutil/query.go @@ -20,7 +20,7 @@ func (s *IntegrationTestSuite) TestQueryAuthorizations() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := ExecGrant( + _, err := CreateGrant( val, []string{ grantee.String(), @@ -98,7 +98,7 @@ func (s *IntegrationTestSuite) TestQueryAuthorization() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := ExecGrant( + _, err := CreateGrant( val, []string{ grantee.String(), diff --git a/x/authz/client/testutil/test_helpers.go b/x/authz/client/testutil/test_helpers.go index 1a1cd4830fc1..f1a990c54c9a 100644 --- a/x/authz/client/testutil/test_helpers.go +++ b/x/authz/client/testutil/test_helpers.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/authz/client/cli" ) -func ExecGrant(val *network.Validator, args []string) (testutil.BufferWriter, error) { +func CreateGrant(val *network.Validator, args []string) (testutil.BufferWriter, error) { cmd := cli.NewCmdGrantAuthorization() clientCtx := val.ClientCtx return clitestutil.ExecTestCLICmd(clientCtx, cmd, args) diff --git a/x/authz/client/testutil/tx.go b/x/authz/client/testutil/tx.go index ebc3e3c31d2b..7659bb8ce78f 100644 --- a/x/authz/client/testutil/tx.go +++ b/x/authz/client/testutil/tx.go @@ -85,8 +85,8 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { val := s.network.Validators[0] grantee := s.grantee - twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - pastHour := time.Now().Add(time.Minute * time.Duration(-60)).Unix() + twoHours := time.Now().Add(time.Minute * 120).Unix() + pastHour := time.Now().Add(-time.Minute * 60).Unix() testCases := []struct { name string @@ -278,15 +278,14 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { clientCtx := val.ClientCtx - out, err := ExecGrant( + out, err := CreateGrant( val, tc.args, ) if tc.expectErr { - s.Require().Error(err) + s.Require().Error(err, out) } else { var txResp sdk.TxResponse s.Require().NoError(err) @@ -310,7 +309,7 @@ func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() // send-authorization - _, err := ExecGrant( + _, err := CreateGrant( val, []string{ grantee.String(), @@ -326,7 +325,7 @@ func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { s.Require().NoError(err) // generic-authorization - _, err = ExecGrant( + _, err = CreateGrant( val, []string{ grantee.String(), @@ -342,7 +341,7 @@ func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { s.Require().NoError(err) // generic-authorization used for amino testing - _, err = ExecGrant( + _, err = CreateGrant( val, []string{ grantee.String(), @@ -455,7 +454,7 @@ func (s *IntegrationTestSuite) TestExecAuthorizationWithExpiration() { grantee := s.grantee tenSeconds := time.Now().Add(time.Second * time.Duration(10)).Unix() - _, err := ExecGrant( + _, err := CreateGrant( val, []string{ grantee.String(), @@ -495,7 +494,7 @@ func (s *IntegrationTestSuite) TestNewExecGenericAuthorized() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := ExecGrant( + _, err := CreateGrant( val, []string{ grantee.String(), @@ -597,7 +596,7 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := ExecGrant( + _, err := CreateGrant( val, []string{ grantee.String(), @@ -682,7 +681,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := ExecGrant( + _, err := CreateGrant( val, []string{ grantee.String(), @@ -774,7 +773,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { } // test delegate no spend-limit - _, err = ExecGrant( + _, err = CreateGrant( val, []string{ grantee.String(), @@ -851,7 +850,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { } // test delegating to denied validator - _, err = ExecGrant( + _, err = CreateGrant( val, []string{ grantee.String(), @@ -886,7 +885,7 @@ func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() { twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() // granting undelegate msg authorization - _, err := ExecGrant( + _, err := CreateGrant( val, []string{ grantee.String(), @@ -995,7 +994,7 @@ func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() { } // grant undelegate authorization without limit - _, err = ExecGrant( + _, err = CreateGrant( val, []string{ grantee.String(), diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go index ce4e421c1259..a09063cb9f55 100644 --- a/x/authz/keeper/keeper.go +++ b/x/authz/keeper/keeper.go @@ -132,7 +132,7 @@ func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, msgs [] func (k Keeper) SaveGrant(ctx sdk.Context, grantee, granter sdk.AccAddress, authorization authz.Authorization, expiration time.Time) error { store := ctx.KVStore(k.storeKey) - grant, err := authz.NewGrant(authorization, expiration) + grant, err := authz.NewGrant(ctx.BlockTime(), authorization, expiration) if err != nil { return err } @@ -232,14 +232,20 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *authz.GenesisState { // InitGenesis new authz genesis func (k Keeper) InitGenesis(ctx sdk.Context, data *authz.GenesisState) { for _, entry := range data.Authorization { + if entry.Expiration.Before(ctx.BlockTime()) { + continue + } + grantee, err := sdk.AccAddressFromBech32(entry.Grantee) if err != nil { panic(err) } + granter, err := sdk.AccAddressFromBech32(entry.Granter) if err != nil { panic(err) } + a, ok := entry.Authorization.GetCachedValue().(authz.Authorization) if !ok { panic("expected authorization") diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 8dfebac95a3b..078c6e7bc479 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -54,13 +54,12 @@ func (s *TestSuite) TestKeeper() { s.Require().Nil(authorization) s.Require().Equal(expiration, time.Time{}) now := s.ctx.BlockHeader().Time - s.Require().NotNil(now) newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) s.T().Log("verify if expired authorization is rejected") x := &banktypes.SendAuthorization{SpendLimit: newCoins} err := app.AuthzKeeper.SaveGrant(ctx, granterAddr, granteeAddr, x, now.Add(-1*time.Hour)) - s.Require().NoError(err) + s.Require().Error(err) authorization, _ = app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, bankSendAuthMsgType) s.Require().Nil(authorization) @@ -104,14 +103,13 @@ func (s *TestSuite) TestKeeperIter() { authorization, expiration := app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, "Abcd") s.Require().Nil(authorization) s.Require().Equal(time.Time{}, expiration) - now := s.ctx.BlockHeader().Time - s.Require().NotNil(now) + now := s.ctx.BlockHeader().Time.Add(time.Second) newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) s.T().Log("verify if expired authorization is rejected") x := &banktypes.SendAuthorization{SpendLimit: newCoins} err := app.AuthzKeeper.SaveGrant(ctx, granteeAddr, granterAddr, x, now.Add(-1*time.Hour)) - s.Require().NoError(err) + s.Require().Error(err) authorization, _ = app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, "abcd") s.Require().Nil(authorization) @@ -130,8 +128,7 @@ func (s *TestSuite) TestKeeperFees() { granteeAddr := addrs[1] recipientAddr := addrs[2] s.Require().NoError(simapp.FundAccount(app.BankKeeper, s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000)))) - now := s.ctx.BlockHeader().Time - s.Require().NotNil(now) + expiration := s.ctx.BlockHeader().Time.Add(1 * time.Second) smallCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 20)) someCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 123)) @@ -156,7 +153,7 @@ func (s *TestSuite) TestKeeperFees() { s.T().Log("verify dispatch executes with correct information") // grant authorization - err = app.AuthzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, &banktypes.SendAuthorization{SpendLimit: smallCoin}, now) + err = app.AuthzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, &banktypes.SendAuthorization{SpendLimit: smallCoin}, expiration) s.Require().NoError(err) authorization, _ := app.AuthzKeeper.GetCleanAuthorization(s.ctx, granteeAddr, granterAddr, bankSendAuthMsgType) s.Require().NotNil(authorization) @@ -205,8 +202,7 @@ func (s *TestSuite) TestDispatchedEvents() { granteeAddr := addrs[1] recipientAddr := addrs[2] require.NoError(simapp.FundAccount(app.BankKeeper, s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000)))) - now := s.ctx.BlockHeader().Time - require.NotNil(now) + expiration := s.ctx.BlockHeader().Time.Add(1 * time.Second) smallCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 20)) msgs := authz.NewMsgExec(granteeAddr, []sdk.Msg{ @@ -218,7 +214,7 @@ func (s *TestSuite) TestDispatchedEvents() { }) // grant authorization - err := app.AuthzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, &banktypes.SendAuthorization{SpendLimit: smallCoin}, now) + err := app.AuthzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, &banktypes.SendAuthorization{SpendLimit: smallCoin}, expiration) require.NoError(err) authorization, _ := app.AuthzKeeper.GetCleanAuthorization(s.ctx, granteeAddr, granterAddr, bankSendAuthMsgType) require.NotNil(authorization) diff --git a/x/authz/msgs_test.go b/x/authz/msgs_test.go index c7b4192d3783..722ba38f0ca8 100644 --- a/x/authz/msgs_test.go +++ b/x/authz/msgs_test.go @@ -80,7 +80,7 @@ func TestMsgGrantAuthorization(t *testing.T) { {"nil granter and grantee address", nil, nil, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now(), false, false}, {"nil authorization", granter, grantee, nil, time.Now(), true, false}, {"valid test case", granter, grantee, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 1, 0), false, true}, - {"past time", granter, grantee, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 0, -1), false, true}, // TODO need 0.45 + {"past time", granter, grantee, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 0, -1), true, true}, } for i, tc := range tests { msg, err := authz.NewMsgGrant( diff --git a/x/authz/simulation/decoder_test.go b/x/authz/simulation/decoder_test.go index cfda286a8377..de50d756a769 100644 --- a/x/authz/simulation/decoder_test.go +++ b/x/authz/simulation/decoder_test.go @@ -20,7 +20,8 @@ func TestDecodeStore(t *testing.T) { cdc := simapp.MakeTestEncodingConfig().Marshaler dec := simulation.NewDecodeStore(cdc) - grant, _ := authz.NewGrant(banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewInt64Coin("foo", 123))), time.Now().UTC()) + now := time.Now().UTC() + grant, _ := authz.NewGrant(now, banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewInt64Coin("foo", 123))), now.Add(1)) grantBz, err := cdc.Marshal(&grant) require.NoError(t, err) kvPairs := kv.Pairs{ diff --git a/x/authz/simulation/genesis.go b/x/authz/simulation/genesis.go index b95207be9758..d6d0e2e8626a 100644 --- a/x/authz/simulation/genesis.go +++ b/x/authz/simulation/genesis.go @@ -2,6 +2,7 @@ package simulation import ( "math/rand" + "time" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -13,7 +14,7 @@ import ( ) // genGrant returns a slice of authorization grants. -func genGrant(r *rand.Rand, accounts []simtypes.Account) []authz.GrantAuthorization { +func genGrant(r *rand.Rand, accounts []simtypes.Account, genT time.Time) []authz.GrantAuthorization { authorizations := make([]authz.GrantAuthorization, len(accounts)-1) for i := 0; i < len(accounts)-1; i++ { granter := accounts[i] @@ -22,6 +23,7 @@ func genGrant(r *rand.Rand, accounts []simtypes.Account) []authz.GrantAuthorizat Granter: granter.Address.String(), Grantee: grantee.Address.String(), Authorization: generateRandomGrant(r), + Expiration: genT.AddDate(1, 0, 0), } } @@ -50,7 +52,7 @@ func RandomizedGenState(simState *module.SimulationState) { var grants []authz.GrantAuthorization simState.AppParams.GetOrGenerate( simState.Cdc, "authz", &grants, simState.Rand, - func(r *rand.Rand) { grants = genGrant(r, simState.Accounts) }, + func(r *rand.Rand) { grants = genGrant(r, simState.Accounts, simState.GenTimestamp) }, ) authzGrantsGenesis := authz.NewGenesisState(grants) diff --git a/x/authz/simulation/operations.go b/x/authz/simulation/operations.go index 6c859bd34836..da13ff88881f 100644 --- a/x/authz/simulation/operations.go +++ b/x/authz/simulation/operations.go @@ -1,11 +1,8 @@ package simulation import ( - "fmt" "math/rand" - "github.com/gogo/protobuf/proto" - "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -49,8 +46,8 @@ func WeightedOperations( var ( weightMsgGrant int - weightRevoke int weightExec int + weightRevoke int ) appParams.GetOrGenerate(cdc, OpWeightMsgGrant, &weightMsgGrant, nil, @@ -59,15 +56,15 @@ func WeightedOperations( }, ) - appParams.GetOrGenerate(cdc, OpWeightRevoke, &weightRevoke, nil, + appParams.GetOrGenerate(cdc, OpWeightExec, &weightExec, nil, func(_ *rand.Rand) { - weightRevoke = WeightRevoke + weightExec = WeightExec }, ) - appParams.GetOrGenerate(cdc, OpWeightExec, &weightExec, nil, + appParams.GetOrGenerate(cdc, OpWeightRevoke, &weightRevoke, nil, func(_ *rand.Rand) { - weightExec = WeightExec + weightRevoke = WeightRevoke }, ) @@ -76,14 +73,14 @@ func WeightedOperations( weightMsgGrant, SimulateMsgGrant(ak, bk, k), ), - simulation.NewWeightedOperation( - weightRevoke, - SimulateMsgRevoke(ak, bk, k), - ), simulation.NewWeightedOperation( weightExec, SimulateMsgExec(ak, bk, k, appCdc), ), + simulation.NewWeightedOperation( + weightRevoke, + SimulateMsgRevoke(ak, bk, k), + ), } } @@ -238,43 +235,46 @@ func SimulateMsgExec(ak authz.AccountKeeper, bk authz.BankKeeper, k keeper.Keepe return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "Account not found"), nil, sdkerrors.Wrapf(sdkerrors.ErrNotFound, "granter account not found") } - if targetGrant.Expiration.Before(ctx.BlockHeader().Time) { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "grant expired"), nil, nil - } - - coins := sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(int64(simtypes.RandIntBetween(r, 100, 1000000))))) + granterspendableCoins := bk.SpendableCoins(ctx, granterAddr) + coins := simtypes.RandSubsetCoins(r, granterspendableCoins) // Check send_enabled status of each sent coin denom if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, nil } - if targetGrant.Authorization.TypeUrl == fmt.Sprintf("/%s", proto.MessageName(&banktype.SendAuthorization{})) { - sendAuthorization := targetGrant.GetAuthorization().(*banktype.SendAuthorization) - if sendAuthorization.SpendLimit.IsAllLT(coins) { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "over spend limit"), nil, nil - } + msg := []sdk.Msg{banktype.NewMsgSend(granterAddr, granteeAddr, coins)} + sendAuth, ok := targetGrant.GetAuthorization().(*banktype.SendAuthorization) + if !ok { + return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "not a send authorization"), nil, nil } - granterspendableCoins := bk.SpendableCoins(ctx, granterAddr) - if granterspendableCoins.IsAllLTE(coins) { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "insufficient funds"), nil, nil + if sendAuth.SpendLimit.IsAllLTE(coins) { + return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "over spend limit"), nil, nil } + res, err := sendAuth.Accept(ctx, msg[0]) + if err != nil { + return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err + } + + if !res.Accept { + return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "expired or invalid grant"), nil, nil + } + + msgExec := authz.NewMsgExec(granteeAddr, msg) granteeSpendableCoins := bk.SpendableCoins(ctx, granteeAddr) feeCoins := granteeSpendableCoins.FilterDenoms([]string{sdk.DefaultBondDenom}) fees, err := simtypes.RandomFees(r, ctx, feeCoins) if err != nil { return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "fee error"), nil, err } - - msg := authz.NewMsgExec(granteeAddr, []sdk.Msg{banktype.NewMsgSend(granterAddr, granteeAddr, coins)}) txCfg := simappparams.MakeTestEncodingConfig().TxConfig granteeAcc := ak.GetAccount(ctx, granteeAddr) tx, err := helpers.GenTx( txCfg, - []sdk.Msg{&msg}, + []sdk.Msg{&msgExec}, fees, helpers.DefaultGenTxGas, chainID, @@ -291,10 +291,10 @@ func SimulateMsgExec(ak authz.AccountKeeper, bk authz.BankKeeper, k keeper.Keepe return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err } - err = msg.UnpackInterfaces(cdc) + err = msgExec.UnpackInterfaces(cdc) if err != nil { return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "unmarshal error"), nil, err } - return simtypes.NewOperationMsg(&msg, true, "success", nil), nil, nil + return simtypes.NewOperationMsg(&msgExec, true, "success", nil), nil, nil } } diff --git a/x/authz/simulation/operations_test.go b/x/authz/simulation/operations_test.go index bdb7f98f82db..8ba094d77e6f 100644 --- a/x/authz/simulation/operations_test.go +++ b/x/authz/simulation/operations_test.go @@ -43,7 +43,7 @@ func (suite *SimTestSuite) TestWeightedOperations() { // setup 3 accounts s := rand.NewSource(1) r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) + accs := suite.getTestingAccounts(r, 2) expected := []struct { weight int @@ -51,8 +51,8 @@ func (suite *SimTestSuite) TestWeightedOperations() { opMsgName string }{ {simulation.WeightGrant, authz.ModuleName, simulation.TypeMsgGrant}, - {simulation.WeightRevoke, authz.ModuleName, simulation.TypeMsgRevoke}, {simulation.WeightExec, authz.ModuleName, simulation.TypeMsgExec}, + {simulation.WeightRevoke, authz.ModuleName, simulation.TypeMsgRevoke}, } for i, w := range weightedOps { From 6c6c5c3283576a6b53e27d7a51ecb378dad1291c Mon Sep 17 00:00:00 2001 From: Riccardo Montagnin Date: Tue, 22 Feb 2022 12:03:01 +0100 Subject: [PATCH 2/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> --- 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 | 65 ++++++++++++++++++++++++ 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 ++++ 19 files changed, 218 insertions(+), 12 deletions(-) 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 211b814aa6d7..1be2ff4f5032 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 e8ecde0553b4..3e2ca0b96184 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 722ba38f0ca8..1e0698628b2a 100644 --- a/x/authz/msgs_test.go +++ b/x/authz/msgs_test.go @@ -4,10 +4,13 @@ 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" ) @@ -115,3 +118,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")), + ) + + 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")), + ) + + 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")), + ) + + 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")), + ) + + 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")), + ) +} diff --git a/x/authz/simulation/operations_test.go b/x/authz/simulation/operations_test.go index 8ba094d77e6f..67d603cd28ac 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) @@ -179,7 +179,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 c9a7555506ad..1ef9648c2931 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 63c29eb4eaeb..3be830664bc3 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" @@ -77,7 +76,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 @@ -140,5 +139,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..fc3e28185c7d 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/legacy/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")), + ) + + 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")), + ) +} diff --git a/x/feegrant/simulation/operations_test.go b/x/feegrant/simulation/operations_test.go index 4d7671f77287..542e47842fde 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/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 7c433d7cd50d04e2c71dc056dec5ed336501f16d Mon Sep 17 00:00:00 2001 From: Riccardo Montagnin Date: Wed, 20 Apr 2022 11:27:40 +0200 Subject: [PATCH 3/3] revert: replace all ModuleCdc instances with legacy.Cdc (#11680) Reverts the usage of a singleton `legacy.Cdc` codec while (de)serializing `x/authz` messages. Closes: #11643 --- *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable) --- docs/core/encoding.md | 8 +++---- x/auth/types/codec.go | 10 ++++---- x/auth/vesting/types/codec.go | 14 ++++++++++-- x/auth/vesting/types/msgs.go | 4 ++-- x/authz/codec.go | 6 ++--- x/authz/codec/cdc.go | 18 +++++++++++++++ x/authz/codec/doc.go | 18 +++++++++++++++ x/authz/msgs.go | 8 +++---- x/bank/types/codec.go | 19 +++++----------- x/crisis/types/codec.go | 19 +++++----------- x/distribution/simulation/operations_test.go | 24 ++++++++++++-------- x/distribution/types/codec.go | 19 +++++----------- x/evidence/types/codec.go | 19 +++++----------- x/evidence/types/msgs.go | 1 - x/feegrant/codec.go | 11 +++++---- x/gov/simulation/operations_test.go | 9 +++++--- x/slashing/types/codec.go | 19 +++++----------- x/staking/types/codec.go | 19 +++++----------- x/upgrade/types/codec.go | 18 +++++++++++++++ 19 files changed, 148 insertions(+), 115 deletions(-) create mode 100644 x/authz/codec/cdc.go create mode 100644 x/authz/codec/doc.go diff --git a/docs/core/encoding.md b/docs/core/encoding.md index 355d631da972..2565e579ebd0 100644 --- a/docs/core/encoding.md +++ b/docs/core/encoding.md @@ -73,12 +73,12 @@ Since the `MsgExec` message type can contain different messages instances, it is add the following code inside the `init` method of their module's `codec.go` file: ```go -import "github.com/cosmos/cosmos-sdk/codec/legacy" +import authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" 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) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } ``` diff --git a/x/auth/types/codec.go b/x/auth/types/codec.go index 1c91ee59a9c2..ae1590a616f4 100644 --- a/x/auth/types/codec.go +++ b/x/auth/types/codec.go @@ -2,10 +2,11 @@ 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" "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" ) // RegisterLegacyAminoCodec registers the account interfaces and concrete types on the @@ -46,8 +47,9 @@ var ( func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) + sdk.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) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/auth/vesting/types/codec.go b/x/auth/vesting/types/codec.go index 6a4b795107d8..15845de63f0d 100644 --- a/x/auth/vesting/types/codec.go +++ b/x/auth/vesting/types/codec.go @@ -3,10 +3,12 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" ) // RegisterLegacyAminoCodec registers the vesting interfaces and concrete types on the @@ -58,9 +60,17 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } -var amino = codec.NewLegacyAmino() +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) +) func init() { RegisterLegacyAminoCodec(amino) - amino.Seal() + cryptocodec.RegisterCrypto(amino) + sdk.RegisterLegacyAminoCodec(amino) + + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/auth/vesting/types/msgs.go b/x/auth/vesting/types/msgs.go index 82b038d600ca..7625b7531bba 100644 --- a/x/auth/vesting/types/msgs.go +++ b/x/auth/vesting/types/msgs.go @@ -69,7 +69,7 @@ func (msg MsgCreateVestingAccount) ValidateBasic() error { // GetSignBytes returns the bytes all expected signers must sign over for a // MsgCreateVestingAccount. func (msg MsgCreateVestingAccount) GetSignBytes() []byte { - return sdk.MustSortJSON(amino.MustMarshalJSON(&msg)) + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) } // GetSigners returns the expected signers for a MsgCreateVestingAccount. @@ -112,7 +112,7 @@ func (msg MsgCreateClawbackVestingAccount) GetSigners() []sdk.AccAddress { // GetSignBytes returns the bytes all expected signers must sign over for a // MsgCreateClawbackVestingAccount. func (msg MsgCreateClawbackVestingAccount) GetSignBytes() []byte { - return sdk.MustSortJSON(amino.MustMarshalJSON(&msg)) + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) } // ValidateBasic Implements Msg. diff --git a/x/authz/codec.go b/x/authz/codec.go index f7f4710bd0f5..65e67437049c 100644 --- a/x/authz/codec.go +++ b/x/authz/codec.go @@ -2,10 +2,10 @@ 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" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" ) // RegisterLegacyAminoCodec registers the necessary x/authz interfaces and concrete types @@ -36,7 +36,7 @@ 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 + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be // used to properly serialize MsgGrant and MsgExec instances - RegisterLegacyAminoCodec(legacy.Cdc) + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/authz/codec/cdc.go b/x/authz/codec/cdc.go new file mode 100644 index 000000000000..520e435afd69 --- /dev/null +++ b/x/authz/codec/cdc.go @@ -0,0 +1,18 @@ +package codec + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + Amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(Amino) +) + +func init() { + cryptocodec.RegisterCrypto(Amino) + codec.RegisterEvidences(Amino) + sdk.RegisterLegacyAminoCodec(Amino) +} diff --git a/x/authz/codec/doc.go b/x/authz/codec/doc.go new file mode 100644 index 000000000000..ecc365a2211b --- /dev/null +++ b/x/authz/codec/doc.go @@ -0,0 +1,18 @@ +/* +Package codec provides a singleton instance of Amino codec that should be used to register +any concrete type that can later be referenced inside a MsgGrant or MsgExec instance so that they +can be (de)serialized properly. + +Amino types should be ideally registered inside this codec within the init function of each module's +codec.go file as follows: + +func init() { + // ... + + RegisterLegacyAminoCodec(authzcodec.Amino) +} + +The codec instance is put inside this package and not the x/authz package in order to avoid any dependency cycle. + +*/ +package codec diff --git a/x/authz/msgs.go b/x/authz/msgs.go index 3e2ca0b96184..de47c2bc29f2 100644 --- a/x/authz/msgs.go +++ b/x/authz/msgs.go @@ -1,7 +1,7 @@ package authz import ( - "github.com/cosmos/cosmos-sdk/codec/legacy" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" "time" "github.com/gogo/protobuf/proto" @@ -79,7 +79,7 @@ func (msg MsgGrant) Route() string { // GetSignBytes implements the LegacyMsg.GetSignBytes method. func (msg MsgGrant) GetSignBytes() []byte { - return sdk.MustSortJSON(legacy.Cdc.MustMarshalJSON(&msg)) + return sdk.MustSortJSON(authzcodec.ModuleCdc.MustMarshalJSON(&msg)) } // GetAuthorization returns the cache value from the MsgGrant.Authorization if present. @@ -172,7 +172,7 @@ func (msg MsgRevoke) Route() string { // GetSignBytes implements the LegacyMsg.GetSignBytes method. func (msg MsgRevoke) GetSignBytes() []byte { - return sdk.MustSortJSON(legacy.Cdc.MustMarshalJSON(&msg)) + return sdk.MustSortJSON(authzcodec.ModuleCdc.MustMarshalJSON(&msg)) } // NewMsgExec creates a new MsgExecAuthorized @@ -243,5 +243,5 @@ func (msg MsgExec) Route() string { // GetSignBytes implements the LegacyMsg.GetSignBytes method. func (msg MsgExec) GetSignBytes() []byte { - return sdk.MustSortJSON(legacy.Cdc.MustMarshalJSON(&msg)) + return sdk.MustSortJSON(authzcodec.ModuleCdc.MustMarshalJSON(&msg)) } diff --git a/x/bank/types/codec.go b/x/bank/types/codec.go index 62e6b4fe1568..a29b48643515 100644 --- a/x/bank/types/codec.go +++ b/x/bank/types/codec.go @@ -2,12 +2,12 @@ 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" "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/x/authz" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" ) // RegisterLegacyAminoCodec registers the necessary x/bank interfaces and concrete types @@ -32,23 +32,16 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { } var ( - amino = codec.NewLegacyAmino() - - // ModuleCdc references the global x/bank 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/staking and - // defined at the application level. + amino = codec.NewLegacyAmino() ModuleCdc = codec.NewAminoCodec(amino) ) func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) - amino.Seal() + sdk.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) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/crisis/types/codec.go b/x/crisis/types/codec.go index 67e32f4cee53..abf1c2c1a6d6 100644 --- a/x/crisis/types/codec.go +++ b/x/crisis/types/codec.go @@ -2,11 +2,11 @@ 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" "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" ) // RegisterLegacyAminoCodec registers the necessary x/crisis interfaces and concrete types @@ -24,23 +24,16 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { } var ( - amino = codec.NewLegacyAmino() - - // ModuleCdc references the global x/crisis 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/crisis and - // defined at the application level. + amino = codec.NewLegacyAmino() ModuleCdc = codec.NewAminoCodec(amino) ) func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) - amino.Seal() + sdk.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) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/distribution/simulation/operations_test.go b/x/distribution/simulation/operations_test.go index 33b59a53cca9..f3cf3f0a405d 100644 --- a/x/distribution/simulation/operations_test.go +++ b/x/distribution/simulation/operations_test.go @@ -166,16 +166,20 @@ func (suite *SimTestSuite) testSimulateMsgWithdrawValidatorCommission(tokenName // execute operation op := simulation.SimulateMsgWithdrawValidatorCommission(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.DistrKeeper, suite.app.StakingKeeper) operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg types.MsgWithdrawValidatorCommission - types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) - - suite.Require().True(operationMsg.OK) - suite.Require().Equal("cosmosvaloper1tnh2q55v8wyygtt9srz5safamzdengsn9dsd7z", msg.ValidatorAddress) - suite.Require().Equal(types.TypeMsgWithdrawValidatorCommission, msg.Type()) - suite.Require().Equal(types.ModuleName, msg.Route()) - suite.Require().Len(futureOperations, 0) + if !operationMsg.OK { + suite.Require().Equal("could not find account", operationMsg.Comment) + } else { + suite.Require().NoError(err) + + var msg types.MsgWithdrawValidatorCommission + types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + + suite.Require().True(operationMsg.OK) + suite.Require().Equal("cosmosvaloper1tnh2q55v8wyygtt9srz5safamzdengsn9dsd7z", msg.ValidatorAddress) + suite.Require().Equal(types.TypeMsgWithdrawValidatorCommission, msg.Type()) + suite.Require().Equal(types.ModuleName, msg.Route()) + suite.Require().Len(futureOperations, 0) + } } // TestSimulateMsgFundCommunityPool tests the normal scenario of a valid message of type TypeMsgFundCommunityPool. diff --git a/x/distribution/types/codec.go b/x/distribution/types/codec.go index a4a5d480d1d8..22bf22ce1c58 100644 --- a/x/distribution/types/codec.go +++ b/x/distribution/types/codec.go @@ -2,11 +2,11 @@ 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" "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -37,23 +37,16 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { } var ( - amino = codec.NewLegacyAmino() - - // ModuleCdc references the global x/distribution 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/distribution and - // defined at the application level. + amino = codec.NewLegacyAmino() ModuleCdc = codec.NewAminoCodec(amino) ) func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) - amino.Seal() + sdk.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) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/evidence/types/codec.go b/x/evidence/types/codec.go index 45644588b43b..2dea1c40206c 100644 --- a/x/evidence/types/codec.go +++ b/x/evidence/types/codec.go @@ -2,11 +2,11 @@ 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" "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" "github.com/cosmos/cosmos-sdk/x/evidence/exported" ) @@ -30,23 +30,16 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { } var ( - amino = codec.NewLegacyAmino() - - // ModuleCdc references the global x/evidence 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/evidence and - // defined at the application level. + amino = codec.NewLegacyAmino() ModuleCdc = codec.NewAminoCodec(amino) ) func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) - amino.Seal() + sdk.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) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/evidence/types/msgs.go b/x/evidence/types/msgs.go index cd2e2ba0321d..f1a57ca76f16 100644 --- a/x/evidence/types/msgs.go +++ b/x/evidence/types/msgs.go @@ -2,7 +2,6 @@ package types import ( "fmt" - "github.com/gogo/protobuf/proto" "github.com/cosmos/cosmos-sdk/codec/types" diff --git a/x/feegrant/codec.go b/x/feegrant/codec.go index aebd654399d2..1b6669673d07 100644 --- a/x/feegrant/codec.go +++ b/x/feegrant/codec.go @@ -2,10 +2,11 @@ package feegrant 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" "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" ) // RegisterLegacyAminoCodec registers the necessary x/feegrant interfaces and concrete types @@ -52,8 +53,10 @@ var ( func init() { RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + sdk.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) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/gov/simulation/operations_test.go b/x/gov/simulation/operations_test.go index 6a5252dc3785..19d7e17c1327 100644 --- a/x/gov/simulation/operations_test.go +++ b/x/gov/simulation/operations_test.go @@ -113,7 +113,8 @@ func TestSimulateMsgSubmitProposal(t *testing.T) { require.NoError(t, err) var msg types.MsgSubmitProposal - types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + require.NoError(t, err) require.True(t, operationMsg.OK) require.Equal(t, "cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.Proposer) @@ -156,7 +157,8 @@ func TestSimulateMsgDeposit(t *testing.T) { require.NoError(t, err) var msg types.MsgDeposit - types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + require.NoError(t, err) require.True(t, operationMsg.OK) require.Equal(t, uint64(1), msg.ProposalId) @@ -198,7 +200,8 @@ func TestSimulateMsgVote(t *testing.T) { require.NoError(t, err) var msg types.MsgVote - types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + require.NoError(t, err) require.True(t, operationMsg.OK) require.Equal(t, uint64(1), msg.ProposalId) diff --git a/x/slashing/types/codec.go b/x/slashing/types/codec.go index d56869d38088..dd6cfb345267 100644 --- a/x/slashing/types/codec.go +++ b/x/slashing/types/codec.go @@ -2,11 +2,11 @@ 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" "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" ) // RegisterLegacyAminoCodec registers concrete types on LegacyAmino codec @@ -23,23 +23,16 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { } var ( - amino = codec.NewLegacyAmino() - - // ModuleCdc references the global x/slashing 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/slashing and - // defined at the application level. + amino = codec.NewLegacyAmino() ModuleCdc = codec.NewAminoCodec(amino) ) func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) - amino.Seal() + sdk.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) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/staking/types/codec.go b/x/staking/types/codec.go index 5b95b543650e..4970eea73558 100644 --- a/x/staking/types/codec.go +++ b/x/staking/types/codec.go @@ -2,12 +2,12 @@ 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" "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/x/authz" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" ) // RegisterLegacyAminoCodec registers the necessary x/staking interfaces and concrete types @@ -43,23 +43,16 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { } var ( - amino = codec.NewLegacyAmino() - - // ModuleCdc references the global x/staking 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/staking and - // defined at the application level. + amino = codec.NewLegacyAmino() ModuleCdc = codec.NewAminoCodec(amino) ) func init() { RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) - amino.Seal() + sdk.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) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) } diff --git a/x/upgrade/types/codec.go b/x/upgrade/types/codec.go index 59703f57a8f9..96fc3848eb60 100644 --- a/x/upgrade/types/codec.go +++ b/x/upgrade/types/codec.go @@ -3,6 +3,9 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -20,3 +23,18 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { &CancelSoftwareUpgradeProposal{}, ) } + +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + sdk.RegisterLegacyAminoCodec(amino) + + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) +}