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:
parent
f7f1b86506
commit
fec35777f9
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -221,7 +221,7 @@ func (s *IntegrationTestSuite) TestQueryGranterGrants() {
|
|||
},
|
||||
false,
|
||||
"",
|
||||
6,
|
||||
7,
|
||||
},
|
||||
{
|
||||
"valid case with pagination",
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue