-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
types: update coin regex #7027
types: update coin regex #7027
Conversation
Codecov Report
@@ Coverage Diff @@
## master #7027 +/- ##
==========================================
+ Coverage 60.99% 61.96% +0.97%
==========================================
Files 380 520 +140
Lines 24753 32022 +7269
==========================================
+ Hits 15097 19843 +4746
- Misses 8467 10551 +2084
- Partials 1189 1628 +439 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It needs to be clear if atom
, ATOM
, and Atom
are the same or different tokens.
And then make that stick in all code - subtracting, adding, ordering. Not just for the dup checks.
I am find with either decision (those 3 denoms are same or different), but it should be consistent
types/coin_test.go
Outdated
{"MineraL", NewInt(1)}, | ||
{"TREE", NewInt(1)}, | ||
{"gAs", NewInt(1)}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this test enforces the ordering by denom as published.
I just think if you normalize cases one place, they should be normalized everywhere.
Also, what if we have bal := Coins{{"atom", NewInt(10)}}
and then bal.Sub(Coins{{"ATOM", NewInt(3)}})
. What is the expected behavior?
Either "atom" == "ATOM"
everywhere or nowhere - if they are considered dups, they should be treated the same by all math functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought "atom" != "ATOM"
everywhere? Is this not correct @fedekunze ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I removed it now
types/coin_test.go
Outdated
assert.False(t, mixedCase1.IsValid(), "Coins denoms contain upper case characters") | ||
assert.False(t, mixedCase2.IsValid(), "First Coins denoms contain upper case characters") | ||
assert.False(t, mixedCase3.IsValid(), "Single denom in Coins contains upper case characters") | ||
assert.True(t, goodCaps.IsValid(), "Coins all caps are valid") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: usually this is some sort of table test, no?
Personally, I like the named table test:
cases := map[string]struct {
someTestData string
}{
"all upper case": { "FOO" },
"mixed case": {"fOO"},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
// whatever you want to test
assert.True(IsValid(tc.someTestData)
}
}
They are all run separately and each failure has the name from the upper test case map.
Co-authored-by: Aaron Craelius <aaron@regen.network>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little confused as to whether the case is ignored or not in denominations
types/coin_test.go
Outdated
{"MineraL", NewInt(1)}, | ||
{"TREE", NewInt(1)}, | ||
{"gAs", NewInt(1)}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought "atom" != "ATOM"
everywhere? Is this not correct @fedekunze ?
types/coin_test.go
Outdated
assert.False(t, mixedCase3.IsValid(), "Single denom in Coins contains upper case characters") | ||
assert.True(t, goodCaps.IsValid(), "Coins all caps are valid") | ||
assert.True(t, unicodeLinearBAndRoman.IsValid(), "Unicode characters") | ||
assert.False(t, unicodeEmoji.IsValid(), "Unicode emoji") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😭
This looks good to me but I'm still a little confused about how customization would fare in an IBC context. For example I would go into |
no, ADR 1 specifically considers this issue. The transfer denom is internally represented as where
Since the This mapping is only internally represented on the SDK. Zones or Hubs implementing different versions of If a zone or hub where to enforce stricter denomination requirements than the default in the SDK, if they did not support:
then it would not be compatible with the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that the tests should be converted to table-form.
Regarding unicode characters, I think we need to be a little careful - are there any two characters which look very similar / identical but are actually represented differently (i.e., are unequal)? This can be an attack vector (where some malicious agent purposefully creates a denom that looks almost exactly like a real one - e.g. atom - but is actually unequal).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM. I think we should take the time to document some key design decisions/rational while everyone is viewing these changes. coin.go
has always been a poorly documented mystery to me without explanations for important code decisions. Sounds to me like we should open an issue for an ADR for coin.go
and DecCoins
return err | ||
} | ||
|
||
if amount.IsNegative() { | ||
return fmt.Errorf("negative coin amount: %v", amount) | ||
if coin.Amount.IsNegative() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we document the rational to why a single coin of ZeroInt is valid but a set of coins with a coin of ZeroInt is invalid? Seems counter-intuitive to me and if we support this it, the reason should be well documented. I'd be in favor of only considering positive amount Coin
s valid
Thanks for your reviews. Regarding the attack vectors and Unicode, I've decided to undo the changes that add Unicode letters support until these changes are documented in an ADR as @colin-axner suggested. This PR was only meant for adding the coin changes from the already approved ADR001, so I guess it makes sense to scope the PR changes to that only. |
… update-coin-regex
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can there be tests confirming that adding atom
+ ATOM
yield 2 coins and not 1 or something similar?
// Denominations can be 3 ~ 64 characters long. | ||
reDnmString = `[a-z][a-z0-9/]{2,63}` | ||
// Denominations can be 3 ~ 128 characters long and support letters, followed by either | ||
// a letter, a number or a separator ('/'). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: There's the potential for confusing UI here.
Suppose I create a denom atom10
, the following Coins
string representation is ambigious to an end user
5atom10,300btc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unfortunately, there's no workaround for this. I added a test case and documented the expected format on the ParseCoin(s)
func
* types: update coin regex * more tests * fix test case * increase coverage * changelog * fix tests * support unicode letters and numbers * remove ToUpper * Update types/coin.go Co-authored-by: Aaron Craelius <aaron@regen.network> * Validate function * fix ICS20 test * table tests and revert unicodes * add test case * add test cases and comment Co-authored-by: Aaron Craelius <aaron@regen.network>
Description
Split coin changes from #6871 for ease of review
closes #6716
Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
docs/
) or specification (x/<module>/spec/
)godoc
comments.Unreleased
section inCHANGELOG.md
Files changed
in the Github PR explorerCodecov Report
in the comment section below once CI passes