Skip to content

Commit

Permalink
fix: obtain multiple multiaddresses from single enode
Browse files Browse the repository at this point in the history
  • Loading branch information
richard-ramos committed Jan 15, 2023
1 parent 6e7c3b6 commit 25486eb
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 90 deletions.
164 changes: 80 additions & 84 deletions waku/v2/utils/enr.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
"go.uber.org/zap"
)

// WakuENRField is the name of the ENR field that contains information about which protocols are supported by the node
Expand Down Expand Up @@ -50,95 +49,92 @@ func NewWakuEnrBitfield(lightpush, filter, store, relay bool) WakuEnrBitfield {
}

// GetENRandIP returns a enr Node and TCP address obtained from a multiaddress. priv key and protocols supported
func GetENRandIP(addr multiaddr.Multiaddr, wakuFlags WakuEnrBitfield, privK *ecdsa.PrivateKey) (*enode.Node, *net.TCPAddr, error) {
var ip string

dns4, err := addr.ValueForProtocol(multiaddr.P_DNS4)
if err != nil {
ip, err = addr.ValueForProtocol(multiaddr.P_IP4)
if err != nil {
return nil, nil, err
}
} else {
netIP, err := net.ResolveIPAddr("ip4", dns4)
if err != nil {
return nil, nil, err
}
ip = netIP.String()
}

portStr, err := addr.ValueForProtocol(multiaddr.P_TCP)
if err != nil {
return nil, nil, err
}

port, err := strconv.Atoi(portStr)
if err != nil {
return nil, nil, err
}

tcpAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", ip, port))
if err != nil {
return nil, nil, err
}

func GetENRandIP(addrs []multiaddr.Multiaddr, wakuFlags WakuEnrBitfield, privK *ecdsa.PrivateKey) (*enode.Node, error) {
r := &enr.Record{}
for _, addr := range addrs {
storeInMultiaddrsKey := false
var multiaddrItems []multiaddr.Multiaddr
_, err := addr.ValueForProtocol(multiaddr.P_WS)
if err == nil {
storeInMultiaddrsKey = true
multiaddrItems = append(multiaddrItems, addr)
}

if port > 0 && port <= math.MaxUint16 {
r.Set(enr.TCP(uint16(port))) // lgtm [go/incorrect-integer-conversion]
} else {
return nil, nil, fmt.Errorf("could not set port %d", port)
}
_, err = addr.ValueForProtocol(multiaddr.P_WSS)
if err == nil {
storeInMultiaddrsKey = true
multiaddrItems = append(multiaddrItems, addr)
}

var multiaddrItems []multiaddr.Multiaddr
if !storeInMultiaddrsKey {
var ip string
dns4, err := addr.ValueForProtocol(multiaddr.P_DNS4)
if err != nil {
ip, err = addr.ValueForProtocol(multiaddr.P_IP4)
if err != nil {
return nil, err
}
} else {
netIP, err := net.ResolveIPAddr("ip4", dns4)
if err != nil {
return nil, err
}
ip = netIP.String()
}

// 31/WAKU2-ENR
portStr, err := addr.ValueForProtocol(multiaddr.P_TCP)
if err != nil {
return nil, err
}

_, err = addr.ValueForProtocol(multiaddr.P_WS)
if err == nil {
multiaddrItems = append(multiaddrItems, addr)
}
port, err := strconv.Atoi(portStr)
if err != nil {
return nil, err
}

_, err = addr.ValueForProtocol(multiaddr.P_WSS)
if err == nil {
multiaddrItems = append(multiaddrItems, addr)
}
if port > 0 && port <= math.MaxUint16 {
r.Set(enr.TCP(uint16(port))) // lgtm [go/incorrect-integer-conversion]
} else {
return nil, fmt.Errorf("could not set port %d", port)
}

p2p, err := addr.ValueForProtocol(multiaddr.P_P2P)
if err != nil {
return nil, nil, err
}
r.Set(enr.IP(net.ParseIP(ip)))
} else {
p2p, err := addr.ValueForProtocol(multiaddr.P_P2P)
if err != nil {
return nil, err
}

p2pAddr, err := multiaddr.NewMultiaddr("/p2p/" + p2p)
if err != nil {
return nil, nil, fmt.Errorf("could not create p2p addr: %w", err)
}
p2pAddr, err := multiaddr.NewMultiaddr("/p2p/" + p2p)
if err != nil {
return nil, fmt.Errorf("could not create p2p addr: %w", err)
}

var fieldRaw []byte
for _, ma := range multiaddrItems {
maRaw := ma.Decapsulate(p2pAddr).Bytes()
maSize := make([]byte, 2)
binary.BigEndian.PutUint16(maSize, uint16(len(maRaw)))
var fieldRaw []byte
for _, ma := range multiaddrItems {
maRaw := ma.Decapsulate(p2pAddr).Bytes()
maSize := make([]byte, 2)
binary.BigEndian.PutUint16(maSize, uint16(len(maRaw)))

fieldRaw = append(fieldRaw, maSize...)
fieldRaw = append(fieldRaw, maRaw...)
}
fieldRaw = append(fieldRaw, maSize...)
fieldRaw = append(fieldRaw, maRaw...)
}

if len(fieldRaw) != 0 {
r.Set(enr.WithEntry(MultiaddrENRField, fieldRaw))
if len(fieldRaw) != 0 {
r.Set(enr.WithEntry(MultiaddrENRField, fieldRaw))
}
}
}

r.Set(enr.IP(net.ParseIP(ip)))
r.Set(enr.WithEntry(WakuENRField, wakuFlags))

err = enode.SignV4(r, privK)
err := enode.SignV4(r, privK)
if err != nil {
return nil, nil, err
return nil, err
}

node, err := enode.New(enode.ValidSchemes, r)

return node, tcpAddr, err
return node, err
}

// EnodeToMultiaddress converts an enode into a multiaddress
Expand All @@ -160,29 +156,29 @@ func Multiaddress(node *enode.Node) ([]multiaddr.Multiaddr, error) {
return nil, err
}

var multiaddrRaw []byte
if err := node.Record().Load(enr.WithEntry(MultiaddrENRField, &multiaddrRaw)); err != nil {
if enr.IsNotFound(err) {
Logger().Debug("trying to convert enode to multiaddress, since I could not retrieve multiaddress field for node ", zap.Any("enode", node))
addr, err := enodeToMultiAddr(node)
if err != nil {
return nil, err
}
return []multiaddr.Multiaddr{addr}, nil
}
var result []multiaddr.Multiaddr

addr, err := enodeToMultiAddr(node)
if err != nil {
return nil, err
}
result = append(result, addr)

if len(multiaddrRaw) < 2 {
return nil, errors.New("invalid multiaddress field length")
var multiaddrRaw []byte
if err := node.Record().Load(enr.WithEntry(MultiaddrENRField, &multiaddrRaw)); err != nil {
if !enr.IsNotFound(err) {
return nil, err
} else {
// No multiaddr entry on enr
return result, nil
}
}

hostInfo, err := multiaddr.NewMultiaddr(fmt.Sprintf("/p2p/%s", peerID.Pretty()))
if err != nil {
return nil, err
}

var result []multiaddr.Multiaddr
offset := 0
for {
maSize := binary.BigEndian.Uint16(multiaddrRaw[offset : offset+2])
Expand Down
16 changes: 10 additions & 6 deletions waku/v2/utils/enr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ func TestGetENRandIP(t *testing.T) {

wakuFlag := NewWakuEnrBitfield(true, true, true, true)

node, resTCPAddr, err := GetENRandIP(ogMultiaddress, wakuFlag, key)
node, err := GetENRandIP([]ma.Multiaddr{ogMultiaddress}, wakuFlag, key)
require.NoError(t, err)
require.Equal(t, hostAddr, resTCPAddr)

parsedNode := enode.MustParse(node.String())
resMultiaddress, err := enodeToMultiAddr(parsedNode)
Expand All @@ -49,14 +48,19 @@ func TestMultiaddr(t *testing.T) {
key, _ := gcrypto.GenerateKey()
pubKey := EcdsaPubKeyToSecp256k1PublicKey(&key.PublicKey)
id, _ := peer.IDFromPublicKey(pubKey)
ogMultiaddress, _ := ma.NewMultiaddr("/ip4/10.0.0.241/tcp/60001/ws/p2p/" + id.Pretty())
wakuFlag := NewWakuEnrBitfield(true, true, true, true)

node, _, err := GetENRandIP(ogMultiaddress, wakuFlag, key)
normalMultiaddr, _ := ma.NewMultiaddr("/ip4/192.1.168.241/tcp/60000/p2p/" + id.Pretty())
wsMultiaddress, _ := ma.NewMultiaddr("/ip4/10.0.0.241/tcp/60001/ws/p2p/" + id.Pretty())

node, err := GetENRandIP([]ma.Multiaddr{normalMultiaddr, wsMultiaddress}, wakuFlag, key)
require.NoError(t, err)

multiaddresses, err := Multiaddress(node)
fmt.Println(multiaddresses)

require.NoError(t, err)
require.Len(t, multiaddresses, 1)
require.True(t, ogMultiaddress.Equal(multiaddresses[0]))
require.Len(t, multiaddresses, 2)
require.True(t, normalMultiaddr.Equal(multiaddresses[0]))
require.True(t, wsMultiaddress.Equal(multiaddresses[1]))
}

0 comments on commit 25486eb

Please sign in to comment.