peerstore: generic address and peer labels.

This commit is contained in:
Raúl Kripalani 2020-03-04 16:47:45 +00:00
parent 56cec28877
commit 0cdae70778
4 changed files with 136 additions and 89 deletions

82
peerstore/labels.go Normal file
View File

@ -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
peerstore/options.go Normal file
View File

@ -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
}
}

View File

@ -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.

View File

@ -1,78 +0,0 @@
package peerstore
import (
"fmt"
"sync"
)
// AddressProvenance specifies the provenance of an address that has been stored
// in the peerstore.
//
// Values [0x00, 0x80) are RESERVED for the developers of libp2p.
//
// Users are free to register custom application-level provenances in the range
// [0x80, 0xff], via the RegisterAddressProvenance function.
type AddressProvenance uint8
const (
// ProvenanceUnknown means that the provenance of an address is unknown.
//
// This is usually the case when an address has been inserted through the
// legacy methods of the peerstore.
ProvenanceUnknown = AddressProvenance(0x00)
// ProvenanceThirdParty indicates that we've learnt this address via a third
// party.
ProvenanceThirdParty = AddressProvenance(0x10)
// ProvenanceUntrusted 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 peer
// record.
ProvenanceUntrusted = AddressProvenance(0x20)
// ProvenanceTrusted means that the address is part of an authenticated
// standard libp2p peer record.
ProvenanceTrusted = AddressProvenance(0x30)
// ProvenanceManual means that an address has been specified manually by a
// human, and therefore should take high precedence.
ProvenanceManual = AddressProvenance(0x7f)
)
var (
// provenanceLk only guards registration (i.e. writes, not reads).
//
// It is assumed that user-defined provenances will be registered during
// system initialisation. Once the system becomes operational, the
// descriptions are accessed by the String() method without taking a lock.
provenanceLk sync.Mutex
// provenanceDescs are the descriptions of the provenances, for debugging
// purposes.
provenanceDescs = [256]string{
0x00: "unknown",
0x10: "third_party",
0x20: "untrusted",
0x30: "trusted",
0x7f: "manual",
}
)
func (p AddressProvenance) String() string {
return provenanceDescs[p]
}
func RegisterAddressProvenance(p AddressProvenance, desc string) error {
provenanceLk.Lock()
defer provenanceLk.Unlock()
if p < 0x80 {
return fmt.Errorf("failed to register user-defined address provenance "+
"due to range violation; should be in [0x80,0xff]; was: %x", p)
}
if d := provenanceDescs[p]; d != "" {
return fmt.Errorf("an address provenance for code %x already exists: %s", p, d)
}
provenanceDescs[p] = desc
return nil
}