From 3849e5da6a07d8be6fcbae747073dc528511dedf Mon Sep 17 00:00:00 2001 From: Daniel Wedul Date: Thu, 25 Aug 2022 13:17:46 -0600 Subject: [PATCH] feat(x/authz): Add the GetAuthorization function. (#13047) * [13027]: Create the GetAuthorization function (in the authz module). * [13027]: Add unit tests for the new GetAuthorization function. * [13027]: Add changelog entry. (cherry picked from commit 5e4651ecafe3f85d6f2efa54fecf15e3989ad71d) # Conflicts: # CHANGELOG.md # x/authz/keeper/keeper_test.go --- CHANGELOG.md | 7 +++ x/authz/keeper/keeper.go | 19 ++++++ x/authz/keeper/keeper_test.go | 109 ++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d3c0a11144..0a3feb01594c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,10 +39,17 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +<<<<<<< HEAD * (export) [#13029](https://github.com/cosmos/cosmos-sdk/pull/13029) Fix exporting the blockParams regression. * [#13046](https://github.com/cosmos/cosmos-sdk/pull/13046) Fix missing return statement in BaseApp.Query. ## [v0.46.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.1) - 2022-08-24 +======= +* (x/authz) [#12648](https://github.com/cosmos/cosmos-sdk/pull/12648) Add an allow list, an optional list of addresses allowed to receive bank assests via authz MsgSend grant. +* (sdk.Coins) [#12627](https://github.com/cosmos/cosmos-sdk/pull/12627) Make a Denoms method on sdk.Coins. +* (testutil) [#12973](https://github.com/cosmos/cosmos-sdk/pull/12973) Add generic `testutil.RandSliceElem` function which selects a random element from the list. +* (x/authz) [#13047](https://github.com/cosmos/cosmos-sdk/pull/13047) Add a GetAuthorization function to the keeper. +>>>>>>> 5e4651eca (feat(x/authz): Add the GetAuthorization function. (#13047)) ### Improvements diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go index 3711f4a1fc4f..6ed19f42cccd 100644 --- a/x/authz/keeper/keeper.go +++ b/x/authz/keeper/keeper.go @@ -251,6 +251,25 @@ func (k Keeper) GetAuthorizations(ctx sdk.Context, grantee sdk.AccAddress, grant return authorizations, nil } +// GetAuthorization returns an Authorization and it's expiration time. +// A nil Authorization is returned under the following circumstances: +// - No grant is found. +// - A grant is found, but it is expired. +// - There was an error getting the authorization from the grant. +func (k Keeper) GetAuthorization(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) (authz.Authorization, *time.Time) { + grant, found := k.getGrant(ctx, grantStoreKey(grantee, granter, msgType)) + if !found || (grant.Expiration != nil && grant.Expiration.Before(ctx.BlockHeader().Time)) { + return nil, nil + } + + auth, err := grant.GetAuthorization() + if err != nil { + return nil, nil + } + + return auth, grant.Expiration +} + // IterateGrants iterates over all authorization grants // This function should be used with caution because it can involve significant IO operations. // It should not be used in query or msg services without charging additional gas. diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 645aab5dfd25..d3058506362b 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -33,12 +33,42 @@ type TestSuite struct { } func (s *TestSuite) SetupTest() { +<<<<<<< HEAD app := simapp.Setup(s.T(), false) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) now := tmtime.Now() ctx = ctx.WithBlockHeader(tmproto.Header{Time: now}) queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) authz.RegisterQueryServer(queryHelper, app.AuthzKeeper) +======= + key := sdk.NewKVStoreKey(authzkeeper.StoreKey) + testCtx := testutil.DefaultContextWithDB(s.T(), key, sdk.NewTransientStoreKey("transient_test")) + s.ctx = testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: tmtime.Now()}) + s.encCfg = moduletestutil.MakeTestEncodingConfig(authzmodule.AppModuleBasic{}) + + s.baseApp = baseapp.NewBaseApp( + "authz", + log.NewNopLogger(), + testCtx.DB, + s.encCfg.TxConfig.TxDecoder(), + ) + s.baseApp.SetCMS(testCtx.CMS) + s.baseApp.SetInterfaceRegistry(s.encCfg.InterfaceRegistry) + + s.addrs = simtestutil.CreateIncrementalAccounts(7) + + // gomock initializations + ctrl := gomock.NewController(s.T()) + s.accountKeeper = authztestutil.NewMockAccountKeeper(ctrl) + s.bankKeeper = authztestutil.NewMockBankKeeper(ctrl) + banktypes.RegisterInterfaces(s.encCfg.InterfaceRegistry) + banktypes.RegisterMsgServer(s.baseApp.MsgServiceRouter(), s.bankKeeper) + + s.authzKeeper = authzkeeper.NewKeeper(key, s.encCfg.Codec, s.baseApp.MsgServiceRouter(), s.accountKeeper) + + queryHelper := baseapp.NewQueryServerTestHelper(s.ctx, s.encCfg.InterfaceRegistry) + authz.RegisterQueryServer(queryHelper, s.authzKeeper) +>>>>>>> 5e4651eca (feat(x/authz): Add the GetAuthorization function. (#13047)) queryClient := authz.NewQueryClient(queryHelper) s.queryClient = queryClient @@ -366,6 +396,85 @@ func (s *TestSuite) TestDequeueAllGrantsQueue() { require.Len(authzs, 1) } +func (s *TestSuite) TestGetAuthorization() { + addr1 := s.addrs[3] + addr2 := s.addrs[4] + addr3 := s.addrs[5] + addr4 := s.addrs[6] + + genAuthMulti := authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktypes.MsgMultiSend{})) + genAuthSend := authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktypes.MsgSend{})) + sendAuth := banktypes.NewSendAuthorization(coins10, nil) + + start := s.ctx.BlockHeader().Time + expired := start.Add(time.Duration(1) * time.Second) + notExpired := start.Add(time.Duration(5) * time.Hour) + + s.Require().NoError(s.authzKeeper.SaveGrant(s.ctx, addr1, addr2, genAuthMulti, nil), "creating grant 1->2") + s.Require().NoError(s.authzKeeper.SaveGrant(s.ctx, addr1, addr3, genAuthSend, &expired), "creating grant 1->3") + s.Require().NoError(s.authzKeeper.SaveGrant(s.ctx, addr1, addr4, sendAuth, ¬Expired), "creating grant 1->4") + // Without access to private keeper methods, I don't know how to save a grant with an invalid authorization. + newCtx := s.ctx.WithBlockTime(start.Add(time.Duration(1) * time.Minute)) + + tests := []struct { + name string + grantee sdk.AccAddress + granter sdk.AccAddress + msgType string + expAuth authz.Authorization + expExp *time.Time + }{ + { + name: "grant has nil exp and is returned", + grantee: addr1, + granter: addr2, + msgType: genAuthMulti.MsgTypeURL(), + expAuth: genAuthMulti, + expExp: nil, + }, + { + name: "grant is expired not returned", + grantee: addr1, + granter: addr3, + msgType: genAuthSend.MsgTypeURL(), + expAuth: nil, + expExp: nil, + }, + { + name: "grant is not expired and is returned", + grantee: addr1, + granter: addr4, + msgType: sendAuth.MsgTypeURL(), + expAuth: sendAuth, + expExp: ¬Expired, + }, + { + name: "grant is not expired but wrong msg type returns nil", + grantee: addr1, + granter: addr4, + msgType: genAuthMulti.MsgTypeURL(), + expAuth: nil, + expExp: nil, + }, + { + name: "no grant exists between the two", + grantee: addr2, + granter: addr3, + msgType: genAuthSend.MsgTypeURL(), + expAuth: nil, + expExp: nil, + }, + } + + for _, tc := range tests { + s.Run(tc.name, func() { + actAuth, actExp := s.authzKeeper.GetAuthorization(newCtx, tc.grantee, tc.granter, tc.msgType) + s.Assert().Equal(tc.expAuth, actAuth, "authorization") + s.Assert().Equal(tc.expExp, actExp, "expiration") + }) + } +} + func TestTestSuite(t *testing.T) { suite.Run(t, new(TestSuite)) }