chore(core): move peers utils module to waku_core

This commit is contained in:
Lorenzo Delgado 2023-04-24 16:37:54 +02:00 committed by GitHub
parent 67e96ba894
commit e041e04342
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 295 additions and 317 deletions

View File

@ -33,7 +33,6 @@ import
../../waku/v2/node/waku_metrics,
../../waku/v2/node/peer_manager,
../../waku/v2/utils/compat,
../../waku/v2/utils/peers,
../../waku/common/utils/nat,
./config_chat2

View File

@ -16,7 +16,6 @@ import
libp2p/errors,
../../../waku/v2/waku_core,
../../../waku/v2/waku_node,
../../../waku/v2/utils/peers,
../../../waku/v2/node/peer_manager,
../../waku/v2/waku_filter,
../../waku/v2/waku_store,

View File

@ -46,7 +46,6 @@ import
../../waku/v2/waku_discv5,
../../waku/v2/waku_peer_exchange,
../../waku/v2/waku_relay/validators,
../../waku/v2/utils/peers,
./wakunode2_setup_rest,
./wakunode2_setup_rpc,
./config

View File

@ -4,7 +4,8 @@
import
./v2/waku_core/test_namespaced_topics,
./v2/waku_core/test_time,
./v2/waku_core/test_message_digest
./v2/waku_core/test_message_digest,
./v2/waku_core/test_peers
# Waku archive test suite
@ -50,7 +51,6 @@ import
./v2/test_wakunode_filter,
./v2/test_waku_peer_exchange,
./v2/test_peer_store_extended,
./v2/test_utils_peers,
./v2/test_message_cache,
./v2/test_peer_manager,
./v2/test_peer_storage,

View File

@ -10,8 +10,8 @@ import
libp2p/crypto/crypto,
libp2p/protocols/pubsub/gossipsub
import
../../waku/v2/waku_core,
../../waku/v2/waku_node,
../../waku/v2/utils/peers,
./testlib/wakucore,
./testlib/wakunode

View File

@ -12,8 +12,8 @@ import
libp2p/stream/connection,
libp2p/crypto/crypto
import
../../waku/v2/waku_core,
../../waku/v2/waku_node,
../../waku/v2/utils/peers,
./testlib/wakucore,
./testlib/wakunode

View File

@ -17,12 +17,11 @@ import
libp2p/nameresolving/mockresolver,
eth/p2p/discoveryv5/enr
import
../../waku/v2/waku_core,
../../waku/v2/waku_node,
../../waku/v2/node/peer_manager,
../../waku/v2/waku_core,
../../waku/v2/waku_relay,
../../waku/v2/waku_peer_exchange,
../../waku/v2/utils/peers,
./testlib/wakucore,
./testlib/wakunode

View File

@ -7,10 +7,9 @@ import
chronos,
libp2p/crypto/crypto
import
../../waku/v2/waku_core,
../../waku/v2/node/peer_manager,
../../waku/v2/waku_node,
../../waku/v2/waku_core,
../../waku/v2/utils/peers,
./testlib/common,
./testlib/wakucore,
./testlib/wakunode

View File

@ -11,7 +11,6 @@ import
../../waku/v2/waku_core,
../../waku/v2/waku_lightpush,
../../waku/v2/node/peer_manager,
../../waku/v2/utils/peers,
../../waku/v2/waku_node,
./testlib/common,
./testlib/wakucore,

View File

@ -7,14 +7,14 @@ import
libp2p/peerid,
libp2p/errors
import
../../waku/v2/utils/peers
../../waku/v2/waku_core
suite "Waku Core - Peers":
suite "Utils - Peers":
test "Peer info parses correctly":
## Given
## Given
let address = "/ip4/127.0.0.1/tcp/65002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
## When
let remotePeerInfoRes = parsePeerInfo(address)
require remotePeerInfoRes.isOk()
@ -26,7 +26,7 @@ suite "Utils - Peers":
$(remotePeerInfo.peerId) == "16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
$(remotePeerInfo.addrs[0][0].tryGet()) == "/ip4/127.0.0.1"
$(remotePeerInfo.addrs[0][1].tryGet()) == "/tcp/65002"
test "DNS multiaddrs parsing - dns peer":
## Given
let address = "/dns/localhost/tcp/65012/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
@ -46,7 +46,7 @@ suite "Utils - Peers":
test "DNS multiaddrs parsing - dnsaddr peer":
## Given
let address = "/dnsaddr/localhost/tcp/65022/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
## When
let dnsAddrPeerRes = parsePeerInfo(address)
require dnsAddrPeerRes.isOk()
@ -74,7 +74,7 @@ suite "Utils - Peers":
$(dns4Peer.peerId) == "16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
$(dns4Peer.addrs[0][0].tryGet()) == "/dns4/localhost"
$(dns4Peer.addrs[0][1].tryGet()) == "/tcp/65032"
test "DNS multiaddrs parsing - dns6 peer":
## Given
let address = "/dns6/localhost/tcp/65042/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
@ -110,7 +110,7 @@ suite "Utils - Peers":
test "Multiaddr parsing should fail with trailing whitespace":
## Given
let address = "/ip4/127.0.0.1/tcp/65072/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc "
## Then
check:
parsePeerInfo(address).isErr()
@ -118,7 +118,7 @@ suite "Utils - Peers":
test "Multiaddress parsing should fail with invalid IP address":
## Given
let address = "/ip4/127.0.0.0.1/tcp/65082/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
## Then
check:
parsePeerInfo(address).isErr()
@ -126,7 +126,7 @@ suite "Utils - Peers":
test "Multiaddress parsing should fail with no peer ID":
## Given
let address = "/ip4/127.0.0.1/tcp/65092"
# Then
check:
parsePeerInfo(address).isErr()
@ -134,7 +134,7 @@ suite "Utils - Peers":
test "Multiaddress parsing should fail with unsupported transport":
## Given
let address = "/ip4/127.0.0.1/udp/65102/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
## Then
check:
parsePeerInfo(address).isErr()

View File

@ -20,7 +20,6 @@ import
import
../../waku/v2/waku_core,
../../waku/v2/node/peer_manager,
../../waku/v2/utils/peers,
../../waku/v2/waku_node,
../../waku/v2/waku_relay,
../../waku/v2/waku_relay/validators,

View File

@ -14,11 +14,10 @@ import
libp2p/protocols/pubsub/pubsub,
eth/keys
import
../../../waku/v2/waku_node,
../../../waku/v2/waku_core,
../../../waku/v2/waku_node,
../../../waku/v2/waku_rln_relay,
../../../waku/v2/waku_keystore,
../../../waku/v2/utils/peers,
../testlib/wakucore,
../testlib/wakunode

View File

@ -14,13 +14,12 @@ import
libp2p/protocols/pubsub/gossipsub
import
../../../waku/common/sqlite,
../../../waku/v2/node/peer_manager,
../../../waku/v2/waku_core,
../../../waku/v2/node/peer_manager,
../../../waku/v2/waku_archive,
../../../waku/v2/waku_archive/driver/sqlite_driver,
../../../waku/v2/waku_store,
../../../waku/v2/waku_filter,
../../../waku/v2/utils/peers,
../../../waku/v2/waku_node,
../testlib/common,
../testlib/wakucore,

View File

@ -10,6 +10,7 @@ import
libp2p/crypto/crypto,
json_rpc/[rpcserver, rpcclient]
import
../../../waku/v2/waku_core,
../../../waku/v2/node/peer_manager,
../../../waku/v2/waku_node,
../../../waku/v2/node/jsonrpc/admin/handlers as admin_api,
@ -19,7 +20,6 @@ import
../../../waku/v2/waku_archive/driver/queue_driver,
../../../waku/v2/waku_store,
../../../waku/v2/waku_filter,
../../../waku/v2/utils/peers,
../testlib/wakucore,
../testlib/wakunode

View File

@ -8,16 +8,15 @@ import
libp2p/crypto/crypto,
json_rpc/[rpcserver, rpcclient]
import
../../../waku/v2/waku_core,
../../../waku/v2/node/peer_manager,
../../../waku/v2/waku_node,
../../../waku/v2/node/message_cache,
../../../waku/v2/node/jsonrpc/filter/handlers as filter_api,
../../../waku/v2/node/jsonrpc/filter/client as filter_api_client,
../../../waku/v2/waku_core,
../../../waku/v2/waku_filter,
../../../waku/v2/waku_filter/rpc,
../../../waku/v2/waku_filter/client,
../../../waku/v2/utils/peers,
../testlib/wakucore,
../testlib/wakunode

View File

@ -9,6 +9,7 @@ import
json_rpc/[rpcserver, rpcclient]
import
../../../waku/common/base64,
../../../waku/v2/waku_core,
../../../waku/v2/node/peer_manager,
../../../waku/v2/node/message_cache,
../../../waku/v2/waku_node,
@ -17,7 +18,6 @@ import
../../../waku/v2/waku_core,
../../../waku/v2/waku_relay,
../../../waku/v2/utils/compat,
../../../waku/v2/utils/peers,
../testlib/common,
../testlib/wakucore,
../testlib/wakunode

View File

@ -8,8 +8,8 @@ import
libp2p/crypto/crypto,
json_rpc/[rpcserver, rpcclient]
import
../../../waku/v2/node/peer_manager,
../../../waku/v2/waku_core,
../../../waku/v2/node/peer_manager,
../../../waku/v2/waku_node,
../../../waku/v2/node/jsonrpc/store/handlers as store_api,
../../../waku/v2/node/jsonrpc/store/client as store_api_client,
@ -17,7 +17,6 @@ import
../../../waku/v2/waku_archive/driver/queue_driver,
../../../waku/v2/waku_store,
../../../waku/v2/waku_store/rpc,
../../../waku/v2/utils/peers,
../../v2/testlib/common,
../../v2/testlib/wakucore,
../../v2/testlib/wakunode

View File

@ -21,7 +21,6 @@ import
../../../waku/v2/waku_archive,
../../../waku/v2/waku_archive/driver/queue_driver,
../../../waku/v2/waku_store as waku_store,
../../../waku/v2/utils/peers,
../../v2/testlib/common,
../../v2/testlib/wakucore,
../../v2/testlib/wakunode

View File

@ -20,7 +20,6 @@ import
../../waku/v2/waku_core,
../../waku/v2/waku_node,
../../waku/v2/utils/compat,
../../waku/v2/utils/peers,
../test_helpers
import

View File

@ -20,13 +20,12 @@ import
metrics/chronos_httpserver,
presto/[route, server, client]
import
../../waku/v2/waku_core,
../../waku/v2/node/peer_manager,
../../waku/v2/waku_node,
../../waku/v2/waku_core,
../../waku/v2/waku_enr,
../../waku/v2/waku_discv5,
../../waku/v2/waku_dnsdisc,
../../waku/v2/utils/peers,
./networkmonitor_metrics,
./networkmonitor_config,
./networkmonitor_utils

View File

@ -11,8 +11,8 @@ import
libp2p/multicodec
import
../../waku/v2/node/peer_manager,
../../waku/v2/waku_node,
../../waku/v2/utils/peers
../../waku/v2/waku_core,
../../waku/v2/waku_node
# protocols and their tag
const ProtocolsTable = {

View File

@ -13,8 +13,8 @@ import
libp2p/muxers/muxer
import
../../../common/nimchronos,
../../waku_core,
../../waku_relay,
../../utils/peers,
./peer_store/peer_storage,
./waku_peer_store

View File

@ -7,8 +7,8 @@ else:
import
stew/results
import
../waku_peer_store,
../../../utils/peers
../../../waku_core,
../waku_peer_store
## This module defines a peer storage interface. Implementations of
## PeerStorage are used to store and retrieve peers

View File

@ -11,8 +11,8 @@ import
libp2p/protobuf/minprotobuf
import
../../../../common/sqlite,
../../../waku_core,
../waku_peer_store,
../../../utils/peers,
./peer_storage
export sqlite

View File

@ -4,14 +4,14 @@ else:
{.push raises: [].}
import
std/[tables, sequtils, sets, options, times, math, strutils],
std/[tables, sequtils, sets, options, times, strutils],
chronos,
eth/p2p/discoveryv5/enr,
libp2p/builders,
libp2p/peerstore
import
../../utils/peers,
../../waku_core,
../../../common/utils/sequence
export peerstore, builders

View File

@ -38,7 +38,6 @@ import
../waku_dnsdisc,
../waku_discv5,
../waku_peer_exchange,
../utils/peers,
./config,
./peer_manager,
./waku_switch

View File

@ -0,0 +1,6 @@
# :warning: DEPRECATION NOTICE :warning:
The `utils` module has been marked as deprecated.
This package submodules are planned to be moved to different modules.
**No new sub-modules must be added to this folder.**

View File

@ -1,4 +0,0 @@
# Utils
Collection of misc utilities that don't fit anywhere else, and are used by
multiple independent modules.

View File

@ -1,261 +0,0 @@
when (NimMajor, NimMinor) < (1, 4):
{.push raises: [Defect].}
else:
{.push raises: [].}
# Collection of utilities related to Waku peers
import
std/[options, sequtils, strutils, uri],
chronos,
stew/results,
stew/shims/net,
eth/keys,
eth/p2p/discoveryv5/enr,
libp2p/crypto/[crypto, secp],
libp2p/[errors,
multiaddress,
multicodec,
peerid,
peerinfo,
routing_record]
#import
# ../node/peer_manager/waku_peer_store
# todo organize this
type
Connectedness* = enum
# NotConnected: default state for a new peer. No connection and no further information on connectedness.
NotConnected,
# CannotConnect: attempted to connect to peer, but failed.
CannotConnect,
# CanConnect: was recently connected to peer and disconnected gracefully.
CanConnect,
# Connected: actively connected to peer.
Connected
PeerOrigin* = enum
UnknownOrigin,
Discv5,
Static,
PeerExcahnge,
Dns
PeerDirection* = enum
UnknownDirection,
Inbound,
Outbound
type
RemotePeerInfo* = ref object of RootObj
peerId*: PeerID
addrs*: seq[MultiAddress]
enr*: Option[enr.Record]
protocols*: seq[string]
agent*: string
protoVersion*: string
publicKey*: crypto.PublicKey
connectedness*: Connectedness
disconnectTime*: int64
origin*: PeerOrigin
direction*: PeerDirection
lastFailedConn*: Moment
numberFailedConn*: int
func `$`*(remotePeerInfo: RemotePeerInfo): string =
$remotePeerInfo.peerId
proc init*(
p: typedesc[RemotePeerInfo],
peerId: PeerID,
addrs: seq[MultiAddress] = @[],
enr: Option[enr.Record] = none(enr.Record),
protocols: seq[string] = @[]): RemotePeerInfo =
let remotePeerInfo = RemotePeerInfo(
peerId: peerId,
addrs: addrs,
enr: enr,
protocols: protocols)
return remotePeerInfo
proc init*(p: typedesc[RemotePeerInfo],
peerId: string,
addrs: seq[MultiAddress] = @[],
enr: Option[enr.Record] = none(enr.Record),
protocols: seq[string] = @[]): RemotePeerInfo
{.raises: [Defect, ResultError[cstring], LPError].} =
let remotePeerInfo = RemotePeerInfo(
peerId: PeerID.init(peerId).tryGet(),
addrs: addrs,
enr: enr,
protocols: protocols)
return remotePeerInfo
## Check if wire Address is supported
proc validWireAddr*(ma: MultiAddress): bool =
const
ValidTransports = mapOr(TCP, WebSockets)
return ValidTransports.match(ma)
func getTransportProtocol(typedR: TypedRecord): Option[IpTransportProtocol] =
if typedR.tcp6.isSome or typedR.tcp.isSome:
return some(IpTransportProtocol.tcpProtocol)
if typedR.udp6.isSome or typedR.udp.isSome:
return some(IpTransportProtocol.udpProtocol)
return none(IpTransportProtocol)
proc parsePeerInfo*(peer: RemotePeerInfo|string):
Result[RemotePeerInfo, string] =
## Parses a fully qualified peer multiaddr, in the
## format `(ip4|ip6)/tcp/p2p`, into dialable PeerInfo
if peer is RemotePeerInfo:
return ok(cast[RemotePeerInfo](peer))
let multiAddr = ? MultiAddress.init($peer)
.mapErr(proc(err: string):
string = "MultiAddress.init [" & err & "]")
var p2pPart: MultiAddress
var wireAddr = MultiAddress()
for addrPart in multiAddr.items():
case addrPart[].protoName()[]
# All protocols listed here: https://github.com/multiformats/multiaddr/blob/b746a7d014e825221cc3aea6e57a92d78419990f/protocols.csv
of "p2p":
p2pPart = ? addrPart.mapErr(proc(err: string):string = "Error getting p2pPart [" & err & "]")
of "ip4", "ip6", "dns", "dnsaddr", "dns4", "dns6", "tcp", "ws", "wss":
let val = ? addrPart.mapErr(proc(err: string):string = "Error getting addrPart [" & err & "]")
? wireAddr.append(val).mapErr(proc(err: string):string = "Error appending addrPart [" & err & "]")
let p2pPartStr = p2pPart.toString()[]
if not p2pPartStr.contains("/"):
let msg = "Error in parsePeerInfo: p2p part should contain / [p2pPartStr:" &
p2pPartStr & "] [peer:" & $peer & "]"
return err(msg)
let peerId = ? PeerID.init(p2pPartStr.split("/")[^1])
.mapErr(proc (e:cstring):string = $e)
if not wireAddr.validWireAddr():
return err("Error in parsePeerInfo: Invalid node multiaddress")
return ok(RemotePeerInfo.init(peerId, @[wireAddr]))
# Checks whether the peerAddr parameter represents a valid p2p multiaddress.
# The param must be in the format `(ip4|ip6)/tcp/p2p/$peerId` but URL-encoded
proc parseUrlPeerAddr*(peerAddr: Option[string]):
Result[Option[RemotePeerInfo], string] =
if not peerAddr.isSome() or peerAddr.get() == "":
return ok(none(RemotePeerInfo))
let parsedAddr = decodeUrl(peerAddr.get())
let parsedPeerInfo = parsePeerInfo(parsedAddr)
if parsedPeerInfo.isOk():
return ok(some(parsedPeerInfo.value))
else:
return err("Failed parsing remote peer info [" &
parsedPeerInfo.error & "]")
## Converts an ENR to dialable RemotePeerInfo
proc toRemotePeerInfo*(enr: enr.Record): Result[RemotePeerInfo, cstring] =
let typedR = ? enr.toTypedRecord
if not typedR.secp256k1.isSome:
return err("enr: no secp256k1 key in record")
let
pubKey = ? keys.PublicKey.fromRaw(typedR.secp256k1.get)
peerId = ? PeerID.init(crypto.PublicKey(scheme: Secp256k1,
skkey: secp.SkPublicKey(pubKey)))
var addrs = newSeq[MultiAddress]()
let transportProto = getTransportProtocol(typedR)
if transportProto.isNone:
return err("enr: could not determine transport protocol")
case transportProto.get()
of tcpProtocol:
if typedR.ip.isSome and typedR.tcp.isSome:
let ip = ipv4(typedR.ip.get)
addrs.add MultiAddress.init(ip, tcpProtocol, Port typedR.tcp.get)
if typedR.ip6.isSome:
let ip = ipv6(typedR.ip6.get)
if typedR.tcp6.isSome:
addrs.add MultiAddress.init(ip, tcpProtocol, Port typedR.tcp6.get)
elif typedR.tcp.isSome:
addrs.add MultiAddress.init(ip, tcpProtocol, Port typedR.tcp.get)
else:
discard
of udpProtocol:
if typedR.ip.isSome and typedR.udp.isSome:
let ip = ipv4(typedR.ip.get)
addrs.add MultiAddress.init(ip, udpProtocol, Port typedR.udp.get)
if typedR.ip6.isSome:
let ip = ipv6(typedR.ip6.get)
if typedR.udp6.isSome:
addrs.add MultiAddress.init(ip, udpProtocol, Port typedR.udp6.get)
elif typedR.udp.isSome:
addrs.add MultiAddress.init(ip, udpProtocol, Port typedR.udp.get)
else:
discard
if addrs.len == 0:
return err("enr: no addresses in record")
return ok(RemotePeerInfo.init(peerId, addrs, some(enr)))
## Converts peer records to dialable RemotePeerInfo
## Useful if signed peer records have been received in an exchange
proc toRemotePeerInfo*(peerRecord: PeerRecord): RemotePeerInfo =
RemotePeerInfo.init(peerRecord.peerId,
peerRecord.addresses.mapIt(it.address))
## Converts the local peerInfo to dialable RemotePeerInfo
## Useful for testing or internal connections
proc toRemotePeerInfo*(peerInfo: PeerInfo): RemotePeerInfo =
RemotePeerInfo.init(peerInfo.peerId,
peerInfo.listenAddrs,
none(enr.Record), # we could generate an ENR from PeerInfo
peerInfo.protocols)
## Checks if a multiaddress contains a given protocol
## Useful for filtering multiaddresses based on their protocols
proc hasProtocol*(ma: MultiAddress, proto: string): bool =
## Returns ``true`` if ``ma`` contains protocol ``proto``.
let protos = ma.protocols()
if protos.isErr():
return false
for p in protos.get():
if p == MultiCodec.codec(proto):
return true
return false
func hasUdpPort*(peer: RemotePeerInfo): bool =
if peer.enr.isNone():
return false
let
enr = peer.enr.get()
typedEnrRes = enr.toTypedRecord()
if typedEnrRes.isErr():
return false
let typedEnr = typedEnrRes.get()
typedEnr.udp.isSome() or typedEnr.udp6.isSome()

View File

@ -1,9 +1,11 @@
import
./waku_core/topics,
./waku_core/time,
./waku_core/message
./waku_core/message,
./waku_core/peers
export
topics,
time,
message
message,
peers

250
waku/v2/waku_core/peers.nim Normal file
View File

@ -0,0 +1,250 @@
when (NimMajor, NimMinor) < (1, 4):
{.push raises: [Defect].}
else:
{.push raises: [].}
import
std/[options, sequtils, strutils, uri],
stew/results,
stew/shims/net,
chronos,
eth/keys,
eth/p2p/discoveryv5/enr,
libp2p/crypto/crypto,
libp2p/crypto/secp,
libp2p/errors,
libp2p/multiaddress,
libp2p/multicodec,
libp2p/peerid,
libp2p/peerinfo,
libp2p/routing_record
type
Connectedness* = enum
# NotConnected: default state for a new peer. No connection and no further information on connectedness.
NotConnected,
# CannotConnect: attempted to connect to peer, but failed.
CannotConnect,
# CanConnect: was recently connected to peer and disconnected gracefully.
CanConnect,
# Connected: actively connected to peer.
Connected
PeerOrigin* = enum
UnknownOrigin,
Discv5,
Static,
PeerExcahnge,
Dns
PeerDirection* = enum
UnknownDirection,
Inbound,
Outbound
type RemotePeerInfo* = ref object
peerId*: PeerID
addrs*: seq[MultiAddress]
enr*: Option[enr.Record]
protocols*: seq[string]
agent*: string
protoVersion*: string
publicKey*: crypto.PublicKey
connectedness*: Connectedness
disconnectTime*: int64
origin*: PeerOrigin
direction*: PeerDirection
lastFailedConn*: Moment
numberFailedConn*: int
func `$`*(remotePeerInfo: RemotePeerInfo): string =
$remotePeerInfo.peerId
proc init*(
T: typedesc[RemotePeerInfo],
peerId: PeerID,
addrs: seq[MultiAddress] = @[],
enr: Option[enr.Record] = none(enr.Record),
protocols: seq[string] = @[]): T =
RemotePeerInfo(peerId: peerId, addrs: addrs, enr: enr, protocols: protocols)
proc init*(T: typedesc[RemotePeerInfo],
peerId: string,
addrs: seq[MultiAddress] = @[],
enr: Option[enr.Record] = none(enr.Record),
protocols: seq[string] = @[]): T
{.raises: [Defect, ResultError[cstring], LPError].} =
let peerId = PeerID.init(peerId).tryGet()
RemotePeerInfo(peerId: peerId, addrs: addrs, enr: enr, protocols: protocols)
## Parse
proc validWireAddr*(ma: MultiAddress): bool =
## Check if wire Address is supported
const
ValidTransports = mapOr(TCP, WebSockets)
return ValidTransports.match(ma)
proc parsePeerInfo*(peer: RemotePeerInfo): Result[RemotePeerInfo, string] =
## Parses a fully qualified peer multiaddr, in the
## format `(ip4|ip6)/tcp/p2p`, into dialable PeerInfo
ok(peer)
proc parsePeerInfo*(peer: MultiAddress): Result[RemotePeerInfo, string] =
## Parses a fully qualified peer multiaddr, in the
## format `(ip4|ip6)/tcp/p2p`, into dialable PeerInfo
var p2pPart: MultiAddress
var wireAddr = MultiAddress()
for addrPart in peer.items():
case addrPart[].protoName()[]
# All protocols listed here: https://github.com/multiformats/multiaddr/blob/b746a7d014e825221cc3aea6e57a92d78419990f/protocols.csv
of "p2p":
p2pPart = ? addrPart.mapErr(proc(err: string): string = "Error getting p2pPart [" & err & "]")
of "ip4", "ip6", "dns", "dnsaddr", "dns4", "dns6", "tcp", "ws", "wss":
let val = ? addrPart.mapErr(proc(err: string): string = "Error getting addrPart [" & err & "]")
? wireAddr.append(val).mapErr(proc(err: string): string = "Error appending addrPart [" & err & "]")
let p2pPartStr = p2pPart.toString().get()
if not p2pPartStr.contains("/"):
let msg = "Error in parsePeerInfo: p2p part should contain / [p2pPartStr:" & p2pPartStr & "] [peer:" & $peer & "]"
return err(msg)
let peerId = ? PeerID.init(p2pPartStr.split("/")[^1])
.mapErr(proc(e: cstring): string = $e)
if not wireAddr.validWireAddr():
return err("invalid multiaddress: no supported transport found")
return ok(RemotePeerInfo.init(peerId, @[wireAddr]))
proc parsePeerInfo*(peer: string): Result[RemotePeerInfo, string] =
## Parses a fully qualified peer multiaddr, in the
## format `(ip4|ip6)/tcp/p2p`, into dialable PeerInfo
let multiAddr = ? MultiAddress.init(peer)
.mapErr(proc(err: string): string = "MultiAddress.init [" & err & "]")
parsePeerInfo(multiAddr)
func getTransportProtocol(typedR: TypedRecord): Option[IpTransportProtocol] =
if typedR.tcp6.isSome() or typedR.tcp.isSome():
return some(IpTransportProtocol.tcpProtocol)
if typedR.udp6.isSome() or typedR.udp.isSome():
return some(IpTransportProtocol.udpProtocol)
return none(IpTransportProtocol)
proc parseUrlPeerAddr*(peerAddr: Option[string]): Result[Option[RemotePeerInfo], string] =
# Checks whether the peerAddr parameter represents a valid p2p multiaddress.
# The param must be in the format `(ip4|ip6)/tcp/p2p/$peerId` but URL-encoded
if not peerAddr.isSome() or peerAddr.get() == "":
return ok(none(RemotePeerInfo))
let parsedAddr = decodeUrl(peerAddr.get())
let parsedPeerInfo = parsePeerInfo(parsedAddr)
if parsedPeerInfo.isErr():
return err("Failed parsing remote peer info [" & parsedPeerInfo.error & "]")
return ok(some(parsedPeerInfo.value))
proc toRemotePeerInfo*(enr: enr.Record): Result[RemotePeerInfo, cstring] =
## Converts an ENR to dialable RemotePeerInfo
let typedR = ? enr.toTypedRecord()
if not typedR.secp256k1.isSome():
return err("enr: no secp256k1 key in record")
let
pubKey = ? keys.PublicKey.fromRaw(typedR.secp256k1.get())
peerId = ? PeerID.init(crypto.PublicKey(scheme: Secp256k1,
skkey: secp.SkPublicKey(pubKey)))
let transportProto = getTransportProtocol(typedR)
if transportProto.isNone():
return err("enr: could not determine transport protocol")
var addrs = newSeq[MultiAddress]()
case transportProto.get()
of tcpProtocol:
if typedR.ip.isSome() and typedR.tcp.isSome():
let ip = ipv4(typedR.ip.get())
addrs.add MultiAddress.init(ip, tcpProtocol, Port(typedR.tcp.get()))
if typedR.ip6.isSome():
let ip = ipv6(typedR.ip6.get())
if typedR.tcp6.isSome():
addrs.add MultiAddress.init(ip, tcpProtocol, Port(typedR.tcp6.get()))
elif typedR.tcp.isSome():
addrs.add MultiAddress.init(ip, tcpProtocol, Port(typedR.tcp.get()))
else:
discard
of udpProtocol:
if typedR.ip.isSome() and typedR.udp.isSome():
let ip = ipv4(typedR.ip.get())
addrs.add MultiAddress.init(ip, udpProtocol, Port(typedR.udp.get()))
if typedR.ip6.isSome():
let ip = ipv6(typedR.ip6.get())
if typedR.udp6.isSome():
addrs.add MultiAddress.init(ip, udpProtocol, Port(typedR.udp6.get()))
elif typedR.udp.isSome():
addrs.add MultiAddress.init(ip, udpProtocol, Port(typedR.udp.get()))
else:
discard
if addrs.len == 0:
return err("enr: no addresses in record")
return ok(RemotePeerInfo.init(peerId, addrs, some(enr)))
converter toRemotePeerInfo*(peerRecord: PeerRecord): RemotePeerInfo =
## Converts peer records to dialable RemotePeerInfo
## Useful if signed peer records have been received in an exchange
RemotePeerInfo.init(
peerRecord.peerId,
peerRecord.addresses.mapIt(it.address)
)
converter toRemotePeerInfo*(peerInfo: PeerInfo): RemotePeerInfo =
## Converts the local peerInfo to dialable RemotePeerInfo
## Useful for testing or internal connections
RemotePeerInfo.init(
peerInfo.peerId,
peerInfo.listenAddrs,
none(enr.Record),
peerInfo.protocols
)
proc hasProtocol*(ma: MultiAddress, proto: string): bool =
## Checks if a multiaddress contains a given protocol
## Useful for filtering multiaddresses based on their protocols
##
## Returns ``true`` if ``ma`` contains protocol ``proto``.
let proto = MultiCodec.codec(proto)
let protos = ma.protocols()
if protos.isErr():
return false
return protos.get().anyIt(it == proto)
func hasUdpPort*(peer: RemotePeerInfo): bool =
if peer.enr.isNone():
return false
let
enr = peer.enr.get()
typedEnrRes = enr.toTypedRecord()
if typedEnrRes.isErr():
return false
let typedEnr = typedEnrRes.get()
typedEnr.udp.isSome() or typedEnr.udp6.isSome()

View File

@ -16,7 +16,7 @@ import
eth/p2p/discoveryv5/node,
eth/p2p/discoveryv5/protocol
import
./utils/peers,
./waku_core,
./waku_enr
export protocol, waku_enr

View File

@ -22,7 +22,7 @@ import
libp2p/peerid,
discovery/dnsdisc/client
import
./utils/peers
./waku_core
export client