Skip to content
Draft
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
1 change: 1 addition & 0 deletions cmd/bootnode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ func printVersion(me string) {
fmt.Fprintf(os.Stderr, "Harmony (C) %d. %v, version %v-%v (%v %v)\n", currentYear, path.Base(me), version, commit, builtBy, builtAt)
}

// todo(sun): quic should be enabled but not prioritized?
func main() {
timestamp := time.Now().Format("20060102150405")
defUserAgent := fmt.Sprintf("bootnode-%s", timestamp)
Expand Down
3 changes: 3 additions & 0 deletions cmd/config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ var defaultConfig = harmonyconfig.HarmonyConfig{
DialTimeout: nodeconfig.DefaultDialTimeout,
Muxer: nodeconfig.DefaultMuxer,
NoRelay: nodeconfig.DefaultNoRelay,
EnableQuic: nodeconfig.DefaultEnableQuic,
QuicPort: nodeconfig.DefaultQuicPort,
QuicPriority: nodeconfig.DefaultQuicPriority,
},
HTTP: harmonyconfig.HttpConfig{
Enabled: true,
Expand Down
25 changes: 25 additions & 0 deletions cmd/config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,21 @@ var (
Usage: "no relay services, direct connections between peers only",
DefValue: defaultConfig.P2P.NoRelay,
}
enableQuicFlag = cli.BoolFlag{
Name: "p2p.enable-quic",
Usage: "enable QUIC transport",
DefValue: defaultConfig.P2P.EnableQuic,
}
quicPortFlag = cli.IntFlag{
Name: "p2p.quic-port",
Usage: "port to listen for QUIC protocols",
DefValue: defaultConfig.P2P.QuicPort,
}
quicPriorityFlag = cli.BoolFlag{
Name: "p2p.quic-priority",
Usage: "prioritize QUIC transport over Tcp",
DefValue: defaultConfig.P2P.QuicPriority,
}
)

func applyP2PFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) {
Expand Down Expand Up @@ -780,6 +795,16 @@ func applyP2PFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) {
if cli.IsFlagChanged(cmd, noRelayFlag) {
config.P2P.NoRelay = cli.GetBoolFlagValue(cmd, noRelayFlag)
}

if cli.IsFlagChanged(cmd, enableQuicFlag) {
config.P2P.EnableQuic = cli.GetBoolFlagValue(cmd, enableQuicFlag)
}
if cli.IsFlagChanged(cmd, quicPortFlag) {
config.P2P.QuicPort = cli.GetIntFlagValue(cmd, quicPortFlag)
}
if cli.IsFlagChanged(cmd, quicPriorityFlag) {
config.P2P.QuicPriority = cli.GetBoolFlagValue(cmd, quicPriorityFlag)
}
}

// http flags
Expand Down
6 changes: 6 additions & 0 deletions cmd/harmony/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ func createGlobalConfig(hc harmonyconfig.HarmonyConfig) (*nodeconfig.ConfigType,
forceReachabilityPublic = true
}

// todo(sun): quic
myHost, err = p2p.NewHost(p2p.HostConfig{
Self: &selfPeer,
BLSKey: nodeConfig.P2PPriKey,
Expand All @@ -622,6 +623,11 @@ func createGlobalConfig(hc harmonyconfig.HarmonyConfig) (*nodeconfig.ConfigType,
DialTimeout: hc.P2P.DialTimeout,
Muxer: hc.P2P.Muxer,
NoRelay: hc.P2P.NoRelay,
QuicConfig: p2p.QuicConfig{
Enabled: hc.P2P.EnableQuic,
Port: strconv.Itoa(hc.P2P.QuicPort),
Priority: hc.P2P.QuicPriority,
},
})
if err != nil {
return nil, errors.Wrap(err, "cannot create P2P network host")
Expand Down
6 changes: 6 additions & 0 deletions internal/configs/harmony/harmony.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ type P2pConfig struct {
Muxer string
// No relay services, direct connections between peers only
NoRelay bool
// EnableQuic enables QUIC transport
EnableQuic bool
// QuicPort is the port to listen for QUIC protocols
QuicPort int
// QuicPriority prioritizes QUIC transport over TCP
QuicPriority bool
}

type GeneralConfig struct {
Expand Down
6 changes: 6 additions & 0 deletions internal/configs/node/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ const (
DefaultMuxer = "yamux, mplexC6"
// DefaultNoRelay disables p2p host relay
DefaultNoRelay = true
// DefaultEnableQuic enables QUIC transport
DefaultEnableQuic = false
// DefaultQuicPort is the default port for QUIC transport
DefaultQuicPort = 9001
// DefaultQuicPriority prioritizes QUIC transport over TCP
DefaultQuicPriority = false
)

const (
Expand Down
53 changes: 52 additions & 1 deletion p2p/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ import (
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
noise "github.com/libp2p/go-libp2p/p2p/security/noise"
tls "github.com/libp2p/go-libp2p/p2p/security/tls"
libp2p_quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
"github.com/multiformats/go-multiaddr"
ma "github.com/multiformats/go-multiaddr"
madns "github.com/multiformats/go-multiaddr-dns"
"github.com/pkg/errors"
quic "github.com/quic-go/quic-go"
"github.com/rs/zerolog"
)

Expand Down Expand Up @@ -84,6 +86,8 @@ type Host interface {
}

// Peer is the object for a p2p peer (node)
// todo(sun): does it need to differentiate between tcp and quic ports?
// todo(sun): for self.peer, if QUIC is enabled, the port should be which port?
type Peer struct {
IP string // IP address of the peer
Port string // Port number of the peer
Expand Down Expand Up @@ -127,6 +131,13 @@ type HostConfig struct {
DialTimeout time.Duration
Muxer string
NoRelay bool
QuicConfig QuicConfig
}

type QuicConfig struct {
Enabled bool
Port string
Priority bool
}

func init() {
Expand All @@ -144,12 +155,16 @@ func init() {
}

// NewHost ..
// todo(sun): implement dialer prioritization
// todo(sun): log the quic address
// todo(sun): upon connection, log the transport type (conn.RemoteMultiaddr())
func NewHost(cfg HostConfig) (Host, error) {
var (
self = cfg.Self
key = cfg.BLSKey
pub = cfg.BLSKey.GetPublic()
dataStorePath = cfg.DataStoreFile
quicConfig = cfg.QuicConfig
)

pubKey := key.GetPublic()
Expand Down Expand Up @@ -205,9 +220,11 @@ func NewHost(cfg HostConfig) (Host, error) {
connGtr = gating.AddMetering(connGtr)

// transporters
// todo: tcp.WithConnectionTimeout is the dial timeout, should be replaced with idle timeout
tcpTransport := libp2p.Transport(
tcp.NewTCPTransport,
tcp.WithConnectionTimeout(time.Minute*60)) // break unused connections
tcp.WithConnectionTimeout(time.Minute*60), // break unused connections
)

// create NAT Manager; it takes care of setting NAT port mappings, and discovering external addresses
var nat libp2p_config.NATManagerC // disabled if nil
Expand Down Expand Up @@ -239,6 +256,13 @@ func NewHost(cfg HostConfig) (Host, error) {
if dto <= 0 {
dto = time.Minute
}

// enable quic
var quicOpts libp2p.Option
if quicConfig.Enabled {
quicOpts = createQuicOption(self.IP, quicConfig)
}

// prepare host options
p2pHostConfig := []libp2p.Option{
libp2p.Identity(key),
Expand Down Expand Up @@ -274,6 +298,8 @@ func NewHost(cfg HostConfig) (Host, error) {
libp2p.EnableNATService(),
// NAT Rate Limiter
libp2p.AutoNATServiceRateLimit(10, 5, time.Second*60),
// quic connections; nil if not enabled
quicOpts,
}
if cfg.ResourceMgrEnabled {
rmgr, err := makeResourceMgr(false, cfg.ResourceMgrMemoryLimitBytes, cfg.ResourceMgrFileDescriptorsLimit, cfg.ConnManagerHighWatermark)
Expand Down Expand Up @@ -444,6 +470,27 @@ func NewHost(cfg HostConfig) (Host, error) {
return h, nil
}

// createQuicOption creates a quic option for the libp2p host
func createQuicOption(ip string, quicCfg QuicConfig) libp2p.Option {
// todo(sun): derive the QUIC port from the base port ONLY when a legacy flag is used (port + 1)
// quic multiaddr
listenAddr := libp2p.ListenAddrStrings(
fmt.Sprintf("ip4/%s/udp/%s/quic-v1", ip, quicCfg.Port),
)

// quic transport
transport := libp2p.Transport(
libp2p_quic.NewTransport,
quic.Config{
MaxIdleTimeout: time.Minute * 60,
MaxIncomingStreams: 256,
KeepAlivePeriod: time.Minute * 30,
},
)

return libp2p.ChainOptions(listenAddr, transport)
}

func createDatastore(peerstorePath *string) (ds.Batching, error) {
var err error
var store ds.Batching
Expand Down Expand Up @@ -620,6 +667,7 @@ func (host *HostV2) SendMessageToGroups(groups []nodeconfig.GroupID, msg []byte)
return err
}

// todo(sun): add quic support
// AddPeer add p2p.Peer into Peerstore
func (host *HostV2) AddPeer(p *Peer) error {
if p.PeerID != "" && len(p.Addrs) != 0 {
Expand Down Expand Up @@ -658,11 +706,13 @@ func (host *HostV2) AddTrustedNodes() {
}
}

// todo(sun): add quic support
func (host *HostV2) AddPeerByIP(IP string, port string) error {
addr := fmt.Sprintf("/ip4/%s/tcp/%s", IP, port)
return host.AddPeerByAddress(addr)
}

// todo(sun): add quic support
// AddPeerByAddress adds a peer by address (ex: /ip4/127.0.0.1/tcp/9000/p2p/QmSomePeerID)
func (host *HostV2) AddPeerByAddress(addrStr string) error {
peerAddr, err := multiaddr.NewMultiaddr(addrStr)
Expand Down Expand Up @@ -763,6 +813,7 @@ func (host *HostV2) Network() libp2p_network.Network {
return host.h.Network()
}

// todo(sun): add quic support
// ConnectHostPeer connects to peer host
func (host *HostV2) ConnectHostPeer(peer Peer) error {
ctx := context.Background()
Expand Down