2021-12-03 13:40:51 +00:00
package utils
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"
2021-12-03 13:40:51 +00:00
)
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
// 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 {
var v uint8 = 0
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 ) {
2022-05-27 19:55:35 +00:00
pubKey := 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
}
2022-10-19 19:39:32 +00:00
return multiaddr . NewMultiaddr ( fmt . Sprintf ( "/ip4/%s/tcp/%d/p2p/%s" , node . IP ( ) , node . TCP ( ) , 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
2022-10-19 19:39:32 +00:00
func Multiaddress ( node * enode . Node ) ( [ ] multiaddr . Multiaddr , error ) {
2022-05-27 19:55:35 +00:00
pubKey := 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 {
return nil , err
}
2023-01-14 19:11:29 +00:00
var result [ ] multiaddr . Multiaddr
addr , err := enodeToMultiAddr ( node )
if err != nil {
2021-12-10 14:26:38 +00:00
return nil , err
}
2023-01-14 19:11:29 +00:00
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 ) {
return nil , err
2023-02-09 22:02:20 +00:00
} else if len ( multiaddrRaw ) < 2 {
2023-01-14 19:11:29 +00:00
// No multiaddr entry on enr
return result , nil
}
2021-12-10 14:26:38 +00:00
}
2022-10-19 19:39:32 +00:00
hostInfo , err := multiaddr . NewMultiaddr ( fmt . Sprintf ( "/p2p/%s" , peerID . Pretty ( ) ) )
2021-12-10 14:26:38 +00:00
if err != nil {
return nil , err
}
offset := 0
for {
maSize := binary . BigEndian . Uint16 ( multiaddrRaw [ offset : offset + 2 ] )
if len ( multiaddrRaw ) < offset + 2 + int ( maSize ) {
return nil , errors . New ( "invalid multiaddress field length" )
}
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 {
return nil , fmt . Errorf ( "invalid multiaddress field length" )
}
result = append ( result , addr . Encapsulate ( hostInfo ) )
offset += 2 + int ( maSize )
if offset >= len ( multiaddrRaw ) {
break
}
}
return result , nil
}
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 ) {
2022-04-25 19:31:26 +00:00
addresses , err := Multiaddress ( node )
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
}
2022-04-25 19:31:26 +00:00
return & res [ 0 ] , nil
2021-12-03 13:40:51 +00:00
}