Fabiana Cecin 1fb4d1eab0
feat: implement Waku API Health spec (#3689)
* Fix protocol strength metric to consider connected peers only
* Remove polling loop; event-driven node connection health updates
* Remove 10s WakuRelay topic health polling loop; now event-driven
* Change NodeHealthStatus to ConnectionStatus
* Change new nodeState (rest API /health) field to connectionStatus
* Add getSyncProtocolHealthInfo and getSyncNodeHealthReport
* Add ConnectionStatusChangeEvent
* Add RequestHealthReport
* Refactor sync/async protocol health queries in the health monitor
* Add EventRelayTopicHealthChange
* Add EventWakuPeer emitted by PeerManager
* Add Edge support for topics health requests and events
* Rename "RelayTopic" -> "Topic"
* Add RequestContentTopicsHealth sync request
* Add EventContentTopicHealthChange
* Rename RequestTopicsHealth -> RequestShardTopicsHealth
* Remove health check gating from checkApiAvailability
* Add basic health smoke tests
* Other misc improvements, refactors, fixes

Co-authored-by: NagyZoltanPeter <113987313+NagyZoltanPeter@users.noreply.github.com>
Co-authored-by: Ivan FB <128452529+Ivansete-status@users.noreply.github.com>
2026-02-12 14:52:39 -03:00

111 lines
3.4 KiB
Nim

{.used.}
import
std/[strutils, sequtils, tempfiles],
stew/byteutils,
chronos,
chronicles,
libp2p/switch,
libp2p/protocols/pubsub/pubsub
from std/times import epochTime
import
waku/[
waku_relay,
node/waku_node,
node/peer_manager,
waku_core,
waku_node,
waku_rln_relay,
common/broker/broker_context,
],
../waku_store/store_utils,
../waku_archive/archive_utils,
../testlib/[wakucore, futures]
proc noopRawHandler*(): WakuRelayHandler =
var handler: WakuRelayHandler
handler = proc(topic: PubsubTopic, msg: WakuMessage): Future[void] {.async, gcsafe.} =
discard
handler
proc newTestWakuRelay*(switch = newTestSwitch()): Future[WakuRelay] {.async.} =
let proto = WakuRelay.new(switch).tryGet()
let protocolMatcher = proc(proto: string): bool {.gcsafe.} =
return proto.startsWith(WakuRelayCodec)
switch.mount(proto, protocolMatcher)
return proto
proc setupRln*(node: WakuNode, identifier: uint) {.async.} =
await node.mountRlnRelay(
WakuRlnConfig(dynamic: false, credIndex: some(identifier), epochSizeSec: 1)
)
proc subscribeToContentTopicWithHandler*(
node: WakuNode, contentTopic: string
): Future[bool] =
var completionFut = newFuture[bool]()
proc relayHandler(
topic: PubsubTopic, msg: WakuMessage
): Future[void] {.async, gcsafe.} =
if topic == topic:
completionFut.complete(true)
(node.subscribe((kind: ContentSub, topic: contentTopic), relayHandler)).isOkOr:
error "Failed to subscribe to content topic", error
completionFut.complete(true)
return completionFut
proc subscribeCompletionHandler*(node: WakuNode, pubsubTopic: string): Future[bool] =
var completionFut = newFuture[bool]()
proc relayHandler(
topic: PubsubTopic, msg: WakuMessage
): Future[void] {.async, gcsafe.} =
if topic == pubsubTopic:
completionFut.complete(true)
(node.subscribe((kind: PubsubSub, topic: pubsubTopic), relayHandler)).isOkOr:
error "Failed to subscribe to pubsub topic", error
completionFut.complete(false)
return completionFut
proc sendRlnMessage*(
client: WakuNode,
pubsubTopic: string,
contentTopic: string,
completionFuture: Future[bool],
payload: seq[byte] = "Hello".toBytes(),
): Future[bool] {.async.} =
var message = WakuMessage(payload: payload, contentTopic: contentTopic)
doAssert(client.wakuRlnRelay.appendRLNProof(message, epochTime()).isOk())
discard await client.publish(some(pubsubTopic), message)
let isCompleted = await completionFuture.withTimeout(FUTURE_TIMEOUT)
return isCompleted
proc sendRlnMessageWithInvalidProof*(
client: WakuNode,
pubsubTopic: string,
contentTopic: string,
completionFuture: Future[bool],
payload: seq[byte] = "Hello".toBytes(),
): Future[bool] {.async.} =
let
extraBytes: seq[byte] = @[byte(1), 2, 3]
rateLimitProofRes = client.wakuRlnRelay.groupManager.generateProof(
concat(payload, extraBytes),
# we add extra bytes to invalidate proof verification against original payload
client.wakuRlnRelay.getCurrentEpoch(),
messageId = MessageId(0),
)
rateLimitProof = rateLimitProofRes.get().encode().buffer
message =
WakuMessage(payload: @payload, contentTopic: contentTopic, proof: rateLimitProof)
discard await client.publish(some(pubsubTopic), message)
let isCompleted = await completionFuture.withTimeout(FUTURE_TIMEOUT)
return isCompleted