Commit dc718fa4 authored by Steven Allen's avatar Steven Allen

feat: support encoding/decoding peer IDs as CIDs _in text_

parent 2f75277a
......@@ -5,7 +5,9 @@ import (
"encoding/hex"
"errors"
"fmt"
"strings"
cid "github.com/ipfs/go-cid"
ic "github.com/libp2p/go-libp2p-core/crypto"
b58 "github.com/mr-tron/base58/base58"
mh "github.com/multiformats/go-multihash"
......@@ -129,23 +131,24 @@ func IDFromBytes(b []byte) (ID, error) {
return ID(b), nil
}
// IDB58Decode accepts a base58-encoded multihash representing a peer ID
// and returns the decoded ID if the input is valid.
// IDB58Decode decodes a peer ID.
//
// Deprecated: Use Decode.
func IDB58Decode(s string) (ID, error) {
m, err := mh.FromB58String(s)
if err != nil {
return "", err
}
return ID(m), err
return Decode(s)
}
// IDB58Encode returns the base58-encoded multihash representation of the ID.
//
// Deprecated: Use Encode.
func IDB58Encode(id ID) string {
return b58.Encode([]byte(id))
}
// IDHexDecode accepts a hex-encoded multihash representing a peer ID
// and returns the decoded ID if the input is valid.
//
// Deprecated: Don't raw-hex encode peer IDs, use base16 CIDs.
func IDHexDecode(s string) (ID, error) {
m, err := mh.FromHexString(s)
if err != nil {
......@@ -155,10 +158,66 @@ func IDHexDecode(s string) (ID, error) {
}
// IDHexEncode returns the hex-encoded multihash representation of the ID.
//
// Deprecated: Don't raw-hex encode peer IDs, use base16 CIDs.
func IDHexEncode(id ID) string {
return hex.EncodeToString([]byte(id))
}
// 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 Decode(s string) (ID, error) {
if strings.HasPrefix(s, "Qm") || strings.HasPrefix(s, "1") {
// base58 encoded sha256 or identity multihash
m, err := mh.FromB58String(s)
if err != nil {
return "", fmt.Errorf("failed to parse peer ID: %s", err)
}
return ID(m), nil
}
c, err := cid.Decode(s)
if err != nil {
return "", fmt.Errorf("failed to parse peer ID: %s", err)
}
return FromCid(c)
}
// Encode encodes a peer ID as a string.
//
// At the moment, it base58 encodes the peer ID but, in the future, it will
// switch to encoding it as a CID by default.
func Encode(id ID) string {
return IDB58Encode(id)
}
// FromCid converts a CID to a peer ID, if possible.
func FromCid(c cid.Cid) (ID, error) {
ty := c.Type()
if ty != cid.Libp2pKey {
s := cid.CodecToStr[ty]
if s == "" {
s = fmt.Sprintf("[unknown multicodec %d]", ty)
}
return "", fmt.Errorf("can't convert CID of type %s to a peer ID", s)
}
return ID(c.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 ToCid(id ID) cid.Cid {
m, err := mh.Cast([]byte(id))
if err != nil {
return cid.Cid{}
}
return cid.NewCidV1(cid.Libp2pKey, m)
}
// IDFromPublicKey returns the Peer ID corresponding to the public key pk.
func IDFromPublicKey(pk ic.PubKey) (ID, error) {
b, err := pk.Bytes()
......
......@@ -153,6 +153,51 @@ func TestIDMatchesPrivateKey(t *testing.T) {
test(man)
}
func TestIDEncoding(t *testing.T) {
test := func(ks keyset) {
p1, err := IDB58Decode(ks.hpkp)
if err != nil {
t.Fatal(err)
}
if ks.hpk != string(p1) {
t.Error("p1 and hpk differ")
}
c := ToCid(p1)
p2, err := FromCid(c)
if err != nil || p1 != p2 {
t.Fatal("failed to round-trip through CID:", err)
}
p3, err := Decode(c.String())
if err != nil {
t.Fatal(err)
}
if p3 != p1 {
t.Fatal("failed to round trip through CID string")
}
if ks.hpkp != Encode(p1) {
t.Fatal("should always encode peer IDs as base58 by default")
}
}
test(gen1)
test(gen2)
test(man)
exampleCid := "bafkreifoybygix7fh3r3g5rqle3wcnhqldgdg4shzf4k3ulyw3gn7mabt4"
_, err := Decode(exampleCid)
if err == nil {
t.Fatal("should refuse to decode a non-peer ID CID")
}
c := ToCid("")
if c.Defined() {
t.Fatal("cid of empty peer ID should have been undefined")
}
}
func TestPublicKeyExtraction(t *testing.T) {
t.Skip("disabled until libp2p/go-libp2p-crypto#51 is fixed")
// Happy path
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment