Skip to content

Commit

Permalink
R4R: Add custom validation for denom (#6755)
Browse files Browse the repository at this point in the history
Allow ValidateDenom to be customized per application.

closes: #6744
  • Loading branch information
okwme authored Oct 6, 2020
1 parent 090bae5 commit 3e6089d
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposa

### Features

* [\#6755](https://github.com/cosmos/cosmos-sdk/pull/6755) Add custom regex validation for `Coin` denom by overwriting `CoinDenomRegex` when using `/types/coin.go`.
* [\#7265](https://github.com/cosmos/cosmos-sdk/pull/7265) Support Tendermint block pruning through a new `min-retain-blocks` configuration that can be set in either `app.toml` or via the CLI. This parameter is used in conjunction with other criteria to determine the height at which Tendermint should prune blocks.
* (vesting) [\#7209](https://github.com/cosmos/cosmos-sdk/pull/7209) Create new `MsgCreateVestingAccount` message type along with CLI handler that allows for the creation of delayed and continuous vesting types.
* (events) [\#7121](https://github.com/cosmos/cosmos-sdk/pull/7121) The application now drives what events are indexed by Tendermint via the `index-events` configuration in `app.toml`, which is a list of events taking the form `{eventType}.{attributeKey}`.
Expand Down
31 changes: 24 additions & 7 deletions types/coin.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,15 +602,32 @@ var (
reAmt = `[[:digit:]]+`
reDecAmt = `[[:digit:]]*\.[[:digit:]]+`
reSpc = `[[:space:]]*`
reDnm = regexp.MustCompile(fmt.Sprintf(`^%s$`, reDnmString))
reCoin = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reAmt, reSpc, reDnmString))
reDecCoin = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reDecAmt, reSpc, reDnmString))
reDnm = returnReDnm
reCoin = returnReCoin
reDecCoin = returnDecCoin
)

// ValidateDenom validates a denomination string returning an error if it is
// invalid.
func returnDecCoin() *regexp.Regexp {
return regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reDecAmt, reSpc, CoinDenomRegex()))
}
func returnReCoin() *regexp.Regexp {
return regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reAmt, reSpc, CoinDenomRegex()))
}
func returnReDnm() *regexp.Regexp {
return regexp.MustCompile(fmt.Sprintf(`^%s$`, CoinDenomRegex()))
}

// DefaultCoinDenomRegex returns the default regex string
func DefaultCoinDenomRegex() string {
return reDnmString
}

// CoinDenomRegex returns the current regex string and can be overwritten for custom validation
var CoinDenomRegex = DefaultCoinDenomRegex

// ValidateDenom is the default validation function for Coin.Denom.
func ValidateDenom(denom string) error {
if !reDnm.MatchString(denom) {
if !reDnm().MatchString(denom) {
return fmt.Errorf("invalid denom: %s", denom)
}
return nil
Expand All @@ -628,7 +645,7 @@ func mustValidateDenom(denom string) {
func ParseCoin(coinStr string) (coin Coin, err error) {
coinStr = strings.TrimSpace(coinStr)

matches := reCoin.FindStringSubmatch(coinStr)
matches := reCoin().FindStringSubmatch(coinStr)
if matches == nil {
return Coin{}, fmt.Errorf("invalid coin expression: %s", coinStr)
}
Expand Down
24 changes: 24 additions & 0 deletions types/coin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,30 @@ func (s *coinTestSuite) TestCoinIsValid() {
}
}

func (s *coinTestSuite) TestCustomValidation() {

newDnmRegex := `[\x{1F600}-\x{1F6FF}]`
sdk.CoinDenomRegex = func() string {
return newDnmRegex
}

cases := []struct {
coin sdk.Coin
expectPass bool
}{
{sdk.Coin{"🙂", sdk.NewInt(1)}, true},
{sdk.Coin{"🙁", sdk.NewInt(1)}, true},
{sdk.Coin{"🌶", sdk.NewInt(1)}, false}, // outside the unicode range listed above
{sdk.Coin{"asdf", sdk.NewInt(1)}, false},
{sdk.Coin{"", sdk.NewInt(1)}, false},
}

for i, tc := range cases {
s.Require().Equal(tc.expectPass, tc.coin.IsValid(), "unexpected result for IsValid, tc #%d", i)
}
sdk.CoinDenomRegex = sdk.DefaultCoinDenomRegex
}

func (s *coinTestSuite) TestAddCoin() {
cases := []struct {
inputOne sdk.Coin
Expand Down
2 changes: 1 addition & 1 deletion types/dec_coin.go
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ func (coins DecCoins) Sort() DecCoins {
func ParseDecCoin(coinStr string) (coin DecCoin, err error) {
coinStr = strings.TrimSpace(coinStr)

matches := reDecCoin.FindStringSubmatch(coinStr)
matches := reDecCoin().FindStringSubmatch(coinStr)
if matches == nil {
return DecCoin{}, fmt.Errorf("invalid decimal coin expression: %s", coinStr)
}
Expand Down

0 comments on commit 3e6089d

Please sign in to comment.