From 56cec2887711a9266ae5bb2be9e19d20f74d938f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 2 Mar 2020 19:10:40 +0000 Subject: [PATCH 1/2] WIP peerstore: model address provenance data type. --- peerstore/provenance.go | 78 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 peerstore/provenance.go diff --git a/peerstore/provenance.go b/peerstore/provenance.go new file mode 100644 index 00000000..983540b5 --- /dev/null +++ b/peerstore/provenance.go @@ -0,0 +1,78 @@ +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 +} From 0cdae707786dc4e27e1bfb224be84c3755b38ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 4 Mar 2020 16:47:45 +0000 Subject: [PATCH 2/2] peerstore: generic address and peer labels. --- peerstore/labels.go | 82 +++++++++++++++++++++++++++++++++++++++++ peerstore/options.go | 43 +++++++++++++++++++++ peerstore/peerstore.go | 22 +++++------ peerstore/provenance.go | 78 --------------------------------------- 4 files changed, 136 insertions(+), 89 deletions(-) create mode 100644 peerstore/labels.go create mode 100644 peerstore/options.go delete mode 100644 peerstore/provenance.go diff --git a/peerstore/labels.go b/peerstore/labels.go new file mode 100644 index 00000000..e4309386 --- /dev/null +++ b/peerstore/labels.go @@ -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 +} diff --git a/peerstore/options.go b/peerstore/options.go new file mode 100644 index 00000000..5d63f0fe --- /dev/null +++ b/peerstore/options.go @@ -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 + } +} diff --git a/peerstore/peerstore.go b/peerstore/peerstore.go index e77b3c13..84953a4f 100644 --- a/peerstore/peerstore.go +++ b/peerstore/peerstore.go @@ -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. diff --git a/peerstore/provenance.go b/peerstore/provenance.go deleted file mode 100644 index 983540b5..00000000 --- a/peerstore/provenance.go +++ /dev/null @@ -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 -}