fix: try to include as many multiaddr as possible without exceeding max enr size

This commit is contained in:
Richard Ramos 2023-02-01 13:37:47 -04:00 committed by RichΛrd
parent 676a1ab361
commit c3b5ab95ab
3 changed files with 99 additions and 50 deletions

View File

@ -24,22 +24,25 @@ func TestExternalAddressSelection(t *testing.T) {
addrs := []ma.Multiaddr{a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11}
w := &WakuNode{}
extAddr, multiaddr, err := w.getENRAddresses(addrs)
extAddr, multiaddr, err := w.getENRAddresses([]ma.Multiaddr{a1, a2, a3, a4, a5, a6, a7, a8})
a5NoP2P, _ := decapsulateP2P(a5)
a8RelayNode, _ := decapsulateCircuitRelayAddr(a8)
require.NoError(t, err)
require.Equal(t, extAddr.IP, net.IPv4(192, 168, 0, 106))
require.Equal(t, extAddr.Port, 60000)
require.Equal(t, multiaddr[0].String(), a5NoP2P.String())
require.Equal(t, multiaddr[1].String(), a8RelayNode.String())
require.Len(t, multiaddr, 5)
require.Len(t, multiaddr, 1) // Should only have 1, without circuit relay
a12, _ := ma.NewMultiaddr("/ip4/188.23.1.8/tcp/30303/p2p/16Uiu2HAmUVVrJo1KMw4QwUANYF7Ws4mfcRqf9xHaaGP87GbMuY2f") // VALID
addrs = append(addrs, a12)
extAddr, _, err = w.getENRAddresses(addrs)
require.NoError(t, err)
require.Equal(t, extAddr.IP, net.IPv4(188, 23, 1, 8))
require.Equal(t, extAddr.Port, 30303)
a8RelayNode, _ := decapsulateCircuitRelayAddr(a8)
_, multiaddr, err = w.getENRAddresses([]ma.Multiaddr{a1, a8})
require.NoError(t, err)
require.Len(t, multiaddr, 1)
require.Equal(t, multiaddr[0].String(), a8RelayNode.String()) // Should have included circuit-relay addr
}

View File

@ -5,7 +5,6 @@ import (
"crypto/ecdsa"
"encoding/binary"
"errors"
"fmt"
"math"
"net"
"strconv"
@ -68,19 +67,47 @@ func (w *WakuNode) updateLocalNode(localnode *enode.LocalNode, multiaddrs []ma.M
}
}
// Adding extra multiaddresses
var fieldRaw []byte
for _, addr := range multiaddrs {
maRaw := addr.Bytes()
maSize := make([]byte, 2)
binary.BigEndian.PutUint16(maSize, uint16(len(maRaw)))
// Adding extra multiaddresses. It will to add as many multiaddresses as possible
// without exceeding the enr max size of 300bytes
var addrAggr []ma.Multiaddr
var err error
for i := len(multiaddrs) - 1; i >= 0; i-- {
addrAggr = append(addrAggr, multiaddrs[0:i]...)
err = func() (err error) {
defer func() {
if e := recover(); e != nil {
err = errors.New("could not write enr record")
}
}()
fieldRaw = append(fieldRaw, maSize...)
fieldRaw = append(fieldRaw, maRaw...)
var fieldRaw []byte
for _, addr := range addrAggr {
maRaw := addr.Bytes()
maSize := make([]byte, 2)
binary.BigEndian.PutUint16(maSize, uint16(len(maRaw)))
fieldRaw = append(fieldRaw, maSize...)
fieldRaw = append(fieldRaw, maRaw...)
}
if len(fieldRaw) != 0 {
localnode.Set(enr.WithEntry(utils.MultiaddrENRField, fieldRaw))
}
// This is to trigger the signing record err due to exceeding 300bytes limit
_ = localnode.Node()
return nil
}()
if err == nil {
break
}
}
if len(fieldRaw) != 0 {
localnode.Set(enr.WithEntry(utils.MultiaddrENRField, fieldRaw))
// In case multiaddr could not be populated at all
if err != nil {
localnode.Delete(enr.WithEntry(utils.MultiaddrENRField, struct{}{}))
}
return nil
@ -163,8 +190,6 @@ func selectMostExternalAddress(addresses []ma.Multiaddr) (*net.TCPAddr, error) {
if err != nil {
continue
}
fmt.Println(ipAddr, addr)
ipAddrs = append(ipAddrs, ipAddr)
}
@ -270,13 +295,18 @@ func (w *WakuNode) getENRAddresses(addrs []ma.Multiaddr) (extAddr *net.TCPAddr,
return nil, nil, err
}
circuitAddrs, err := selectCircuitRelayListenAddresses(addrs)
if err != nil {
return nil, nil, err
}
multiaddr = append(multiaddr, wssAddrs...)
multiaddr = append(multiaddr, circuitAddrs...)
// to use WSS, you should have a valid certificate with a domain name.
// that means you're reachable. So circuit relay addresses are ignored
if len(wssAddrs) == 0 {
circuitAddrs, err := selectCircuitRelayListenAddresses(addrs)
if err != nil {
return nil, nil, err
}
multiaddr = append(multiaddr, circuitAddrs...)
}
return
}

View File

@ -3,7 +3,6 @@ package utils
import (
"encoding/binary"
"errors"
"fmt"
"math"
"net"
"testing"
@ -26,7 +25,7 @@ func TestEnodeToMultiAddr(t *testing.T) {
require.Equal(t, expectedMultiAddr, actualMultiAddr.String())
}
// TODO: this function is duplicated in localnode.go. Extract to utils
// TODO: this function is duplicated in localnode.go. Remove duplication
func updateLocalNode(localnode *enode.LocalNode, multiaddrs []ma.Multiaddr, ipAddr *net.TCPAddr, udpPort uint, wakuFlags WakuEnrBitfield, advertiseAddr *net.IP, shouldAutoUpdate bool, log *zap.Logger) error {
localnode.SetFallbackUDP(int(udpPort))
localnode.Set(enr.WithEntry(WakuENRField, wakuFlags))
@ -70,19 +69,45 @@ func updateLocalNode(localnode *enode.LocalNode, multiaddrs []ma.Multiaddr, ipAd
}
}
// Adding extra multiaddresses
var fieldRaw []byte
for _, addr := range multiaddrs {
maRaw := addr.Bytes()
maSize := make([]byte, 2)
binary.BigEndian.PutUint16(maSize, uint16(len(maRaw)))
var addrAggr []ma.Multiaddr
var err error
for i := len(multiaddrs) - 1; i >= 0; i-- {
addrAggr = append(addrAggr, multiaddrs[0:i]...)
err = func() (err error) {
defer func() {
if e := recover(); e != nil {
err = errors.New("could not write enr record")
}
}()
fieldRaw = append(fieldRaw, maSize...)
fieldRaw = append(fieldRaw, maRaw...)
var fieldRaw []byte
for _, addr := range addrAggr {
maRaw := addr.Bytes()
maSize := make([]byte, 2)
binary.BigEndian.PutUint16(maSize, uint16(len(maRaw)))
fieldRaw = append(fieldRaw, maSize...)
fieldRaw = append(fieldRaw, maRaw...)
}
if len(fieldRaw) != 0 {
localnode.Set(enr.WithEntry(MultiaddrENRField, fieldRaw))
}
// This is to trigger the signing record err due to exceeding 300bytes limit
_ = localnode.Node()
return nil
}()
if err == nil {
break
}
}
if len(fieldRaw) != 0 {
localnode.Set(enr.WithEntry(MultiaddrENRField, fieldRaw))
// In case multiaddr could not be populated at all
if err != nil {
localnode.Delete(enr.WithEntry(MultiaddrENRField, struct{}{}))
}
return nil
@ -106,19 +131,10 @@ func TestMultiaddr(t *testing.T) {
db, _ := enode.OpenDB("")
localNode := enode.NewLocalNode(db, key)
err := updateLocalNode(localNode, multiaddrValues, &net.TCPAddr{IP: net.IPv4(192, 168, 1, 241), Port: 60000}, 50000, wakuFlag, nil, false, Logger())
if err != nil {
fmt.Println("ERROR WRITING ENR", err)
} else {
fmt.Println("==========================================")
fmt.Println(localNode.Node())
fmt.Println("==========================================")
require.NoError(t, err)
multiaddresses, err := Multiaddress(localNode.Node())
require.NoError(t, err)
for _, a := range multiaddresses {
fmt.Println(a)
}
}
_ = localNode.Node() // Should not panic
_, err = Multiaddress(localNode.Node())
require.NoError(t, err)
}