Skip to content
This repository has been archived by the owner on Sep 6, 2022. It is now read-only.

peerstore: model address labels #123

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions peerstore/labels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package peerstore

import (
"fmt"
"sync"
)

// Label is an arbitrary label attached to an address or a peer. A Label can
// indicate the source of an address, a "pin" by a subsystem, an address scope,
// or an arbitrary tag.
//
// Labels are byte values in binary format, bound to strings via the `BindLabel`
// function to facilitate debugging.
//
// Values [0x00, 0x80) are RESERVED for the developers of libp2p. Users are free
// to register custom application-level labels in the range [0x80, 0xff], via
// the BindLabel function.
type Label uint8

const (
// LabelSourceUnknown means that the source of an address is unknown.
//
// This is usually the case when an address has been inserted through the
// legacy methods of the peerstore.
LabelSourceUnknown = Label(0x00)

// LabelSourceThirdParty indicates that we've learnt this address via a
// third party.
LabelSourceThirdParty = Label(0x01)

// LabelSourceUncertified means that an address has been returned by the
// peer in question, but it is not authenticated, i.e. it is not part of a
// certified peer record.
LabelSourceUncertified = Label(0x02)

// LabelSourceCertified means that the address is part of a standard
// certified libp2p peer record.
LabelSourceCertified = Label(0x03)

// LabelSourceManual means that an address has been specified manually by a
// human, and therefore should take high precedence.
LabelSourceManual = Label(0x04)
)

var (
// labelsLk only guards registration (i.e. writes, not reads).
//
// It is assumed that user-defined labels will be registered during system
// initialisation. Once the system becomes operational, the descriptions are
// accessed by the String() method *without taking a lock*.
labelsLk sync.Mutex

// labelsTable stores label allocations and their string mappings.
labelsTable = [256]string{
0x00: "unknown",
0x01: "third_party",
0x02: "untrusted",
0x03: "trusted",
0x04: "manual",
}
)

func (p Label) String() string {
return labelsTable[p]
}

// BindLabel registers a user-defined label and binds it to a string
// description.
func BindLabel(p Label, desc string) error {
labelsLk.Lock()
defer labelsLk.Unlock()

if p < 0x80 {
return fmt.Errorf("failed to register user-defined peerstore label "+
"due to range violation; should be in [0x80,0xff]; was: %x", p)
}
if d := labelsTable[p]; d != "" {
return fmt.Errorf("a label mapping for %x already exists: %s", p, d)
}
labelsTable[p] = desc
return nil
}
43 changes: 43 additions & 0 deletions peerstore/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package peerstore

// WriteOpt is an option to be used in peerstore write operations.
type WriteOpt func(*writeOpts) error

// ReadOpt is an option to be used in peerstore read/query operations.
type ReadOpt func(*readOpts) error

type writeOpts struct {
labels []Label
}

type readOpts struct {
includeLabels []Label
excludeLabels []Label
}

// Labels is a write option to set labels on addresses or peers during a write
// operation.
func Labels(labels ...Label) WriteOpt {
return func(wo *writeOpts) error {
wo.labels = labels
return nil
}
}

// IncludeLabels is a read option that restricts the results of a read/query
// operation to include ONLY addresses or peers with the listed labels.
func IncludeLabels(labels ...Label) ReadOpt {
return func(ro *readOpts) error {
ro.includeLabels = labels
return nil
}
}

// ExcludeLabels is a read option that restricts the results of a read/query
// operation to include all hits BUT the ones with the listed labels.
func ExcludeLabels(labels ...Label) ReadOpt {
return func(ro *readOpts) error {
ro.excludeLabels = labels
return nil
}
}
22 changes: 11 additions & 11 deletions peerstore/peerstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,38 +88,38 @@ type PeerMetadata interface {
// AddrBook holds the multiaddrs of peers.
type AddrBook interface {

// AddAddr calls AddAddrs(p, []ma.Multiaddr{addr}, ttl)
AddAddr(p peer.ID, addr ma.Multiaddr, ttl time.Duration)
// AddAddr calls AddAddrs(p, []ma.Multiaddr{addr}, ttl, opts...)
AddAddr(p peer.ID, addr ma.Multiaddr, ttl time.Duration, opts ...WriteOpt)

// AddAddrs gives this AddrBook 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 peer.ID, addrs []ma.Multiaddr, ttl time.Duration)
AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration, opts ...WriteOpt)

// SetAddr calls mgr.SetAddrs(p, addr, ttl)
SetAddr(p peer.ID, addr ma.Multiaddr, ttl time.Duration)
// SetAddr calls SetAddrs(p, []ma.Multiaddr{addr}, ttl, opts...)
SetAddr(p peer.ID, addr ma.Multiaddr, ttl time.Duration, opts ...WriteOpt)

// 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 peer.ID, addrs []ma.Multiaddr, ttl time.Duration)
SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration, opts ...WriteOpt)

// UpdateAddrs updates the addresses associated with the given peer that have
// the given oldTTL to have the given newTTL.
UpdateAddrs(p peer.ID, oldTTL time.Duration, newTTL time.Duration)
UpdateAddrs(p peer.ID, oldTTL time.Duration, newTTL time.Duration, opts ...WriteOpt)

// Addrs returns all known (and valid) addresses for a given peer.
Addrs(p peer.ID) []ma.Multiaddr
Addrs(p peer.ID, opts ...ReadOpt) []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, peer.ID) <-chan ma.Multiaddr
AddrStream(context.Context, peer.ID, ...ReadOpt) <-chan ma.Multiaddr

// ClearAddresses removes all previously stored addresses
ClearAddrs(p peer.ID)
ClearAddrs(p peer.ID, opts ...WriteOpt)

// PeersWithAddrs returns all of the peer IDs stored in the AddrBook
PeersWithAddrs() peer.IDSlice
PeersWithAddrs(...ReadOpt) peer.IDSlice
}

// CertifiedAddrBook manages "self-certified" addresses for remote peers.
Expand Down