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

feat: implement relay service #931

Merged
merged 6 commits into from
Jan 11, 2024
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
2 changes: 0 additions & 2 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ func TestLocalnetConfig(t *testing.T) {

assert.NoError(t, conf.BasicCheck())
assert.Empty(t, conf.Network.ListenAddrStrings)
assert.Empty(t, conf.Network.RelayAddrStrings)
assert.Equal(t, conf.Network.NetworkName, "pactus-localnet")
assert.Equal(t, conf.Network.DefaultPort, 21666)
assert.Equal(t, conf.Store.TxCacheSize, param.DefaultParams().TransactionToLiveInterval)
Expand All @@ -63,7 +62,6 @@ func TestTestnetConfig(t *testing.T) {
assert.NoError(t, conf.BasicCheck())
assert.NotEmpty(t, conf.Network.DefaultRelayAddrStrings)
assert.Empty(t, conf.Network.ListenAddrStrings)
assert.Empty(t, conf.Network.RelayAddrStrings)
assert.Equal(t, conf.Network.NetworkName, "pactus-testnet-v2")
assert.Equal(t, conf.Network.DefaultPort, 21777)
assert.Equal(t, conf.Store.TxCacheSize, param.DefaultParams().TransactionToLiveInterval)
Expand Down
9 changes: 5 additions & 4 deletions config/example_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@
# `listen_addrs` specifies the addresses and ports where the node will listen for incoming connections from other nodes.
## listen_addrs = []

# `relay_addrs` provides the necessary relay addresses. These should be specified if 'enable_relay' is 'true'.
# Note: this parameter will be ignored if 'enable_relay' is 'false'.
## relay_addrs = []

# `bootstrap_addrs` is a list of peer addresses needed for peer discovery.
# These addresses are used by the Pactus node to discover and connect to other peers on the network.
## bootstrap_addrs = []
Expand All @@ -58,6 +54,11 @@
# Default is `false`.
## enable_relay = false

# `enable_relay_service` indicates whether relay service should be enabled or not.
# Relay service is a transport protocol that enables peers to discover each other on the peer-to-peer network.
# Default is `false`.
## enable_relay_service = false

# `enable_mdns` indicates whether MDNS should be enabled or not.
# MDNS is a protocol to discover local peers quickly and efficiently.
# Default is `false`.
Expand Down
28 changes: 17 additions & 11 deletions network/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ type Config struct {
NetworkKey string `toml:"network_key"`
PublicAddrString string `toml:"public_addr"`
ListenAddrStrings []string `toml:"listen_addrs"`
RelayAddrStrings []string `toml:"relay_addrs"`
BootstrapAddrStrings []string `toml:"bootstrap_addrs"`
MaxConns int `toml:"max_connections"`
EnableUDP bool `toml:"enable_udp"`
EnableNATService bool `toml:"enable_nat_service"`
EnableUPnP bool `toml:"enable_upnp"`
EnableRelay bool `toml:"enable_relay"`
EnableRelayService bool `toml:"enable_relay_service"`
EnableMdns bool `toml:"enable_mdns"`
EnableMetrics bool `toml:"enable_metrics"`
ForcePrivateNetwork bool `toml:"force_private_network"`
Expand All @@ -37,13 +37,13 @@ func DefaultConfig() *Config {
NetworkKey: "network_key",
PublicAddrString: "",
ListenAddrStrings: []string{},
RelayAddrStrings: []string{},
BootstrapAddrStrings: []string{},
MaxConns: 64,
EnableUDP: false,
EnableNATService: false,
EnableUPnP: false,
EnableRelay: false,
EnableRelayService: false,
EnableMdns: false,
EnableMetrics: false,
ForcePrivateNetwork: false,
Expand All @@ -54,12 +54,22 @@ func DefaultConfig() *Config {

func validateMultiAddr(addrs ...string) error {
_, err := MakeMultiAddrs(addrs)
if err != nil {
return ConfigError{
Reason: fmt.Sprintf("address is not valid: %s", err.Error()),
}
}
return err
}

func validateAddrInfo(addrs ...string) error {
_, err := MakeAddrInfos(addrs)
return err
if err != nil {
return ConfigError{
Reason: fmt.Sprintf("address is not valid: %s", err.Error()),
}
}
return nil
}

// BasicCheck performs basic checks on the configuration.
Expand All @@ -78,8 +88,10 @@ func (conf *Config) BasicCheck() error {
if err := validateAddrInfo(conf.DefaultRelayAddrStrings...); err != nil {
return err
}
if err := validateAddrInfo(conf.RelayAddrStrings...); err != nil {
return err
if conf.EnableRelay && conf.EnableRelayService {
return ConfigError{
Reason: "both the relay and relay service cannot be active at the same time",
}
}
return validateAddrInfo(conf.BootstrapAddrStrings...)
}
Expand All @@ -106,12 +118,6 @@ func (conf *Config) ListenAddrs() []multiaddr.Multiaddr {
return addrs
}

func (conf *Config) RelayAddrInfos() []lp2ppeer.AddrInfo {
addrs := util.Merge(conf.DefaultRelayAddrStrings, conf.RelayAddrStrings)
addrInfos, _ := MakeAddrInfos(addrs)
return addrInfos
}

func (conf *Config) BootstrapAddrInfos() []lp2ppeer.AddrInfo {
addrs := util.Merge(conf.DefaultBootstrapAddrStrings, conf.BootstrapAddrStrings)
addrInfos, _ := MakeAddrInfos(addrs)
Expand Down
87 changes: 54 additions & 33 deletions network/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,89 +10,99 @@ import (
func TestConfigBasicCheck(t *testing.T) {
testCases := []struct {
name string
expectError bool
expectError error
updateFn func(c *Config)
}{
{
name: "Empty ListenAddrStrings - Expect Error",
expectError: true,
name: "Empty ListenAddrStrings - Expect Error",
expectError: ConfigError{
Reason: "address is not valid: failed to parse multiaddr \"\": empty multiaddr",
},
updateFn: func(c *Config) {
c.ListenAddrStrings = []string{""}
},
},
{
name: "Invalid ListenAddrStrings - Expect Error",
expectError: true,
name: "Both Relay and Relay Service be true - Expect Error",
expectError: ConfigError{
Reason: "both the relay and relay service cannot be active at the same time",
},
updateFn: func(c *Config) {
c.EnableRelay = true
c.EnableRelayService = true
},
},
{
name: "Invalid ListenAddrStrings - Expect Error",
expectError: ConfigError{
Reason: "address is not valid: failed to parse multiaddr \"127.0.0.1\": must begin with /",
},
updateFn: func(c *Config) {
c.ListenAddrStrings = []string{"127.0.0.1"}
},
},
{
name: "Invalid ListenAddrStrings (No port) - Expect Error",
expectError: true,
name: "Invalid ListenAddrStrings (No port) - Expect Error",
expectError: ConfigError{
Reason: "address is not valid: failed to parse multiaddr \"/ip4\": unexpected end of multiaddr",
},
updateFn: func(c *Config) {
c.ListenAddrStrings = []string{"/ip4"}
},
},
{
name: "Invalid Public Address - Expect Error",
expectError: true,
name: "Invalid Public Address - Expect Error",
expectError: ConfigError{
Reason: "address is not valid: failed to parse multiaddr \"/ip4\": unexpected end of multiaddr",
},
updateFn: func(c *Config) {
c.PublicAddrString = "/ip4"
},
},
{
name: "Invalid DefaultRelayAddrStrings - Expect Error",
expectError: true,
name: "Invalid DefaultRelayAddrStrings - Expect Error",
expectError: ConfigError{
Reason: "address is not valid: invalid p2p multiaddr",
},
updateFn: func(c *Config) {
c.DefaultRelayAddrStrings = []string{"/ip4/127.0.0.1/"}
},
},
{
name: "Invalid RelayAddrStrings - Expect Error",
expectError: true,
updateFn: func(c *Config) {
c.RelayAddrStrings = []string{"/ip4/127.0.0.1/"}
name: "Invalid DefaultBootstrapAddrStrings - Expect Error",
expectError: ConfigError{
Reason: "address is not valid: invalid p2p multiaddr",
},
},
{
name: "Invalid DefaultBootstrapAddrStrings - Expect Error",
expectError: true,
updateFn: func(c *Config) {
c.DefaultBootstrapAddrStrings = []string{"/ip4/127.0.0.1/"}
},
},
{
name: "Invalid BootstrapAddrStrings - Expect Error",
expectError: true,
name: "Invalid BootstrapAddrStrings - Expect Error",
expectError: ConfigError{
Reason: "address is not valid: invalid p2p multiaddr",
},
updateFn: func(c *Config) {
c.BootstrapAddrStrings = []string{"/ip4/127.0.0.1/"}
},
},
{
name: "Valid Public Address - No Error",
expectError: false,
expectError: nil,
updateFn: func(c *Config) {
c.PublicAddrString = "/ip4/127.0.0.1/"
},
},
{
name: "Valid RelayAddrStrings - No Error",
expectError: false,
updateFn: func(c *Config) {
c.RelayAddrStrings = []string{"/ip4/127.0.0.1/p2p/12D3KooWQBpPV6NtZy1dvN2oF7dJdLoooRZfEmwtHiDUf42ArDjT"}
},
},
{
name: "Valid ListenAddrStrings - No Error",
expectError: false,
expectError: nil,
updateFn: func(c *Config) {
c.ListenAddrStrings = []string{"/ip4/127.0.0.1"}
},
},
{
name: "Valid BootstrapAddrStrings - No Error",
expectError: false,
expectError: nil,
updateFn: func(c *Config) {
c.BootstrapAddrStrings = []string{"/ip4/127.0.0.1/p2p/12D3KooWQBpPV6NtZy1dvN2oF7dJdLoooRZfEmwtHiDUf42ArDjT"}
},
Expand All @@ -103,8 +113,10 @@ func TestConfigBasicCheck(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
conf := DefaultConfig()
tc.updateFn(conf)
if tc.expectError {
assert.Error(t, conf.BasicCheck(), "Expected error for Test %d: %s", i, tc.name)
if tc.expectError != nil {
err := conf.BasicCheck()
assert.ErrorIs(t, tc.expectError, err,
"Expected error not matched for test %d-%s: expected %s, got: %s", i, tc.name, tc.expectError, err)
} else {
assert.NoError(t, conf.BasicCheck(), "Expected no error for Test %d: %s", i, tc.name)
}
Expand Down Expand Up @@ -162,3 +174,12 @@ func TestScaledConns(t *testing.T) {
}
}
}

func TestPublicAddr(t *testing.T) {
conf1 := DefaultConfig()
assert.Nil(t, conf1.PublicAddr())

conf2 := DefaultConfig()
conf2.PublicAddrString = "/ip4/127.0.0.1/p2p/12D3KooWQBpPV6NtZy1dvN2oF7dJdLoooRZfEmwtHiDUf42ArDjT"
assert.NotNil(t, conf2.PublicAddr())
}
15 changes: 11 additions & 4 deletions network/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

import "fmt"

// ConfigError is returned when the config is not valid with a descriptive Reason message.
type ConfigError struct {
Reason string
}

func (e ConfigError) Error() string {
return e.Reason

Check warning on line 11 in network/errors.go

View check run for this annotation

Codecov / codecov/patch

network/errors.go#L11

Added line #L11 was not covered by tests
}

// NotSubscribedError is returned when the peer is not subscribed to a
// specific topic.
type NotSubscribedError struct {
Expand All @@ -18,8 +27,7 @@
}

func (e InvalidTopicError) Error() string {
return fmt.Sprintf("invalid topic: '%s'",
e.TopicID.String())
return fmt.Sprintf("invalid topic: '%s'", e.TopicID.String())

Check warning on line 30 in network/errors.go

View check run for this annotation

Codecov / codecov/patch

network/errors.go#L30

Added line #L30 was not covered by tests
}

// LibP2PError is returned when an underlying libp2p operation encounters an error.
Expand All @@ -28,6 +36,5 @@
}

func (e LibP2PError) Error() string {
return fmt.Sprintf("libp2p error: %s",
e.Err.Error())
return fmt.Sprintf("libp2p error: %s", e.Err.Error())

Check warning on line 39 in network/errors.go

View check run for this annotation

Codecov / codecov/patch

network/errors.go#L39

Added line #L39 was not covered by tests
}
Loading
Loading