Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authorization logic of staking module: panic when handling amounts greater than authorized #11478

Closed
4 tasks
ivan-gavran opened this issue Mar 28, 2022 · 4 comments · Fixed by #11512
Closed
4 tasks

Comments

@ivan-gavran
Copy link
Contributor

ivan-gavran commented Mar 28, 2022

Summary of Bug

The Accept function of staking modules's authz.go file checks whether the amount to delegate is covered by the authorization. It does so by calling the Sub function (line 106). This function will panic if the resulting amount is negative.

This is in contrast to how a similar check in the bank module handles the same situation: there, the SafeSub function is called, and the ErrInsusfficientFunds is returned if the amount is negative.

Wouldn't it be better if both modules were handling this situation in the same way? I believe that returning an error would be the way to go (but perhaps I am missing some context).

I ran into this issue when working on model-based testing of authz, generating tests covering the situation in which insufficient grant was provided for an execution.

Version

master (commit: 5491be2)


For Admin Use

  • Not duplicate issue
  • Appropriate labels applied
  • Appropriate contributors tagged
  • Contributor assigned/self-assigned
@atheeshp atheeshp mentioned this issue Mar 31, 2022
19 tasks
@mergify mergify bot closed this as completed in #11512 Apr 4, 2022
mergify bot pushed a commit that referenced this issue Apr 4, 2022
## Description

Closes: #11478



---

### 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)
@ivan-gavran
Copy link
Contributor Author

hi, @atheeshp ! I just noticed that the issue was closed by a recent commit: could you please give some context? From what I can read from the commit, the panicking is removed by using SafeSub, so the banks's way was the right approach?

Furthermore, the SafeSub was used in the commit, but not to calculate the final amount (instead, SafeSub was used to check for errors, and then followed by Sub if there is none). Why is that?

@atheeshp
Copy link
Contributor

atheeshp commented Apr 5, 2022

hi, @atheeshp ! I just noticed that the issue was closed by a recent commit: could you please give some context? From what I can read from the commit, the panicking is removed by using SafeSub, so the banks's way was the right approach?

Furthermore, the SafeSub was used in the commit, but not to calculate the final amount (instead, SafeSub was used to check for errors, and then followed by Sub if there is none). Why is that?

we have SafeSub method for sdk.Coins, but in authz sdk.Coin is being used at a.MaxTokens, there is no SafeSub method for sdk.Coin. because of that I've converted a.MaxTokens (which is sdk.Coin) to sdk.Coins to use SafeSub method here.

// check sufficient balance exists.
if _, isNegative := sdk.NewCoins(*a.MaxTokens).SafeSub(sdk.NewCoins(amount)); isNegative {
return authz.AcceptResponse{}, sdkerrors.ErrInsufficientFunds.Wrapf("amount is more than max tokens")
}

@ivan-gavran
Copy link
Contributor Author

cool, thanks for the explanation!

@dalmirel
Copy link

dalmirel commented Apr 7, 2022

Hello @atheeshp ! When you find some time, could you please explain is there some particular reason why SafeSub func could not be implemented for sdk.Coin in order for you to skip the conversion to sdk.Coins here?
(I assume you just did not want to introduce changes to other packages...)

It looks to me, that introducting SafeSub for sdk.Coin could be used in a same way as SafeSub for sdk.Coins:

cosmos-sdk/types/coin.go

Lines 386 to 393 in 8800d2e

func (coins Coins) Sub(coinsB Coins) Coins {
diff, hasNeg := coins.SafeSub(coinsB)
if hasNeg {
panic("negative coin amount")
}
return diff
}

That is: for sdk.Coin SafeSub could be called from Sub func and if it returns true for negative coin value result
the Sub function could panic or the result of subtraction would be returned.
This new, one function could be called from authz.go instead of both conversion and:

limitLeft := a.MaxTokens.Sub(amount)

and you could gain the necessary information for returning ErrInsufficientFunds err and the limitLeft with one function call.

Since I will be working on model-based testing of authz module as well, but I'm also doing some code inspection for possible improvements, every information could be useful.

Thanks in advance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants