mirror of
https://github.com/libp2p/go-libp2p-peerstore.git
synced 2025-03-22 12:50:07 +08:00
extract peerstore from peer package
This commit is contained in:
parent
0089910775
commit
350c2ce7c2
@ -1,11 +1,12 @@
|
||||
package peer
|
||||
package peerstore
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
addr "github.com/ipfs/go-libp2p-peer/addr"
|
||||
peer "github.com/ipfs/go-libp2p-peer"
|
||||
addr "github.com/ipfs/go-libp2p-peerstore/addr"
|
||||
ma "github.com/jbenet/go-multiaddr"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@ -53,30 +54,30 @@ type addrSet map[string]expiringAddr
|
||||
// The zero-value is ready to be used.
|
||||
type AddrManager struct {
|
||||
addrmu sync.Mutex // guards addrs
|
||||
addrs map[ID]addrSet
|
||||
addrs map[peer.ID]addrSet
|
||||
|
||||
addrSubs map[ID][]*addrSub
|
||||
addrSubs map[peer.ID][]*addrSub
|
||||
}
|
||||
|
||||
// ensures the AddrManager is initialized.
|
||||
// So we can use the zero value.
|
||||
func (mgr *AddrManager) init() {
|
||||
if mgr.addrs == nil {
|
||||
mgr.addrs = make(map[ID]addrSet)
|
||||
mgr.addrs = make(map[peer.ID]addrSet)
|
||||
}
|
||||
if mgr.addrSubs == nil {
|
||||
mgr.addrSubs = make(map[ID][]*addrSub)
|
||||
mgr.addrSubs = make(map[peer.ID][]*addrSub)
|
||||
}
|
||||
}
|
||||
|
||||
func (mgr *AddrManager) Peers() []ID {
|
||||
func (mgr *AddrManager) Peers() []peer.ID {
|
||||
mgr.addrmu.Lock()
|
||||
defer mgr.addrmu.Unlock()
|
||||
if mgr.addrs == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
pids := make([]ID, 0, len(mgr.addrs))
|
||||
pids := make([]peer.ID, 0, len(mgr.addrs))
|
||||
for pid := range mgr.addrs {
|
||||
pids = append(pids, pid)
|
||||
}
|
||||
@ -84,14 +85,14 @@ func (mgr *AddrManager) Peers() []ID {
|
||||
}
|
||||
|
||||
// AddAddr calls AddAddrs(p, []ma.Multiaddr{addr}, ttl)
|
||||
func (mgr *AddrManager) AddAddr(p ID, addr ma.Multiaddr, ttl time.Duration) {
|
||||
func (mgr *AddrManager) AddAddr(p peer.ID, addr ma.Multiaddr, ttl time.Duration) {
|
||||
mgr.AddAddrs(p, []ma.Multiaddr{addr}, ttl)
|
||||
}
|
||||
|
||||
// AddAddrs gives AddrManager addresses to use, with a given ttl
|
||||
// (time-to-live), after which the address is no longer valid.
|
||||
// If the manager has a longer TTL, the operation is a no-op for that address
|
||||
func (mgr *AddrManager) AddAddrs(p ID, addrs []ma.Multiaddr, ttl time.Duration) {
|
||||
func (mgr *AddrManager) AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration) {
|
||||
mgr.addrmu.Lock()
|
||||
defer mgr.addrmu.Unlock()
|
||||
|
||||
@ -132,13 +133,13 @@ func (mgr *AddrManager) AddAddrs(p ID, addrs []ma.Multiaddr, ttl time.Duration)
|
||||
}
|
||||
|
||||
// SetAddr calls mgr.SetAddrs(p, addr, ttl)
|
||||
func (mgr *AddrManager) SetAddr(p ID, addr ma.Multiaddr, ttl time.Duration) {
|
||||
func (mgr *AddrManager) SetAddr(p peer.ID, addr ma.Multiaddr, ttl time.Duration) {
|
||||
mgr.SetAddrs(p, []ma.Multiaddr{addr}, ttl)
|
||||
}
|
||||
|
||||
// SetAddrs sets the ttl on addresses. This clears any TTL there previously.
|
||||
// This is used when we receive the best estimate of the validity of an address.
|
||||
func (mgr *AddrManager) SetAddrs(p ID, addrs []ma.Multiaddr, ttl time.Duration) {
|
||||
func (mgr *AddrManager) SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration) {
|
||||
mgr.addrmu.Lock()
|
||||
defer mgr.addrmu.Unlock()
|
||||
|
||||
@ -175,7 +176,7 @@ func (mgr *AddrManager) SetAddrs(p ID, addrs []ma.Multiaddr, ttl time.Duration)
|
||||
}
|
||||
|
||||
// Addresses returns all known (and valid) addresses for a given
|
||||
func (mgr *AddrManager) Addrs(p ID) []ma.Multiaddr {
|
||||
func (mgr *AddrManager) Addrs(p peer.ID) []ma.Multiaddr {
|
||||
mgr.addrmu.Lock()
|
||||
defer mgr.addrmu.Unlock()
|
||||
|
||||
@ -208,7 +209,7 @@ func (mgr *AddrManager) Addrs(p ID) []ma.Multiaddr {
|
||||
}
|
||||
|
||||
// ClearAddresses removes all previously stored addresses
|
||||
func (mgr *AddrManager) ClearAddrs(p ID) {
|
||||
func (mgr *AddrManager) ClearAddrs(p peer.ID) {
|
||||
mgr.addrmu.Lock()
|
||||
defer mgr.addrmu.Unlock()
|
||||
mgr.init()
|
||||
@ -216,7 +217,7 @@ func (mgr *AddrManager) ClearAddrs(p ID) {
|
||||
mgr.addrs[p] = make(addrSet) // clear what was there before
|
||||
}
|
||||
|
||||
func (mgr *AddrManager) removeSub(p ID, s *addrSub) {
|
||||
func (mgr *AddrManager) removeSub(p peer.ID, s *addrSub) {
|
||||
mgr.addrmu.Lock()
|
||||
defer mgr.addrmu.Unlock()
|
||||
subs := mgr.addrSubs[p]
|
||||
@ -243,7 +244,7 @@ func (s *addrSub) pubAddr(a ma.Multiaddr) {
|
||||
}
|
||||
}
|
||||
|
||||
func (mgr *AddrManager) AddrStream(ctx context.Context, p ID) <-chan ma.Multiaddr {
|
||||
func (mgr *AddrManager) AddrStream(ctx context.Context, p peer.ID) <-chan ma.Multiaddr {
|
||||
mgr.addrmu.Lock()
|
||||
defer mgr.addrmu.Unlock()
|
||||
mgr.init()
|
||||
|
@ -1,14 +1,15 @@
|
||||
package peer
|
||||
package peerstore
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/go-libp2p-peer"
|
||||
ma "github.com/jbenet/go-multiaddr"
|
||||
)
|
||||
|
||||
func IDS(t *testing.T, ids string) ID {
|
||||
id, err := IDB58Decode(ids)
|
||||
func IDS(t *testing.T, ids string) peer.ID {
|
||||
id, err := peer.IDB58Decode(ids)
|
||||
if err != nil {
|
||||
t.Fatalf("id %q is bad: %s", ids, err)
|
||||
}
|
||||
|
16
metrics.go
16
metrics.go
@ -1,8 +1,10 @@
|
||||
package peer
|
||||
package peerstore
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/go-libp2p-peer"
|
||||
)
|
||||
|
||||
// LatencyEWMASmooting governs the decay of the EWMA (the speed
|
||||
@ -15,26 +17,26 @@ var LatencyEWMASmoothing = 0.1
|
||||
type Metrics interface {
|
||||
|
||||
// RecordLatency records a new latency measurement
|
||||
RecordLatency(ID, time.Duration)
|
||||
RecordLatency(peer.ID, time.Duration)
|
||||
|
||||
// LatencyEWMA returns an exponentially-weighted moving avg.
|
||||
// of all measurements of a peer's latency.
|
||||
LatencyEWMA(ID) time.Duration
|
||||
LatencyEWMA(peer.ID) time.Duration
|
||||
}
|
||||
|
||||
type metrics struct {
|
||||
latmap map[ID]time.Duration
|
||||
latmap map[peer.ID]time.Duration
|
||||
latmu sync.RWMutex
|
||||
}
|
||||
|
||||
func NewMetrics() Metrics {
|
||||
return &metrics{
|
||||
latmap: make(map[ID]time.Duration),
|
||||
latmap: make(map[peer.ID]time.Duration),
|
||||
}
|
||||
}
|
||||
|
||||
// RecordLatency records a new latency measurement
|
||||
func (m *metrics) RecordLatency(p ID, next time.Duration) {
|
||||
func (m *metrics) RecordLatency(p peer.ID, next time.Duration) {
|
||||
nextf := float64(next)
|
||||
s := LatencyEWMASmoothing
|
||||
if s > 1 || s < 0 {
|
||||
@ -55,7 +57,7 @@ func (m *metrics) RecordLatency(p ID, next time.Duration) {
|
||||
|
||||
// LatencyEWMA returns an exponentially-weighted moving avg.
|
||||
// of all measurements of a peer's latency.
|
||||
func (m *metrics) LatencyEWMA(p ID) time.Duration {
|
||||
func (m *metrics) LatencyEWMA(p peer.ID) time.Duration {
|
||||
m.latmu.RLock()
|
||||
lat := m.latmap[p]
|
||||
m.latmu.RUnlock()
|
||||
|
@ -1,4 +1,4 @@
|
||||
package peer_test
|
||||
package peerstore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -7,14 +7,13 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
peer "github.com/ipfs/go-libp2p-peer"
|
||||
testutil "github.com/ipfs/go-libp2p-peer/test"
|
||||
)
|
||||
|
||||
func TestLatencyEWMAFun(t *testing.T) {
|
||||
t.Skip("run it for fun")
|
||||
|
||||
m := peer.NewMetrics()
|
||||
m := NewMetrics()
|
||||
id, err := testutil.RandPeerID()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -41,7 +40,7 @@ func TestLatencyEWMAFun(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLatencyEWMA(t *testing.T) {
|
||||
m := peer.NewMetrics()
|
||||
m := NewMetrics()
|
||||
id, err := testutil.RandPeerID()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
18
package.json
18
package.json
@ -7,18 +7,6 @@
|
||||
"dvcsimport": "github.com/ipfs/go-libp2p-peer"
|
||||
},
|
||||
"gxDependencies": [
|
||||
{
|
||||
"author": "whyrusleeping",
|
||||
"hash": "QmT8rehPR3F6bmwL6zjUN8XpiDBFFpMP2myPdC6ApsWfJf",
|
||||
"name": "go-base58",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
{
|
||||
"author": "whyrusleeping",
|
||||
"hash": "QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku",
|
||||
"name": "go-multihash",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
{
|
||||
"author": "whyrusleeping",
|
||||
"hash": "QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1",
|
||||
@ -66,6 +54,12 @@
|
||||
"hash": "QmeLQ13LftT9XhNn22piZc3GP56fGqhijuL5Y8KdUaRn1g",
|
||||
"name": "mafmt",
|
||||
"version": "1.1.1"
|
||||
},
|
||||
{
|
||||
"author": "whyrusleeping",
|
||||
"hash": "QmQGwpJy9P4yXZySmqkZEXCmbBpJUb8xntCv8Ca4taZwDC",
|
||||
"name": "go-libp2p-peer",
|
||||
"version": "2.0.0"
|
||||
}
|
||||
],
|
||||
"gxVersion": "0.4.0",
|
||||
|
185
peer.go
185
peer.go
@ -1,185 +0,0 @@
|
||||
// package peer implements an object used to represent peers in the ipfs network.
|
||||
package peer
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
u "github.com/ipfs/go-ipfs-util"
|
||||
ic "github.com/ipfs/go-libp2p-crypto"
|
||||
logging "github.com/ipfs/go-log" // ID represents the identity of a peer.
|
||||
b58 "github.com/jbenet/go-base58"
|
||||
ma "github.com/jbenet/go-multiaddr"
|
||||
mh "github.com/jbenet/go-multihash"
|
||||
)
|
||||
|
||||
var log = logging.Logger("peer")
|
||||
|
||||
type ID string
|
||||
|
||||
// Pretty returns a b58-encoded string of the ID
|
||||
func (id ID) Pretty() string {
|
||||
return IDB58Encode(id)
|
||||
}
|
||||
|
||||
func (id ID) Loggable() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"peerID": id.Pretty(),
|
||||
}
|
||||
}
|
||||
|
||||
// String prints out the peer.
|
||||
//
|
||||
// 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 ID) String() string {
|
||||
pid := id.Pretty()
|
||||
|
||||
//All sha256 nodes start with Qm
|
||||
//We can skip the Qm to make the peer.ID more useful
|
||||
if strings.HasPrefix(pid, "Qm") {
|
||||
pid = pid[2:]
|
||||
}
|
||||
|
||||
maxRunes := 6
|
||||
if len(pid) < maxRunes {
|
||||
maxRunes = len(pid)
|
||||
}
|
||||
return fmt.Sprintf("<peer.ID %s>", pid[:maxRunes])
|
||||
}
|
||||
|
||||
// MatchesPrivateKey tests whether this ID was derived from sk
|
||||
func (id ID) MatchesPrivateKey(sk ic.PrivKey) bool {
|
||||
return id.MatchesPublicKey(sk.GetPublic())
|
||||
}
|
||||
|
||||
// MatchesPublicKey tests whether this ID was derived from pk
|
||||
func (id ID) MatchesPublicKey(pk ic.PubKey) bool {
|
||||
oid, err := IDFromPublicKey(pk)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return oid == id
|
||||
}
|
||||
|
||||
// IDFromString cast a string to ID type, and validate
|
||||
// the id to make sure it is a multihash.
|
||||
func IDFromString(s string) (ID, error) {
|
||||
if _, err := mh.Cast([]byte(s)); err != nil {
|
||||
return ID(""), err
|
||||
}
|
||||
return ID(s), nil
|
||||
}
|
||||
|
||||
// IDFromBytes cast a string to ID type, and validate
|
||||
// the id to make sure it is a multihash.
|
||||
func IDFromBytes(b []byte) (ID, error) {
|
||||
if _, err := mh.Cast(b); err != nil {
|
||||
return ID(""), err
|
||||
}
|
||||
return ID(b), nil
|
||||
}
|
||||
|
||||
// IDB58Decode returns a b58-decoded Peer
|
||||
func IDB58Decode(s string) (ID, error) {
|
||||
m, err := mh.FromB58String(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ID(m), err
|
||||
}
|
||||
|
||||
// IDB58Encode returns b58-encoded string
|
||||
func IDB58Encode(id ID) string {
|
||||
return b58.Encode([]byte(id))
|
||||
}
|
||||
|
||||
// IDHexDecode returns a b58-decoded Peer
|
||||
func IDHexDecode(s string) (ID, error) {
|
||||
m, err := mh.FromHexString(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ID(m), err
|
||||
}
|
||||
|
||||
// IDHexEncode returns b58-encoded string
|
||||
func IDHexEncode(id ID) string {
|
||||
return hex.EncodeToString([]byte(id))
|
||||
}
|
||||
|
||||
// IDFromPublicKey returns the Peer ID corresponding to pk
|
||||
func IDFromPublicKey(pk ic.PubKey) (ID, error) {
|
||||
b, err := pk.Bytes()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
hash := u.Hash(b)
|
||||
return ID(hash), nil
|
||||
}
|
||||
|
||||
// IDFromPrivateKey returns the Peer ID corresponding to sk
|
||||
func IDFromPrivateKey(sk ic.PrivKey) (ID, error) {
|
||||
return IDFromPublicKey(sk.GetPublic())
|
||||
}
|
||||
|
||||
// Map maps a Peer ID to a struct.
|
||||
type Set map[ID]struct{}
|
||||
|
||||
// PeerInfo is a small struct used to pass around a peer with
|
||||
// a set of addresses (and later, keys?). This is not meant to be
|
||||
// a complete view of the system, but rather to model updates to
|
||||
// the peerstore. It is used by things like the routing system.
|
||||
type PeerInfo struct {
|
||||
ID ID
|
||||
Addrs []ma.Multiaddr
|
||||
}
|
||||
|
||||
func (pi *PeerInfo) Loggable() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"peerID": pi.ID.Pretty(),
|
||||
"addrs": pi.Addrs,
|
||||
}
|
||||
}
|
||||
|
||||
func (pi *PeerInfo) MarshalJSON() ([]byte, error) {
|
||||
out := make(map[string]interface{})
|
||||
out["ID"] = IDB58Encode(pi.ID)
|
||||
var addrs []string
|
||||
for _, a := range pi.Addrs {
|
||||
addrs = append(addrs, a.String())
|
||||
}
|
||||
out["Addrs"] = addrs
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
func (pi *PeerInfo) UnmarshalJSON(b []byte) error {
|
||||
var data map[string]interface{}
|
||||
err := json.Unmarshal(b, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pid, err := IDB58Decode(data["ID"].(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pi.ID = pid
|
||||
addrs, ok := data["Addrs"].([]interface{})
|
||||
if ok {
|
||||
for _, a := range addrs {
|
||||
pi.Addrs = append(pi.Addrs, ma.StringCast(a.(string)))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IDSlice for sorting peers
|
||||
type IDSlice []ID
|
||||
|
||||
func (es IDSlice) Len() int { return len(es) }
|
||||
func (es IDSlice) Swap(i, j int) { es[i], es[j] = es[j], es[i] }
|
||||
func (es IDSlice) Less(i, j int) bool { return string(es[i]) < string(es[j]) }
|
163
peer_test.go
163
peer_test.go
@ -1,163 +0,0 @@
|
||||
package peer_test
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
u "github.com/ipfs/go-ipfs-util"
|
||||
ic "github.com/ipfs/go-libp2p-crypto"
|
||||
. "github.com/ipfs/go-libp2p-peer"
|
||||
tu "github.com/ipfs/go-libp2p-peer/test"
|
||||
|
||||
b58 "github.com/jbenet/go-base58"
|
||||
)
|
||||
|
||||
var gen1 keyset // generated
|
||||
var gen2 keyset // generated
|
||||
var man keyset // manual
|
||||
|
||||
func init() {
|
||||
if err := gen1.generate(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := gen2.generate(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
skManBytes = strings.Replace(skManBytes, "\n", "", -1)
|
||||
if err := man.load(hpkpMan, skManBytes); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type keyset struct {
|
||||
sk ic.PrivKey
|
||||
pk ic.PubKey
|
||||
hpk string
|
||||
hpkp string
|
||||
}
|
||||
|
||||
func (ks *keyset) generate() error {
|
||||
var err error
|
||||
ks.sk, ks.pk, err = tu.RandTestKeyPair(512)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bpk, err := ks.pk.Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ks.hpk = string(u.Hash(bpk))
|
||||
ks.hpkp = b58.Encode([]byte(ks.hpk))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ks *keyset) load(hpkp, skBytesStr string) error {
|
||||
skBytes, err := base64.StdEncoding.DecodeString(skBytesStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ks.sk, err = ic.UnmarshalPrivateKey(skBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ks.pk = ks.sk.GetPublic()
|
||||
bpk, err := ks.pk.Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ks.hpk = string(u.Hash(bpk))
|
||||
ks.hpkp = b58.Encode([]byte(ks.hpk))
|
||||
if ks.hpkp != hpkp {
|
||||
return fmt.Errorf("hpkp doesn't match key. %s", hpkp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestIDMatchesPublicKey(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")
|
||||
}
|
||||
|
||||
if !p1.MatchesPublicKey(ks.pk) {
|
||||
t.Fatal("p1 does not match pk")
|
||||
}
|
||||
|
||||
p2, err := IDFromPublicKey(ks.pk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if p1 != p2 {
|
||||
t.Error("p1 and p2 differ", p1.Pretty(), p2.Pretty())
|
||||
}
|
||||
|
||||
if p2.Pretty() != ks.hpkp {
|
||||
t.Error("hpkp and p2.Pretty differ", ks.hpkp, p2.Pretty())
|
||||
}
|
||||
}
|
||||
|
||||
test(gen1)
|
||||
test(gen2)
|
||||
test(man)
|
||||
}
|
||||
|
||||
func TestIDMatchesPrivateKey(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")
|
||||
}
|
||||
|
||||
if !p1.MatchesPrivateKey(ks.sk) {
|
||||
t.Fatal("p1 does not match sk")
|
||||
}
|
||||
|
||||
p2, err := IDFromPrivateKey(ks.sk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if p1 != p2 {
|
||||
t.Error("p1 and p2 differ", p1.Pretty(), p2.Pretty())
|
||||
}
|
||||
}
|
||||
|
||||
test(gen1)
|
||||
test(gen2)
|
||||
test(man)
|
||||
}
|
||||
|
||||
var hpkpMan = `QmRK3JgmVEGiewxWbhpXLJyjWuGuLeSTMTndA1coMHEy5o`
|
||||
var skManBytes = `
|
||||
CAAS4AQwggJcAgEAAoGBAL7w+Wc4VhZhCdM/+Hccg5Nrf4q9NXWwJylbSrXz/unFS24wyk6pEk0zi3W
|
||||
7li+vSNVO+NtJQw9qGNAMtQKjVTP+3Vt/jfQRnQM3s6awojtjueEWuLYVt62z7mofOhCtj+VwIdZNBo
|
||||
/EkLZ0ETfcvN5LVtLYa8JkXybnOPsLvK+PAgMBAAECgYBdk09HDM7zzL657uHfzfOVrdslrTCj6p5mo
|
||||
DzvCxLkkjIzYGnlPuqfNyGjozkpSWgSUc+X+EGLLl3WqEOVdWJtbM61fewEHlRTM5JzScvwrJ39t7o6
|
||||
CCAjKA0cBWBd6UWgbN/t53RoWvh9HrA2AW5YrT0ZiAgKe9y7EMUaENVJ8QJBAPhpdmb4ZL4Fkm4OKia
|
||||
NEcjzn6mGTlZtef7K/0oRC9+2JkQnCuf6HBpaRhJoCJYg7DW8ZY+AV6xClKrgjBOfERMCQQDExhnzu2
|
||||
dsQ9k8QChBlpHO0TRbZBiQfC70oU31kM1AeLseZRmrxv9Yxzdl8D693NNWS2JbKOXl0kMHHcuGQLMVA
|
||||
kBZ7WvkmPV3aPL6jnwp2pXepntdVnaTiSxJ1dkXShZ/VSSDNZMYKY306EtHrIu3NZHtXhdyHKcggDXr
|
||||
qkBrdgErAkAlpGPojUwemOggr4FD8sLX1ot2hDJyyV7OK2FXfajWEYJyMRL1Gm9Uk1+Un53RAkJneqp
|
||||
JGAzKpyttXBTIDO51AkEA98KTiROMnnU8Y6Mgcvr68/SMIsvCYMt9/mtwSBGgl80VaTQ5Hpaktl6Xbh
|
||||
VUt5Wv0tRxlXZiViCGCD1EtrrwTw==
|
||||
`
|
55
peerinfo.go
Normal file
55
peerinfo.go
Normal file
@ -0,0 +1,55 @@
|
||||
package peerstore
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/ipfs/go-libp2p-peer"
|
||||
ma "github.com/jbenet/go-multiaddr"
|
||||
)
|
||||
|
||||
// PeerInfo is a small struct used to pass around a peer with
|
||||
// a set of addresses (and later, keys?). This is not meant to be
|
||||
// a complete view of the system, but rather to model updates to
|
||||
// the peerstore. It is used by things like the routing system.
|
||||
type PeerInfo struct {
|
||||
ID peer.ID
|
||||
Addrs []ma.Multiaddr
|
||||
}
|
||||
|
||||
func (pi *PeerInfo) Loggable() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"peerID": pi.ID.Pretty(),
|
||||
"addrs": pi.Addrs,
|
||||
}
|
||||
}
|
||||
|
||||
func (pi *PeerInfo) MarshalJSON() ([]byte, error) {
|
||||
out := make(map[string]interface{})
|
||||
out["ID"] = pi.ID.Pretty()
|
||||
var addrs []string
|
||||
for _, a := range pi.Addrs {
|
||||
addrs = append(addrs, a.String())
|
||||
}
|
||||
out["Addrs"] = addrs
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
func (pi *PeerInfo) UnmarshalJSON(b []byte) error {
|
||||
var data map[string]interface{}
|
||||
err := json.Unmarshal(b, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pid, err := peer.IDB58Decode(data["ID"].(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pi.ID = pid
|
||||
addrs, ok := data["Addrs"].([]interface{})
|
||||
if ok {
|
||||
for _, a := range addrs {
|
||||
pi.Addrs = append(pi.Addrs, ma.StringCast(a.(string)))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
74
peerstore.go
74
peerstore.go
@ -1,4 +1,4 @@
|
||||
package peer
|
||||
package peerstore
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -9,10 +9,14 @@ import (
|
||||
|
||||
//ds "github.com/jbenet/go-datastore"
|
||||
//dssync "github.com/jbenet/go-datastore/sync"
|
||||
"github.com/ipfs/go-libp2p-peer"
|
||||
logging "github.com/ipfs/go-log"
|
||||
ma "github.com/jbenet/go-multiaddr"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var log = logging.Logger("peerstore")
|
||||
|
||||
const (
|
||||
// AddressTTL is the expiration time of addresses.
|
||||
AddressTTL = time.Hour
|
||||
@ -26,18 +30,18 @@ type Peerstore interface {
|
||||
Metrics
|
||||
|
||||
// Peers returns a list of all peer.IDs in this Peerstore
|
||||
Peers() []ID
|
||||
Peers() []peer.ID
|
||||
|
||||
// PeerInfo returns a peer.PeerInfo struct for given peer.ID.
|
||||
// This is a small slice of the information Peerstore has on
|
||||
// that peer, useful to other services.
|
||||
PeerInfo(ID) PeerInfo
|
||||
PeerInfo(peer.ID) PeerInfo
|
||||
|
||||
// Get/Put is a simple registry for other peer-related key/value pairs.
|
||||
// if we find something we use often, it should become its own set of
|
||||
// methods. this is a last resort.
|
||||
Get(id ID, key string) (interface{}, error)
|
||||
Put(id ID, key string, val interface{}) error
|
||||
Get(id peer.ID, key string) (interface{}, error)
|
||||
Put(id peer.ID, key string, val interface{}) error
|
||||
}
|
||||
|
||||
// AddrBook is an interface that fits the new AddrManager. I'm patching
|
||||
@ -45,58 +49,58 @@ type Peerstore interface {
|
||||
type AddrBook interface {
|
||||
|
||||
// AddAddr calls AddAddrs(p, []ma.Multiaddr{addr}, ttl)
|
||||
AddAddr(p ID, addr ma.Multiaddr, ttl time.Duration)
|
||||
AddAddr(p peer.ID, addr ma.Multiaddr, ttl time.Duration)
|
||||
|
||||
// AddAddrs gives AddrManager addresses to use, with a given ttl
|
||||
// (time-to-live), after which the address is no longer valid.
|
||||
// If the manager has a longer TTL, the operation is a no-op for that address
|
||||
AddAddrs(p ID, addrs []ma.Multiaddr, ttl time.Duration)
|
||||
AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration)
|
||||
|
||||
// SetAddr calls mgr.SetAddrs(p, addr, ttl)
|
||||
SetAddr(p ID, addr ma.Multiaddr, ttl time.Duration)
|
||||
SetAddr(p peer.ID, addr ma.Multiaddr, ttl time.Duration)
|
||||
|
||||
// SetAddrs sets the ttl on addresses. This clears any TTL there previously.
|
||||
// This is used when we receive the best estimate of the validity of an address.
|
||||
SetAddrs(p ID, addrs []ma.Multiaddr, ttl time.Duration)
|
||||
SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration)
|
||||
|
||||
// Addresses returns all known (and valid) addresses for a given
|
||||
Addrs(p ID) []ma.Multiaddr
|
||||
Addrs(p peer.ID) []ma.Multiaddr
|
||||
|
||||
// AddrStream returns a channel that gets all addresses for a given
|
||||
// peer sent on it. If new addresses are added after the call is made
|
||||
// they will be sent along through the channel as well.
|
||||
AddrStream(context.Context, ID) <-chan ma.Multiaddr
|
||||
AddrStream(context.Context, peer.ID) <-chan ma.Multiaddr
|
||||
|
||||
// ClearAddresses removes all previously stored addresses
|
||||
ClearAddrs(p ID)
|
||||
ClearAddrs(p peer.ID)
|
||||
}
|
||||
|
||||
// KeyBook tracks the Public keys of Peers.
|
||||
type KeyBook interface {
|
||||
PubKey(ID) ic.PubKey
|
||||
AddPubKey(ID, ic.PubKey) error
|
||||
PubKey(peer.ID) ic.PubKey
|
||||
AddPubKey(peer.ID, ic.PubKey) error
|
||||
|
||||
PrivKey(ID) ic.PrivKey
|
||||
AddPrivKey(ID, ic.PrivKey) error
|
||||
PrivKey(peer.ID) ic.PrivKey
|
||||
AddPrivKey(peer.ID, ic.PrivKey) error
|
||||
}
|
||||
|
||||
type keybook struct {
|
||||
pks map[ID]ic.PubKey
|
||||
sks map[ID]ic.PrivKey
|
||||
pks map[peer.ID]ic.PubKey
|
||||
sks map[peer.ID]ic.PrivKey
|
||||
|
||||
sync.RWMutex // same lock. wont happen a ton.
|
||||
}
|
||||
|
||||
func newKeybook() *keybook {
|
||||
return &keybook{
|
||||
pks: map[ID]ic.PubKey{},
|
||||
sks: map[ID]ic.PrivKey{},
|
||||
pks: map[peer.ID]ic.PubKey{},
|
||||
sks: map[peer.ID]ic.PrivKey{},
|
||||
}
|
||||
}
|
||||
|
||||
func (kb *keybook) Peers() []ID {
|
||||
func (kb *keybook) Peers() []peer.ID {
|
||||
kb.RLock()
|
||||
ps := make([]ID, 0, len(kb.pks)+len(kb.sks))
|
||||
ps := make([]peer.ID, 0, len(kb.pks)+len(kb.sks))
|
||||
for p := range kb.pks {
|
||||
ps = append(ps, p)
|
||||
}
|
||||
@ -109,14 +113,14 @@ func (kb *keybook) Peers() []ID {
|
||||
return ps
|
||||
}
|
||||
|
||||
func (kb *keybook) PubKey(p ID) ic.PubKey {
|
||||
func (kb *keybook) PubKey(p peer.ID) ic.PubKey {
|
||||
kb.RLock()
|
||||
pk := kb.pks[p]
|
||||
kb.RUnlock()
|
||||
return pk
|
||||
}
|
||||
|
||||
func (kb *keybook) AddPubKey(p ID, pk ic.PubKey) error {
|
||||
func (kb *keybook) AddPubKey(p peer.ID, pk ic.PubKey) error {
|
||||
|
||||
// check it's correct first
|
||||
if !p.MatchesPublicKey(pk) {
|
||||
@ -129,14 +133,14 @@ func (kb *keybook) AddPubKey(p ID, pk ic.PubKey) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (kb *keybook) PrivKey(p ID) ic.PrivKey {
|
||||
func (kb *keybook) PrivKey(p peer.ID) ic.PrivKey {
|
||||
kb.RLock()
|
||||
sk := kb.sks[p]
|
||||
kb.RUnlock()
|
||||
return sk
|
||||
}
|
||||
|
||||
func (kb *keybook) AddPrivKey(p ID, sk ic.PrivKey) error {
|
||||
func (kb *keybook) AddPrivKey(p peer.ID, sk ic.PrivKey) error {
|
||||
|
||||
if sk == nil {
|
||||
return errors.New("sk is nil (PrivKey)")
|
||||
@ -176,7 +180,7 @@ func NewPeerstore() Peerstore {
|
||||
}
|
||||
}
|
||||
|
||||
func (ps *peerstore) Put(p ID, key string, val interface{}) error {
|
||||
func (ps *peerstore) Put(p peer.ID, key string, val interface{}) error {
|
||||
//dsk := ds.NewKey(string(p) + "/" + key)
|
||||
//return ps.ds.Put(dsk, val)
|
||||
ps.dslock.Lock()
|
||||
@ -185,7 +189,7 @@ func (ps *peerstore) Put(p ID, key string, val interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ps *peerstore) Get(p ID, key string) (interface{}, error) {
|
||||
func (ps *peerstore) Get(p peer.ID, key string) (interface{}, error) {
|
||||
//dsk := ds.NewKey(string(p) + "/" + key)
|
||||
//return ps.ds.Get(dsk)
|
||||
|
||||
@ -198,8 +202,8 @@ func (ps *peerstore) Get(p ID, key string) (interface{}, error) {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (ps *peerstore) Peers() []ID {
|
||||
set := map[ID]struct{}{}
|
||||
func (ps *peerstore) Peers() []peer.ID {
|
||||
set := map[peer.ID]struct{}{}
|
||||
for _, p := range ps.keybook.Peers() {
|
||||
set[p] = struct{}{}
|
||||
}
|
||||
@ -207,21 +211,21 @@ func (ps *peerstore) Peers() []ID {
|
||||
set[p] = struct{}{}
|
||||
}
|
||||
|
||||
pps := make([]ID, 0, len(set))
|
||||
pps := make([]peer.ID, 0, len(set))
|
||||
for p := range set {
|
||||
pps = append(pps, p)
|
||||
}
|
||||
return pps
|
||||
}
|
||||
|
||||
func (ps *peerstore) PeerInfo(p ID) PeerInfo {
|
||||
func (ps *peerstore) PeerInfo(p peer.ID) PeerInfo {
|
||||
return PeerInfo{
|
||||
ID: p,
|
||||
Addrs: ps.AddrManager.Addrs(p),
|
||||
}
|
||||
}
|
||||
|
||||
func PeerInfos(ps Peerstore, peers []ID) []PeerInfo {
|
||||
func PeerInfos(ps Peerstore, peers []peer.ID) []PeerInfo {
|
||||
pi := make([]PeerInfo, len(peers))
|
||||
for i, p := range peers {
|
||||
pi[i] = ps.PeerInfo(p)
|
||||
@ -229,8 +233,8 @@ func PeerInfos(ps Peerstore, peers []ID) []PeerInfo {
|
||||
return pi
|
||||
}
|
||||
|
||||
func PeerInfoIDs(pis []PeerInfo) []ID {
|
||||
ps := make([]ID, len(pis))
|
||||
func PeerInfoIDs(pis []PeerInfo) []peer.ID {
|
||||
ps := make([]peer.ID, len(pis))
|
||||
for i, pi := range pis {
|
||||
ps[i] = pi.ID
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package peer
|
||||
package peerstore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
peer "github.com/ipfs/go-libp2p-peer"
|
||||
ma "github.com/jbenet/go-multiaddr"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@ -26,7 +27,7 @@ func getAddrs(t *testing.T, n int) []ma.Multiaddr {
|
||||
func TestAddrStream(t *testing.T) {
|
||||
addrs := getAddrs(t, 100)
|
||||
|
||||
pid := ID("testpeer")
|
||||
pid := peer.ID("testpeer")
|
||||
|
||||
ps := NewPeerstore()
|
||||
|
||||
@ -91,7 +92,7 @@ func TestAddrStream(t *testing.T) {
|
||||
|
||||
func TestGetStreamBeforePeerAdded(t *testing.T) {
|
||||
addrs := getAddrs(t, 10)
|
||||
pid := ID("testpeer")
|
||||
pid := peer.ID("testpeer")
|
||||
|
||||
ps := NewPeerstore()
|
||||
|
||||
@ -142,7 +143,7 @@ func TestGetStreamBeforePeerAdded(t *testing.T) {
|
||||
|
||||
func TestAddrStreamDuplicates(t *testing.T) {
|
||||
addrs := getAddrs(t, 10)
|
||||
pid := ID("testpeer")
|
||||
pid := peer.ID("testpeer")
|
||||
|
||||
ps := NewPeerstore()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user