Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update bootstrapPeers to be func() []peer.AddrInfo #716

Merged
merged 6 commits into from
Jun 25, 2021
Merged
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
13 changes: 7 additions & 6 deletions dht.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ type IpfsDHT struct {

autoRefresh bool

// A set of bootstrap peers to fallback on if all other attempts to fix
// A function returning a set of bootstrap peers to fallback on if all other attempts to fix
// the routing table fail (or, e.g., this is the first time this node is
// connecting to the network).
bootstrapPeers []peer.AddrInfo
bootstrapPeers func() []peer.AddrInfo

maxRecordAge time.Duration

Expand Down Expand Up @@ -473,15 +473,16 @@ func (dht *IpfsDHT) fixLowPeers(ctx context.Context) {
// We should first use non-bootstrap peers we knew of from previous
// snapshots of the Routing Table before we connect to the bootstrappers.
// See https://github.com/libp2p/go-libp2p-kad-dht/issues/387.
if dht.routingTable.Size() == 0 {
if len(dht.bootstrapPeers) == 0 {
if dht.routingTable.Size() == 0 && dht.bootstrapPeers != nil {
bootstrapPeers := dht.bootstrapPeers()
if len(bootstrapPeers) == 0 {
// No point in continuing, we have no peers!
return
}

found := 0
for _, i := range rand.Perm(len(dht.bootstrapPeers)) {
ai := dht.bootstrapPeers[i]
for _, i := range rand.Perm(len(bootstrapPeers)) {
ai := bootstrapPeers[i]
err := dht.Host().Connect(ctx, ai)
if err == nil {
found++
Expand Down
13 changes: 12 additions & 1 deletion dht_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,18 @@ func RoutingTableFilter(filter RouteTableFilterFunc) Option {
// and refresh our Routing Table if it becomes empty.
func BootstrapPeers(bootstrappers ...peer.AddrInfo) Option {
return func(c *dhtcfg.Config) error {
c.BootstrapPeers = bootstrappers
c.BootstrapPeers = func() []peer.AddrInfo {
return bootstrappers
}
return nil
}
}

// BootstrapPeersFunc configures the function that returns the bootstrapping nodes that we will
// connect to to seed and refresh our Routing Table if it becomes empty.
func BootstrapPeersFunc(getBootstrapPeers func() []peer.AddrInfo) Option {
return func(c *dhtcfg.Config) error {
c.BootstrapPeers = getBootstrapPeers
return nil
}
}
Expand Down
33 changes: 33 additions & 0 deletions dht_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2051,6 +2051,39 @@ func TestBootStrapWhenRTIsEmpty(t *testing.T) {
}, 5*time.Second, 500*time.Millisecond)
}

func TestBootstrapPeersFunc(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@noot can you fix up this test so it's not racey?

  === RUN   TestBootstrapPeersFunc
  ==================
  WARNING: DATA RACE
  Read at 0x00c00263b1e8 by goroutine 2824:
    github.com/libp2p/go-libp2p-kad-dht.TestBootstrapPeersFunc.func2()
        /home/runner/work/go-libp2p-kad-dht/go-libp2p-kad-dht/dht_test.go:2065 +0x4a
    github.com/libp2p/go-libp2p-kad-dht.(*IpfsDHT).fixLowPeers()
        /home/runner/work/go-libp2p-kad-dht/go-libp2p-kad-dht/dht.go:477 +0x2a7
    github.com/libp2p/go-libp2p-kad-dht.(*IpfsDHT).populatePeers()
        /home/runner/work/go-libp2p-kad-dht/go-libp2p-kad-dht/dht.go:428 +0x290
    github.com/libp2p/go-libp2p-kad-dht.(*IpfsDHT).populatePeers-fm()
        /home/runner/work/go-libp2p-kad-dht/go-libp2p-kad-dht/dht.go:426 +0x5e
    github.com/jbenet/goprocess.(*process).Go.func1()
        /home/runner/go/pkg/mod/github.com/jbenet/goprocess@v0.1.4/impl-mutex.go:134 +0x49
  
  Previous write at 0x00c00263b1e8 by goroutine 3251:
    github.com/libp2p/go-libp2p-kad-dht.TestBootstrapPeersFunc()
        /home/runner/work/go-libp2p-kad-dht/go-libp2p-kad-dht/dht_test.go:2075 +0x466
    testing.tRunner()
        /opt/hostedtoolcache/go/1.16.5/x64/src/testing/testing.go:1193 +0x202
  
  Goroutine 2824 (running) created at:
    github.com/jbenet/goprocess.(*process).Go()
        /home/runner/go/pkg/mod/github.com/jbenet/goprocess@v0.1.4/impl-mutex.go:133 +0x435
    github.com/libp2p/go-libp2p-kad-dht.New()
        /home/runner/work/go-libp2p-kad-dht/go-libp2p-kad-dht/dht.go:239 +0xf0a
    github.com/libp2p/go-libp2p-kad-dht.setupDHT()
        /home/runner/work/go-libp2p-kad-dht/go-libp2p-kad-dht/dht_test.go:119 +0x33d
    github.com/libp2p/go-libp2p-kad-dht.TestBootstrapPeersFunc()
        /home/runner/work/go-libp2p-kad-dht/go-libp2p-kad-dht/dht_test.go:2067 +0x276
    testing.tRunner()
        /opt/hostedtoolcache/go/1.16.5/x64/src/testing/testing.go:1193 +0x202
  
  Goroutine 3251 (running) created at:
    testing.(*T).Run()
        /opt/hostedtoolcache/go/1.16.5/x64/src/testing/testing.go:1238 +0x5d7
    testing.runTests.func1()
        /opt/hostedtoolcache/go/1.16.5/x64/src/testing/testing.go:1511 +0xa6
    testing.tRunner()
        /opt/hostedtoolcache/go/1.16.5/x64/src/testing/testing.go:1193 +0x202
    testing.runTests()
        /opt/hostedtoolcache/go/1.16.5/x64/src/testing/testing.go:1509 +0x612
    testing.(*M).Run()
        /opt/hostedtoolcache/go/1.16.5/x64/src/testing/testing.go:1417 +0x3b3
    github.com/libp2p/go-libp2p-kad-dht.TestMain()
        /home/runner/work/go-libp2p-kad-dht/go-libp2p-kad-dht/nofile_test.go:22 +0x7a
    main.main()
        _testmain.go:181 +0x271
  ==================
      testing.go:1092: race detected during execution of test
  --- FAIL: TestBootstrapPeersFunc (0.04s)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
var lock sync.Mutex

bootstrapFuncA := func() []peer.AddrInfo {
return []peer.AddrInfo{}
}
dhtA := setupDHT(ctx, t, false, BootstrapPeersFunc(bootstrapFuncA))

bootstrapPeersB := []peer.AddrInfo{}
bootstrapFuncB := func() []peer.AddrInfo {
lock.Lock()
defer lock.Unlock()
return bootstrapPeersB
}

dhtB := setupDHT(ctx, t, false, BootstrapPeersFunc(bootstrapFuncB))
require.Equal(t, 0, len(dhtB.host.Network().Peers()))

addrA := peer.AddrInfo{
ID: dhtA.self,
Addrs: dhtA.host.Addrs(),
}

lock.Lock()
bootstrapPeersB = []peer.AddrInfo{addrA}
lock.Unlock()

dhtB.fixLowPeers(ctx)
require.NotEqual(t, 0, len(dhtB.host.Network().Peers()))
}

func TestPreconnectedNodes(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down
2 changes: 1 addition & 1 deletion fullrt/dht.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func NewFullRT(h host.Host, protocolPrefix protocol.ID, options ...Option) (*Ful

var bsPeers []*peer.AddrInfo

for _, ai := range dhtcfg.BootstrapPeers {
for _, ai := range dhtcfg.BootstrapPeers() {
tmpai := ai
bsPeers = append(bsPeers, &tmpai)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ type Config struct {
DiversityFilter peerdiversity.PeerIPGroupFilter
}

BootstrapPeers []peer.AddrInfo
BootstrapPeers func() []peer.AddrInfo

// test specific Config options
DisableFixLowPeers bool
Expand Down