diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d3c0a11144..f11371c63493 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Features + +* (x/authz) [#13047](https://github.com/cosmos/cosmos-sdk/pull/13047) Add a GetAuthorization function to the keeper. + ### Bug Fixes * (export) [#13029](https://github.com/cosmos/cosmos-sdk/pull/13029) Fix exporting the blockParams regression. 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..fdf8d5d08135 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -45,7 +45,7 @@ func (s *TestSuite) SetupTest() { s.app = app s.ctx = ctx s.queryClient = queryClient - s.addrs = simapp.AddTestAddrsIncremental(app, ctx, 3, sdk.NewInt(30000000)) + s.addrs = simapp.AddTestAddrsIncremental(app, ctx, 7, sdk.NewInt(30000000)) } func (s *TestSuite) TestKeeper() { @@ -366,6 +366,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) + + 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.app.AuthzKeeper.SaveGrant(s.ctx, addr1, addr2, genAuthMulti, nil), "creating grant 1->2") + s.Require().NoError(s.app.AuthzKeeper.SaveGrant(s.ctx, addr1, addr3, genAuthSend, &expired), "creating grant 1->3") + s.Require().NoError(s.app.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.app.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)) }