2023-04-20 18:51:13 +00:00
package enr
2021-12-03 13:40:51 +00:00
import (
2021-12-10 14:26:38 +00:00
"encoding/binary"
"errors"
2021-12-03 13:40:51 +00:00
"fmt"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
2022-10-19 19:39:32 +00:00
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
2023-04-20 18:51:13 +00:00
"github.com/waku-org/go-waku/waku/v2/utils"
2021-12-03 13:40:51 +00:00
)
2024-06-20 07:20:15 +00:00
var ErrNoPortAvailable = errors . New ( "port not available" )
2022-04-25 19:31:26 +00:00
// WakuENRField is the name of the ENR field that contains information about which protocols are supported by the node
2021-12-03 13:40:51 +00:00
const WakuENRField = "waku2"
2022-04-25 19:31:26 +00:00
// MultiaddrENRField is the name of the ENR field that will contain multiaddresses that cannot be described using the
// already available ENR fields (i.e. in the case of websocket connections)
2021-12-10 14:26:38 +00:00
const MultiaddrENRField = "multiaddrs"
2021-12-03 13:40:51 +00:00
2023-04-20 18:51:13 +00:00
const ShardingIndicesListEnrField = "rs"
const ShardingBitVectorEnrField = "rsv"
2021-12-03 13:40:51 +00:00
// WakuEnrBitfield is a8-bit flag field to indicate Waku capabilities. Only the 4 LSBs are currently defined according to RFC31 (https://rfc.vac.dev/spec/31/).
type WakuEnrBitfield = uint8
2022-04-25 19:31:26 +00:00
// NewWakuEnrBitfield creates a WakuEnrBitField whose value will depend on which protocols are enabled in the node
2021-12-03 13:40:51 +00:00
func NewWakuEnrBitfield ( lightpush , filter , store , relay bool ) WakuEnrBitfield {
2023-09-11 14:24:05 +00:00
var v uint8
2021-12-03 13:40:51 +00:00
if lightpush {
v |= ( 1 << 3 )
}
if filter {
v |= ( 1 << 2 )
}
if store {
v |= ( 1 << 1 )
}
if relay {
v |= ( 1 << 0 )
}
return v
}
2022-04-25 19:31:26 +00:00
// EnodeToMultiaddress converts an enode into a multiaddress
2022-10-19 19:39:32 +00:00
func enodeToMultiAddr ( node * enode . Node ) ( multiaddr . Multiaddr , error ) {
2023-04-20 18:51:13 +00:00
pubKey := utils . EcdsaPubKeyToSecp256k1PublicKey ( node . Pubkey ( ) )
2022-02-21 19:21:31 +00:00
peerID , err := peer . IDFromPublicKey ( pubKey )
2021-12-03 13:40:51 +00:00
if err != nil {
return nil , err
}
2023-05-30 14:34:34 +00:00
ipType := "ip4"
portNumber := node . TCP ( )
2024-06-20 07:20:15 +00:00
if portNumber == 0 {
return nil , ErrNoPortAvailable
}
2023-05-30 14:34:34 +00:00
if utils . IsIPv6 ( node . IP ( ) . String ( ) ) {
ipType = "ip6"
var port enr . TCP6
if err := node . Record ( ) . Load ( & port ) ; err != nil {
return nil , err
}
portNumber = int ( port )
}
return multiaddr . NewMultiaddr ( fmt . Sprintf ( "/%s/%s/tcp/%d/p2p/%s" , ipType , node . IP ( ) , portNumber , peerID ) )
2021-12-03 13:40:51 +00:00
}
2022-04-25 19:31:26 +00:00
// Multiaddress is used to extract all the multiaddresses that are part of a ENR record
2023-02-16 22:10:20 +00:00
func Multiaddress ( node * enode . Node ) ( peer . ID , [ ] multiaddr . Multiaddr , error ) {
2023-04-20 18:51:13 +00:00
pubKey := utils . EcdsaPubKeyToSecp256k1PublicKey ( node . Pubkey ( ) )
2022-02-21 19:21:31 +00:00
peerID , err := peer . IDFromPublicKey ( pubKey )
2021-12-10 14:26:38 +00:00
if err != nil {
2023-02-16 22:10:20 +00:00
return "" , nil , err
2021-12-10 14:26:38 +00:00
}
2023-01-14 19:11:29 +00:00
var result [ ] multiaddr . Multiaddr
addr , err := enodeToMultiAddr ( node )
if err != nil {
2024-06-20 07:20:15 +00:00
if ! errors . Is ( err , ErrNoPortAvailable ) {
return "" , nil , err
}
} else {
result = append ( result , addr )
2021-12-10 14:26:38 +00:00
}
2023-01-14 19:11:29 +00:00
var multiaddrRaw [ ] byte
if err := node . Record ( ) . Load ( enr . WithEntry ( MultiaddrENRField , & multiaddrRaw ) ) ; err != nil {
if ! enr . IsNotFound ( err ) {
2023-02-16 22:10:20 +00:00
return "" , nil , err
2023-01-14 19:11:29 +00:00
}
2023-09-11 14:24:05 +00:00
// No multiaddr entry on enr
return peerID , result , nil
2021-12-10 14:26:38 +00:00
}
2023-02-13 13:33:41 +00:00
if len ( multiaddrRaw ) < 2 {
// There was no error loading the multiaddr field, but its length is incorrect
2023-02-16 22:10:20 +00:00
return peerID , result , nil
2023-02-13 13:33:41 +00:00
}
2021-12-10 14:26:38 +00:00
offset := 0
for {
maSize := binary . BigEndian . Uint16 ( multiaddrRaw [ offset : offset + 2 ] )
if len ( multiaddrRaw ) < offset + 2 + int ( maSize ) {
2023-02-16 22:10:20 +00:00
return "" , nil , errors . New ( "invalid multiaddress field length" )
2021-12-10 14:26:38 +00:00
}
maRaw := multiaddrRaw [ offset + 2 : offset + 2 + int ( maSize ) ]
2022-10-19 19:39:32 +00:00
addr , err := multiaddr . NewMultiaddrBytes ( maRaw )
2021-12-10 14:26:38 +00:00
if err != nil {
2023-02-16 22:10:20 +00:00
return "" , nil , fmt . Errorf ( "invalid multiaddress field length" )
2021-12-10 14:26:38 +00:00
}
2024-01-12 17:40:27 +00:00
hostInfoStr := fmt . Sprintf ( "/p2p/%s" , peerID . String ( ) )
2023-06-30 15:26:04 +00:00
_ , pID := peer . SplitAddr ( addr )
if pID != "" && pID != peerID {
// Addresses in the ENR that contain a p2p component are circuit relay addr
hostInfoStr = "/p2p-circuit" + hostInfoStr
}
hostInfo , err := multiaddr . NewMultiaddr ( hostInfoStr )
if err != nil {
return "" , nil , err
}
2021-12-10 14:26:38 +00:00
result = append ( result , addr . Encapsulate ( hostInfo ) )
offset += 2 + int ( maSize )
if offset >= len ( multiaddrRaw ) {
break
}
}
2023-02-16 22:10:20 +00:00
return peerID , result , nil
2021-12-10 14:26:38 +00:00
}
2022-07-25 15:28:17 +00:00
// EnodeToPeerInfo extracts the peer ID and multiaddresses defined in an ENR
2021-12-03 13:40:51 +00:00
func EnodeToPeerInfo ( node * enode . Node ) ( * peer . AddrInfo , error ) {
2023-02-16 22:10:20 +00:00
_ , addresses , err := Multiaddress ( node )
2022-04-25 19:31:26 +00:00
if err != nil {
return nil , err
}
res , err := peer . AddrInfosFromP2pAddrs ( addresses ... )
2021-12-03 13:40:51 +00:00
if err != nil {
return nil , err
}
2023-11-07 17:13:19 +00:00
if len ( res ) == 0 {
return nil , errors . New ( "could not retrieve peer addresses from enr" )
}
2022-04-25 19:31:26 +00:00
return & res [ 0 ] , nil
2021-12-03 13:40:51 +00:00
}