Skip to content

Commit

Permalink
feat: create new grantee, if it doesn't exist (#10703)
Browse files Browse the repository at this point in the history
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->

## Description
If the grantee of an authorization doesn't exist, create a new account.

Closes: #10590 

<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->

---

### Author Checklist

*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

### Reviewers Checklist

*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)
  • Loading branch information
likhita-809 committed Dec 10, 2021
1 parent f7f1b86 commit fec3577
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

* [\#10703](https://github.com/cosmos/cosmos-sdk/pull/10703) Create a new grantee account, if the grantee of an authorization does not exist.
* [\#10592](https://github.com/cosmos/cosmos-sdk/pull/10592) Add a `DecApproxEq` function that checks to see if `|d1 - d2| < tol` for some Dec `d1, d2, tol`.
* [\#10393](https://github.com/cosmos/cosmos-sdk/pull/10393) Add `HasSupply` method to bank keeper to ensure that input denom actually exists on chain.
* [\#9933](https://github.com/cosmos/cosmos-sdk/pull/9933) Introduces the notion of a Cosmos "Scalar" type, which would just be simple aliases that give human-understandable meaning to the underlying type, both in Go code and in Proto definitions.
Expand Down
2 changes: 1 addition & 1 deletion simapp/app.go
Expand Up @@ -285,7 +285,7 @@ func NewSimApp(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)

app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.msgSvcRouter)
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.msgSvcRouter, app.AccountKeeper)

// register the proposal types
govRouter := govtypes.NewRouter()
Expand Down
6 changes: 3 additions & 3 deletions x/authz/client/testutil/grpc.go
Expand Up @@ -193,14 +193,14 @@ func (s *IntegrationTestSuite) TestQueryGranterGrantsGRPC() {
fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/%s", val.APIAddress, val.Address.String()),
false,
"",
6,
7,
},
{
"valid query: expect two grants",
"valid query: expect seven grants",
fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/%s", val.APIAddress, val.Address.String()),
false,
"",
6,
7,
},
}
for _, tc := range testCases {
Expand Down
2 changes: 1 addition & 1 deletion x/authz/client/testutil/query.go
Expand Up @@ -221,7 +221,7 @@ func (s *IntegrationTestSuite) TestQueryGranterGrants() {
},
false,
"",
6,
7,
},
{
"valid case with pagination",
Expand Down
51 changes: 48 additions & 3 deletions x/authz/client/testutil/tx.go
Expand Up @@ -43,7 +43,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.Require().NoError(err)

val := s.network.Validators[0]
s.grantee = make([]sdk.AccAddress, 2)
s.grantee = make([]sdk.AccAddress, 3)

// Send some funds to the new account.
// Create new account in the keyring.
Expand Down Expand Up @@ -79,6 +79,31 @@ func (s *IntegrationTestSuite) SetupSuite() {

_, err = s.network.WaitForHeight(1)
s.Require().NoError(err)

// Create new account in the keyring.
s.grantee[2] = s.createAccount("grantee3")

// grant send authorization to grantee3
out, err = ExecGrant(val, []string{
s.grantee[2].String(),
"send",
fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()),
})
s.Require().NoError(err)

err = s.network.WaitForNextBlock()
s.Require().NoError(err)

var response sdk.TxResponse
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
s.Require().Equal(int(response.Code), 0)
s.Require().NotEqual(int(response.Height), 0)

}

func (s *IntegrationTestSuite) createAccount(uid string) sdk.AccAddress {
Expand Down Expand Up @@ -631,6 +656,7 @@ func (s *IntegrationTestSuite) TestNewExecGenericAuthorized() {
func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() {
val := s.network.Validators[0]
grantee := s.grantee[0]
grantee1 := s.grantee[2]
twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()

_, err := ExecGrant(
Expand Down Expand Up @@ -667,6 +693,7 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() {
args []string
expectedCode uint32
expectErr bool
expectErrMsg string
}{
{
"valid txn",
Expand All @@ -679,6 +706,20 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() {
},
0,
false,
"",
},
{
"error over grantee doesn't exist on chain",
[]string{
execMsg.Name(),
fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee1.String()),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
},
0,
true,
"insufficient funds", // earlier the error was account not found here.
},
{
"error over spent",
Expand All @@ -691,6 +732,7 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() {
},
4,
false,
"",
},
}

Expand All @@ -701,10 +743,13 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() {
clientCtx := val.ClientCtx

out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
var response sdk.TxResponse
if tc.expectErrMsg != "" {
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
s.Require().Contains(response.RawLog, tc.expectErrMsg)
} else if tc.expectErr {
s.Require().Error(err)
} else {
var response sdk.TxResponse
s.Require().NoError(err)
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
s.Require().Equal(tc.expectedCode, response.Code, out.String())
Expand Down
17 changes: 10 additions & 7 deletions x/authz/keeper/keeper.go
Expand Up @@ -13,22 +13,25 @@ import (
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
"github.com/cosmos/cosmos-sdk/x/authz"
)

type Keeper struct {
storeKey storetypes.StoreKey
cdc codec.BinaryCodec
router *middleware.MsgServiceRouter
storeKey storetypes.StoreKey
cdc codec.BinaryCodec
router *middleware.MsgServiceRouter
authKeeper authkeeper.AccountKeeper
}

// NewKeeper constructs a message authorization Keeper
func NewKeeper(storeKey storetypes.StoreKey, cdc codec.BinaryCodec, router *middleware.MsgServiceRouter) Keeper {
func NewKeeper(storeKey storetypes.StoreKey, cdc codec.BinaryCodec, router *middleware.MsgServiceRouter, ak authkeeper.AccountKeeper) Keeper {
return Keeper{
storeKey: storeKey,
cdc: cdc,
router: router,
storeKey: storeKey,
cdc: cdc,
router: router,
authKeeper: ak,
}
}

Expand Down
7 changes: 7 additions & 0 deletions x/authz/keeper/msg_server.go
Expand Up @@ -17,6 +17,13 @@ func (k Keeper) Grant(goCtx context.Context, msg *authz.MsgGrant) (*authz.MsgGra
if err != nil {
return nil, err
}
// create the account if it is not in account state
granteeAcc := k.authKeeper.GetAccount(ctx, grantee)
if granteeAcc == nil {
granteeAcc = k.authKeeper.NewAccountWithAddress(ctx, grantee)
k.authKeeper.SetAccount(ctx, granteeAcc)
}

granter, err := sdk.AccAddressFromBech32(msg.Granter)
if err != nil {
return nil, err
Expand Down

0 comments on commit fec3577

Please sign in to comment.