You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

66 lines
1.8 KiB

  1. package types
  2. import (
  3. "encoding/hex"
  4. "errors"
  5. "fmt"
  6. "regexp"
  7. "strings"
  8. "github.com/tendermint/tendermint/crypto"
  9. )
  10. // NodeIDByteLength is the length of a crypto.Address. Currently only 20.
  11. // FIXME: support other length addresses?
  12. const NodeIDByteLength = crypto.AddressSize
  13. // reNodeID is a regexp for valid node IDs.
  14. var reNodeID = regexp.MustCompile(`^[0-9a-f]{40}$`)
  15. // NodeID is a hex-encoded crypto.Address. It must be lowercased
  16. // (for uniqueness) and of length 2*NodeIDByteLength.
  17. type NodeID string
  18. // NewNodeID returns a lowercased (normalized) NodeID, or errors if the
  19. // node ID is invalid.
  20. func NewNodeID(nodeID string) (NodeID, error) {
  21. n := NodeID(strings.ToLower(nodeID))
  22. return n, n.Validate()
  23. }
  24. // IDAddressString returns id@hostPort. It strips the leading
  25. // protocol from protocolHostPort if it exists.
  26. func (id NodeID) AddressString(protocolHostPort string) string {
  27. return fmt.Sprintf("%s@%s", id, removeProtocolIfDefined(protocolHostPort))
  28. }
  29. // NodeIDFromPubKey creates a node ID from a given PubKey address.
  30. func NodeIDFromPubKey(pubKey crypto.PubKey) NodeID {
  31. return NodeID(hex.EncodeToString(pubKey.Address()))
  32. }
  33. // Bytes converts the node ID to its binary byte representation.
  34. func (id NodeID) Bytes() ([]byte, error) {
  35. bz, err := hex.DecodeString(string(id))
  36. if err != nil {
  37. return nil, fmt.Errorf("invalid node ID encoding: %w", err)
  38. }
  39. return bz, nil
  40. }
  41. // Validate validates the NodeID.
  42. func (id NodeID) Validate() error {
  43. switch {
  44. case len(id) == 0:
  45. return errors.New("empty node ID")
  46. case len(id) != 2*NodeIDByteLength:
  47. return fmt.Errorf("invalid node ID length %d, expected %d", len(id), 2*NodeIDByteLength)
  48. case !reNodeID.MatchString(string(id)):
  49. return fmt.Errorf("node ID can only contain lowercased hex digits")
  50. default:
  51. return nil
  52. }
  53. }