feat: create new grantee, if it doesn't exist (#10703)

<!--
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)
This commit is contained in:
likhita-809 2021-12-10 10:19:39 +05:30 committed by GitHub
parent f7f1b86506
commit fec35777f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 15 deletions

View File

@ -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.

View File

@ -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()

View File

@ -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 {

View File

@ -221,7 +221,7 @@ func (s *IntegrationTestSuite) TestQueryGranterGrants() {
},
false,
"",
6,
7,
},
{
"valid case with pagination",

View File

@ -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.
@ -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 {
@ -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(
@ -667,6 +693,7 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() {
args []string
expectedCode uint32
expectErr bool
expectErrMsg string
}{
{
"valid txn",
@ -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",
@ -691,6 +732,7 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() {
},
4,
false,
"",
},
}
@ -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())

View File

@ -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,
}
}

View File

@ -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