From c9a573467883ea8c0e13bbd2f86b4c6610c4ac63 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 29 Jan 2020 15:39:12 +0100 Subject: [PATCH 1/4] x/ibc ICS24 --- x/ibc/24-host/errors.go | 15 ++++++ x/ibc/24-host/utils.go | 11 ++++ x/ibc/24-host/validate.go | 102 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 x/ibc/24-host/errors.go create mode 100644 x/ibc/24-host/utils.go create mode 100644 x/ibc/24-host/validate.go diff --git a/x/ibc/24-host/errors.go b/x/ibc/24-host/errors.go new file mode 100644 index 000000000000..26b7919e6cb5 --- /dev/null +++ b/x/ibc/24-host/errors.go @@ -0,0 +1,15 @@ +package host + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// SubModuleName defines the ICS 24 host +const SubModuleName = "host" + +// IBC client sentinel errors +var ( + ErrInvalidID = sdkerrors.Register(SubModuleName, 1, "invalid identifier") + ErrInvalidPath = sdkerrors.Register(SubModuleName, 2, "invalid path") + ErrInvalidPacket = sdkerrors.Register(SubModuleName, 3, "invalid packet") +) diff --git a/x/ibc/24-host/utils.go b/x/ibc/24-host/utils.go new file mode 100644 index 000000000000..c75f356561f6 --- /dev/null +++ b/x/ibc/24-host/utils.go @@ -0,0 +1,11 @@ +package host + +// RemovePath is an util function to remove a path from a set. +func RemovePath(paths []string, path string) ([]string, bool) { + for i, p := range paths { + if p == path { + return append(paths[:i], paths[i+1:]...), true + } + } + return paths, false +} diff --git a/x/ibc/24-host/validate.go b/x/ibc/24-host/validate.go new file mode 100644 index 000000000000..c360abf8616f --- /dev/null +++ b/x/ibc/24-host/validate.go @@ -0,0 +1,102 @@ +package host + +import ( + "regexp" + "strings" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// ICS 024 Identifier and Path Validation Implementation +// +// This file defines ValidateFn to validate identifier and path strings +// The spec for ICS 024 can be located here: +// https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements + +// regular expression to check string is lowercase alphabetic characters only +var isAlphaLower = regexp.MustCompile(`^[a-z]+$`).MatchString + +// regular expression to check string is alphanumeric +var isAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString + +// ValidateFn function type to validate path and identifier bytestrings +type ValidateFn func(string) error + +func defaultIdentifierValidator(id string, min, max int) error { + // valid id MUST NOT contain "/" separator + if strings.Contains(id, "/") { + return sdkerrors.Wrapf(ErrInvalidID, "identifier %s cannot contain separator '/'", id) + } + // valid id must be between 10 and 20 characters + if len(id) < min || len(id) > max { + return sdkerrors.Wrapf(ErrInvalidID, "identifier %s has invalid length: %d, must be between %d-%d characters", id, len(id), min, max) + } + // valid id must contain only lower alphabetic characters + if !isAlphaLower(id) { + return sdkerrors.Wrapf(ErrInvalidID, "identifier %s must contain only lowercase alphabetic characters", id) + } + return nil +} + +// DefaultClientIdentifierValidator is the default validator function for Client identifiers +// A valid Identifier must be between 10-20 characters and only contain lowercase +// alphabetic characters, +func DefaultClientIdentifierValidator(id string) error { + return defaultIdentifierValidator(id, 10, 20) +} + +// DefaultConnectionIdentifierValidator is the default validator function for Connection identifiers +// A valid Identifier must be between 10-20 characters and only contain lowercase +// alphabetic characters, +func DefaultConnectionIdentifierValidator(id string) error { + return defaultIdentifierValidator(id, 10, 20) +} + +// DefaultChannelIdentifierValidator is the default validator function for Channel identifiers +// A valid Identifier must be between 10-20 characters and only contain lowercase +// alphabetic characters, +func DefaultChannelIdentifierValidator(id string) error { + return defaultIdentifierValidator(id, 10, 20) +} + +// DefaultPortIdentifierValidator is the default validator function for Port identifiers +// A valid Identifier must be between 2-20 characters and only contain lowercase +// alphabetic characters, +func DefaultPortIdentifierValidator(id string) error { + return defaultIdentifierValidator(id, 2, 20) +} + +// NewPathValidator takes in a Identifier Validator function and returns +// a Path Validator function which requires path only has valid identifiers +// alphanumeric character strings, and "/" separators +func NewPathValidator(idValidator ValidateFn) ValidateFn { + return func(path string) error { + pathArr := strings.Split(path, "/") + for _, p := range pathArr { + // Each path element must either be valid identifier or alphanumeric + err := idValidator(p) + if err != nil && !isAlphaNumeric(p) { + return sdkerrors.Wrapf(ErrInvalidPath, "path %s contains invalid identifier or non-alphanumeric path element: %s", path, p) + } + } + return nil + } +} + +// DefaultPathValidator takes in path string and validates +// with default identifier rules. This is optimized by simply +// checking that all path elements are alphanumeric +func DefaultPathValidator(path string) error { + pathArr := strings.Split(path, "/") + if pathArr[0] == path { + return sdkerrors.Wrapf(ErrInvalidPath, "path %s doesn't contain any separator '/'", path) + } + + for _, p := range pathArr { + // Each path element must be alphanumeric and non-blank + if strings.TrimSpace(p) == "" || !isAlphaNumeric(p) { + return sdkerrors.Wrapf(ErrInvalidPath, "path %s contains an invalid non-alphanumeric character: '%s'", path, p) + } + } + return nil +} From 3aafe11c5ac2f0753b9f13a52945a75ec06c2672 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 29 Jan 2020 15:45:48 +0100 Subject: [PATCH 2/4] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0bbca18522d..199037cc0a03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (modules) [\#5555](https://github.com/cosmos/cosmos-sdk/pull/5555) Move x/auth/client/utils/ types and functions to x/auth/client/. +### Features + +* (x/ibc) [\#5588](https://github.com/cosmos/cosmos-sdk/pull/5588) Add [ICS 024 - Host State Machine Requirements](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements) subpackage to `x/ibc` module. + ### Bug Fixes * (x/bank) [\#5531](https://github.com/cosmos/cosmos-sdk/issues/5531) Added missing amount event to MsgMultiSend, emitted for each output. From 03cf9b2608d53881d0bbadb8fff7fb716ea578fd Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 18 Feb 2020 13:58:14 +0100 Subject: [PATCH 3/4] move regex to /types --- types/router.go | 16 ++++++++++++++++ x/ibc/24-host/validate.go | 8 +++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/types/router.go b/types/router.go index f3593f5530ff..987a05cf3430 100644 --- a/types/router.go +++ b/types/router.go @@ -6,6 +6,22 @@ import "regexp" // values. var IsAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString +// IsAlphaLower defines regular expression to check if the string has lowercase +// alphabetic characters only. +var IsAlphaLower = regexp.MustCompile(`^[a-z]+$`).MatchString + +// IsAlphaUpper defines regular expression to check if the string has uppercase +// alphabetic characters only. +var IsAlphaUpper = regexp.MustCompile(`^[A-Z]+$`).MatchString + +// IsAlpha defines regular expression to check if the string has alphabetic +// characters only. +var IsAlpha = regexp.MustCompile(`^[a-zA-Z]+$`).MatchString + +// IsNumeric defines regular expression to check if the string has numeric +// characters only. +var IsNumeric = regexp.MustCompile(`^[0-9]+$`).MatchString + // Router provides handlers for each transaction type. type Router interface { AddRoute(r string, h Handler) Router diff --git a/x/ibc/24-host/validate.go b/x/ibc/24-host/validate.go index c360abf8616f..10f212345c07 100644 --- a/x/ibc/24-host/validate.go +++ b/x/ibc/24-host/validate.go @@ -4,6 +4,7 @@ import ( "regexp" "strings" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -16,9 +17,6 @@ import ( // regular expression to check string is lowercase alphabetic characters only var isAlphaLower = regexp.MustCompile(`^[a-z]+$`).MatchString -// regular expression to check string is alphanumeric -var isAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString - // ValidateFn function type to validate path and identifier bytestrings type ValidateFn func(string) error @@ -75,7 +73,7 @@ func NewPathValidator(idValidator ValidateFn) ValidateFn { for _, p := range pathArr { // Each path element must either be valid identifier or alphanumeric err := idValidator(p) - if err != nil && !isAlphaNumeric(p) { + if err != nil && !sdk.IsAlphaNumeric(p) { return sdkerrors.Wrapf(ErrInvalidPath, "path %s contains invalid identifier or non-alphanumeric path element: %s", path, p) } } @@ -94,7 +92,7 @@ func DefaultPathValidator(path string) error { for _, p := range pathArr { // Each path element must be alphanumeric and non-blank - if strings.TrimSpace(p) == "" || !isAlphaNumeric(p) { + if strings.TrimSpace(p) == "" || !sdk.IsAlphaNumeric(p) { return sdkerrors.Wrapf(ErrInvalidPath, "path %s contains an invalid non-alphanumeric character: '%s'", path, p) } } From 52ac056fb6f0799d5a21068b7f3001cfa79bf811 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 19 Feb 2020 10:13:05 +0100 Subject: [PATCH 4/4] address @alexanderbez comments --- types/router.go | 40 ++++++++++++++++++++------------------- x/ibc/24-host/validate.go | 6 +----- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/types/router.go b/types/router.go index 987a05cf3430..12d0455f805d 100644 --- a/types/router.go +++ b/types/router.go @@ -2,25 +2,27 @@ package types import "regexp" -// IsAlphaNumeric defines a regular expression for matching against alpha-numeric -// values. -var IsAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString - -// IsAlphaLower defines regular expression to check if the string has lowercase -// alphabetic characters only. -var IsAlphaLower = regexp.MustCompile(`^[a-z]+$`).MatchString - -// IsAlphaUpper defines regular expression to check if the string has uppercase -// alphabetic characters only. -var IsAlphaUpper = regexp.MustCompile(`^[A-Z]+$`).MatchString - -// IsAlpha defines regular expression to check if the string has alphabetic -// characters only. -var IsAlpha = regexp.MustCompile(`^[a-zA-Z]+$`).MatchString - -// IsNumeric defines regular expression to check if the string has numeric -// characters only. -var IsNumeric = regexp.MustCompile(`^[0-9]+$`).MatchString +var ( + // IsAlphaNumeric defines a regular expression for matching against alpha-numeric + // values. + IsAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString + + // IsAlphaLower defines regular expression to check if the string has lowercase + // alphabetic characters only. + IsAlphaLower = regexp.MustCompile(`^[a-z]+$`).MatchString + + // IsAlphaUpper defines regular expression to check if the string has uppercase + // alphabetic characters only. + IsAlphaUpper = regexp.MustCompile(`^[A-Z]+$`).MatchString + + // IsAlpha defines regular expression to check if the string has alphabetic + // characters only. + IsAlpha = regexp.MustCompile(`^[a-zA-Z]+$`).MatchString + + // IsNumeric defines regular expression to check if the string has numeric + // characters only. + IsNumeric = regexp.MustCompile(`^[0-9]+$`).MatchString +) // Router provides handlers for each transaction type. type Router interface { diff --git a/x/ibc/24-host/validate.go b/x/ibc/24-host/validate.go index 10f212345c07..e75e63e6c2dd 100644 --- a/x/ibc/24-host/validate.go +++ b/x/ibc/24-host/validate.go @@ -1,7 +1,6 @@ package host import ( - "regexp" "strings" sdk "github.com/cosmos/cosmos-sdk/types" @@ -14,9 +13,6 @@ import ( // The spec for ICS 024 can be located here: // https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements -// regular expression to check string is lowercase alphabetic characters only -var isAlphaLower = regexp.MustCompile(`^[a-z]+$`).MatchString - // ValidateFn function type to validate path and identifier bytestrings type ValidateFn func(string) error @@ -30,7 +26,7 @@ func defaultIdentifierValidator(id string, min, max int) error { return sdkerrors.Wrapf(ErrInvalidID, "identifier %s has invalid length: %d, must be between %d-%d characters", id, len(id), min, max) } // valid id must contain only lower alphabetic characters - if !isAlphaLower(id) { + if !sdk.IsAlphaLower(id) { return sdkerrors.Wrapf(ErrInvalidID, "identifier %s must contain only lowercase alphabetic characters", id) } return nil