2024-06-28 16:04:57 +05:30
|
|
|
|
{.push raises: [].}
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
|
|
|
|
|
import
|
2025-04-24 08:36:02 +02:00
|
|
|
|
std/[sets, strformat, sequtils, tables],
|
2023-10-05 14:00:09 +02:00
|
|
|
|
chronicles,
|
2025-06-12 10:50:08 +02:00
|
|
|
|
chronicles/topics_registry,
|
2023-10-05 14:00:09 +02:00
|
|
|
|
json_serialization,
|
|
|
|
|
|
presto/route,
|
2025-04-24 08:36:02 +02:00
|
|
|
|
libp2p/[peerinfo, switch, peerid, protocols/pubsub/pubsubpeer]
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
|
|
|
|
|
import
|
2025-04-24 08:36:02 +02:00
|
|
|
|
waku/[
|
|
|
|
|
|
waku_core,
|
|
|
|
|
|
waku_core/topics/pubsub_topic,
|
|
|
|
|
|
waku_store_legacy/common,
|
|
|
|
|
|
waku_store/common,
|
|
|
|
|
|
waku_filter_v2,
|
|
|
|
|
|
waku_lightpush_legacy/common,
|
|
|
|
|
|
waku_relay,
|
|
|
|
|
|
waku_peer_exchange,
|
|
|
|
|
|
waku_node,
|
|
|
|
|
|
node/peer_manager,
|
|
|
|
|
|
waku_enr/sharding,
|
|
|
|
|
|
],
|
2023-10-05 14:00:09 +02:00
|
|
|
|
../responses,
|
|
|
|
|
|
../serdes,
|
2023-11-14 16:59:53 +01:00
|
|
|
|
../rest_serdes,
|
2023-10-05 14:00:09 +02:00
|
|
|
|
./types
|
|
|
|
|
|
|
|
|
|
|
|
export types
|
|
|
|
|
|
|
|
|
|
|
|
logScope:
|
|
|
|
|
|
topics = "waku node rest admin api"
|
|
|
|
|
|
|
2025-06-10 02:10:06 +02:00
|
|
|
|
const ROUTE_ADMIN_V1_PEERS_STATS* = "/admin/v1/peers/stats" # provides peer statistics
|
|
|
|
|
|
|
2025-04-24 08:36:02 +02:00
|
|
|
|
const ROUTE_ADMIN_V1_PEERS* = "/admin/v1/peers" # returns all peers
|
|
|
|
|
|
const ROUTE_ADMIN_V1_SINGLE_PEER* = "/admin/v1/peer/{peerId}"
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
const ROUTE_ADMIN_V1_SERVICE_PEERS* = "/admin/v1/peers/service" # returns all peers
|
|
|
|
|
|
|
2025-04-24 08:36:02 +02:00
|
|
|
|
const ROUTE_ADMIN_V1_CONNECTED_PEERS* = "/admin/v1/peers/connected"
|
|
|
|
|
|
const ROUTE_ADMIN_V1_CONNECTED_PEERS_ON_SHARD* =
|
|
|
|
|
|
"/admin/v1/peers/connected/on/{shardId}"
|
2025-04-25 15:36:41 +02:00
|
|
|
|
const ROUTE_ADMIN_V1_RELAY_PEERS* = "/admin/v1/peers/relay"
|
|
|
|
|
|
const ROUTE_ADMIN_V1_RELAY_PEERS_ON_SHARD* = "/admin/v1/peers/relay/on/{shardId}"
|
2025-04-24 08:36:02 +02:00
|
|
|
|
const ROUTE_ADMIN_V1_MESH_PEERS* = "/admin/v1/peers/mesh"
|
|
|
|
|
|
const ROUTE_ADMIN_V1_MESH_PEERS_ON_SHARD* = "/admin/v1/peers/mesh/on/{shardId}"
|
|
|
|
|
|
|
2024-01-09 11:42:29 +01:00
|
|
|
|
const ROUTE_ADMIN_V1_FILTER_SUBS* = "/admin/v1/filter/subscriptions"
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
2025-06-12 10:50:08 +02:00
|
|
|
|
const ROUTE_ADMIN_V1_POST_LOG_LEVEL* = "/admin/v1/log-level/{logLevel}"
|
|
|
|
|
|
# sets the new log level for the node
|
|
|
|
|
|
|
2024-06-26 17:59:12 +02:00
|
|
|
|
type PeerProtocolTuple =
|
2025-04-24 08:36:02 +02:00
|
|
|
|
tuple[
|
|
|
|
|
|
multiaddr: string,
|
|
|
|
|
|
protocol: string,
|
|
|
|
|
|
shards: seq[uint16],
|
|
|
|
|
|
connected: Connectedness,
|
|
|
|
|
|
agent: string,
|
|
|
|
|
|
origin: PeerOrigin,
|
|
|
|
|
|
]
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
|
|
|
|
|
proc tuplesToWakuPeers(peers: var WakuPeers, peersTup: seq[PeerProtocolTuple]) =
|
|
|
|
|
|
for peer in peersTup:
|
2025-04-24 08:36:02 +02:00
|
|
|
|
peers.add(
|
|
|
|
|
|
peer.multiaddr, peer.protocol, peer.shards, peer.connected, peer.agent,
|
|
|
|
|
|
peer.origin,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
proc populateAdminPeerInfo(
|
|
|
|
|
|
peers: var WakuPeers, node: WakuNode, codec: Option[string] = none[string]()
|
|
|
|
|
|
) =
|
|
|
|
|
|
if codec.isNone():
|
|
|
|
|
|
peers = node.peerManager.switch.peerStore.peers().mapIt(WakuPeer.init(it))
|
|
|
|
|
|
else:
|
|
|
|
|
|
let peersTuples = node.peerManager.switch.peerStore.peers(codec.get()).mapIt(
|
|
|
|
|
|
(
|
|
|
|
|
|
multiaddr: constructMultiaddrStr(it),
|
|
|
|
|
|
protocol: codec.get(),
|
|
|
|
|
|
shards: it.getShards(),
|
|
|
|
|
|
connected: it.connectedness,
|
|
|
|
|
|
agent: it.agent,
|
|
|
|
|
|
origin: it.origin,
|
|
|
|
|
|
)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
)
|
2025-04-25 15:36:41 +02:00
|
|
|
|
tuplesToWakuPeers(peers, peersTuples)
|
|
|
|
|
|
|
|
|
|
|
|
proc populateAdminPeerInfoForAll(node: WakuNode): WakuPeers =
|
|
|
|
|
|
var peers: WakuPeers = @[]
|
|
|
|
|
|
populateAdminPeerInfo(peers, node)
|
|
|
|
|
|
return peers
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
|
|
|
|
|
proc populateAdminPeerInfoForCodecs(node: WakuNode, codecs: seq[string]): WakuPeers =
|
|
|
|
|
|
var peers: WakuPeers = @[]
|
|
|
|
|
|
|
|
|
|
|
|
for codec in codecs:
|
2025-04-25 15:36:41 +02:00
|
|
|
|
populateAdminPeerInfo(peers, node, some(codec))
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
|
|
|
|
|
return peers
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
2025-06-10 02:10:06 +02:00
|
|
|
|
proc getRelayPeers(node: WakuNode): PeersOfShards =
|
|
|
|
|
|
var relayPeers: PeersOfShards = @[]
|
|
|
|
|
|
if not node.wakuRelay.isNil():
|
|
|
|
|
|
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)),
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
return relayPeers
|
|
|
|
|
|
|
|
|
|
|
|
proc getMeshPeers(node: WakuNode): PeersOfShards =
|
|
|
|
|
|
var meshPeers: PeersOfShards = @[]
|
|
|
|
|
|
if not node.wakuRelay.isNil():
|
|
|
|
|
|
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))
|
|
|
|
|
|
meshPeers.add(
|
|
|
|
|
|
PeersOfShard(
|
|
|
|
|
|
shard: relayShard.shardId,
|
|
|
|
|
|
peers: toSeq(peers).mapIt(WakuPeer.init(it, node.peerManager)),
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
return meshPeers
|
|
|
|
|
|
|
2023-10-05 14:00:09 +02:00
|
|
|
|
proc installAdminV1GetPeersHandler(router: var RestRouter, node: WakuNode) =
|
2024-03-16 00:08:47 +01:00
|
|
|
|
router.api(MethodGet, ROUTE_ADMIN_V1_PEERS) do() -> RestApiResponse:
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let peers = populateAdminPeerInfoForAll(node)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(peers, status = Http200).valueOr:
|
|
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
2025-04-24 08:36:02 +02:00
|
|
|
|
return RestApiResponse.internalServerError(
|
2025-04-25 15:36:41 +02:00
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
2024-07-23 12:58:56 +02:00
|
|
|
|
)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
return resp
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
|
|
|
|
|
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)
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(peer, status = Http200).valueOr:
|
|
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
2025-04-24 08:36:02 +02:00
|
|
|
|
return RestApiResponse.internalServerError(
|
2025-04-25 15:36:41 +02:00
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
2024-03-16 00:08:47 +01:00
|
|
|
|
)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
return resp
|
2025-04-24 08:36:02 +02:00
|
|
|
|
else:
|
|
|
|
|
|
return RestApiResponse.notFound(fmt("Peer with ID {peerId} not found"))
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
router.api(MethodGet, ROUTE_ADMIN_V1_SERVICE_PEERS) do() -> RestApiResponse:
|
|
|
|
|
|
let peers = populateAdminPeerInfoForCodecs(
|
2025-04-24 08:36:02 +02:00
|
|
|
|
node,
|
|
|
|
|
|
@[
|
|
|
|
|
|
WakuRelayCodec, WakuFilterSubscribeCodec, WakuStoreCodec, WakuLegacyStoreCodec,
|
|
|
|
|
|
WakuLegacyLightPushCodec, WakuLightPushCodec, WakuPeerExchangeCodec,
|
2025-08-07 00:03:35 +05:30
|
|
|
|
WakuReconciliationCodec, WakuTransferCodec,
|
2025-04-24 08:36:02 +02:00
|
|
|
|
],
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(peers, status = Http200).valueOr:
|
|
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
|
|
|
|
|
return RestApiResponse.internalServerError(
|
|
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return resp
|
|
|
|
|
|
|
|
|
|
|
|
router.api(MethodGet, ROUTE_ADMIN_V1_CONNECTED_PEERS) do() -> RestApiResponse:
|
|
|
|
|
|
let allPeers = populateAdminPeerInfoForAll(node)
|
|
|
|
|
|
|
2025-04-24 08:36:02 +02:00
|
|
|
|
let connectedPeers = allPeers.filterIt(it.connected == Connectedness.Connected)
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(connectedPeers, status = Http200).valueOr:
|
|
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
2025-04-24 08:36:02 +02:00
|
|
|
|
return RestApiResponse.internalServerError(
|
2025-04-25 15:36:41 +02:00
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
2024-07-23 12:58:56 +02:00
|
|
|
|
)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
return resp
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
|
|
|
|
|
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}"))
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let allPeers = populateAdminPeerInfoForAll(node)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
|
|
|
|
|
let connectedPeers = allPeers.filterIt(
|
|
|
|
|
|
it.connected == Connectedness.Connected and it.shards.contains(shard)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(connectedPeers, status = Http200).valueOr:
|
|
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
2025-04-24 08:36:02 +02:00
|
|
|
|
return RestApiResponse.internalServerError(
|
2025-04-25 15:36:41 +02:00
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
2024-07-23 12:58:56 +02:00
|
|
|
|
)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
return resp
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
router.api(MethodGet, ROUTE_ADMIN_V1_RELAY_PEERS) do() -> RestApiResponse:
|
2025-04-24 08:36:02 +02:00
|
|
|
|
if node.wakuRelay.isNil():
|
|
|
|
|
|
return RestApiResponse.serviceUnavailable(
|
|
|
|
|
|
"Error: Relay Protocol is not mounted to the node"
|
2024-07-23 12:58:56 +02:00
|
|
|
|
)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-06-10 02:10:06 +02:00
|
|
|
|
var relayPeers: PeersOfShards = getRelayPeers(node)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(relayPeers, status = Http200).valueOr:
|
|
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
2025-04-24 08:36:02 +02:00
|
|
|
|
return RestApiResponse.internalServerError(
|
2025-04-25 15:36:41 +02:00
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
2025-04-24 08:36:02 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
return resp
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
router.api(MethodGet, ROUTE_ADMIN_V1_RELAY_PEERS_ON_SHARD) do(
|
2025-04-24 08:36:02 +02:00
|
|
|
|
shardId: uint16
|
|
|
|
|
|
) -> RestApiResponse:
|
|
|
|
|
|
let shard = shardId.valueOr:
|
|
|
|
|
|
return RestApiResponse.badRequest(fmt("Invalid shardId: {error}"))
|
|
|
|
|
|
|
2025-07-04 17:10:53 +10:00
|
|
|
|
if node.wakuMetadata.isNil():
|
|
|
|
|
|
return RestApiResponse.serviceUnavailable(
|
|
|
|
|
|
"Error: Metadata Protocol is not mounted to the node"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-24 08:36:02 +02:00
|
|
|
|
if node.wakuRelay.isNil():
|
|
|
|
|
|
return RestApiResponse.serviceUnavailable(
|
|
|
|
|
|
"Error: Relay Protocol is not mounted to the node"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-07-04 17:10:53 +10:00
|
|
|
|
# TODO: clusterId and shards should be uint16 across all codebase and probably be defined as a type
|
|
|
|
|
|
let topic = toPubsubTopic(
|
|
|
|
|
|
RelayShard(clusterId: node.wakuMetadata.clusterId.uint16, shardId: shard)
|
|
|
|
|
|
)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
let pubsubPeers =
|
|
|
|
|
|
node.wakuRelay.getConnectedPubSubPeers(topic).get(initHashSet[PubSubPeer](0))
|
|
|
|
|
|
let relayPeer = PeersOfShard(
|
|
|
|
|
|
shard: shard, peers: toSeq(pubsubPeers).mapIt(WakuPeer.init(it, node.peerManager))
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(relayPeer, status = Http200).valueOr:
|
|
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
2025-04-24 08:36:02 +02:00
|
|
|
|
return RestApiResponse.internalServerError(
|
2025-04-25 15:36:41 +02:00
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
2024-07-23 12:58:56 +02:00
|
|
|
|
)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
return resp
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
|
|
|
|
|
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"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-06-10 02:10:06 +02:00
|
|
|
|
var meshPeers: PeersOfShards = getMeshPeers(node)
|
2023-11-22 10:56:23 +02:00
|
|
|
|
|
2025-06-10 02:10:06 +02:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(meshPeers, status = Http200).valueOr:
|
2025-04-25 15:36:41 +02:00
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
2025-04-24 08:36:02 +02:00
|
|
|
|
return RestApiResponse.internalServerError(
|
2025-04-25 15:36:41 +02:00
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
2025-04-24 08:36:02 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
return resp
|
2025-04-24 08:36:02 +02:00
|
|
|
|
|
|
|
|
|
|
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}"))
|
|
|
|
|
|
|
2025-07-04 17:10:53 +10:00
|
|
|
|
if node.wakuMetadata.isNil():
|
|
|
|
|
|
return RestApiResponse.serviceUnavailable(
|
|
|
|
|
|
"Error: Metadata Protocol is not mounted to the node"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-24 08:36:02 +02:00
|
|
|
|
if node.wakuRelay.isNil():
|
|
|
|
|
|
return RestApiResponse.serviceUnavailable(
|
|
|
|
|
|
"Error: Relay Protocol is not mounted to the node"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-07-04 17:10:53 +10:00
|
|
|
|
let topic = toPubsubTopic(
|
|
|
|
|
|
RelayShard(clusterId: node.wakuMetadata.clusterId.uint16, shardId: shard)
|
|
|
|
|
|
)
|
2025-04-24 08:36:02 +02:00
|
|
|
|
let peers =
|
|
|
|
|
|
node.wakuRelay.getPubSubPeersInMesh(topic).get(initHashSet[PubSubPeer](0))
|
|
|
|
|
|
let relayPeer = PeersOfShard(
|
|
|
|
|
|
shard: shard, peers: toSeq(peers).mapIt(WakuPeer.init(it, node.peerManager))
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(relayPeer, status = Http200).valueOr:
|
|
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
2024-03-16 00:08:47 +01:00
|
|
|
|
return RestApiResponse.internalServerError(
|
2025-04-25 15:36:41 +02:00
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
2024-03-16 00:08:47 +01:00
|
|
|
|
)
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
2025-04-25 15:36:41 +02:00
|
|
|
|
return resp
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
2025-06-10 02:10:06 +02:00
|
|
|
|
router.api(MethodGet, ROUTE_ADMIN_V1_PEERS_STATS) do() -> RestApiResponse:
|
|
|
|
|
|
let peers = populateAdminPeerInfoForAll(node)
|
|
|
|
|
|
|
|
|
|
|
|
var stats: PeerStats = initOrderedTable[string, OrderedTable[string, int]]()
|
|
|
|
|
|
|
|
|
|
|
|
stats["Sum"] = {"Total peers": peers.len()}.toOrderedTable()
|
|
|
|
|
|
|
|
|
|
|
|
# stats of connectedness
|
|
|
|
|
|
var connectednessStats = initOrderedTable[string, int]()
|
|
|
|
|
|
connectednessStats[$Connectedness.Connected] =
|
|
|
|
|
|
peers.countIt(it.connected == Connectedness.Connected)
|
|
|
|
|
|
connectednessStats[$Connectedness.NotConnected] =
|
|
|
|
|
|
peers.countIt(it.connected == Connectedness.NotConnected)
|
|
|
|
|
|
connectednessStats[$Connectedness.CannotConnect] =
|
|
|
|
|
|
peers.countIt(it.connected == Connectedness.CannotConnect)
|
|
|
|
|
|
connectednessStats[$Connectedness.CanConnect] =
|
|
|
|
|
|
peers.countIt(it.connected == Connectedness.CanConnect)
|
|
|
|
|
|
stats["By Connectedness"] = connectednessStats
|
|
|
|
|
|
|
|
|
|
|
|
# stats of relay peers
|
|
|
|
|
|
var totalRelayPeers = 0
|
|
|
|
|
|
stats["Relay peers"] = block:
|
|
|
|
|
|
let relayPeers = getRelayPeers(node)
|
|
|
|
|
|
var stat = initOrderedTable[string, int]()
|
|
|
|
|
|
for ps in relayPeers:
|
|
|
|
|
|
totalRelayPeers += ps.peers.len
|
|
|
|
|
|
stat[$ps.shard] = ps.peers.len
|
|
|
|
|
|
stat["Total relay peers"] = relayPeers.len
|
|
|
|
|
|
stat
|
|
|
|
|
|
|
|
|
|
|
|
# stats of mesh peers
|
|
|
|
|
|
stats["Mesh peers"] = block:
|
|
|
|
|
|
let meshPeers = getMeshPeers(node)
|
|
|
|
|
|
var totalMeshPeers = 0
|
|
|
|
|
|
var stat = initOrderedTable[string, int]()
|
|
|
|
|
|
for ps in meshPeers:
|
|
|
|
|
|
totalMeshPeers += ps.peers.len
|
|
|
|
|
|
stat[$ps.shard] = ps.peers.len
|
|
|
|
|
|
stat["Total mesh peers"] = meshPeers.len
|
|
|
|
|
|
stat
|
|
|
|
|
|
|
|
|
|
|
|
var protoStats = initOrderedTable[string, int]()
|
|
|
|
|
|
protoStats[WakuRelayCodec] = peers.countIt(it.protocols.contains(WakuRelayCodec))
|
|
|
|
|
|
protoStats[WakuFilterSubscribeCodec] =
|
|
|
|
|
|
peers.countIt(it.protocols.contains(WakuFilterSubscribeCodec))
|
|
|
|
|
|
protoStats[WakuFilterPushCodec] =
|
|
|
|
|
|
peers.countIt(it.protocols.contains(WakuFilterPushCodec))
|
|
|
|
|
|
protoStats[WakuStoreCodec] = peers.countIt(it.protocols.contains(WakuStoreCodec))
|
|
|
|
|
|
protoStats[WakuLegacyStoreCodec] =
|
|
|
|
|
|
peers.countIt(it.protocols.contains(WakuLegacyStoreCodec))
|
|
|
|
|
|
protoStats[WakuLightPushCodec] =
|
|
|
|
|
|
peers.countIt(it.protocols.contains(WakuLightPushCodec))
|
|
|
|
|
|
protoStats[WakuLegacyLightPushCodec] =
|
|
|
|
|
|
peers.countIt(it.protocols.contains(WakuLegacyLightPushCodec))
|
|
|
|
|
|
protoStats[WakuPeerExchangeCodec] =
|
|
|
|
|
|
peers.countIt(it.protocols.contains(WakuPeerExchangeCodec))
|
|
|
|
|
|
protoStats[WakuReconciliationCodec] =
|
|
|
|
|
|
peers.countIt(it.protocols.contains(WakuReconciliationCodec))
|
|
|
|
|
|
|
|
|
|
|
|
stats["By Protocols"] = protoStats
|
|
|
|
|
|
|
|
|
|
|
|
let resp = RestApiResponse.jsonResponse(stats, status = Http200).valueOr:
|
|
|
|
|
|
error "An error occurred while building the json response: ", error = error
|
|
|
|
|
|
return RestApiResponse.internalServerError(
|
|
|
|
|
|
fmt("An error occurred while building the json response: {error}")
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return resp
|
|
|
|
|
|
|
2023-10-05 14:00:09 +02:00
|
|
|
|
proc installAdminV1PostPeersHandler(router: var RestRouter, node: WakuNode) =
|
2024-03-16 00:08:47 +01:00
|
|
|
|
router.api(MethodPost, ROUTE_ADMIN_V1_PEERS) do(
|
|
|
|
|
|
contentBody: Option[ContentBody]
|
|
|
|
|
|
) -> RestApiResponse:
|
2023-10-05 14:00:09 +02:00
|
|
|
|
let peers: seq[string] = decodeRequestBody[seq[string]](contentBody).valueOr:
|
2024-09-09 10:45:14 +02:00
|
|
|
|
let e = $error
|
|
|
|
|
|
return RestApiResponse.badRequest(fmt("Failed to decode request: {e}"))
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
|
|
|
|
|
for i, peer in peers:
|
|
|
|
|
|
let peerInfo = parsePeerInfo(peer).valueOr:
|
2024-09-09 10:45:14 +02:00
|
|
|
|
let e = $error
|
|
|
|
|
|
return RestApiResponse.badRequest(fmt("Couldn't parse remote peer info: {e}"))
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
2024-10-29 18:37:07 +02:00
|
|
|
|
if not (await node.peerManager.connectPeer(peerInfo, source = "rest")):
|
2024-03-16 00:08:47 +01:00
|
|
|
|
return RestApiResponse.badRequest(
|
|
|
|
|
|
fmt("Failed to connect to peer at index: {i} - {peer}")
|
|
|
|
|
|
)
|
2023-10-05 14:00:09 +02:00
|
|
|
|
|
|
|
|
|
|
return RestApiResponse.ok()
|
|
|
|
|
|
|
2024-01-09 11:42:29 +01:00
|
|
|
|
proc installAdminV1GetFilterSubsHandler(router: var RestRouter, node: WakuNode) =
|
2024-03-16 00:08:47 +01:00
|
|
|
|
router.api(MethodGet, ROUTE_ADMIN_V1_FILTER_SUBS) do() -> RestApiResponse:
|
2024-01-09 11:42:29 +01:00
|
|
|
|
if node.wakuFilter.isNil():
|
2024-03-16 00:08:47 +01:00
|
|
|
|
return
|
|
|
|
|
|
RestApiResponse.badRequest("Error: Filter Protocol is not mounted to the node")
|
2024-01-09 11:42:29 +01:00
|
|
|
|
|
|
|
|
|
|
var
|
|
|
|
|
|
subscriptions: seq[FilterSubscription] = @[]
|
|
|
|
|
|
filterCriteria: seq[FilterTopic]
|
|
|
|
|
|
|
2024-01-16 17:27:40 +01:00
|
|
|
|
for peerId in node.wakuFilter.subscriptions.peersSubscribed.keys:
|
2024-03-16 00:08:47 +01:00
|
|
|
|
filterCriteria = node.wakuFilter.subscriptions.getPeerSubscriptions(peerId).mapIt(
|
|
|
|
|
|
FilterTopic(pubsubTopic: it[0], contentTopic: it[1])
|
|
|
|
|
|
)
|
2024-01-09 11:42:29 +01:00
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
|
subscriptions.add(
|
|
|
|
|
|
FilterSubscription(peerId: $peerId, filterCriteria: filterCriteria)
|
|
|
|
|
|
)
|
2024-01-09 11:42:29 +01:00
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
|
let resp = RestApiResponse.jsonResponse(subscriptions, status = Http200)
|
2024-01-09 11:42:29 +01:00
|
|
|
|
if resp.isErr():
|
2024-03-16 00:08:47 +01:00
|
|
|
|
error "An error ocurred while building the json respose: ", error = resp.error
|
|
|
|
|
|
return RestApiResponse.internalServerError(
|
|
|
|
|
|
fmt("An error ocurred while building the json respose: {resp.error}")
|
|
|
|
|
|
)
|
2024-01-09 11:42:29 +01:00
|
|
|
|
|
|
|
|
|
|
return resp.get()
|
|
|
|
|
|
|
2025-06-12 10:50:08 +02:00
|
|
|
|
proc installAdminV1PostLogLevelHandler(router: var RestRouter, node: WakuNode) =
|
|
|
|
|
|
router.api(MethodPost, ROUTE_ADMIN_V1_POST_LOG_LEVEL) do(
|
|
|
|
|
|
logLevel: string
|
|
|
|
|
|
) -> RestApiResponse:
|
|
|
|
|
|
when runtimeFilteringEnabled:
|
|
|
|
|
|
if logLevel.isErr() or logLevel.value().isEmptyOrWhitespace():
|
|
|
|
|
|
return RestApiResponse.badRequest("Invalid log-level, it can’t be empty")
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
let newLogLevel = parseEnum[LogLevel](logLevel.value().capitalizeAscii())
|
|
|
|
|
|
|
|
|
|
|
|
if newLogLevel < enabledLogLevel:
|
|
|
|
|
|
return RestApiResponse.badRequest(
|
|
|
|
|
|
fmt(
|
|
|
|
|
|
"Log level {newLogLevel} is lower than the lowest log level - {enabledLogLevel} - the binary is compiled with."
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
setLogLevel(newLogLevel)
|
|
|
|
|
|
except ValueError:
|
|
|
|
|
|
return RestApiResponse.badRequest(
|
|
|
|
|
|
fmt(
|
|
|
|
|
|
"Invalid log-level: {logLevel.value()}. Please specify one of TRACE, DEBUG, INFO, NOTICE, WARN, ERROR or FATAL"
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return RestApiResponse.ok()
|
|
|
|
|
|
else:
|
|
|
|
|
|
return RestApiResponse.serviceUnavailable(
|
|
|
|
|
|
"Dynamic Log level management is not enabled in this build. Please recompile with `-d:chronicles_runtime_filtering:on`."
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2023-10-05 14:00:09 +02:00
|
|
|
|
proc installAdminApiHandlers*(router: var RestRouter, node: WakuNode) =
|
|
|
|
|
|
installAdminV1GetPeersHandler(router, node)
|
|
|
|
|
|
installAdminV1PostPeersHandler(router, node)
|
2024-01-09 11:42:29 +01:00
|
|
|
|
installAdminV1GetFilterSubsHandler(router, node)
|
2025-06-12 10:50:08 +02:00
|
|
|
|
installAdminV1PostLogLevelHandler(router, node)
|