mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-01-07 16:33:08 +00:00
chore: extended /admin/v1 RESP API with different option to look at current connected/relay/mesh state of the node (#3382)
* Extended /admin/v1 RESP API with different option to look at current connected/relay/mesh state of the node * Added score information for peer info retrievals
This commit is contained in:
parent
0304f063b8
commit
ab8a30d3d6
@ -1,11 +1,11 @@
|
|||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sequtils, net],
|
std/[sequtils, strformat, net],
|
||||||
stew/shims/net,
|
|
||||||
testutils/unittests,
|
testutils/unittests,
|
||||||
presto,
|
presto,
|
||||||
presto/client as presto_client,
|
presto/client as presto_client,
|
||||||
|
presto /../ tests/helpers,
|
||||||
libp2p/crypto/crypto
|
libp2p/crypto/crypto
|
||||||
|
|
||||||
import
|
import
|
||||||
@ -43,10 +43,11 @@ suite "Waku v2 Rest API - Admin":
|
|||||||
node3 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(60604))
|
node3 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(60604))
|
||||||
|
|
||||||
await allFutures(node1.start(), node2.start(), node3.start())
|
await allFutures(node1.start(), node2.start(), node3.start())
|
||||||
|
let shards = @[RelayShard(clusterId: 1, shardId: 0)]
|
||||||
await allFutures(
|
await allFutures(
|
||||||
node1.mountRelay(),
|
node1.mountRelay(shards = shards),
|
||||||
node2.mountRelay(),
|
node2.mountRelay(shards = shards),
|
||||||
node3.mountRelay(),
|
node3.mountRelay(shards = shards),
|
||||||
node3.mountPeerExchange(),
|
node3.mountPeerExchange(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -203,3 +204,96 @@ suite "Waku v2 Rest API - Admin":
|
|||||||
getRes.data.anyIt(it.origin == Discv5)
|
getRes.data.anyIt(it.origin == Discv5)
|
||||||
# Check peer 3
|
# Check peer 3
|
||||||
getRes.data.anyIt(it.origin == PeerExchange)
|
getRes.data.anyIt(it.origin == PeerExchange)
|
||||||
|
|
||||||
|
asyncTest "get peers by id":
|
||||||
|
# Connect to nodes 2 and 3 using the Admin API
|
||||||
|
let postRes = await client.postPeers(
|
||||||
|
@[constructMultiaddrStr(peerInfo2), constructMultiaddrStr(peerInfo3)]
|
||||||
|
)
|
||||||
|
|
||||||
|
check:
|
||||||
|
postRes.status == 200
|
||||||
|
|
||||||
|
let getRes = await client.getPeerById($peerInfo2.peerId)
|
||||||
|
|
||||||
|
check:
|
||||||
|
getRes.status == 200
|
||||||
|
$getRes.contentType == $MIMETYPE_JSON
|
||||||
|
getRes.data.protocols.find(WakuRelayCodec) >= 0
|
||||||
|
getRes.data.multiaddr == constructMultiaddrStr(peerInfo2)
|
||||||
|
|
||||||
|
## nim-presto library's RestClient does not support text error case decode if
|
||||||
|
## the RestResponse expects a JSON with complex type
|
||||||
|
# let getRes2 = await client.getPeerById("bad peer id")
|
||||||
|
let getRes2 = await httpClient(
|
||||||
|
restServer.httpServer.address, MethodGet, "/admin/v1/peer/bad+peer+id", ""
|
||||||
|
)
|
||||||
|
check:
|
||||||
|
getRes2.status == 400
|
||||||
|
getRes2.data == "Invalid argument:peerid: incorrect PeerId string"
|
||||||
|
|
||||||
|
asyncTest "get connected peers":
|
||||||
|
# Connect to nodes 2 and 3 using the Admin API
|
||||||
|
let postRes = await client.postPeers(
|
||||||
|
@[constructMultiaddrStr(peerInfo2), constructMultiaddrStr(peerInfo3)]
|
||||||
|
)
|
||||||
|
|
||||||
|
check:
|
||||||
|
postRes.status == 200
|
||||||
|
|
||||||
|
let getRes = await client.getConnectedPeers()
|
||||||
|
|
||||||
|
check:
|
||||||
|
getRes.status == 200
|
||||||
|
$getRes.contentType == $MIMETYPE_JSON
|
||||||
|
getRes.data.len() == 2
|
||||||
|
# Check peer 2
|
||||||
|
getRes.data.anyIt(it.multiaddr == constructMultiaddrStr(peerInfo2))
|
||||||
|
# Check peer 3
|
||||||
|
getRes.data.anyIt(it.multiaddr == constructMultiaddrStr(peerInfo3))
|
||||||
|
|
||||||
|
# Seems shard info is not available in the peer manager
|
||||||
|
# let getRes2 = await client.getConnectedPeersByShard(0)
|
||||||
|
# check:
|
||||||
|
# getRes2.status == 200
|
||||||
|
# $getRes2.contentType == $MIMETYPE_JSON
|
||||||
|
# getRes2.data.len() == 2
|
||||||
|
|
||||||
|
let getRes3 = await client.getConnectedPeersByShard(99)
|
||||||
|
check:
|
||||||
|
getRes3.status == 200
|
||||||
|
$getRes3.contentType == $MIMETYPE_JSON
|
||||||
|
getRes3.data.len() == 0
|
||||||
|
|
||||||
|
asyncTest "get relay peers":
|
||||||
|
# Connect to nodes 2 and 3 using the Admin API
|
||||||
|
let postRes = await client.postPeers(
|
||||||
|
@[constructMultiaddrStr(peerInfo2), constructMultiaddrStr(peerInfo3)]
|
||||||
|
)
|
||||||
|
|
||||||
|
check:
|
||||||
|
postRes.status == 200
|
||||||
|
|
||||||
|
let getRes = await client.getConnectedRelayPeers()
|
||||||
|
|
||||||
|
check:
|
||||||
|
getRes.status == 200
|
||||||
|
$getRes.contentType == $MIMETYPE_JSON
|
||||||
|
require getRes.data.len() == 1 # Check peer 2
|
||||||
|
check getRes.data[0].peers.anyIt(it.multiaddr == constructMultiaddrStr(peerInfo2))
|
||||||
|
# Check peer 2
|
||||||
|
check getRes.data[0].peers.anyIt(it.multiaddr == constructMultiaddrStr(peerInfo3))
|
||||||
|
# Check peer 3
|
||||||
|
|
||||||
|
# Todo: investigate why the test setup missing remote peer's shard info
|
||||||
|
# let getRes2 = await client.getConnectedRelayPeersByShard(0)
|
||||||
|
# check:
|
||||||
|
# getRes2.status == 200
|
||||||
|
# $getRes2.contentType == $MIMETYPE_JSON
|
||||||
|
# getRes2.data.peers.len() == 2
|
||||||
|
|
||||||
|
let getRes3 = await client.getConnectedRelayPeersByShard(99)
|
||||||
|
check:
|
||||||
|
getRes3.status == 200
|
||||||
|
$getRes3.contentType == $MIMETYPE_JSON
|
||||||
|
getRes3.data.peers.len() == 0
|
||||||
|
|||||||
@ -154,7 +154,7 @@ proc addPeer*(
|
|||||||
|
|
||||||
pm.storage.insertOrReplace(remotePeerInfo)
|
pm.storage.insertOrReplace(remotePeerInfo)
|
||||||
|
|
||||||
proc getPeer(pm: PeerManager, peerId: PeerId): RemotePeerInfo =
|
proc getPeer*(pm: PeerManager, peerId: PeerId): RemotePeerInfo =
|
||||||
return pm.switch.peerStore.getPeer(peerId)
|
return pm.switch.peerStore.getPeer(peerId)
|
||||||
|
|
||||||
proc loadFromStorage(pm: PeerManager) {.gcsafe.} =
|
proc loadFromStorage(pm: PeerManager) {.gcsafe.} =
|
||||||
|
|||||||
@ -22,6 +22,44 @@ proc postPeers*(
|
|||||||
rest, endpoint: "/admin/v1/peers", meth: HttpMethod.MethodPost
|
rest, endpoint: "/admin/v1/peers", meth: HttpMethod.MethodPost
|
||||||
.}
|
.}
|
||||||
|
|
||||||
|
proc getPeerById*(
|
||||||
|
peerId: string
|
||||||
|
): RestResponse[WakuPeer] {.
|
||||||
|
rest, endpoint: "/admin/v1/peer/{peerId}", meth: HttpMethod.MethodGet
|
||||||
|
.}
|
||||||
|
|
||||||
|
proc getConnectedPeers*(): RestResponse[seq[WakuPeer]] {.
|
||||||
|
rest, endpoint: "/admin/v1/peers/connected", meth: HttpMethod.MethodGet
|
||||||
|
.}
|
||||||
|
|
||||||
|
proc getConnectedPeersByShard*(
|
||||||
|
shardId: uint16
|
||||||
|
): RestResponse[seq[WakuPeer]] {.
|
||||||
|
rest, endpoint: "/admin/v1/peers/connected/on/{shardId}", meth: HttpMethod.MethodGet
|
||||||
|
.}
|
||||||
|
|
||||||
|
proc getConnectedRelayPeers*(): RestResponse[PeersOfShards] {.
|
||||||
|
rest, endpoint: "/admin/v1/peers/connected/relay", meth: HttpMethod.MethodGet
|
||||||
|
.}
|
||||||
|
|
||||||
|
proc getConnectedRelayPeersByShard*(
|
||||||
|
shardId: uint16
|
||||||
|
): RestResponse[PeersOfShard] {.
|
||||||
|
rest,
|
||||||
|
endpoint: "/admin/v1/peers/connected/relay/on/{shardId}",
|
||||||
|
meth: HttpMethod.MethodGet
|
||||||
|
.}
|
||||||
|
|
||||||
|
proc getMeshPeers*(): RestResponse[PeersOfShards] {.
|
||||||
|
rest, endpoint: "/admin/v1/peers/mesh", meth: HttpMethod.MethodGet
|
||||||
|
.}
|
||||||
|
|
||||||
|
proc getMeshPeersByShard*(
|
||||||
|
shardId: uint16
|
||||||
|
): RestResponse[PeersOfShard] {.
|
||||||
|
rest, endpoint: "/admin/v1/peers/mesh/on/{shardId}", meth: HttpMethod.MethodGet
|
||||||
|
.}
|
||||||
|
|
||||||
proc getFilterSubscriptions*(): RestResponse[seq[FilterSubscription]] {.
|
proc getFilterSubscriptions*(): RestResponse[seq[FilterSubscription]] {.
|
||||||
rest, endpoint: "/admin/v1/filter/subscriptions", meth: HttpMethod.MethodGet
|
rest, endpoint: "/admin/v1/filter/subscriptions", meth: HttpMethod.MethodGet
|
||||||
.}
|
.}
|
||||||
|
|||||||
@ -1,22 +1,26 @@
|
|||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[strformat, sequtils, tables],
|
std/[sets, strformat, sequtils, tables],
|
||||||
chronicles,
|
chronicles,
|
||||||
json_serialization,
|
json_serialization,
|
||||||
presto/route,
|
presto/route,
|
||||||
libp2p/[peerinfo, switch]
|
libp2p/[peerinfo, switch, peerid, protocols/pubsub/pubsubpeer]
|
||||||
|
|
||||||
import
|
import
|
||||||
../../../waku_core,
|
waku/[
|
||||||
../../../waku_store_legacy/common,
|
waku_core,
|
||||||
../../../waku_store/common,
|
waku_core/topics/pubsub_topic,
|
||||||
../../../waku_filter_v2,
|
waku_store_legacy/common,
|
||||||
../../../waku_lightpush_legacy/common,
|
waku_store/common,
|
||||||
../../../waku_relay,
|
waku_filter_v2,
|
||||||
../../../waku_peer_exchange,
|
waku_lightpush_legacy/common,
|
||||||
../../../waku_node,
|
waku_relay,
|
||||||
../../../node/peer_manager,
|
waku_peer_exchange,
|
||||||
|
waku_node,
|
||||||
|
node/peer_manager,
|
||||||
|
waku_enr/sharding,
|
||||||
|
],
|
||||||
../responses,
|
../responses,
|
||||||
../serdes,
|
../serdes,
|
||||||
../rest_serdes,
|
../rest_serdes,
|
||||||
@ -27,103 +31,260 @@ export types
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku node rest admin api"
|
topics = "waku node rest admin api"
|
||||||
|
|
||||||
const ROUTE_ADMIN_V1_PEERS* = "/admin/v1/peers"
|
const ROUTE_ADMIN_V1_PEERS* = "/admin/v1/peers" # returns all peers
|
||||||
|
const ROUTE_ADMIN_V1_SINGLE_PEER* = "/admin/v1/peer/{peerId}"
|
||||||
|
|
||||||
|
const ROUTE_ADMIN_V1_CONNECTED_PEERS* = "/admin/v1/peers/connected"
|
||||||
|
const ROUTE_ADMIN_V1_CONNECTED_PEERS_ON_SHARD* =
|
||||||
|
"/admin/v1/peers/connected/on/{shardId}"
|
||||||
|
const ROUTE_ADMIN_V1_CONNECTED_RELAY_PEERS* = "/admin/v1/peers/connected/relay"
|
||||||
|
const ROUTE_ADMIN_V1_CONNECTED_RELAY_PEERS_ON_SHARD* =
|
||||||
|
"/admin/v1/peers/connected/relay/on/{shardId}"
|
||||||
|
const ROUTE_ADMIN_V1_MESH_PEERS* = "/admin/v1/peers/mesh"
|
||||||
|
const ROUTE_ADMIN_V1_MESH_PEERS_ON_SHARD* = "/admin/v1/peers/mesh/on/{shardId}"
|
||||||
|
|
||||||
const ROUTE_ADMIN_V1_FILTER_SUBS* = "/admin/v1/filter/subscriptions"
|
const ROUTE_ADMIN_V1_FILTER_SUBS* = "/admin/v1/filter/subscriptions"
|
||||||
|
|
||||||
type PeerProtocolTuple =
|
type PeerProtocolTuple =
|
||||||
tuple[multiaddr: string, protocol: string, connected: bool, origin: PeerOrigin]
|
tuple[
|
||||||
|
multiaddr: string,
|
||||||
|
protocol: string,
|
||||||
|
shards: seq[uint16],
|
||||||
|
connected: Connectedness,
|
||||||
|
agent: string,
|
||||||
|
origin: PeerOrigin,
|
||||||
|
]
|
||||||
|
|
||||||
proc tuplesToWakuPeers(peers: var WakuPeers, peersTup: seq[PeerProtocolTuple]) =
|
proc tuplesToWakuPeers(peers: var WakuPeers, peersTup: seq[PeerProtocolTuple]) =
|
||||||
for peer in peersTup:
|
for peer in peersTup:
|
||||||
peers.add(peer.multiaddr, peer.protocol, peer.connected, peer.origin)
|
peers.add(
|
||||||
|
peer.multiaddr, peer.protocol, peer.shards, peer.connected, peer.agent,
|
||||||
|
peer.origin,
|
||||||
|
)
|
||||||
|
|
||||||
|
proc populateAdminPeerInfo(peers: var WakuPeers, node: WakuNode, codec: string) =
|
||||||
|
let peersForCodec = node.peerManager.switch.peerStore.peers(codec).mapIt(
|
||||||
|
(
|
||||||
|
multiaddr: constructMultiaddrStr(it),
|
||||||
|
protocol: codec,
|
||||||
|
shards: it.getShards(),
|
||||||
|
connected: it.connectedness,
|
||||||
|
agent: it.agent,
|
||||||
|
origin: it.origin,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
tuplesToWakuPeers(peers, peersForCodec)
|
||||||
|
|
||||||
|
proc populateAdminPeerInfoForCodecs(node: WakuNode, codecs: seq[string]): WakuPeers =
|
||||||
|
var peers: WakuPeers = @[]
|
||||||
|
|
||||||
|
for codec in codecs:
|
||||||
|
populateAdminPeerInfo(peers, node, codec)
|
||||||
|
|
||||||
|
return peers
|
||||||
|
|
||||||
proc installAdminV1GetPeersHandler(router: var RestRouter, node: WakuNode) =
|
proc installAdminV1GetPeersHandler(router: var RestRouter, node: WakuNode) =
|
||||||
router.api(MethodGet, ROUTE_ADMIN_V1_PEERS) do() -> RestApiResponse:
|
router.api(MethodGet, ROUTE_ADMIN_V1_PEERS) do() -> RestApiResponse:
|
||||||
var peers: WakuPeers = @[]
|
let peers = populateAdminPeerInfoForCodecs(
|
||||||
|
node,
|
||||||
let relayPeers = node.peerManager.switch.peerStore.peers(WakuRelayCodec).mapIt(
|
@[
|
||||||
(
|
WakuRelayCodec, WakuFilterSubscribeCodec, WakuStoreCodec, WakuLegacyStoreCodec,
|
||||||
multiaddr: constructMultiaddrStr(it),
|
WakuLegacyLightPushCodec, WakuLightPushCodec, WakuPeerExchangeCodec,
|
||||||
protocol: WakuRelayCodec,
|
WakuReconciliationCodec,
|
||||||
connected: it.connectedness == Connectedness.Connected,
|
],
|
||||||
origin: it.origin,
|
|
||||||
)
|
)
|
||||||
)
|
|
||||||
tuplesToWakuPeers(peers, relayPeers)
|
|
||||||
|
|
||||||
let filterV2Peers = node.peerManager.switch.peerStore
|
|
||||||
.peers(WakuFilterSubscribeCodec)
|
|
||||||
.mapIt(
|
|
||||||
(
|
|
||||||
multiaddr: constructMultiaddrStr(it),
|
|
||||||
protocol: WakuFilterSubscribeCodec,
|
|
||||||
connected: it.connectedness == Connectedness.Connected,
|
|
||||||
origin: it.origin,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tuplesToWakuPeers(peers, filterV2Peers)
|
|
||||||
|
|
||||||
let storePeers = node.peerManager.switch.peerStore.peers(WakuStoreCodec).mapIt(
|
|
||||||
(
|
|
||||||
multiaddr: constructMultiaddrStr(it),
|
|
||||||
protocol: WakuStoreCodec,
|
|
||||||
connected: it.connectedness == Connectedness.Connected,
|
|
||||||
origin: it.origin,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tuplesToWakuPeers(peers, storePeers)
|
|
||||||
|
|
||||||
let legacyStorePeers = node.peerManager.switch.peerStore
|
|
||||||
.peers(WakuLegacyStoreCodec)
|
|
||||||
.mapIt(
|
|
||||||
(
|
|
||||||
multiaddr: constructMultiaddrStr(it),
|
|
||||||
protocol: WakuLegacyStoreCodec,
|
|
||||||
connected: it.connectedness == Connectedness.Connected,
|
|
||||||
origin: it.origin,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tuplesToWakuPeers(peers, legacyStorePeers)
|
|
||||||
|
|
||||||
let legacyLightpushPeers = node.peerManager.switch.peerStore
|
|
||||||
.peers(WakuLegacyLightPushCodec)
|
|
||||||
.mapIt(
|
|
||||||
(
|
|
||||||
multiaddr: constructMultiaddrStr(it),
|
|
||||||
protocol: WakuLegacyLightPushCodec,
|
|
||||||
connected: it.connectedness == Connectedness.Connected,
|
|
||||||
origin: it.origin,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tuplesToWakuPeers(peers, legacyLightpushPeers)
|
|
||||||
|
|
||||||
let lightpushPeers = node.peerManager.switch.peerStore
|
|
||||||
.peers(WakuLightPushCodec)
|
|
||||||
.mapIt(
|
|
||||||
(
|
|
||||||
multiaddr: constructMultiaddrStr(it),
|
|
||||||
protocol: WakuLightPushCodec,
|
|
||||||
connected: it.connectedness == Connectedness.Connected,
|
|
||||||
origin: it.origin,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tuplesToWakuPeers(peers, lightpushPeers)
|
|
||||||
|
|
||||||
let pxPeers = node.peerManager.switch.peerStore.peers(WakuPeerExchangeCodec).mapIt(
|
|
||||||
(
|
|
||||||
multiaddr: constructMultiaddrStr(it),
|
|
||||||
protocol: WakuPeerExchangeCodec,
|
|
||||||
connected: it.connectedness == Connectedness.Connected,
|
|
||||||
origin: it.origin,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tuplesToWakuPeers(peers, pxPeers)
|
|
||||||
|
|
||||||
let resp = RestApiResponse.jsonResponse(peers, status = Http200)
|
let resp = RestApiResponse.jsonResponse(peers, status = Http200)
|
||||||
if resp.isErr():
|
if resp.isErr():
|
||||||
error "An error ocurred while building the json respose: ", error = resp.error
|
error "An error occurred while building the json response: ", error = resp.error
|
||||||
return RestApiResponse.internalServerError(
|
return RestApiResponse.internalServerError(
|
||||||
fmt("An error ocurred while building the json respose: {resp.error}")
|
fmt("An error occurred while building the json response: {resp.error}")
|
||||||
|
)
|
||||||
|
|
||||||
|
return resp.get()
|
||||||
|
|
||||||
|
router.api(MethodGet, ROUTE_ADMIN_V1_SINGLE_PEER) do(
|
||||||
|
peerId: string
|
||||||
|
) -> RestApiResponse:
|
||||||
|
let peerIdString = peerId.valueOr:
|
||||||
|
return RestApiResponse.badRequest("Invalid argument:" & $error)
|
||||||
|
|
||||||
|
let peerIdVal: PeerId = PeerId.init(peerIdString).valueOr:
|
||||||
|
return RestApiResponse.badRequest("Invalid argument:" & $error)
|
||||||
|
|
||||||
|
if node.peerManager.switch.peerStore.peerExists(peerIdVal):
|
||||||
|
let peerInfo = node.peerManager.switch.peerStore.getPeer(peerIdVal)
|
||||||
|
let peer = WakuPeer.init(peerInfo)
|
||||||
|
let resp = RestApiResponse.jsonResponse(peer, status = Http200)
|
||||||
|
if resp.isErr():
|
||||||
|
error "An error occurred while building the json response: ", error = resp.error
|
||||||
|
return RestApiResponse.internalServerError(
|
||||||
|
fmt("An error occurred while building the json response: {resp.error}")
|
||||||
|
)
|
||||||
|
|
||||||
|
return resp.get()
|
||||||
|
else:
|
||||||
|
return RestApiResponse.notFound(fmt("Peer with ID {peerId} not found"))
|
||||||
|
|
||||||
|
router.api(MethodGet, ROUTE_ADMIN_V1_CONNECTED_PEERS) do() -> RestApiResponse:
|
||||||
|
let allPeers = populateAdminPeerInfoForCodecs(
|
||||||
|
node,
|
||||||
|
@[
|
||||||
|
WakuRelayCodec, WakuFilterSubscribeCodec, WakuStoreCodec, WakuLegacyStoreCodec,
|
||||||
|
WakuLegacyLightPushCodec, WakuLightPushCodec, WakuPeerExchangeCodec,
|
||||||
|
WakuReconciliationCodec,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
let connectedPeers = allPeers.filterIt(it.connected == Connectedness.Connected)
|
||||||
|
|
||||||
|
let resp = RestApiResponse.jsonResponse(connectedPeers, status = Http200)
|
||||||
|
if resp.isErr():
|
||||||
|
error "An error occurred while building the json response: ", error = resp.error
|
||||||
|
return RestApiResponse.internalServerError(
|
||||||
|
fmt("An error occurred while building the json response: {resp.error}")
|
||||||
|
)
|
||||||
|
|
||||||
|
return resp.get()
|
||||||
|
|
||||||
|
router.api(MethodGet, ROUTE_ADMIN_V1_CONNECTED_PEERS_ON_SHARD) do(
|
||||||
|
shardId: uint16
|
||||||
|
) -> RestApiResponse:
|
||||||
|
let shard = shardId.valueOr:
|
||||||
|
return RestApiResponse.badRequest(fmt("Invalid shardId: {error}"))
|
||||||
|
|
||||||
|
let allPeers = populateAdminPeerInfoForCodecs(
|
||||||
|
node,
|
||||||
|
@[
|
||||||
|
WakuRelayCodec, WakuFilterSubscribeCodec, WakuStoreCodec, WakuLegacyStoreCodec,
|
||||||
|
WakuLegacyLightPushCodec, WakuLightPushCodec, WakuPeerExchangeCodec,
|
||||||
|
WakuReconciliationCodec,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
let connectedPeers = allPeers.filterIt(
|
||||||
|
it.connected == Connectedness.Connected and it.shards.contains(shard)
|
||||||
|
)
|
||||||
|
|
||||||
|
let resp = RestApiResponse.jsonResponse(connectedPeers, status = Http200)
|
||||||
|
if resp.isErr():
|
||||||
|
error "An error occurred while building the json response: ", error = resp.error
|
||||||
|
return RestApiResponse.internalServerError(
|
||||||
|
fmt("An error occurred while building the json response: {resp.error}")
|
||||||
|
)
|
||||||
|
|
||||||
|
return resp.get()
|
||||||
|
|
||||||
|
router.api(MethodGet, ROUTE_ADMIN_V1_CONNECTED_RELAY_PEERS) do() -> RestApiResponse:
|
||||||
|
if node.wakuRelay.isNil():
|
||||||
|
return RestApiResponse.serviceUnavailable(
|
||||||
|
"Error: Relay Protocol is not mounted to the node"
|
||||||
|
)
|
||||||
|
|
||||||
|
var relayPeers: PeersOfShards = @[]
|
||||||
|
for topic in node.wakuRelay.getSubscribedTopics():
|
||||||
|
let relayShard = RelayShard.parse(topic).valueOr:
|
||||||
|
error "Invalid subscribed topic", error = error, topic = topic
|
||||||
|
continue
|
||||||
|
let pubsubPeers =
|
||||||
|
node.wakuRelay.getConnectedPubSubPeers(topic).get(initHashSet[PubSubPeer](0))
|
||||||
|
relayPeers.add(
|
||||||
|
PeersOfShard(
|
||||||
|
shard: relayShard.shardId,
|
||||||
|
peers: toSeq(pubsubPeers).mapIt(WakuPeer.init(it, node.peerManager)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
let resp = RestApiResponse.jsonResponse(relayPeers, status = Http200)
|
||||||
|
if resp.isErr():
|
||||||
|
error "An error occurred while building the json response: ", error = resp.error
|
||||||
|
return RestApiResponse.internalServerError(
|
||||||
|
fmt("An error occurred while building the json response: {resp.error}")
|
||||||
|
)
|
||||||
|
|
||||||
|
return resp.get()
|
||||||
|
|
||||||
|
router.api(MethodGet, ROUTE_ADMIN_V1_CONNECTED_RELAY_PEERS_ON_SHARD) do(
|
||||||
|
shardId: uint16
|
||||||
|
) -> RestApiResponse:
|
||||||
|
let shard = shardId.valueOr:
|
||||||
|
return RestApiResponse.badRequest(fmt("Invalid shardId: {error}"))
|
||||||
|
|
||||||
|
if node.wakuRelay.isNil():
|
||||||
|
return RestApiResponse.serviceUnavailable(
|
||||||
|
"Error: Relay Protocol is not mounted to the node"
|
||||||
|
)
|
||||||
|
|
||||||
|
let topic =
|
||||||
|
toPubsubTopic(RelayShard(clusterId: node.wakuSharding.clusterId, shardId: shard))
|
||||||
|
let pubsubPeers =
|
||||||
|
node.wakuRelay.getConnectedPubSubPeers(topic).get(initHashSet[PubSubPeer](0))
|
||||||
|
let relayPeer = PeersOfShard(
|
||||||
|
shard: shard, peers: toSeq(pubsubPeers).mapIt(WakuPeer.init(it, node.peerManager))
|
||||||
|
)
|
||||||
|
|
||||||
|
let resp = RestApiResponse.jsonResponse(relayPeer, status = Http200)
|
||||||
|
if resp.isErr():
|
||||||
|
error "An error occurred while building the json response: ", error = resp.error
|
||||||
|
return RestApiResponse.internalServerError(
|
||||||
|
fmt("An error occurred while building the json response: {resp.error}")
|
||||||
|
)
|
||||||
|
|
||||||
|
return resp.get()
|
||||||
|
|
||||||
|
router.api(MethodGet, ROUTE_ADMIN_V1_MESH_PEERS) do() -> RestApiResponse:
|
||||||
|
if node.wakuRelay.isNil():
|
||||||
|
return RestApiResponse.serviceUnavailable(
|
||||||
|
"Error: Relay Protocol is not mounted to the node"
|
||||||
|
)
|
||||||
|
|
||||||
|
var relayPeers: PeersOfShards = @[]
|
||||||
|
for topic in node.wakuRelay.getSubscribedTopics():
|
||||||
|
let relayShard = RelayShard.parse(topic).valueOr:
|
||||||
|
error "Invalid subscribed topic", error = error, topic = topic
|
||||||
|
continue
|
||||||
|
let peers =
|
||||||
|
node.wakuRelay.getPubSubPeersInMesh(topic).get(initHashSet[PubSubPeer](0))
|
||||||
|
relayPeers.add(
|
||||||
|
PeersOfShard(
|
||||||
|
shard: relayShard.shardId,
|
||||||
|
peers: toSeq(peers).mapIt(WakuPeer.init(it, node.peerManager)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
let resp = RestApiResponse.jsonResponse(relayPeers, status = Http200)
|
||||||
|
if resp.isErr():
|
||||||
|
error "An error occurred while building the json response: ", error = resp.error
|
||||||
|
return RestApiResponse.internalServerError(
|
||||||
|
fmt("An error occurred while building the json response: {resp.error}")
|
||||||
|
)
|
||||||
|
|
||||||
|
return resp.get()
|
||||||
|
|
||||||
|
router.api(MethodGet, ROUTE_ADMIN_V1_MESH_PEERS_ON_SHARD) do(
|
||||||
|
shardId: uint16
|
||||||
|
) -> RestApiResponse:
|
||||||
|
let shard = shardId.valueOr:
|
||||||
|
return RestApiResponse.badRequest(fmt("Invalid shardId: {error}"))
|
||||||
|
|
||||||
|
if node.wakuRelay.isNil():
|
||||||
|
return RestApiResponse.serviceUnavailable(
|
||||||
|
"Error: Relay Protocol is not mounted to the node"
|
||||||
|
)
|
||||||
|
|
||||||
|
let topic =
|
||||||
|
toPubsubTopic(RelayShard(clusterId: node.wakuSharding.clusterId, shardId: shard))
|
||||||
|
let peers =
|
||||||
|
node.wakuRelay.getPubSubPeersInMesh(topic).get(initHashSet[PubSubPeer](0))
|
||||||
|
let relayPeer = PeersOfShard(
|
||||||
|
shard: shard, peers: toSeq(peers).mapIt(WakuPeer.init(it, node.peerManager))
|
||||||
|
)
|
||||||
|
|
||||||
|
let resp = RestApiResponse.jsonResponse(relayPeer, status = Http200)
|
||||||
|
if resp.isErr():
|
||||||
|
error "An error occurred while building the json response: ", error = resp.error
|
||||||
|
return RestApiResponse.internalServerError(
|
||||||
|
fmt("An error occurred while building the json response: {resp.error}")
|
||||||
)
|
)
|
||||||
|
|
||||||
return resp.get()
|
return resp.get()
|
||||||
|
|||||||
@ -4,22 +4,29 @@ import
|
|||||||
chronicles,
|
chronicles,
|
||||||
json_serialization,
|
json_serialization,
|
||||||
json_serialization/std/options,
|
json_serialization/std/options,
|
||||||
json_serialization/lexer
|
json_serialization/lexer,
|
||||||
import ../serdes, ../../../waku_core
|
results,
|
||||||
|
libp2p/protocols/pubsub/pubsubpeer
|
||||||
|
import waku/[waku_core, node/peer_manager], ../serdes
|
||||||
|
|
||||||
#### Types
|
#### Types
|
||||||
|
|
||||||
type ProtocolState* = object
|
|
||||||
protocol*: string
|
|
||||||
connected*: bool
|
|
||||||
|
|
||||||
type WakuPeer* = object
|
type WakuPeer* = object
|
||||||
multiaddr*: string
|
multiaddr*: string
|
||||||
protocols*: seq[ProtocolState]
|
protocols*: seq[string]
|
||||||
|
shards*: seq[uint16]
|
||||||
|
connected*: Connectedness
|
||||||
|
agent*: string
|
||||||
origin*: PeerOrigin
|
origin*: PeerOrigin
|
||||||
|
score*: Option[float64]
|
||||||
|
|
||||||
type WakuPeers* = seq[WakuPeer]
|
type WakuPeers* = seq[WakuPeer]
|
||||||
|
|
||||||
|
type PeersOfShard* = object
|
||||||
|
shard*: uint16
|
||||||
|
peers*: WakuPeers
|
||||||
|
|
||||||
|
type PeersOfShards* = seq[PeersOfShard]
|
||||||
|
|
||||||
type FilterTopic* = object
|
type FilterTopic* = object
|
||||||
pubsubTopic*: string
|
pubsubTopic*: string
|
||||||
contentTopic*: string
|
contentTopic*: string
|
||||||
@ -29,22 +36,25 @@ type FilterSubscription* = object
|
|||||||
filterCriteria*: seq[FilterTopic]
|
filterCriteria*: seq[FilterTopic]
|
||||||
|
|
||||||
#### Serialization and deserialization
|
#### Serialization and deserialization
|
||||||
|
|
||||||
proc writeValue*(
|
|
||||||
writer: var JsonWriter[RestJson], value: ProtocolState
|
|
||||||
) {.raises: [IOError].} =
|
|
||||||
writer.beginRecord()
|
|
||||||
writer.writeField("protocol", value.protocol)
|
|
||||||
writer.writeField("connected", value.connected)
|
|
||||||
writer.endRecord()
|
|
||||||
|
|
||||||
proc writeValue*(
|
proc writeValue*(
|
||||||
writer: var JsonWriter[RestJson], value: WakuPeer
|
writer: var JsonWriter[RestJson], value: WakuPeer
|
||||||
) {.raises: [IOError].} =
|
) {.raises: [IOError].} =
|
||||||
writer.beginRecord()
|
writer.beginRecord()
|
||||||
writer.writeField("multiaddr", value.multiaddr)
|
writer.writeField("multiaddr", value.multiaddr)
|
||||||
writer.writeField("protocols", value.protocols)
|
writer.writeField("protocols", value.protocols)
|
||||||
|
writer.writeField("shards", value.shards)
|
||||||
|
writer.writeField("connected", value.connected)
|
||||||
|
writer.writeField("agent", value.agent)
|
||||||
writer.writeField("origin", value.origin)
|
writer.writeField("origin", value.origin)
|
||||||
|
writer.writeField("score", value.score)
|
||||||
|
writer.endRecord()
|
||||||
|
|
||||||
|
proc writeValue*(
|
||||||
|
writer: var JsonWriter[RestJson], value: PeersOfShard
|
||||||
|
) {.raises: [IOError].} =
|
||||||
|
writer.beginRecord()
|
||||||
|
writer.writeField("shard", value.shard)
|
||||||
|
writer.writeField("peers", value.peers)
|
||||||
writer.endRecord()
|
writer.endRecord()
|
||||||
|
|
||||||
proc writeValue*(
|
proc writeValue*(
|
||||||
@ -63,43 +73,17 @@ proc writeValue*(
|
|||||||
writer.writeField("filterCriteria", value.filterCriteria)
|
writer.writeField("filterCriteria", value.filterCriteria)
|
||||||
writer.endRecord()
|
writer.endRecord()
|
||||||
|
|
||||||
proc readValue*(
|
|
||||||
reader: var JsonReader[RestJson], value: var ProtocolState
|
|
||||||
) {.gcsafe, raises: [SerializationError, IOError].} =
|
|
||||||
var
|
|
||||||
protocol: Option[string]
|
|
||||||
connected: Option[bool]
|
|
||||||
|
|
||||||
for fieldName in readObjectFields(reader):
|
|
||||||
case fieldName
|
|
||||||
of "protocol":
|
|
||||||
if protocol.isSome():
|
|
||||||
reader.raiseUnexpectedField("Multiple `protocol` fields found", "ProtocolState")
|
|
||||||
protocol = some(reader.readValue(string))
|
|
||||||
of "connected":
|
|
||||||
if connected.isSome():
|
|
||||||
reader.raiseUnexpectedField(
|
|
||||||
"Multiple `connected` fields found", "ProtocolState"
|
|
||||||
)
|
|
||||||
connected = some(reader.readValue(bool))
|
|
||||||
else:
|
|
||||||
unrecognizedFieldWarning(value)
|
|
||||||
|
|
||||||
if connected.isNone():
|
|
||||||
reader.raiseUnexpectedValue("Field `connected` is missing")
|
|
||||||
|
|
||||||
if protocol.isNone():
|
|
||||||
reader.raiseUnexpectedValue("Field `protocol` is missing")
|
|
||||||
|
|
||||||
value = ProtocolState(protocol: protocol.get(), connected: connected.get())
|
|
||||||
|
|
||||||
proc readValue*(
|
proc readValue*(
|
||||||
reader: var JsonReader[RestJson], value: var WakuPeer
|
reader: var JsonReader[RestJson], value: var WakuPeer
|
||||||
) {.gcsafe, raises: [SerializationError, IOError].} =
|
) {.gcsafe, raises: [SerializationError, IOError].} =
|
||||||
var
|
var
|
||||||
multiaddr: Option[string]
|
multiaddr: Option[string]
|
||||||
protocols: Option[seq[ProtocolState]]
|
protocols: Option[seq[string]]
|
||||||
|
shards: Option[seq[uint16]]
|
||||||
|
connected: Option[Connectedness]
|
||||||
|
agent: Option[string]
|
||||||
origin: Option[PeerOrigin]
|
origin: Option[PeerOrigin]
|
||||||
|
score: Option[float64]
|
||||||
|
|
||||||
for fieldName in readObjectFields(reader):
|
for fieldName in readObjectFields(reader):
|
||||||
case fieldName
|
case fieldName
|
||||||
@ -110,11 +94,27 @@ proc readValue*(
|
|||||||
of "protocols":
|
of "protocols":
|
||||||
if protocols.isSome():
|
if protocols.isSome():
|
||||||
reader.raiseUnexpectedField("Multiple `protocols` fields found", "WakuPeer")
|
reader.raiseUnexpectedField("Multiple `protocols` fields found", "WakuPeer")
|
||||||
protocols = some(reader.readValue(seq[ProtocolState]))
|
protocols = some(reader.readValue(seq[string]))
|
||||||
|
of "shards":
|
||||||
|
if shards.isSome():
|
||||||
|
reader.raiseUnexpectedField("Multiple `shards` fields found", "WakuPeer")
|
||||||
|
shards = some(reader.readValue(seq[uint16]))
|
||||||
|
of "connected":
|
||||||
|
if connected.isSome():
|
||||||
|
reader.raiseUnexpectedField("Multiple `connected` fields found", "WakuPeer")
|
||||||
|
connected = some(reader.readValue(Connectedness))
|
||||||
|
of "agent":
|
||||||
|
if agent.isSome():
|
||||||
|
reader.raiseUnexpectedField("Multiple `agent` fields found", "WakuPeer")
|
||||||
|
agent = some(reader.readValue(string))
|
||||||
of "origin":
|
of "origin":
|
||||||
if origin.isSome():
|
if origin.isSome():
|
||||||
reader.raiseUnexpectedField("Multiple `origin` fields found", "WakuPeer")
|
reader.raiseUnexpectedField("Multiple `origin` fields found", "WakuPeer")
|
||||||
origin = some(reader.readValue(PeerOrigin))
|
origin = some(reader.readValue(PeerOrigin))
|
||||||
|
of "score":
|
||||||
|
if score.isSome():
|
||||||
|
reader.raiseUnexpectedField("Multiple `score` fields found", "WakuPeer")
|
||||||
|
score = some(reader.readValue(float64))
|
||||||
else:
|
else:
|
||||||
unrecognizedFieldWarning(value)
|
unrecognizedFieldWarning(value)
|
||||||
|
|
||||||
@ -124,13 +124,56 @@ proc readValue*(
|
|||||||
if protocols.isNone():
|
if protocols.isNone():
|
||||||
reader.raiseUnexpectedValue("Field `protocols` are missing")
|
reader.raiseUnexpectedValue("Field `protocols` are missing")
|
||||||
|
|
||||||
|
if shards.isNone():
|
||||||
|
reader.raiseUnexpectedValue("Field `shards` is missing")
|
||||||
|
|
||||||
|
if connected.isNone():
|
||||||
|
reader.raiseUnexpectedValue("Field `connected` is missing")
|
||||||
|
|
||||||
|
if agent.isNone():
|
||||||
|
reader.raiseUnexpectedValue("Field `agent` is missing")
|
||||||
|
|
||||||
if origin.isNone():
|
if origin.isNone():
|
||||||
reader.raiseUnexpectedValue("Field `origin` is missing")
|
reader.raiseUnexpectedValue("Field `origin` is missing")
|
||||||
|
|
||||||
value = WakuPeer(
|
value = WakuPeer(
|
||||||
multiaddr: multiaddr.get(), protocols: protocols.get(), origin: origin.get()
|
multiaddr: multiaddr.get(),
|
||||||
|
protocols: protocols.get(),
|
||||||
|
shards: shards.get(),
|
||||||
|
connected: connected.get(),
|
||||||
|
agent: agent.get(),
|
||||||
|
origin: origin.get(),
|
||||||
|
score: score,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
proc readValue*(
|
||||||
|
reader: var JsonReader[RestJson], value: var PeersOfShard
|
||||||
|
) {.gcsafe, raises: [SerializationError, IOError].} =
|
||||||
|
var
|
||||||
|
shard: Option[uint16]
|
||||||
|
peers: Option[WakuPeers]
|
||||||
|
|
||||||
|
for fieldName in readObjectFields(reader):
|
||||||
|
case fieldName
|
||||||
|
of "shard":
|
||||||
|
if shard.isSome():
|
||||||
|
reader.raiseUnexpectedField("Multiple `shard` fields found", "PeersOfShard")
|
||||||
|
shard = some(reader.readValue(uint16))
|
||||||
|
of "peers":
|
||||||
|
if peers.isSome():
|
||||||
|
reader.raiseUnexpectedField("Multiple `peers` fields found", "PeersOfShard")
|
||||||
|
peers = some(reader.readValue(WakuPeers))
|
||||||
|
else:
|
||||||
|
unrecognizedFieldWarning(value)
|
||||||
|
|
||||||
|
if shard.isNone():
|
||||||
|
reader.raiseUnexpectedValue("Field `shard` is missing")
|
||||||
|
|
||||||
|
if peers.isNone():
|
||||||
|
reader.raiseUnexpectedValue("Field `peers` are missing")
|
||||||
|
|
||||||
|
value = PeersOfShard(shard: shard.get(), peers: peers.get())
|
||||||
|
|
||||||
proc readValue*(
|
proc readValue*(
|
||||||
reader: var JsonReader[RestJson], value: var FilterTopic
|
reader: var JsonReader[RestJson], value: var FilterTopic
|
||||||
) {.gcsafe, raises: [SerializationError, IOError].} =
|
) {.gcsafe, raises: [SerializationError, IOError].} =
|
||||||
@ -195,26 +238,47 @@ proc readValue*(
|
|||||||
|
|
||||||
value = FilterSubscription(peerId: peerId.get(), filterCriteria: filterCriteria.get())
|
value = FilterSubscription(peerId: peerId.get(), filterCriteria: filterCriteria.get())
|
||||||
|
|
||||||
## Utility for populating WakuPeers and ProtocolState
|
|
||||||
func `==`*(a, b: ProtocolState): bool {.inline.} =
|
|
||||||
return a.protocol == b.protocol
|
|
||||||
|
|
||||||
func `==`*(a: ProtocolState, b: string): bool {.inline.} =
|
|
||||||
return a.protocol == b
|
|
||||||
|
|
||||||
func `==`*(a, b: WakuPeer): bool {.inline.} =
|
func `==`*(a, b: WakuPeer): bool {.inline.} =
|
||||||
return a.multiaddr == b.multiaddr
|
return a.multiaddr == b.multiaddr
|
||||||
|
|
||||||
|
proc init*(T: type WakuPeer, peerInfo: RemotePeerInfo): WakuPeer =
|
||||||
|
result = WakuPeer(
|
||||||
|
multiaddr: constructMultiaddrStr(peerInfo),
|
||||||
|
protocols: peerInfo.protocols,
|
||||||
|
shards: peerInfo.getShards(),
|
||||||
|
connected: peerInfo.connectedness,
|
||||||
|
agent: peerInfo.agent,
|
||||||
|
origin: peerInfo.origin,
|
||||||
|
score: none(float64),
|
||||||
|
)
|
||||||
|
|
||||||
|
proc init*(T: type WakuPeer, pubsubPeer: PubSubPeer, pm: PeerManager): WakuPeer =
|
||||||
|
let peerInfo = pm.getPeer(pubsubPeer.peerId)
|
||||||
|
result = WakuPeer(
|
||||||
|
multiaddr: constructMultiaddrStr(peerInfo),
|
||||||
|
protocols: peerInfo.protocols,
|
||||||
|
shards: peerInfo.getShards(),
|
||||||
|
connected: peerInfo.connectedness,
|
||||||
|
agent: peerInfo.agent,
|
||||||
|
origin: peerInfo.origin,
|
||||||
|
score: some(pubsubPeer.score),
|
||||||
|
)
|
||||||
|
|
||||||
proc add*(
|
proc add*(
|
||||||
peers: var WakuPeers,
|
peers: var WakuPeers,
|
||||||
multiaddr: string,
|
multiaddr: string,
|
||||||
protocol: string,
|
protocol: string,
|
||||||
connected: bool,
|
shards: seq[uint16],
|
||||||
|
connected: Connectedness,
|
||||||
|
agent: string,
|
||||||
origin: PeerOrigin,
|
origin: PeerOrigin,
|
||||||
) =
|
) =
|
||||||
var peer: WakuPeer = WakuPeer(
|
var peer: WakuPeer = WakuPeer(
|
||||||
multiaddr: multiaddr,
|
multiaddr: multiaddr,
|
||||||
protocols: @[ProtocolState(protocol: protocol, connected: connected)],
|
protocols: @[protocol],
|
||||||
|
shards: shards,
|
||||||
|
connected: connected,
|
||||||
|
agent: agent,
|
||||||
origin: origin,
|
origin: origin,
|
||||||
)
|
)
|
||||||
let idx = peers.find(peer)
|
let idx = peers.find(peer)
|
||||||
@ -222,4 +286,4 @@ proc add*(
|
|||||||
if idx < 0:
|
if idx < 0:
|
||||||
peers.add(peer)
|
peers.add(peer)
|
||||||
else:
|
else:
|
||||||
peers[idx].protocols.add(ProtocolState(protocol: protocol, connected: connected))
|
peers[idx].protocols.add(protocol)
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/typetraits,
|
std/[typetraits, parseutils],
|
||||||
results,
|
results,
|
||||||
stew/byteutils,
|
stew/[byteutils, base10],
|
||||||
chronicles,
|
chronicles,
|
||||||
serialization,
|
serialization,
|
||||||
json_serialization,
|
json_serialization,
|
||||||
@ -100,3 +100,13 @@ proc encodeString*(value: string): RestResult[string] =
|
|||||||
|
|
||||||
proc decodeString*(t: typedesc[string], value: string): RestResult[string] =
|
proc decodeString*(t: typedesc[string], value: string): RestResult[string] =
|
||||||
ok(value)
|
ok(value)
|
||||||
|
|
||||||
|
proc encodeString*(value: SomeUnsignedInt): RestResult[string] =
|
||||||
|
ok(Base10.toString(value))
|
||||||
|
|
||||||
|
proc decodeString*(T: typedesc[SomeUnsignedInt], value: string): RestResult[T] =
|
||||||
|
let v = Base10.decode(T, value)
|
||||||
|
if v.isErr():
|
||||||
|
return err(v.error())
|
||||||
|
else:
|
||||||
|
return ok(v.get())
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import
|
|||||||
libp2p/routing_record,
|
libp2p/routing_record,
|
||||||
regex,
|
regex,
|
||||||
json_serialization
|
json_serialization
|
||||||
import ../waku_enr/capabilities
|
import ../waku_enr
|
||||||
|
|
||||||
type
|
type
|
||||||
Connectedness* = enum
|
Connectedness* = enum
|
||||||
@ -231,7 +231,7 @@ proc parsePeerInfo*(maddrs: varargs[string]): Result[RemotePeerInfo, string] =
|
|||||||
|
|
||||||
parsePeerInfo(multiAddresses)
|
parsePeerInfo(multiAddresses)
|
||||||
|
|
||||||
func getTransportProtocol(typedR: TypedRecord): Option[IpTransportProtocol] =
|
func getTransportProtocol(typedR: enr.TypedRecord): Option[IpTransportProtocol] =
|
||||||
if typedR.tcp6.isSome() or typedR.tcp.isSome():
|
if typedR.tcp6.isSome() or typedR.tcp.isSome():
|
||||||
return some(IpTransportProtocol.tcpProtocol)
|
return some(IpTransportProtocol.tcpProtocol)
|
||||||
|
|
||||||
@ -255,9 +255,9 @@ proc parseUrlPeerAddr*(
|
|||||||
|
|
||||||
return ok(some(parsedPeerInfo.value))
|
return ok(some(parsedPeerInfo.value))
|
||||||
|
|
||||||
proc toRemotePeerInfo*(enr: enr.Record): Result[RemotePeerInfo, cstring] =
|
proc toRemotePeerInfo*(enrRec: enr.Record): Result[RemotePeerInfo, cstring] =
|
||||||
## Converts an ENR to dialable RemotePeerInfo
|
## Converts an ENR to dialable RemotePeerInfo
|
||||||
let typedR = TypedRecord.fromRecord(enr)
|
let typedR = enr.TypedRecord.fromRecord(enrRec)
|
||||||
if not typedR.secp256k1.isSome():
|
if not typedR.secp256k1.isSome():
|
||||||
return err("enr: no secp256k1 key in record")
|
return err("enr: no secp256k1 key in record")
|
||||||
|
|
||||||
@ -303,7 +303,7 @@ proc toRemotePeerInfo*(enr: enr.Record): Result[RemotePeerInfo, cstring] =
|
|||||||
return err("enr: no addresses in record")
|
return err("enr: no addresses in record")
|
||||||
|
|
||||||
let protocolsRes = catch:
|
let protocolsRes = catch:
|
||||||
enr.getCapabilitiesCodecs()
|
enrRec.getCapabilitiesCodecs()
|
||||||
|
|
||||||
var protocols: seq[string]
|
var protocols: seq[string]
|
||||||
if not protocolsRes.isErr():
|
if not protocolsRes.isErr():
|
||||||
@ -312,7 +312,7 @@ proc toRemotePeerInfo*(enr: enr.Record): Result[RemotePeerInfo, cstring] =
|
|||||||
error "Could not retrieve supported protocols from enr",
|
error "Could not retrieve supported protocols from enr",
|
||||||
peerId = peerId, msg = protocolsRes.error.msg
|
peerId = peerId, msg = protocolsRes.error.msg
|
||||||
|
|
||||||
return ok(RemotePeerInfo.init(peerId, addrs, some(enr), protocols))
|
return ok(RemotePeerInfo.init(peerId, addrs, some(enrRec), protocols))
|
||||||
|
|
||||||
converter toRemotePeerInfo*(peerRecord: PeerRecord): RemotePeerInfo =
|
converter toRemotePeerInfo*(peerRecord: PeerRecord): RemotePeerInfo =
|
||||||
## Converts peer records to dialable RemotePeerInfo
|
## Converts peer records to dialable RemotePeerInfo
|
||||||
@ -350,8 +350,8 @@ func hasUdpPort*(peer: RemotePeerInfo): bool =
|
|||||||
return false
|
return false
|
||||||
|
|
||||||
let
|
let
|
||||||
enr = peer.enr.get()
|
enrRec = peer.enr.get()
|
||||||
typedEnr = TypedRecord.fromRecord(enr)
|
typedEnr = enr.TypedRecord.fromRecord(enrRec)
|
||||||
|
|
||||||
typedEnr.udp.isSome() or typedEnr.udp6.isSome()
|
typedEnr.udp.isSome() or typedEnr.udp6.isSome()
|
||||||
|
|
||||||
@ -361,3 +361,18 @@ proc getAgent*(peer: RemotePeerInfo): string =
|
|||||||
return "unknown"
|
return "unknown"
|
||||||
|
|
||||||
return peer.agent
|
return peer.agent
|
||||||
|
|
||||||
|
proc getShards*(peer: RemotePeerInfo): seq[uint16] =
|
||||||
|
if peer.enr.isNone():
|
||||||
|
return @[]
|
||||||
|
|
||||||
|
let enrRec = peer.enr.get()
|
||||||
|
let typedRecord = enrRec.toTyped().valueOr:
|
||||||
|
trace "invalid ENR record", error = error
|
||||||
|
return @[]
|
||||||
|
|
||||||
|
let shards = typedRecord.relaySharding()
|
||||||
|
if shards.isSome():
|
||||||
|
return shards.get().shardIds
|
||||||
|
|
||||||
|
return @[]
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import
|
|||||||
eth/keys,
|
eth/keys,
|
||||||
libp2p/[multiaddress, multicodec],
|
libp2p/[multiaddress, multicodec],
|
||||||
libp2p/crypto/crypto
|
libp2p/crypto/crypto
|
||||||
import ../common/enr, ../waku_core
|
import ../common/enr, ../waku_core/topics/pubsub_topic
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "waku enr sharding"
|
topics = "waku enr sharding"
|
||||||
|
|||||||
@ -323,31 +323,42 @@ proc addObserver*(w: WakuRelay, observer: PubSubObserver) {.gcsafe.} =
|
|||||||
proc getDHigh*(T: type WakuRelay): int =
|
proc getDHigh*(T: type WakuRelay): int =
|
||||||
return GossipsubParameters.dHigh
|
return GossipsubParameters.dHigh
|
||||||
|
|
||||||
proc getPeersInMesh*(
|
proc getPubSubPeersInMesh*(
|
||||||
w: WakuRelay, pubsubTopic: PubsubTopic
|
w: WakuRelay, pubsubTopic: PubsubTopic
|
||||||
): Result[seq[PeerId], string] =
|
): Result[HashSet[PubSubPeer], string] =
|
||||||
## Returns the list of peerIds in a mesh defined by the passed pubsub topic.
|
## Returns the list of PubSubPeers in a mesh defined by the passed pubsub topic.
|
||||||
## The 'mesh' atribute is defined in the GossipSub ref object.
|
## The 'mesh' atribute is defined in the GossipSub ref object.
|
||||||
|
|
||||||
if not w.mesh.hasKey(pubsubTopic):
|
if not w.mesh.hasKey(pubsubTopic):
|
||||||
debug "getPeersInMesh - there is no mesh peer for the given pubsub topic",
|
debug "getPubSubPeersInMesh - there is no mesh peer for the given pubsub topic",
|
||||||
pubsubTopic = pubsubTopic
|
pubsubTopic = pubsubTopic
|
||||||
return ok(newSeq[PeerId]())
|
return ok(initHashSet[PubSubPeer]())
|
||||||
|
|
||||||
let peersRes = catch:
|
let peersRes = catch:
|
||||||
w.mesh[pubsubTopic]
|
w.mesh[pubsubTopic]
|
||||||
|
|
||||||
let peers: HashSet[PubSubPeer] = peersRes.valueOr:
|
let peers: HashSet[PubSubPeer] = peersRes.valueOr:
|
||||||
return err("getPeersInMesh - exception accessing " & pubsubTopic & ": " & error.msg)
|
return err(
|
||||||
|
"getPubSubPeersInMesh - exception accessing " & pubsubTopic & ": " & error.msg
|
||||||
|
)
|
||||||
|
|
||||||
let peerIds = toSeq(peers).mapIt(it.peerId)
|
return ok(peers)
|
||||||
|
|
||||||
|
proc getPeersInMesh*(
|
||||||
|
w: WakuRelay, pubsubTopic: PubsubTopic
|
||||||
|
): Result[seq[PeerId], string] =
|
||||||
|
## Returns the list of peerIds in a mesh defined by the passed pubsub topic.
|
||||||
|
## The 'mesh' atribute is defined in the GossipSub ref object.
|
||||||
|
let pubSubPeers = w.getPubSubPeersInMesh(pubsubTopic).valueOr:
|
||||||
|
return err(error)
|
||||||
|
let peerIds = toSeq(pubSubPeers).mapIt(it.peerId)
|
||||||
|
|
||||||
return ok(peerIds)
|
return ok(peerIds)
|
||||||
|
|
||||||
proc getNumPeersInMesh*(w: WakuRelay, pubsubTopic: PubsubTopic): Result[int, string] =
|
proc getNumPeersInMesh*(w: WakuRelay, pubsubTopic: PubsubTopic): Result[int, string] =
|
||||||
## Returns the number of peers in a mesh defined by the passed pubsub topic.
|
## Returns the number of peers in a mesh defined by the passed pubsub topic.
|
||||||
|
|
||||||
let peers = w.getPeersInMesh(pubsubTopic).valueOr:
|
let peers = w.getPubSubPeersInMesh(pubsubTopic).valueOr:
|
||||||
return err(
|
return err(
|
||||||
"getNumPeersInMesh - failed retrieving peers in mesh: " & pubsubTopic & ": " &
|
"getNumPeersInMesh - failed retrieving peers in mesh: " & pubsubTopic & ": " &
|
||||||
error
|
error
|
||||||
@ -557,18 +568,17 @@ proc publish*(
|
|||||||
|
|
||||||
return ok(relayedPeerCount)
|
return ok(relayedPeerCount)
|
||||||
|
|
||||||
proc getConnectedPeers*(
|
proc getConnectedPubSubPeers*(
|
||||||
w: WakuRelay, pubsubTopic: PubsubTopic
|
w: WakuRelay, pubsubTopic: PubsubTopic
|
||||||
): Result[seq[PeerId], string] =
|
): Result[HashSet[PubsubPeer], string] =
|
||||||
## Returns the list of peerIds of connected peers and subscribed to the passed pubsub topic.
|
## Returns the list of peerIds of connected peers and subscribed to the passed pubsub topic.
|
||||||
## The 'gossipsub' atribute is defined in the GossipSub ref object.
|
## The 'gossipsub' atribute is defined in the GossipSub ref object.
|
||||||
|
|
||||||
if pubsubTopic == "":
|
if pubsubTopic == "":
|
||||||
## Return all the connected peers
|
## Return all the connected peers
|
||||||
var peerIds = newSeq[PeerId]()
|
var peerIds = initHashSet[PubsubPeer]()
|
||||||
for k, v in w.gossipsub:
|
for k, v in w.gossipsub:
|
||||||
peerIds.add(toSeq(v).mapIt(it.peerId))
|
peerIds = peerIds + v
|
||||||
# alternatively: peerIds &= toSeq(v).mapIt(it.peerId)
|
|
||||||
return ok(peerIds)
|
return ok(peerIds)
|
||||||
|
|
||||||
if not w.gossipsub.hasKey(pubsubTopic):
|
if not w.gossipsub.hasKey(pubsubTopic):
|
||||||
@ -584,6 +594,17 @@ proc getConnectedPeers*(
|
|||||||
return
|
return
|
||||||
err("getConnectedPeers - exception accessing " & pubsubTopic & ": " & error.msg)
|
err("getConnectedPeers - exception accessing " & pubsubTopic & ": " & error.msg)
|
||||||
|
|
||||||
|
return ok(peers)
|
||||||
|
|
||||||
|
proc getConnectedPeers*(
|
||||||
|
w: WakuRelay, pubsubTopic: PubsubTopic
|
||||||
|
): Result[seq[PeerId], string] =
|
||||||
|
## Returns the list of peerIds of connected peers and subscribed to the passed pubsub topic.
|
||||||
|
## The 'gossipsub' atribute is defined in the GossipSub ref object.
|
||||||
|
|
||||||
|
let peers = w.getConnectedPubSubPeers(pubsubTopic).valueOr:
|
||||||
|
return err(error)
|
||||||
|
|
||||||
let peerIds = toSeq(peers).mapIt(it.peerId)
|
let peerIds = toSeq(peers).mapIt(it.peerId)
|
||||||
return ok(peerIds)
|
return ok(peerIds)
|
||||||
|
|
||||||
@ -593,7 +614,7 @@ proc getNumConnectedPeers*(
|
|||||||
## Returns the number of connected peers and subscribed to the passed pubsub topic.
|
## Returns the number of connected peers and subscribed to the passed pubsub topic.
|
||||||
|
|
||||||
## Return all the connected peers
|
## Return all the connected peers
|
||||||
let peers = w.getConnectedPeers(pubsubTopic).valueOr:
|
let peers = w.getConnectedPubSubPeers(pubsubTopic).valueOr:
|
||||||
return err(
|
return err(
|
||||||
"getNumConnectedPeers - failed retrieving peers in mesh: " & pubsubTopic & ": " &
|
"getNumConnectedPeers - failed retrieving peers in mesh: " & pubsubTopic & ": " &
|
||||||
error
|
error
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user