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

QSP-16 Fix Support for IPv6 #6363

Merged
merged 28 commits into from
Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9ea0b3e
checkpoint changes
nisdas Jun 23, 2020
68cf157
Merge branch 'master' into fixIPv6
nisdas Jun 23, 2020
fb5e44e
Merge branch 'master' of https://github.com/prysmaticlabs/geth-shardi…
nisdas Jun 24, 2020
71b1c98
Merge branch 'master' of https://github.com/prysmaticlabs/geth-shardi…
nisdas Jun 24, 2020
ea2ffb5
Merge branch 'master' into fixIPv6
nisdas Jul 3, 2020
4aedb17
Merge branch 'fixIPv6' of https://github.com/prysmaticlabs/geth-shard…
nisdas Jul 17, 2020
92ae3d9
Merge branch 'master' of https://github.com/prysmaticlabs/geth-shardi…
nisdas Jul 17, 2020
5743de1
Merge branch 'master' into fixIPv6
prestonvanloon Sep 10, 2020
ea0bf7f
new changes
nisdas Sep 13, 2020
a8bc51a
comment
nisdas Sep 13, 2020
7e9a8be
clean up
nisdas Sep 14, 2020
29602cf
set
nisdas Sep 14, 2020
ab4541f
fix
nisdas Sep 14, 2020
f9dd8f7
fix more
nisdas Sep 14, 2020
54f1187
more stuff
nisdas Sep 14, 2020
9a30679
clean up
nisdas Sep 14, 2020
0098091
clean up
nisdas Sep 14, 2020
5e791bb
remove
nisdas Sep 14, 2020
c768702
clean up
nisdas Sep 14, 2020
288301a
clean up
nisdas Sep 14, 2020
540e8aa
Merge branch 'master' into fixIPv6
nisdas Sep 14, 2020
85addee
comment
nisdas Sep 14, 2020
921936a
Merge branch 'fixIPv6' of https://github.com/prysmaticlabs/geth-shard…
nisdas Sep 14, 2020
346911d
Merge refs/heads/master into fixIPv6
prylabs-bulldozer[bot] Sep 14, 2020
6fcea21
Merge refs/heads/master into fixIPv6
prylabs-bulldozer[bot] Sep 14, 2020
b3295d8
Merge refs/heads/master into fixIPv6
prylabs-bulldozer[bot] Sep 15, 2020
cec784b
Merge refs/heads/master into fixIPv6
prylabs-bulldozer[bot] Sep 15, 2020
d6daebb
Merge refs/heads/master into fixIPv6
prylabs-bulldozer[bot] Sep 15, 2020
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 beacon-chain/p2p/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ go_test(
"//shared/testutil:go_default_library",
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",
"@com_github_ethereum_go_ethereum//crypto:go_default_library",
"@com_github_ethereum_go_ethereum//p2p/discover:go_default_library",
"@com_github_ethereum_go_ethereum//p2p/enode:go_default_library",
"@com_github_ethereum_go_ethereum//p2p/enr:go_default_library",
Expand Down
15 changes: 3 additions & 12 deletions beacon-chain/p2p/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package p2p
import (
"bytes"
"crypto/ecdsa"
"fmt"
"net"
"strconv"
"time"
Expand Down Expand Up @@ -124,9 +123,10 @@ func (s *Service) createListener(
if err != nil {
return nil, errors.Wrap(err, "could not listen to UDP")
}

localNode, err := s.createLocalNode(
privKey,
ipAddr,
udpAddr.IP,
int(s.cfg.UDPPort),
int(s.cfg.TCPPort),
)
Expand Down Expand Up @@ -365,22 +365,13 @@ func convertToAddrInfo(node *enode.Node) (*peer.AddrInfo, ma.Multiaddr, error) {
}

func convertToSingleMultiAddr(node *enode.Node) (ma.Multiaddr, error) {
ip4 := node.IP().To4()
if ip4 == nil {
return nil, errors.Errorf("node doesn't have an ip4 address, it's stated IP is %s", node.IP().String())
}
pubkey := node.Pubkey()
assertedKey := convertToInterfacePubkey(pubkey)
id, err := peer.IDFromPublicKey(assertedKey)
if err != nil {
return nil, errors.Wrap(err, "could not get peer id")
}
multiAddrString := fmt.Sprintf("/ip4/%s/tcp/%d/p2p/%s", ip4.String(), node.TCP(), id)
multiAddr, err := ma.NewMultiaddr(multiAddrString)
if err != nil {
return nil, errors.Wrap(err, "could not get multiaddr")
}
return multiAddr, nil
return multiAddressBuilderWithID(node.IP().String(), uint(node.TCP()), id)
}

func peersFromStringAddrs(addrs []string) ([]ma.Multiaddr, error) {
Expand Down
15 changes: 15 additions & 0 deletions beacon-chain/p2p/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net"

"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/peer"
noise "github.com/libp2p/go-libp2p-noise"
secio "github.com/libp2p/go-libp2p-secio"
ma "github.com/multiformats/go-multiaddr"
Expand Down Expand Up @@ -85,6 +86,20 @@ func multiAddressBuilder(ipAddr string, port uint) (ma.Multiaddr, error) {
return ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/tcp/%d", ipAddr, port))
}

func multiAddressBuilderWithID(ipAddr string, port uint, id peer.ID) (ma.Multiaddr, error) {
parsedIP := net.ParseIP(ipAddr)
if parsedIP.To4() == nil && parsedIP.To16() == nil {
return nil, errors.Errorf("invalid ip address provided: %s", ipAddr)
}
if id.String() == "" {
return nil, errors.New("empty peer id given")
}
if parsedIP.To4() != nil {
return ma.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d/p2p/%s", ipAddr, port, id.String()))
}
return ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/tcp/%d/p2p/%s", ipAddr, port, id.String()))
}

// Adds a private key to the libp2p option if the option was provided.
// If the private key file is missing or cannot be read, or if the
// private key contents cannot be marshaled, an exception is thrown.
Expand Down
31 changes: 31 additions & 0 deletions beacon-chain/p2p/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import (
"crypto/rand"
"encoding/hex"
"io/ioutil"
"net"
"os"
"testing"

gethCrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
Expand Down Expand Up @@ -46,3 +50,30 @@ func TestPrivateKeyLoading(t *testing.T) {
t.Errorf("Private keys do not match got %#x but wanted %#x", rawBytes, newRaw)
}
}

func TestIPV6Support(t *testing.T) {
key, err := gethCrypto.GenerateKey()
db, err := enode.OpenDB("")
if err != nil {
log.Error("could not open node's peer database")
}
lNode := enode.NewLocalNode(db, key)
mockIPV6 := net.IP{0xff, 0x02, 0xAA, 0, 0x1F, 0, 0x2E, 0, 0, 0x36, 0x45, 0, 0, 0, 0, 0x02}
lNode.Set(enr.IP(mockIPV6))
ma, err := convertToSingleMultiAddr(lNode.Node())
if err != nil {
t.Fatal(err)
}
ipv6Exists := false
for _, p := range ma.Protocols() {
if p.Name == "ip4" {
t.Error("Got ip4 address instead of ip6")
}
if p.Name == "ip6" {
ipv6Exists = true
}
}
if !ipv6Exists {
t.Error("Multiaddress did not have ipv6 protocol")
}
}
4 changes: 2 additions & 2 deletions beacon-chain/p2p/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func metaDataFromConfig(cfg *Config) (*pbp2p.MetaData, error) {

// Retrieves an external ipv4 address and converts into a libp2p formatted value.
func ipAddr() net.IP {
ip, err := iputils.ExternalIPv4()
ip, err := iputils.ExternalIP()
if err != nil {
log.Fatalf("Could not get IPv4 address: %v", err)
}
Expand All @@ -160,7 +160,7 @@ func ipAddr() net.IP {
// Attempt to dial an address to verify its connectivity
func verifyConnectivity(addr string, port uint, protocol string) {
if addr != "" {
a := fmt.Sprintf("%s:%d", addr, port)
a := net.JoinHostPort(addr, fmt.Sprintf("%d", port))
fields := logrus.Fields{
"protocol": protocol,
"address": a,
Expand Down
66 changes: 58 additions & 8 deletions shared/iputils/external_ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,64 @@ import (

// ExternalIPv4 returns the first IPv4 available.
func ExternalIPv4() (string, error) {
ifaces, err := net.Interfaces()
ips, err := retrieveIPAddrs()
if err != nil {
return "", err
}
if len(ips) == 0 {
return "127.0.0.1", nil
}
for _, ip := range ips {
ip = ip.To4()
if ip == nil {
continue // not an ipv4 address
}
return ip.String(), nil
}
return "127.0.0.1", nil
}

// ExternalIPv6 retrieves any allocated IPv6 addresses
// from the accessible network interfaces.
func ExternalIPv6() (string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized ExternalIPv6() is not covered in external_ip_test.go . Should we cover it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue would be in bazels sandbox the ipv6 address isnt availble from the accessible network interface which makes it hard to test something like this.

ips, err := retrieveIPAddrs()
if err != nil {
return "", err
}
if len(ips) == 0 {
return "127.0.0.1", nil
}
for _, ip := range ips {
if ip.To4() != nil {
continue // not an ipv6 address
}
if ip.To16() == nil {
continue
}
return ip.String(), nil
}
return "127.0.0.1", nil
}

// ExternalIP returns the first IPv4/IPv6 available.
func ExternalIP() (string, error) {
ips, err := retrieveIPAddrs()
if err != nil {
return "", err
}
if len(ips) == 0 {
return "127.0.0.1", nil
}
return ips[0].String(), nil
}

// retrieveIP returns all the valid IPs available.
func retrieveIPAddrs() ([]net.IP, error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
ipAddrs := []net.IP{}
for _, iface := range ifaces {
if iface.Flags&net.FlagUp == 0 {
continue // interface down
Expand All @@ -20,7 +74,7 @@ func ExternalIPv4() (string, error) {
}
addrs, err := iface.Addrs()
if err != nil {
return "", err
return nil, err
}
for _, addr := range addrs {
var ip net.IP
Expand All @@ -33,12 +87,8 @@ func ExternalIPv4() (string, error) {
if ip == nil || ip.IsLoopback() {
continue
}
ip = ip.To4()
if ip == nil {
continue // not an ipv4 address
}
return ip.String(), nil
ipAddrs = append(ipAddrs, ip)
}
}
return "127.0.0.1", nil
return ipAddrs, nil
}
12 changes: 12 additions & 0 deletions shared/iputils/external_ip_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package iputils_test

import (
"net"
"regexp"
"testing"

Expand All @@ -18,3 +19,14 @@ func TestExternalIPv4(t *testing.T) {
valid := regexp.MustCompile(IPv4Format)
assert.Equal(t, true, valid.MatchString(test))
}

func TestRetrieveIP(t *testing.T) {
ip, err := iputils.ExternalIP()
if err != nil {
t.Fatal(err)
}
retIP := net.ParseIP(ip)
if retIP.To4() == nil && retIP.To16() == nil {
t.Errorf("An invalid IP was retrieved: %s", ip)
}
}