Skip to content

Commit

Permalink
feat(network): adding bootstrapper mode to the network config
Browse files Browse the repository at this point in the history
  • Loading branch information
themantre committed Oct 20, 2023
1 parent 715de9f commit aa76093
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 8 deletions.
5 changes: 3 additions & 2 deletions config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config

import (
"fmt"
"strings"
"testing"

Expand Down Expand Up @@ -76,8 +77,8 @@ func TestExampleConfig(t *testing.T) {
exampleToml = strings.ReplaceAll(exampleToml, "\n\n", "\n")
defaultToml = strings.ReplaceAll(defaultToml, "\n\n", "\n")

// fmt.Println(defaultToml)
// fmt.Println(exampleToml)
fmt.Println(defaultToml)
fmt.Println(exampleToml)
assert.Equal(t, defaultToml, exampleToml)
}

Expand Down
4 changes: 4 additions & 0 deletions config/example_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
# Default is false.
## enable_metrics = false

# `bootstrapper` if enabled, it runs the node in bootstrap mode.
# Default is false.
## bootstrapper = false

# `network.bootstrap` contains configuration for bootstrapping the node.
[network.bootstrap]

Expand Down
2 changes: 2 additions & 0 deletions network/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Config struct {
RelayAddrs []string `toml:"relay_addresses"`
EnableMdns bool `toml:"enable_mdns"`
EnableMetrics bool `toml:"enable_metrics"`
Bootstrapper bool `toml:"bootstrapper"`
Bootstrap *BootstrapConfig `toml:"bootstrap"`
}

Expand Down Expand Up @@ -56,6 +57,7 @@ func DefaultConfig() *Config {
EnableRelay: false,
EnableMdns: false,
EnableMetrics: false,
Bootstrapper: false,
Bootstrap: &BootstrapConfig{
Addresses: addresses,
MinThreshold: 8,
Expand Down
15 changes: 13 additions & 2 deletions network/dht.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@ type dhtService struct {
}

func newDHTService(ctx context.Context, host lp2phost.Host, protocolID lp2pcore.ProtocolID,
conf *BootstrapConfig, logger *logger.SubLogger,
conf *BootstrapConfig, bootstrapper bool, logger *logger.SubLogger,
) *dhtService {
mode := lp2pdht.ModeAuto
if bootstrapper {
mode = lp2pdht.ModeServer
}
opts := []lp2pdht.Option{
lp2pdht.Mode(lp2pdht.ModeAuto),
lp2pdht.Mode(mode),
lp2pdht.ProtocolPrefix(protocolID),
lp2pdht.DisableProviders(),
lp2pdht.DisableValues(),
}

kademlia, err := lp2pdht.New(ctx, host, opts...)
Expand All @@ -31,6 +37,11 @@ func newDHTService(ctx context.Context, host lp2phost.Host, protocolID lp2pcore.
return nil
}

err = kademlia.Bootstrap(ctx)
if err != nil {
panic(err.Error())
}

bootstrap := newBootstrap(ctx,
host, host.Network(), kademlia,
conf, logger)
Expand Down
2 changes: 1 addition & 1 deletion network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func newNetwork(networkName string, conf *Config, opts []lp2p.Option) (*network,
kadProtocolID := lp2pcore.ProtocolID(fmt.Sprintf("/%s/gossip/v1", n.name))
streamProtocolID := lp2pcore.ProtocolID(fmt.Sprintf("/%s/stream/v1", n.name))

n.dht = newDHTService(n.ctx, n.host, kadProtocolID, conf.Bootstrap, n.logger)
n.dht = newDHTService(n.ctx, n.host, kadProtocolID, conf.Bootstrap, conf.Bootstrapper, n.logger)
n.stream = newStreamService(ctx, n.host, streamProtocolID, relayAddrs, n.eventChannel, n.logger)
n.gossip = newGossipService(ctx, n.host, n.eventChannel, n.logger)
n.notifee = newNotifeeService(n.host, n.eventChannel, n.logger, streamProtocolID)
Expand Down
84 changes: 81 additions & 3 deletions network/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,15 @@ func TestNetwork(t *testing.T) {
// Bootstrap node
confB := testConfig()
bootstrapPort := ts.RandInt32(9999) + 10000
confB.Bootstrapper = true
confB.Listens = []string{
fmt.Sprintf("/ip4/127.0.0.1/tcp/%v", bootstrapPort),
fmt.Sprintf("/ip6/::1/tcp/%v", bootstrapPort),
}
fmt.Println("Starting Bootstrap node")
networkB := makeTestNetwork(t, confB, []lp2p.Option{})
networkB := makeTestNetwork(t, confB, []lp2p.Option{
lp2p.ForceReachabilityPublic(),
})
bootstrapAddresses := []string{
fmt.Sprintf("/ip4/127.0.0.1/tcp/%v/p2p/%v", bootstrapPort, networkB.SelfID().String()),
fmt.Sprintf("/ip6/::1/tcp/%v/p2p/%v", bootstrapPort, networkB.SelfID().String()),
Expand Down Expand Up @@ -274,10 +277,13 @@ func TestNetwork(t *testing.T) {
assert.Equal(t, eN.Data, msg)
})

t.Run("node P (public) is not directly accessible by nodes M and N (private behind NAT)", func(t *testing.T) {
t.Run("node P (public) is directly accessible by nodes M and N (private behind NAT)", func(t *testing.T) {
msgM := []byte("test-stream-from-m")

require.Error(t, networkM.SendTo(msgM, networkP.SelfID()))
require.NoError(t, networkM.SendTo(msgM, networkP.SelfID()))
eB := shouldReceiveEvent(t, networkP, EventTypeStream).(*StreamMessage)
assert.Equal(t, eB.Source, networkM.SelfID())
assert.Equal(t, readData(t, eB.Reader, len(msgM)), msgM)
})

t.Run("node P (public) is directly accessible by node B (bootstrap)", func(t *testing.T) {
Expand Down Expand Up @@ -327,3 +333,75 @@ func TestInvalidRelayAddress(t *testing.T) {
_, err = NewNetwork("test", conf)
assert.Error(t, err)
}

func TestConnections(t *testing.T) {
t.Parallel() // run the tests in parallel

ts := testsuite.NewTestSuite(t)

tests := []struct {
bootstrapAddr string
peerAddr string
}{
{"/ip4/127.0.0.1/tcp/%d", "/ip4/127.0.0.1/tcp/0"},
{"/ip4/127.0.0.1/udp/%d/quic-v1", "/ip4/127.0.0.1/udp/0/quic-v1"},
{"/ip6/::1/tcp/%d", "/ip6/::1/tcp/0"},
{"/ip6/::1/udp/%d/quic-v1", "/ip6/::1/udp/0/quic-v1"},
}

for i, test := range tests {
// Bootstrap node
confB := testConfig()
bootstrapPort := ts.RandInt32(9999) + 10000
bootstrapAddr := fmt.Sprintf(test.bootstrapAddr, bootstrapPort)
confB.Listens = []string{bootstrapAddr}
fmt.Println("Starting Bootstrap node")
networkB := makeTestNetwork(t, confB, []lp2p.Option{
lp2p.ForceReachabilityPublic(),
})

// Public node
confP := testConfig()
confP.Bootstrap.Addresses = []string{
fmt.Sprintf("%s/p2p/%v", bootstrapAddr, networkB.SelfID().String()),
}
confP.Listens = []string{test.peerAddr}
fmt.Println("Starting Public node")
networkP := makeTestNetwork(t, confP, []lp2p.Option{
lp2p.ForceReachabilityPublic(),
})

t.Run(fmt.Sprintf("Running test %d: %s <-> %s ... ",
i, test.bootstrapAddr, test.peerAddr), func(t *testing.T) {
t.Parallel() // run the tests in parallel

testConnection(t, networkP, networkB)
})
}
}

func testConnection(t *testing.T, networkP *network, networkB *network) {
t.Helper()

// Ensure that peers are connected to each other
for i := 0; i < 20; i++ {
if networkP.NumConnectedPeers() >= 1 &&
networkB.NumConnectedPeers() >= 1 {
break
}
time.Sleep(100 * time.Millisecond)
}

assert.Equal(t, networkB.NumConnectedPeers(), 1)
assert.Equal(t, networkP.NumConnectedPeers(), 1)

msg := []byte("test-msg")

require.NoError(t, networkP.SendTo(msg, networkB.SelfID()))
e := shouldReceiveEvent(t, networkB, EventTypeStream).(*StreamMessage)
assert.Equal(t, e.Source, networkP.SelfID())
assert.Equal(t, readData(t, e.Reader, len(msg)), msg)

networkB.Stop()
networkP.Stop()
}
1 change: 1 addition & 0 deletions tests/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func TestMain(m *testing.M) {
tConfigs[i].Sync.NodeNetwork = false
tConfigs[i].Sync.Firewall.Enabled = false
tConfigs[i].Network.EnableMdns = true
tConfigs[i].Network.Bootstrapper = true
tConfigs[i].Network.NetworkKey = util.TempFilePath()
tConfigs[i].Network.Listens = []string{"/ip4/127.0.0.1/tcp/0", "/ip4/127.0.0.1/udp/0/quic-v1"}
tConfigs[i].Network.Bootstrap.Addresses = []string{}
Expand Down

0 comments on commit aa76093

Please sign in to comment.