github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/24-host/validate.go (about)

     1  package host
     2  
     3  import (
     4  	"regexp"
     5  	"strings"
     6  
     7  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
     8  )
     9  
    10  // DefaultMaxCharacterLength defines the default maximum character length used
    11  // in validation of identifiers including the client, connection, port and
    12  // channel identifiers.
    13  //
    14  // NOTE: this restriction is specific to this golang implementation of IBC. If
    15  // your use case demands a higher limit, please open an issue and we will consider
    16  // adjusting this restriction.
    17  const DefaultMaxCharacterLength = 64
    18  
    19  // DefaultMaxPortCharacterLength defines the default maximum character length used
    20  // in validation of port identifiers.
    21  var DefaultMaxPortCharacterLength = 128
    22  
    23  // IsValidID defines regular expression to check if the string consist of
    24  // characters in one of the following categories only:
    25  // - Alphanumeric
    26  // - `.`, `_`, `+`, `-`, `#`
    27  // - `[`, `]`, `<`, `>`
    28  var IsValidID = regexp.MustCompile(`^[a-zA-Z0-9\.\_\+\-\#\[\]\<\>]+$`).MatchString
    29  
    30  // ICS 024 Identifier and Path Validation Implementation
    31  //
    32  // This file defines ValidateFn to validate identifier and path strings
    33  // The spec for ICS 024 can be located here:
    34  // https://github.com/cosmos/ibc/tree/master/spec/core/ics-024-host-requirements
    35  
    36  // ValidateFn function type to validate path and identifier bytestrings
    37  type ValidateFn func(string) error
    38  
    39  func defaultIdentifierValidator(id string, min, max int) error { //nolint:unparam
    40  	if strings.TrimSpace(id) == "" {
    41  		return sdkerrors.Wrap(ErrInvalidID, "identifier cannot be blank")
    42  	}
    43  	// valid id MUST NOT contain "/" separator
    44  	if strings.Contains(id, "/") {
    45  		return sdkerrors.Wrapf(ErrInvalidID, "identifier %s cannot contain separator '/'", id)
    46  	}
    47  	// valid id must fit the length requirements
    48  	if len(id) < min || len(id) > max {
    49  		return sdkerrors.Wrapf(ErrInvalidID, "identifier %s has invalid length: %d, must be between %d-%d characters", id, len(id), min, max)
    50  	}
    51  	// valid id must contain only lower alphabetic characters
    52  	if !IsValidID(id) {
    53  		return sdkerrors.Wrapf(
    54  			ErrInvalidID,
    55  			"identifier %s must contain only alphanumeric or the following characters: '.', '_', '+', '-', '#', '[', ']', '<', '>'",
    56  			id,
    57  		)
    58  	}
    59  	return nil
    60  }
    61  
    62  // ClientIdentifierValidator is the default validator function for Client identifiers.
    63  // A valid Identifier must be between 9-64 characters and only contain alphanumeric and some allowed
    64  // special characters (see IsValidID).
    65  func ClientIdentifierValidator(id string) error {
    66  	return defaultIdentifierValidator(id, 9, DefaultMaxCharacterLength)
    67  }
    68  
    69  // ConnectionIdentifierValidator is the default validator function for Connection identifiers.
    70  // A valid Identifier must be between 10-64 characters and only contain alphanumeric and some allowed
    71  // special characters (see IsValidID).
    72  func ConnectionIdentifierValidator(id string) error {
    73  	return defaultIdentifierValidator(id, 10, DefaultMaxCharacterLength)
    74  }
    75  
    76  // ChannelIdentifierValidator is the default validator function for Channel identifiers.
    77  // A valid Identifier must be between 8-64 characters and only contain alphanumeric and some allowed
    78  // special characters (see IsValidID).
    79  func ChannelIdentifierValidator(id string) error {
    80  	return defaultIdentifierValidator(id, 8, DefaultMaxCharacterLength)
    81  }
    82  
    83  // PortIdentifierValidator is the default validator function for Port identifiers.
    84  // A valid Identifier must be between 2-64 characters and only contain alphanumeric and some allowed
    85  // special characters (see IsValidID).
    86  func PortIdentifierValidator(id string) error {
    87  	return defaultIdentifierValidator(id, 2, DefaultMaxPortCharacterLength)
    88  }
    89  
    90  // NewPathValidator takes in a Identifier Validator function and returns
    91  // a Path Validator function which requires path to consist of `/`-separated valid identifiers,
    92  // where a valid identifier is between 1-64 characters, contains only alphanumeric and some allowed
    93  // special characters (see IsValidID), and satisfies the custom `idValidator` function.
    94  func NewPathValidator(idValidator ValidateFn) ValidateFn {
    95  	return func(path string) error {
    96  		pathArr := strings.Split(path, "/")
    97  		if len(pathArr) > 0 && pathArr[0] == path {
    98  			return sdkerrors.Wrapf(ErrInvalidPath, "path %s doesn't contain any separator '/'", path)
    99  		}
   100  
   101  		for _, p := range pathArr {
   102  			// a path beginning or ending in a separator returns empty string elements.
   103  			if p == "" {
   104  				return sdkerrors.Wrapf(ErrInvalidPath, "path %s cannot begin or end with '/'", path)
   105  			}
   106  
   107  			if err := idValidator(p); err != nil {
   108  				return err
   109  			}
   110  			// Each path element must either be a valid identifier or constant number
   111  			if err := defaultIdentifierValidator(p, 1, DefaultMaxCharacterLength); err != nil {
   112  				return sdkerrors.Wrapf(err, "path %s contains an invalid identifier: '%s'", path, p)
   113  			}
   114  		}
   115  
   116  		return nil
   117  	}
   118  }