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

R4R: Make coins denoms case insensitive #3092

Merged
merged 5 commits into from
Dec 18, 2018

Conversation

alessio
Copy link
Contributor

@alessio alessio commented Dec 12, 2018

Closes: #3064

  • Linked to github-issue with discussion and accepted design OR link to spec that describes this work.
  • Wrote tests
  • Updated relevant documentation (docs/)
  • Added entries in PENDING.md with issue #
  • rereviewed Files changed in the github PR explorer

For Admin Use:

  • Added appropriate labels to PR (ex. wip, ready-for-review, docs)
  • Reviewers Assigned
  • Squashed all commits, uses message "Merge pull request #XYZ: [title]" (coding standards)

@codecov
Copy link

codecov bot commented Dec 12, 2018

Codecov Report

Merging #3092 into develop will increase coverage by 0.02%.
The diff coverage is 0%.

@@             Coverage Diff             @@
##           develop    #3092      +/-   ##
===========================================
+ Coverage    55.01%   55.04%   +0.02%     
===========================================
  Files          133      133              
  Lines         9435     9434       -1     
===========================================
+ Hits          5191     5193       +2     
+ Misses        3927     3924       -3     
  Partials       317      317

@alessio alessio requested a review from jaekwon December 12, 2018 18:13
Copy link
Contributor

@alexanderbez alexanderbez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good but I agree that I think it should be lowercase.

Copy link
Contributor

@cwgoes cwgoes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should do any runtime conversion - that's unnecessary and a waste of compute - but validating genesis / CLI / REST input for only-uppercase or only-lowercase makes sense.

@alessio
Copy link
Contributor Author

alessio commented Dec 13, 2018

@fedekunze @jackzampolin @alexanderbez

@rigelrozanski dixit:

I agree that it makes sense to prevent the either lowercase or uppercase - I guess making it all caps makes sense as tokens are usually listed as all caps

I agree with Rigel here - yet I'm open to change it lowercase if we reach a wider consensus

@alessio
Copy link
Contributor Author

alessio commented Dec 13, 2018

@cwgoes the safest way to do this is to normalize the denom on NewCoin() call. AmountOf() could assume that denom is already uppercase though, even though I don't really believe that a single call to ToUpper() will have such a big impact. Thoughts?

@alessio
Copy link
Contributor Author

alessio commented Dec 13, 2018

Furthermore, IMHO denom should never be empty. Thoughts on that?

@cwgoes
Copy link
Contributor

cwgoes commented Dec 13, 2018

the safest way to do this is to normalize the denom on NewCoin() call

Unfortunately, I think we don't use NewCoin uniformly - we also use sdk.Coin{} (maybe we could lint for that). Even if we did, I don't think we should implement this style of fix. It's not too expensive, you're right, but I would still prefer to fix other parts of our code instead of performing conversion at runtime - the latter costs us forever long-term, where the former just requires that we find the occurrences of incorrect capitalization now.

What would be fine, I think, is for NewCoin (and AmountOf) to panic upon receiving an uppercase denom - what do you think about that? That should help find any miscreant callers.

@alessio
Copy link
Contributor Author

alessio commented Dec 13, 2018

@cwgoes

What would be fine, I think, is for NewCoin (and AmountOf) to panic upon receiving an uppercase denom - what do you think about that? That should help find any miscreant callers.

I like that 👍

@alessio
Copy link
Contributor Author

alessio commented Dec 13, 2018

@cwgoes amended, please review

@jackzampolin
Copy link
Member

jackzampolin commented Dec 13, 2018

I like this idea:

Unfortunately, I think we don't use NewCoin uniformly - we also use sdk.Coin{} (maybe we could lint for that).

Grepping through the code revels that we aren't using sdk.Coin{} in many places at all. Mainly in []sdk.Coin{sdk.NewCoin()} calls.

@alessio alessio force-pushed the alessio/3064-case-insensitive-coins branch from 160ca1e to d932fdb Compare December 13, 2018 19:50
@alessio
Copy link
Contributor Author

alessio commented Dec 13, 2018

Unfortunately, I think we don't use NewCoin uniformly

alessio@bangalter:~/.../cosmos/cosmos-sdk$ grep -rw 'Coin{' 
types/coin_test.go:		{NewInt64Coin("a", 1), NewInt64Coin("a", 5), Coin{}, true},
types/coin.go:	return Coin{
types/coin.go:		res = append(res, Coin{
types/coin.go:		return Coin{}, fmt.Errorf("invalid coin expression: %s", coinStr)
types/coin.go:		return Coin{}, fmt.Errorf("failed to parse coin amount: %s", amountStr)
types/coin.go:		return Coin{}, fmt.Errorf("denom cannot contain upper case characters: %s", denomStr)
x/auth/client/txbuilder/txbuilder.go:	fee := sdk.Coin{}

@alessio
Copy link
Contributor Author

alessio commented Dec 14, 2018

@cwgoes amended as requested. Please review

@cwgoes cwgoes self-assigned this Dec 14, 2018
Copy link
Contributor

@cwgoes cwgoes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more requested change. Note also I think we'll need to sanitize input wherever we accept sdk.Coins directly in user-input messages (mostly in x/bank) to ensure maliciously crafted mixed-case denoms can't cause panics or unusual behaviour.

types/coin.go Outdated
@@ -320,13 +323,14 @@ func (coins Coins) Empty() bool {

// Returns the amount of a denom from coins
func (coins Coins) AmountOf(denom string) Int {
lowercaseDenom := strings.ToLower(denom)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this function, can we also check the case like we do on line 464? I think that would be preferable to just converting to lowercase - we should be enforcing that all "denoms" are lowercase.

Copy link
Contributor Author

@alessio alessio Dec 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AmountOf at the moment is just converting denom to lowercase and process it (basically implementing real case insensitivity). I couldn't quite get what you would like to see instead - maybe you would prefer AmountOf to panic if a non-all-lowcase string is encountered?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly (instead of converting). Just want to ensure we don't accidentally have mixed-case somewhere in our code, which is implicitly converted in AmountOf - better to panic (and find such places if they exist).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amended @cwgoes, please review

@alessio alessio force-pushed the alessio/3064-case-insensitive-coins branch from 5192b4c to e5667f0 Compare December 16, 2018 19:10
@cwgoes
Copy link
Contributor

cwgoes commented Dec 17, 2018

Your changes look fine but now many tests seem to fail - are we panicking because of non-lowercase denominations somewhere?

@alessio
Copy link
Contributor Author

alessio commented Dec 17, 2018

@cwgoes no, I needed to merge develop in

Copy link
Contributor

@cwgoes cwgoes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested ACK

A reminder that we'll need to keep in mind the necessity of sanitizing user input (calling IsValid on every JSON-parsed sdk.Coins in ValidateBasic, basically).

@jackzampolin
Copy link
Member

@cwgoes should that change be made with this PR or should we open an issue for that?

@cwgoes
Copy link
Contributor

cwgoes commented Dec 18, 2018

@cwgoes should that change be made with this PR or should we open an issue for that?

Oh - it's already fine in x/bank, I just mean as a reminder for the future.

@cwgoes
Copy link
Contributor

cwgoes commented Dec 18, 2018

(this needs a second review & approval, and it is a breaking change)

@jackzampolin jackzampolin added the T: API Breaking Breaking changes that impact APIs and the SDK only (not state machine). label Dec 18, 2018
Copy link
Contributor

@alexanderbez alexanderbez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM -- as long as we're consistent and use the constructors (NewCoin, NewInt64Coin) 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T: API Breaking Breaking changes that impact APIs and the SDK only (not state machine).
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants