Skip to content

Commit

Permalink
feat: make static p2p nodes configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
krish-nr committed Apr 30, 2024
1 parent bb6be88 commit 874db0b
Showing 1 changed file with 85 additions and 17 deletions.
102 changes: 85 additions & 17 deletions cmd/bootnode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"fmt"
"net"
"os"
"strconv"
"strings"
"time"

"github.com/ethereum/go-ethereum/cmd/utils"
Expand All @@ -38,17 +40,18 @@ import (

func main() {
var (
listenAddr = flag.String("addr", ":30301", "listen address")
genKey = flag.String("genkey", "", "generate a node key")
writeAddr = flag.Bool("writeaddress", false, "write out the node's public key and quit")
nodeKeyFile = flag.String("nodekey", "", "private key filename")
nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)")
natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|pmp:<IP>|extip:<IP>)")
netrestrict = flag.String("netrestrict", "", "restrict network communication to the given IP networks (CIDR masks)")
runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode")
verbosity = flag.Int("verbosity", 3, "log verbosity (0-5)")
vmodule = flag.String("vmodule", "", "log verbosity pattern")
network = flag.String("network", "", "testnet/mainnet")
listenAddr = flag.String("addr", ":30301", "listen address")
genKey = flag.String("genkey", "", "generate a node key")
writeAddr = flag.Bool("writeaddress", false, "write out the node's public key and quit")
nodeKeyFile = flag.String("nodekey", "", "private key filename")
nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)")
natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|pmp:<IP>|extip:<IP>)")
netrestrict = flag.String("netrestrict", "", "restrict network communication to the given IP networks (CIDR masks)")
runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode")
verbosity = flag.Int("verbosity", 3, "log verbosity (0-5)")
vmodule = flag.String("vmodule", "", "log verbosity pattern")
network = flag.String("network", "", "testnet/mainnet")
staticP2pNodes = flag.String("staticnodes", "", "static p2p nodes for discovery")

nodeKey *ecdsa.PrivateKey
err error
Expand Down Expand Up @@ -94,10 +97,17 @@ func main() {
}
}

if *network == "testnet" {
staticV4Nodes = staticV4NodesTestnet
if *staticP2pNodes == "" {
if *network == "testnet" {
staticV4Nodes = staticV4NodesTestnet
} else {
staticV4Nodes = staticV4NodesMainnet
}
} else {
staticV4Nodes = staticV4NodesMainnet
parsedNodes, err := parseStaticNodes(*staticP2pNodes)
if err == nil {
staticV4Nodes = parsedNodes
}
}

if *writeAddr {
Expand Down Expand Up @@ -160,9 +170,10 @@ func main() {
// Start discovery services.
if *runv5 {
cfg := discover.Config{
PrivateKey: nodeKey,
NetRestrict: restrictList,
Unhandled: unhandled,
PrivateKey: nodeKey,
NetRestrict: restrictList,
Unhandled: unhandled,
StaticV4Nodes: staticV4Nodes,
}
_, err := discover.ListenV4(conn, ln, cfg)
if err != nil {
Expand Down Expand Up @@ -264,6 +275,63 @@ func doPortMapping(natm nat.Interface, ln *enode.LocalNode, addr *net.UDPAddr) *
return extaddr
}

// parseStaticNodes parses a comma-separated list of node URLs into a slice of Node structs.
func parseStaticNodes(nodeList string) ([]v4wire.Node, error) {
nodes := strings.Split(nodeList, ",")
var result []v4wire.Node

for _, node := range nodes {
// Trim spaces that might surround the node entry
node = strings.TrimSpace(node)
if node == "" {
continue
}

// Parse the node URL
if !strings.HasPrefix(node, "enode://") {
return nil, fmt.Errorf("parse error: node does not start with 'enode://'")
}

// Separate the node ID from the IP and port
atPos := strings.Index(node, "@")
if atPos == -1 {
return nil, fmt.Errorf("parse error: '@' not found in node string")
}

idPart := node[8:atPos] // skip "enode://"
ipPortPart := node[atPos+1:]

colonPos := strings.LastIndex(ipPortPart, ":")
if colonPos == -1 {
return nil, fmt.Errorf("parse error: ':' not found in IP:port part")
}

ipStr := ipPortPart[:colonPos]
portStr := ipPortPart[colonPos+1:]

port, err := strconv.ParseUint(portStr, 10, 16)
if err != nil {
return nil, fmt.Errorf("parse error: invalid port number")
}

ip := net.ParseIP(ipStr)
if ip == nil {
return nil, fmt.Errorf("parse error: invalid IP address")
}

nodeStruct := v4wire.Node{
IP: ip,
UDP: uint16(port),
TCP: uint16(port),
ID: decodePubkeyV4(idPart),
}

result = append(result, nodeStruct)
}

return result, nil
}

// shared connection
// sharedUDPConn implements a shared connection. Write sends messages to the underlying connection while read returns
// messages that were found unprocessable and sent to the unhandled channel by the primary listener.
Expand Down

0 comments on commit 874db0b

Please sign in to comment.