p2p: support configuring NAT in TOML

This commit is contained in:
Felix Lange 2025-01-17 16:35:07 +01:00
parent 6909dd9978
commit 50e0380533
3 changed files with 309 additions and 99 deletions

144
p2p/config.go Normal file
View File

@ -0,0 +1,144 @@
// Copyright 2025 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package p2p
import (
"crypto/ecdsa"
"fmt"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/p2p/netutil"
)
//go:generate go run github.com/fjl/gencodec -type Config -field-override configMarshaling -formats toml -out config_toml.go
// Config holds Server options.
type Config struct {
// This field must be set to a valid secp256k1 private key.
PrivateKey *ecdsa.PrivateKey `toml:"-"`
// MaxPeers is the maximum number of peers that can be
// connected. It must be greater than zero.
MaxPeers int
// MaxPendingPeers is the maximum number of peers that can be pending in the
// handshake phase, counted separately for inbound and outbound connections.
// Zero defaults to preset values.
MaxPendingPeers int `toml:",omitempty"`
// DialRatio controls the ratio of inbound to dialed connections.
// Example: a DialRatio of 2 allows 1/2 of connections to be dialed.
// Setting DialRatio to zero defaults it to 3.
DialRatio int `toml:",omitempty"`
// NoDiscovery can be used to disable the peer discovery mechanism.
// Disabling is useful for protocol debugging (manual topology).
NoDiscovery bool
// DiscoveryV4 specifies whether V4 discovery should be started.
DiscoveryV4 bool `toml:",omitempty"`
// DiscoveryV5 specifies whether the new topic-discovery based V5 discovery
// protocol should be started or not.
DiscoveryV5 bool `toml:",omitempty"`
// Name sets the node name of this server.
Name string `toml:"-"`
// BootstrapNodes are used to establish connectivity
// with the rest of the network.
BootstrapNodes []*enode.Node
// BootstrapNodesV5 are used to establish connectivity
// with the rest of the network using the V5 discovery
// protocol.
BootstrapNodesV5 []*enode.Node `toml:",omitempty"`
// Static nodes are used as pre-configured connections which are always
// maintained and re-connected on disconnects.
StaticNodes []*enode.Node
// Trusted nodes are used as pre-configured connections which are always
// allowed to connect, even above the peer limit.
TrustedNodes []*enode.Node
// Connectivity can be restricted to certain IP networks.
// If this option is set to a non-nil value, only hosts which match one of the
// IP networks contained in the list are considered.
NetRestrict *netutil.Netlist `toml:",omitempty"`
// NodeDatabase is the path to the database containing the previously seen
// live nodes in the network.
NodeDatabase string `toml:",omitempty"`
// Protocols should contain the protocols supported
// by the server. Matching protocols are launched for
// each peer.
Protocols []Protocol `toml:"-" json:"-"`
// If ListenAddr is set to a non-nil address, the server
// will listen for incoming connections.
//
// If the port is zero, the operating system will pick a port. The
// ListenAddr field will be updated with the actual address when
// the server is started.
ListenAddr string
// If DiscAddr is set to a non-nil value, the server will use ListenAddr
// for TCP and DiscAddr for the UDP discovery protocol.
DiscAddr string
// If set to a non-nil value, the given NAT port mapper
// is used to make the listening port available to the
// Internet.
NAT nat.Interface `toml:",omitempty"`
// If Dialer is set to a non-nil value, the given Dialer
// is used to dial outbound peer connections.
Dialer NodeDialer `toml:"-"`
// If NoDial is true, the server will not dial any peers.
NoDial bool `toml:",omitempty"`
// If EnableMsgEvents is set then the server will emit PeerEvents
// whenever a message is sent to or received from a peer
EnableMsgEvents bool
// Logger is a custom logger to use with the p2p.Server.
Logger log.Logger `toml:"-"`
clock mclock.Clock
}
type configMarshaling struct {
NAT configNAT
}
type configNAT struct {
nat.Interface
}
func (w *configNAT) UnmarshalText(input []byte) error {
n, err := nat.Parse(string(input))
if err != nil {
return fmt.Errorf("invalid NAT specification: %v", err)
}
w.Interface = n
return nil
}

165
p2p/config_toml.go Normal file
View File

@ -0,0 +1,165 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package p2p
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/p2p/netutil"
)
var _ = (*configMarshaling)(nil)
// MarshalTOML marshals as TOML.
func (c Config) MarshalTOML() (interface{}, error) {
type Config struct {
PrivateKey *ecdsa.PrivateKey `toml:"-"`
MaxPeers int
MaxPendingPeers int `toml:",omitempty"`
DialRatio int `toml:",omitempty"`
NoDiscovery bool
DiscoveryV4 bool `toml:",omitempty"`
DiscoveryV5 bool `toml:",omitempty"`
Name string `toml:"-"`
BootstrapNodes []*enode.Node
BootstrapNodesV5 []*enode.Node `toml:",omitempty"`
StaticNodes []*enode.Node
TrustedNodes []*enode.Node
NetRestrict *netutil.Netlist `toml:",omitempty"`
NodeDatabase string `toml:",omitempty"`
Protocols []Protocol `toml:"-" json:"-"`
ListenAddr string
DiscAddr string
NAT nat.Interface `toml:",omitempty"`
Dialer NodeDialer `toml:"-"`
NoDial bool `toml:",omitempty"`
EnableMsgEvents bool
Logger log.Logger `toml:"-"`
}
var enc Config
enc.PrivateKey = c.PrivateKey
enc.MaxPeers = c.MaxPeers
enc.MaxPendingPeers = c.MaxPendingPeers
enc.DialRatio = c.DialRatio
enc.NoDiscovery = c.NoDiscovery
enc.DiscoveryV4 = c.DiscoveryV4
enc.DiscoveryV5 = c.DiscoveryV5
enc.Name = c.Name
enc.BootstrapNodes = c.BootstrapNodes
enc.BootstrapNodesV5 = c.BootstrapNodesV5
enc.StaticNodes = c.StaticNodes
enc.TrustedNodes = c.TrustedNodes
enc.NetRestrict = c.NetRestrict
enc.NodeDatabase = c.NodeDatabase
enc.Protocols = c.Protocols
enc.ListenAddr = c.ListenAddr
enc.DiscAddr = c.DiscAddr
enc.NAT = c.NAT
enc.Dialer = c.Dialer
enc.NoDial = c.NoDial
enc.EnableMsgEvents = c.EnableMsgEvents
enc.Logger = c.Logger
return &enc, nil
}
// UnmarshalTOML unmarshals from TOML.
func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
type Config struct {
PrivateKey *ecdsa.PrivateKey `toml:"-"`
MaxPeers *int
MaxPendingPeers *int `toml:",omitempty"`
DialRatio *int `toml:",omitempty"`
NoDiscovery *bool
DiscoveryV4 *bool `toml:",omitempty"`
DiscoveryV5 *bool `toml:",omitempty"`
Name *string `toml:"-"`
BootstrapNodes []*enode.Node
BootstrapNodesV5 []*enode.Node `toml:",omitempty"`
StaticNodes []*enode.Node
TrustedNodes []*enode.Node
NetRestrict *netutil.Netlist `toml:",omitempty"`
NodeDatabase *string `toml:",omitempty"`
Protocols []Protocol `toml:"-" json:"-"`
ListenAddr *string
DiscAddr *string
NAT *configNAT `toml:",omitempty"`
Dialer NodeDialer `toml:"-"`
NoDial *bool `toml:",omitempty"`
EnableMsgEvents *bool
Logger log.Logger `toml:"-"`
}
var dec Config
if err := unmarshal(&dec); err != nil {
return err
}
if dec.PrivateKey != nil {
c.PrivateKey = dec.PrivateKey
}
if dec.MaxPeers != nil {
c.MaxPeers = *dec.MaxPeers
}
if dec.MaxPendingPeers != nil {
c.MaxPendingPeers = *dec.MaxPendingPeers
}
if dec.DialRatio != nil {
c.DialRatio = *dec.DialRatio
}
if dec.NoDiscovery != nil {
c.NoDiscovery = *dec.NoDiscovery
}
if dec.DiscoveryV4 != nil {
c.DiscoveryV4 = *dec.DiscoveryV4
}
if dec.DiscoveryV5 != nil {
c.DiscoveryV5 = *dec.DiscoveryV5
}
if dec.Name != nil {
c.Name = *dec.Name
}
if dec.BootstrapNodes != nil {
c.BootstrapNodes = dec.BootstrapNodes
}
if dec.BootstrapNodesV5 != nil {
c.BootstrapNodesV5 = dec.BootstrapNodesV5
}
if dec.StaticNodes != nil {
c.StaticNodes = dec.StaticNodes
}
if dec.TrustedNodes != nil {
c.TrustedNodes = dec.TrustedNodes
}
if dec.NetRestrict != nil {
c.NetRestrict = dec.NetRestrict
}
if dec.NodeDatabase != nil {
c.NodeDatabase = *dec.NodeDatabase
}
if dec.Protocols != nil {
c.Protocols = dec.Protocols
}
if dec.ListenAddr != nil {
c.ListenAddr = *dec.ListenAddr
}
if dec.DiscAddr != nil {
c.DiscAddr = *dec.DiscAddr
}
if dec.NAT != nil {
c.NAT = dec.NAT
}
if dec.Dialer != nil {
c.Dialer = dec.Dialer
}
if dec.NoDial != nil {
c.NoDial = *dec.NoDial
}
if dec.EnableMsgEvents != nil {
c.EnableMsgEvents = *dec.EnableMsgEvents
}
if dec.Logger != nil {
c.Logger = dec.Logger
}
return nil
}

View File

@ -39,7 +39,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/p2p/netutil"
)
@ -72,104 +71,6 @@ var (
errProtoHandshakeError = errors.New("rlpx proto error")
)
// Config holds Server options.
type Config struct {
// This field must be set to a valid secp256k1 private key.
PrivateKey *ecdsa.PrivateKey `toml:"-"`
// MaxPeers is the maximum number of peers that can be
// connected. It must be greater than zero.
MaxPeers int
// MaxPendingPeers is the maximum number of peers that can be pending in the
// handshake phase, counted separately for inbound and outbound connections.
// Zero defaults to preset values.
MaxPendingPeers int `toml:",omitempty"`
// DialRatio controls the ratio of inbound to dialed connections.
// Example: a DialRatio of 2 allows 1/2 of connections to be dialed.
// Setting DialRatio to zero defaults it to 3.
DialRatio int `toml:",omitempty"`
// NoDiscovery can be used to disable the peer discovery mechanism.
// Disabling is useful for protocol debugging (manual topology).
NoDiscovery bool
// DiscoveryV4 specifies whether V4 discovery should be started.
DiscoveryV4 bool `toml:",omitempty"`
// DiscoveryV5 specifies whether the new topic-discovery based V5 discovery
// protocol should be started or not.
DiscoveryV5 bool `toml:",omitempty"`
// Name sets the node name of this server.
Name string `toml:"-"`
// BootstrapNodes are used to establish connectivity
// with the rest of the network.
BootstrapNodes []*enode.Node
// BootstrapNodesV5 are used to establish connectivity
// with the rest of the network using the V5 discovery
// protocol.
BootstrapNodesV5 []*enode.Node `toml:",omitempty"`
// Static nodes are used as pre-configured connections which are always
// maintained and re-connected on disconnects.
StaticNodes []*enode.Node
// Trusted nodes are used as pre-configured connections which are always
// allowed to connect, even above the peer limit.
TrustedNodes []*enode.Node
// Connectivity can be restricted to certain IP networks.
// If this option is set to a non-nil value, only hosts which match one of the
// IP networks contained in the list are considered.
NetRestrict *netutil.Netlist `toml:",omitempty"`
// NodeDatabase is the path to the database containing the previously seen
// live nodes in the network.
NodeDatabase string `toml:",omitempty"`
// Protocols should contain the protocols supported
// by the server. Matching protocols are launched for
// each peer.
Protocols []Protocol `toml:"-" json:"-"`
// If ListenAddr is set to a non-nil address, the server
// will listen for incoming connections.
//
// If the port is zero, the operating system will pick a port. The
// ListenAddr field will be updated with the actual address when
// the server is started.
ListenAddr string
// If DiscAddr is set to a non-nil value, the server will use ListenAddr
// for TCP and DiscAddr for the UDP discovery protocol.
DiscAddr string
// If set to a non-nil value, the given NAT port mapper
// is used to make the listening port available to the
// Internet.
NAT nat.Interface `toml:",omitempty"`
// If Dialer is set to a non-nil value, the given Dialer
// is used to dial outbound peer connections.
Dialer NodeDialer `toml:"-"`
// If NoDial is true, the server will not dial any peers.
NoDial bool `toml:",omitempty"`
// If EnableMsgEvents is set then the server will emit PeerEvents
// whenever a message is sent to or received from a peer
EnableMsgEvents bool
// Logger is a custom logger to use with the p2p.Server.
Logger log.Logger `toml:",omitempty"`
clock mclock.Clock
}
// Server manages all peer connections.
type Server struct {
// Config fields may not be modified while the server is running.