// Package peer implements an object used to represent peers in the libp2p network.
package peer import ( ic b58 mc mh ) var ( // ErrEmptyPeerID is an error for empty peer ID. ErrEmptyPeerID = errors.New("empty peer ID") // ErrNoPublicKey is an error for peer IDs that don't embed public keys ErrNoPublicKey = errors.New("public key is not embedded in peer ID") ) // AdvancedEnableInlining enables automatically inlining keys shorter than // 42 bytes into the peer ID (using the "identity" multihash function). // // WARNING: This flag will likely be set to false in the future and eventually // be removed in favor of using a hash function specified by the key itself. // See: https://github.com/libp2p/specs/issues/138 // // DO NOT change this flag unless you know what you're doing. // // This currently defaults to true for backwards compatibility but will likely // be set to false by default when an upgrade path is determined. var AdvancedEnableInlining = true const maxInlineKeyLength = 42 // ID is a libp2p peer identity. // // Peer IDs are derived by hashing a peer's public key and encoding the // hash output as a multihash. See IDFromPublicKey for details. type ID string // Loggable returns a pretty peer ID string in loggable JSON format. func ( ID) () map[string]interface{} { return map[string]interface{}{ "peerID": .String(), } } func ( ID) () string { return b58.Encode([]byte()) } // ShortString prints out the peer ID. // // TODO(brian): ensure correctness at ID generation and // enforce this by only exposing functions that generate // IDs safely. Then any peer.ID type found in the // codebase is known to be correct. func ( ID) () string { := .String() if len() <= 10 { return fmt.Sprintf("<peer.ID %s>", ) } return fmt.Sprintf("<peer.ID %s*%s>", [:2], [len()-6:]) } // MatchesPrivateKey tests whether this ID was derived from the secret key sk. func ( ID) ( ic.PrivKey) bool { return .MatchesPublicKey(.GetPublic()) } // MatchesPublicKey tests whether this ID was derived from the public key pk. func ( ID) ( ic.PubKey) bool { , := IDFromPublicKey() if != nil { return false } return == } // ExtractPublicKey attempts to extract the public key from an ID. // // This method returns ErrNoPublicKey if the peer ID looks valid, but it can't extract // the public key. func ( ID) () (ic.PubKey, error) { , := mh.Decode([]byte()) if != nil { return nil, } if .Code != mh.IDENTITY { return nil, ErrNoPublicKey } , := ic.UnmarshalPublicKey(.Digest) if != nil { return nil, } return , nil } // Validate checks if ID is empty or not. func ( ID) () error { if == ID("") { return ErrEmptyPeerID } return nil } // IDFromBytes casts a byte slice to the ID type, and validates // the value to make sure it is a multihash. func ( []byte) (ID, error) { if , := mh.Cast(); != nil { return ID(""), } return ID(), nil } // Decode accepts an encoded peer ID and returns the decoded ID if the input is // valid. // // The encoded peer ID can either be a CID of a key or a raw multihash (identity // or sha256-256). func ( string) (ID, error) { if strings.HasPrefix(, "Qm") || strings.HasPrefix(, "1") { // base58 encoded sha256 or identity multihash , := mh.FromB58String() if != nil { return "", fmt.Errorf("failed to parse peer ID: %s", ) } return ID(), nil } , := cid.Decode() if != nil { return "", fmt.Errorf("failed to parse peer ID: %s", ) } return FromCid() } // FromCid converts a CID to a peer ID, if possible. func ( cid.Cid) (ID, error) { := mc.Code(.Type()) if != mc.Libp2pKey { return "", fmt.Errorf("can't convert CID of type %q to a peer ID", ) } return ID(.Hash()), nil } // ToCid encodes a peer ID as a CID of the public key. // // If the peer ID is invalid (e.g., empty), this will return the empty CID. func ( ID) cid.Cid { , := mh.Cast([]byte()) if != nil { return cid.Cid{} } return cid.NewCidV1(cid.Libp2pKey, ) } // IDFromPublicKey returns the Peer ID corresponding to the public key pk. func ( ic.PubKey) (ID, error) { , := ic.MarshalPublicKey() if != nil { return "", } var uint64 = mh.SHA2_256 if AdvancedEnableInlining && len() <= maxInlineKeyLength { = mh.IDENTITY } , := mh.Sum(, , -1) return ID(), nil } // IDFromPrivateKey returns the Peer ID corresponding to the secret key sk. func ( ic.PrivKey) (ID, error) { return IDFromPublicKey(.GetPublic()) } // IDSlice for sorting peers. type IDSlice []ID func ( IDSlice) () int { return len() } func ( IDSlice) (, int) { [], [] = [], [] } func ( IDSlice) (, int) bool { return string([]) < string([]) } func ( IDSlice) () string { := make([]string, len()) for , := range { [] = .String() } return strings.Join(, ", ") }