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.

67 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. hostPort := removeProtocolIfDefined(protocolHostPort)
  28. return fmt.Sprintf("%s@%s", id, hostPort)
  29. }
  30. // NodeIDFromPubKey creates a node ID from a given PubKey address.
  31. func NodeIDFromPubKey(pubKey crypto.PubKey) NodeID {
  32. return NodeID(hex.EncodeToString(pubKey.Address()))
  33. }
  34. // Bytes converts the node ID to its binary byte representation.
  35. func (id NodeID) Bytes() ([]byte, error) {
  36. bz, err := hex.DecodeString(string(id))
  37. if err != nil {
  38. return nil, fmt.Errorf("invalid node ID encoding: %w", err)
  39. }
  40. return bz, nil
  41. }
  42. // Validate validates the NodeID.
  43. func (id NodeID) Validate() error {
  44. switch {
  45. case len(id) == 0:
  46. return errors.New("empty node ID")
  47. case len(id) != 2*NodeIDByteLength:
  48. return fmt.Errorf("invalid node ID length %d, expected %d", len(id), 2*NodeIDByteLength)
  49. case !reNodeID.MatchString(string(id)):
  50. return fmt.Errorf("node ID can only contain lowercased hex digits")
  51. default:
  52. return nil
  53. }
  54. }