github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/types/node_id.go (about)

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