diff --git a/fullrt/dht.go b/fullrt/dht.go index 825eabfab..ad165b370 100644 --- a/fullrt/dht.go +++ b/fullrt/dht.go @@ -183,8 +183,17 @@ func NewFullRT(h host.Host, protocolPrefix protocol.ID, options ...Option) (*Ful bulkSendParallelism: 20, } + var seedPeers []peer.AddrInfo + if fullrtcfg.skipInitialRTVerification { + for _, ai := range fullrtcfg.initialRTPeers { + rt.peerAddrs[ai.ID] = ai.Addrs + } + } else { + seedPeers = fullrtcfg.initialRTPeers[:] + } + rt.wg.Add(1) - go rt.runCrawler(ctx) + go rt.runCrawler(ctx, seedPeers) return rt, nil } @@ -216,6 +225,16 @@ func (dht *FullRT) Stat() map[string]peer.ID { return newMap } +func (dht *FullRT) GetRoutingTablePeers() []peer.AddrInfo { + dht.peerAddrsLk.RLock() + defer dht.peerAddrsLk.RUnlock() + ais := make([]peer.AddrInfo, 0, len(dht.peerAddrs)) + for id, addrs := range dht.peerAddrs { + ais = append(ais, peer.AddrInfo{ID: id, Addrs: addrs}) + } + return ais +} + func (dht *FullRT) Ready() bool { dht.rtLk.RLock() lastCrawlTime := dht.lastCrawlTime @@ -238,7 +257,7 @@ func (dht *FullRT) Host() host.Host { return dht.h } -func (dht *FullRT) runCrawler(ctx context.Context) { +func (dht *FullRT) runCrawler(ctx context.Context, initialSeedPeers []peer.AddrInfo) { defer dht.wg.Done() t := time.NewTicker(dht.crawlerInterval) @@ -248,6 +267,8 @@ func (dht *FullRT) runCrawler(ctx context.Context) { initialTrigger := make(chan struct{}, 1) initialTrigger <- struct{}{} + firstCrawl := true + for { select { case <-t.C: @@ -258,6 +279,13 @@ func (dht *FullRT) runCrawler(ctx context.Context) { } var addrs []*peer.AddrInfo + if firstCrawl { + firstCrawl = false + for _, ai := range initialSeedPeers { + addrs = append(addrs, &ai) + } + } + dht.peerAddrsLk.Lock() for k := range m { addrs = append(addrs, &peer.AddrInfo{ID: k}) // Addrs: v.addrs diff --git a/fullrt/options.go b/fullrt/options.go index cd0f9ba59..d5be2b56b 100644 --- a/fullrt/options.go +++ b/fullrt/options.go @@ -2,11 +2,14 @@ package fullrt import ( "fmt" + "github.com/libp2p/go-libp2p-core/peer" kaddht "github.com/libp2p/go-libp2p-kad-dht" ) type config struct { - dhtOpts []kaddht.Option + dhtOpts []kaddht.Option + initialRTPeers []peer.AddrInfo + skipInitialRTVerification bool } func (cfg *config) apply(opts ...Option) error { @@ -26,3 +29,20 @@ func DHTOption(opts ...kaddht.Option) Option { return nil } } + +// LoadRoutingTable loads the given set of peers into the routing table. +// If skipInitialVerification is true then the DHT client will be immediately usable, +// instead of using the peers as seeds for the initial routing table scan. +// +// Note: While skipping the initial verification will result in the DHT client being +// usable more quickly on startup, if the persisted routing table is out of date or +// corrupted then any initial operations might not give accurate results (e.g. not +// finding data present in the network or putting data to fewer nodes or nodes +// that are no longer closest to the keys) +func LoadRoutingTable(peers []peer.AddrInfo, skipInitialVerification bool) Option { + return func(c *config) error { + c.initialRTPeers = peers + c.skipInitialRTVerification = skipInitialVerification + return nil + } +}