4242 baseLogger = logger .Desugar ()
4343)
4444
45- // BaseConnMgrScore is the base of the score set on the connection manager "kbucket" tag.
46- // It is added with the common prefix length between two peer IDs.
47- const BaseConnMgrScore = 5
45+ const (
46+ // BaseConnMgrScore is the base of the score set on the connection
47+ // manager "kbucket" tag. It is added with the common prefix length
48+ // between two peer IDs.
49+ baseConnMgrScore = 5
50+
51+ // UsefulConnMgrScore is given to peers that are among the first peers
52+ // to respond to a query.
53+ //
54+ // This score is given to peers the first time they're useful and lasts
55+ // until we disconnect from the peer.
56+ usefulConnMgrScore = 20
57+
58+ // UsefulConnMgrProtectedBuckets is the number of buckets where useful
59+ // peers are _protected_, instead of just given the useful score.
60+ usefulConnMgrProtectedBuckets = 2
61+ )
4862
4963type mode int
5064
@@ -58,11 +72,17 @@ const (
5872 kad2 protocol.ID = "/kad/2.0.0"
5973)
6074
75+ const (
76+ dhtUsefulTag = "dht-useful"
77+ kbucketTag = "kbucket"
78+ )
79+
6180// IpfsDHT is an implementation of Kademlia with S/Kademlia modifications.
6281// It is used to implement the base Routing module.
6382type IpfsDHT struct {
64- host host.Host // the network services we need
65- self peer.ID // Local peer (yourself)
83+ host host.Host // the network services we need
84+ self peer.ID // Local peer (yourself)
85+ selfKey kb.ID
6686 peerstore peerstore.Peerstore // Peer Registry
6787
6888 datastore ds.Datastore // Local data
@@ -250,6 +270,7 @@ func makeDHT(ctx context.Context, h host.Host, cfg config) (*IpfsDHT, error) {
250270 dht := & IpfsDHT {
251271 datastore : cfg .datastore ,
252272 self : h .ID (),
273+ selfKey : kb .ConvertPeerID (h .ID ()),
253274 peerstore : h .Peerstore (),
254275 host : h ,
255276 strmap : make (map [peer.ID ]* messageSender ),
@@ -337,17 +358,22 @@ func makeRtRefreshManager(dht *IpfsDHT, cfg config, maxLastSuccessfulOutboundThr
337358}
338359
339360func makeRoutingTable (dht * IpfsDHT , cfg config , maxLastSuccessfulOutboundThreshold time.Duration ) (* kb.RoutingTable , error ) {
340- self := kb .ConvertPeerID (dht .host .ID ())
341-
342- rt , err := kb .NewRoutingTable (cfg .bucketSize , self , time .Minute , dht .host .Peerstore (), maxLastSuccessfulOutboundThreshold )
361+ rt , err := kb .NewRoutingTable (cfg .bucketSize , dht .selfKey , time .Minute , dht .host .Peerstore (), maxLastSuccessfulOutboundThreshold )
343362 cmgr := dht .host .ConnManager ()
344363
345364 rt .PeerAdded = func (p peer.ID ) {
346- commonPrefixLen := kb .CommonPrefixLen (self , kb .ConvertPeerID (p ))
347- cmgr .TagPeer (p , "kbucket" , BaseConnMgrScore + commonPrefixLen )
365+ // We tag our closest peers with higher and higher scores so we
366+ // stay connected to our nearest neighbors.
367+ //
368+ // We _also_ (elsewhere) protect useful peers in the furthest
369+ // buckets (our "core" routing nodes) and give high scores to
370+ // all other useful peers.
371+ commonPrefixLen := kb .CommonPrefixLen (dht .selfKey , kb .ConvertPeerID (p ))
372+ cmgr .TagPeer (p , kbucketTag , baseConnMgrScore + commonPrefixLen )
348373 }
349374 rt .PeerRemoved = func (p peer.ID ) {
350- cmgr .UntagPeer (p , "kbucket" )
375+ cmgr .Unprotect (p , dhtUsefulTag )
376+ cmgr .UntagPeer (p , kbucketTag )
351377
352378 // try to fix the RT
353379 dht .fixRTIfNeeded ()
0 commit comments