2024-06-28 10:34:57 +00:00
{. push raises : [ ] . }
2022-10-18 14:05:53 +00:00
import
2024-05-16 20:29:11 +00:00
std / [ hashes , options , sugar , tables , strutils , sequtils , os , net ] ,
2024-03-15 23:08:47 +00:00
chronos ,
chronicles ,
metrics ,
2024-07-09 11:14:28 +00:00
results ,
2022-10-18 14:05:53 +00:00
stew / byteutils ,
eth / keys ,
nimcrypto ,
bearssl / rand ,
eth / p2p / discoveryv5 / enr ,
libp2p / crypto / crypto ,
libp2p / protocols / ping ,
2022-11-04 09:52:08 +00:00
libp2p / protocols / pubsub / gossipsub ,
libp2p / protocols / pubsub / rpc / messages ,
2023-01-11 09:57:49 +00:00
libp2p / protocols / connectivity / autonat / client ,
libp2p / protocols / connectivity / autonat / service ,
2023-06-01 19:43:10 +00:00
libp2p / protocols / rendezvous ,
2022-11-04 09:52:08 +00:00
libp2p / builders ,
2023-11-16 16:15:27 +00:00
libp2p / transports / transport ,
2022-11-04 09:52:08 +00:00
libp2p / transports / tcptransport ,
libp2p / transports / wstransport
2022-10-18 14:05:53 +00:00
import
2023-04-19 11:29:23 +00:00
.. / waku_core ,
2023-09-26 11:33:52 +00:00
.. / waku_core / topics / sharding ,
2023-04-18 13:22:10 +00:00
.. / waku_relay ,
.. / waku_archive ,
2024-07-12 16:19:12 +00:00
.. / waku_archive_legacy ,
2024-04-25 13:09:52 +00:00
.. / waku_store_legacy / protocol as legacy_store ,
.. / waku_store_legacy / client as legacy_store_client ,
.. / waku_store_legacy / common as legacy_store_common ,
.. / waku_store / protocol as store ,
2023-04-18 13:22:10 +00:00
.. / waku_store / client as store_client ,
2024-04-25 13:09:52 +00:00
.. / waku_store / common as store_common ,
2024-07-30 11:23:39 +00:00
.. / waku_store / resume ,
2023-04-18 13:22:10 +00:00
.. / waku_filter_v2 ,
2023-09-14 19:28:57 +00:00
.. / waku_filter_v2 / client as filter_client ,
2024-01-16 16:27:40 +00:00
.. / waku_filter_v2 / subscriptions as filter_subscriptions ,
2023-10-11 06:58:45 +00:00
.. / waku_metadata ,
2024-08-13 11:27:34 +00:00
.. / waku_sync ,
2023-04-18 13:22:10 +00:00
.. / waku_lightpush / client as lightpush_client ,
2024-01-30 12:28:21 +00:00
.. / waku_lightpush / common ,
.. / waku_lightpush / protocol ,
2024-04-26 10:42:47 +00:00
.. / waku_lightpush / self_req_handler ,
2024-06-13 17:10:00 +00:00
.. / waku_lightpush / callbacks ,
2023-04-18 13:22:10 +00:00
.. / waku_enr ,
.. / waku_peer_exchange ,
2023-09-11 06:32:31 +00:00
.. / waku_rln_relay ,
2023-04-05 07:46:13 +00:00
. / config ,
2024-04-15 13:28:35 +00:00
. / peer_manager ,
2024-07-16 13:46:21 +00:00
.. / common / rate_limit / setting
2022-10-18 14:05:53 +00:00
declarePublicCounter waku_node_messages , " number of messages received " , [ " type " ]
2024-03-15 23:08:47 +00:00
declarePublicHistogram waku_histogram_message_size ,
" message size histogram in kB " ,
2024-03-14 11:38:02 +00:00
buckets = [ 0 .0 , 5 .0 , 15 .0 , 50 .0 , 75 .0 , 100 .0 , 125 .0 , 150 .0 , 300 .0 , 700 .0 , 1000 .0 , Inf ]
2023-04-20 11:45:29 +00:00
2024-03-15 23:08:47 +00:00
declarePublicGauge waku_version ,
" Waku version info (in git describe format) " , [ " version " ]
2022-10-18 14:05:53 +00:00
declarePublicGauge waku_node_errors , " number of wakunode errors " , [ " type " ]
2022-10-28 14:30:01 +00:00
declarePublicGauge waku_lightpush_peers , " number of lightpush peers "
2022-11-02 10:59:58 +00:00
declarePublicGauge waku_filter_peers , " number of filter peers "
2022-10-28 18:11:28 +00:00
declarePublicGauge waku_store_peers , " number of store peers "
2024-03-15 23:08:47 +00:00
declarePublicGauge waku_px_peers ,
" number of peers (in the node ' s peerManager) supporting the peer exchange protocol "
2022-10-28 14:30:01 +00:00
2022-10-18 14:05:53 +00:00
logScope :
2022-11-03 15:36:24 +00:00
topics = " waku node "
2022-10-18 14:05:53 +00:00
2023-04-05 07:46:13 +00:00
# TODO: Move to application instance (e.g., `WakuNode2`)
2022-10-18 14:05:53 +00:00
# Git version in git describe format (defined compile time)
const git_version * {. strdefine . } = " n/a "
# Default clientId
const clientId * = " Nimbus Waku v2 node "
2023-05-12 16:08:41 +00:00
const WakuNodeVersionString * = " version / git commit hash: " & git_version
2022-10-18 14:05:53 +00:00
# key and crypto modules different
type
2023-04-05 07:46:13 +00:00
# TODO: Move to application instance (e.g., `WakuNode2`)
2024-03-15 23:08:47 +00:00
WakuInfo * = object # NOTE One for simplicity, can extend later as needed
2022-10-18 14:05:53 +00:00
listenAddresses * : seq [ string ]
2024-03-15 23:08:47 +00:00
enrUri * : string #multiaddrStrings*: seq[string]
2022-10-18 14:05:53 +00:00
# NOTE based on Eth2Node in NBC eth2_network.nim
2022-10-27 15:29:09 +00:00
WakuNode * = ref object
2022-10-18 14:05:53 +00:00
peerManager * : PeerManager
switch * : Switch
wakuRelay * : WakuRelay
2024-07-12 16:19:12 +00:00
wakuArchive * : waku_archive . WakuArchive
wakuLegacyArchive * : waku_archive_legacy . WakuArchive
2024-04-25 13:09:52 +00:00
wakuLegacyStore * : legacy_store . WakuStore
wakuLegacyStoreClient * : legacy_store_client . WakuStoreClient
wakuStore * : store . WakuStore
wakuStoreClient * : store_client . WakuStoreClient
2024-07-30 11:23:39 +00:00
wakuStoreResume * : StoreResume
2023-04-11 08:12:54 +00:00
wakuFilter * : waku_filter_v2 . WakuFilter
2023-09-14 19:28:57 +00:00
wakuFilterClient * : filter_client . WakuFilterClient
2023-09-11 06:32:31 +00:00
wakuRlnRelay * : WakuRLNRelay
2022-10-18 14:05:53 +00:00
wakuLightPush * : WakuLightPush
2022-10-28 14:30:01 +00:00
wakuLightpushClient * : WakuLightPushClient
2022-10-18 14:05:53 +00:00
wakuPeerExchange * : WakuPeerExchange
2023-10-11 06:58:45 +00:00
wakuMetadata * : WakuMetadata
2024-03-13 09:58:13 +00:00
wakuSharding * : Sharding
2024-08-13 11:27:34 +00:00
wakuSync * : WakuSync
2022-10-18 14:05:53 +00:00
enr * : enr . Record
libp2pPing * : Ping
rng * : ref rand . HmacDrbgContext
2023-06-01 19:43:10 +00:00
rendezvous * : RendezVous
2024-03-15 23:08:47 +00:00
announcedAddresses * : seq [ MultiAddress ]
2022-10-18 14:05:53 +00:00
started * : bool # Indicates that node has started listening
2023-08-23 13:53:17 +00:00
topicSubscriptionQueue * : AsyncEventQueue [ SubscriptionEvent ]
2023-09-26 11:33:52 +00:00
contentTopicHandlers : Table [ ContentTopic , TopicHandler ]
2024-09-18 13:58:07 +00:00
rateLimitSettings * : ProtocolRateLimitSettings
2022-10-18 14:05:53 +00:00
2023-04-05 07:46:13 +00:00
proc getAutonatService * ( rng : ref HmacDrbgContext ) : AutonatService =
2023-01-11 09:57:49 +00:00
## AutonatService request other peers to dial us back
## flagging us as Reachable or NotReachable.
## minConfidence is used as threshold to determine the state.
## If maxQueueSize > numPeersToAsk past samples are considered
## in the calculation.
let autonatService = AutonatService . new (
autonatClient = AutonatClient . new ( ) ,
rng = rng ,
2023-09-22 10:54:23 +00:00
scheduleInterval = Opt . some ( chronos . seconds ( 120 ) ) ,
2023-01-11 09:57:49 +00:00
askNewConnectedPeers = false ,
numPeersToAsk = 3 ,
maxQueueSize = 3 ,
2024-03-15 23:08:47 +00:00
minConfidence = 0 .7 ,
)
2023-01-11 09:57:49 +00:00
2024-03-15 23:08:47 +00:00
proc statusAndConfidenceHandler (
networkReachability : NetworkReachability , confidence : Opt [ float ]
) : Future [ void ] {. gcsafe , async . } =
2023-01-11 09:57:49 +00:00
if confidence . isSome ( ) :
2024-03-15 23:08:47 +00:00
info " Peer reachability status " ,
networkReachability = networkReachability , confidence = confidence . get ( )
2023-01-11 09:57:49 +00:00
autonatService . statusAndConfidenceHandler ( statusAndConfidenceHandler )
2023-02-07 13:06:50 +00:00
return autonatService
2024-03-15 23:08:47 +00:00
proc new * (
T : type WakuNode ,
netConfig : NetConfig ,
enr : enr . Record ,
switch : Switch ,
peerManager : PeerManager ,
# TODO: make this argument required after tests are updated
rng : ref HmacDrbgContext = crypto . newRng ( ) ,
) : T {. raises : [ Defect , LPError , IOError , TLSStreamProtocolError ] . } =
2023-02-07 13:06:50 +00:00
## Creates a Waku Node instance.
2024-03-15 23:08:47 +00:00
info " Initializing networking " , addrs = $ netConfig . announcedAddresses
2022-10-18 14:05:53 +00:00
2024-03-25 14:33:01 +00:00
let queue = newAsyncEventQueue [ SubscriptionEvent ] ( 0 )
2023-08-23 13:53:17 +00:00
2023-10-11 06:58:45 +00:00
let node = WakuNode (
2023-06-23 13:30:28 +00:00
peerManager : peerManager ,
2022-10-18 14:05:53 +00:00
switch : switch ,
rng : rng ,
2023-06-22 20:58:14 +00:00
enr : enr ,
2023-02-07 13:06:50 +00:00
announcedAddresses : netConfig . announcedAddresses ,
2024-03-15 23:08:47 +00:00
topicSubscriptionQueue : queue ,
2024-09-18 13:58:07 +00:00
rateLimitSettings : DefaultProtocolRateLimit ,
2022-10-18 14:05:53 +00:00
)
2023-10-11 06:58:45 +00:00
return node
2022-11-21 08:36:41 +00:00
proc peerInfo * ( node : WakuNode ) : PeerInfo =
2022-10-18 14:05:53 +00:00
node . switch . peerInfo
2023-02-27 15:36:24 +00:00
proc peerId * ( node : WakuNode ) : PeerId =
node . peerInfo . peerId
2023-04-05 07:46:13 +00:00
# TODO: Move to application instance (e.g., `WakuNode2`)
2022-10-27 15:29:09 +00:00
# TODO: Extend with more relevant info: topics, peers, memory usage, online time, etc
proc info * ( node : WakuNode ) : WakuInfo =
## Returns information about the Node, such as what multiaddress it can be reached at.
let peerInfo = node . switch . peerInfo
2022-11-21 08:36:41 +00:00
2024-03-15 23:08:47 +00:00
var listenStr : seq [ string ]
2022-10-27 15:29:09 +00:00
for address in node . announcedAddresses :
var fulladdr = $ address & " /p2p/ " & $ peerInfo . peerId
listenStr & = fulladdr
let enrUri = node . enr . toUri ( )
let wakuInfo = WakuInfo ( listenAddresses : listenStr , enrUri : enrUri )
return wakuInfo
2024-03-15 23:08:47 +00:00
proc connectToNodes * (
node : WakuNode , nodes : seq [ RemotePeerInfo ] | seq [ string ] , source = " api "
) {. async . } =
2022-10-27 15:29:09 +00:00
## `source` indicates source of node addrs (static config, api call, discovery, etc)
2023-03-28 11:29:48 +00:00
# NOTE Connects to the node without a give protocol, which automatically creates streams for relay
2024-03-15 23:08:47 +00:00
await peer_manager . connectToNodes ( node . peerManager , nodes , source = source )
2022-10-27 15:29:09 +00:00
2024-08-13 11:27:34 +00:00
## Waku Sync
proc mountWakuSync * (
node : WakuNode ,
maxFrameSize : int = DefaultMaxFrameSize ,
syncRange : timer . Duration = DefaultSyncRange ,
syncInterval : timer . Duration = DefaultSyncInterval ,
relayJitter : Duration = DefaultGossipSubJitter ,
) : Future [ Result [ void , string ] ] {. async . } =
if not node . wakuSync . isNil ( ) :
return err ( " already mounted " )
node . wakuSync = (
await WakuSync . new (
peerManager = node . peerManager ,
maxFrameSize = maxFrameSize ,
syncRange = syncRange ,
syncInterval = syncInterval ,
relayJitter = relayJitter ,
wakuArchive = node . wakuArchive ,
wakuStoreClient = node . wakuStoreClient ,
)
) . valueOr :
return err ( " initialization failed: " & error )
let catchable = catch :
node . switch . mount ( node . wakuSync , protocolMatcher ( WakuSyncCodec ) )
if catchable . isErr ( ) :
return err ( " switch mounting failed: " & catchable . error . msg )
if node . started :
node . wakuSync . start ( )
return ok ( )
2023-11-21 20:15:39 +00:00
## Waku Metadata
proc mountMetadata * ( node : WakuNode , clusterId : uint32 ) : Result [ void , string ] =
if not node . wakuMetadata . isNil ( ) :
return err ( " Waku metadata already mounted, skipping " )
2024-01-16 16:27:40 +00:00
2023-11-21 20:15:39 +00:00
let metadata = WakuMetadata . new ( clusterId , node . enr , node . topicSubscriptionQueue )
node . wakuMetadata = metadata
node . peerManager . wakuMetadata = metadata
2024-03-15 23:08:47 +00:00
let catchRes = catch :
node . switch . mount ( node . wakuMetadata , protocolMatcher ( WakuMetadataCodec ) )
2023-11-21 20:15:39 +00:00
if catchRes . isErr ( ) :
return err ( catchRes . error . msg )
return ok ( )
2022-10-27 15:29:09 +00:00
2024-03-13 09:58:13 +00:00
## Waku Sharding
2024-03-15 23:08:47 +00:00
proc mountSharding * (
2024-06-05 13:32:35 +00:00
node : WakuNode , clusterId : uint16 , shardCount : uint32
2024-03-15 23:08:47 +00:00
) : Result [ void , string ] =
info " mounting sharding " , clusterId = clusterId , shardCount = shardCount
2024-03-13 09:58:13 +00:00
node . wakuSharding = Sharding ( clusterId : clusterId , shardCountGenZero : shardCount )
return ok ( )
2022-10-27 15:29:09 +00:00
## Waku relay
2023-02-08 15:09:59 +00:00
proc registerRelayDefaultHandler ( node : WakuNode , topic : PubsubTopic ) =
if node . wakuRelay . isSubscribed ( topic ) :
2022-10-18 14:05:53 +00:00
return
2024-06-17 11:14:05 +00:00
proc traceHandler ( topic : PubsubTopic , msg : WakuMessage ) {. async , gcsafe . } =
let msg_hash = topic . computeMessageHash ( msg ) . to0xHex ( )
let msgSizeKB = msg . payload . len / 1000
waku_node_messages . inc ( labelValues = [ " relay " ] )
waku_histogram_message_size . observe ( msgSizeKB )
2023-02-08 15:09:59 +00:00
proc filterHandler ( topic : PubsubTopic , msg : WakuMessage ) {. async , gcsafe . } =
if node . wakuFilter . isNil ( ) :
return
2022-11-21 08:36:41 +00:00
2023-02-08 15:09:59 +00:00
await node . wakuFilter . handleMessage ( topic , msg )
2022-10-18 14:05:53 +00:00
2023-02-08 15:09:59 +00:00
proc archiveHandler ( topic : PubsubTopic , msg : WakuMessage ) {. async , gcsafe . } =
2024-07-12 16:19:12 +00:00
if not node . wakuLegacyArchive . isNil ( ) :
## we try to store with legacy archive
await node . wakuLegacyArchive . handleMessage ( topic , msg )
return
2023-02-08 15:09:59 +00:00
if node . wakuArchive . isNil ( ) :
return
2022-10-18 14:05:53 +00:00
2023-05-25 15:34:34 +00:00
await node . wakuArchive . handleMessage ( topic , msg )
2022-10-18 14:05:53 +00:00
2024-08-13 11:27:34 +00:00
proc syncHandler ( topic : PubsubTopic , msg : WakuMessage ) {. async . } =
if node . wakuSync . isNil ( ) :
return
node . wakuSync . messageIngress ( topic , msg )
2024-03-15 23:08:47 +00:00
let defaultHandler = proc (
topic : PubsubTopic , msg : WakuMessage
) : Future [ void ] {. async , gcsafe . } =
2024-06-17 11:14:05 +00:00
await traceHandler ( topic , msg )
2023-06-06 17:28:47 +00:00
await filterHandler ( topic , msg )
await archiveHandler ( topic , msg )
2024-08-13 11:27:34 +00:00
await syncHandler ( topic , msg )
2023-02-08 15:09:59 +00:00
2023-09-26 11:33:52 +00:00
discard node . wakuRelay . subscribe ( topic , defaultHandler )
2022-10-18 14:05:53 +00:00
2024-03-15 23:08:47 +00:00
proc subscribe * (
node : WakuNode , subscription : SubscriptionEvent , handler = none ( WakuRelayHandler )
) =
2023-09-26 11:33:52 +00:00
## Subscribes to a PubSub or Content topic. Triggers handler when receiving messages on
## this topic. WakuRelayHandler is a method that takes a topic and a Waku message.
2023-10-02 13:38:40 +00:00
2023-02-08 15:09:59 +00:00
if node . wakuRelay . isNil ( ) :
error " Invalid API call to `subscribe`. WakuRelay not mounted. "
return
2023-09-26 11:33:52 +00:00
let ( pubsubTopic , contentTopicOp ) =
2024-03-15 23:08:47 +00:00
case subscription . kind
of ContentSub :
let shard = node . wakuSharding . getShard ( ( subscription . topic ) ) . valueOr :
error " Autosharding error " , error = error
return
2023-09-26 11:33:52 +00:00
2024-09-10 21:07:12 +00:00
( $ shard , some ( subscription . topic ) )
2024-03-15 23:08:47 +00:00
of PubsubSub :
( subscription . topic , none ( ContentTopic ) )
else :
return
2023-10-02 13:38:40 +00:00
2023-09-26 11:33:52 +00:00
if contentTopicOp . isSome ( ) and node . contentTopicHandlers . hasKey ( contentTopicOp . get ( ) ) :
error " Invalid API call to `subscribe`. Was already subscribed "
2023-02-08 15:09:59 +00:00
return
2024-03-15 23:08:47 +00:00
debug " subscribe " , pubsubTopic = pubsubTopic
2023-09-26 11:33:52 +00:00
node . topicSubscriptionQueue . emit ( ( kind : PubsubSub , topic : pubsubTopic ) )
node . registerRelayDefaultHandler ( pubsubTopic )
2022-10-18 14:05:53 +00:00
2023-09-26 11:33:52 +00:00
if handler . isSome ( ) :
let wrappedHandler = node . wakuRelay . subscribe ( pubsubTopic , handler . get ( ) )
2023-02-08 15:09:59 +00:00
2023-09-26 11:33:52 +00:00
if contentTopicOp . isSome ( ) :
node . contentTopicHandlers [ contentTopicOp . get ( ) ] = wrappedHandler
2022-11-21 08:36:41 +00:00
2023-09-26 11:33:52 +00:00
proc unsubscribe * ( node : WakuNode , subscription : SubscriptionEvent ) =
## Unsubscribes from a specific PubSub or Content topic.
2023-10-02 13:38:40 +00:00
2022-10-27 15:29:09 +00:00
if node . wakuRelay . isNil ( ) :
2023-06-06 17:28:47 +00:00
error " Invalid API call to `unsubscribe`. WakuRelay not mounted. "
2022-10-18 14:05:53 +00:00
return
2022-11-21 08:36:41 +00:00
2023-09-26 11:33:52 +00:00
let ( pubsubTopic , contentTopicOp ) =
2024-03-15 23:08:47 +00:00
case subscription . kind
of ContentUnsub :
let shard = node . wakuSharding . getShard ( ( subscription . topic ) ) . valueOr :
error " Autosharding error " , error = error
return
2022-10-18 14:05:53 +00:00
2024-09-10 21:07:12 +00:00
( $ shard , some ( subscription . topic ) )
2024-03-15 23:08:47 +00:00
of PubsubUnsub :
( subscription . topic , none ( ContentTopic ) )
else :
return
2023-02-08 15:09:59 +00:00
2023-09-26 11:33:52 +00:00
if not node . wakuRelay . isSubscribed ( pubsubTopic ) :
error " Invalid API call to `unsubscribe`. Was not subscribed "
return
2022-11-21 08:36:41 +00:00
2023-09-26 11:33:52 +00:00
if contentTopicOp . isSome ( ) :
# Remove this handler only
var handler : TopicHandler
if node . contentTopicHandlers . pop ( contentTopicOp . get ( ) , handler ) :
2024-03-15 23:08:47 +00:00
debug " unsubscribe " , contentTopic = contentTopicOp . get ( )
2023-09-26 11:33:52 +00:00
node . wakuRelay . unsubscribe ( pubsubTopic , handler )
if contentTopicOp . isNone ( ) or node . wakuRelay . topics . getOrDefault ( pubsubTopic ) . len = = 1 :
# Remove all handlers
2024-03-15 23:08:47 +00:00
debug " unsubscribe " , pubsubTopic = pubsubTopic
2023-09-26 11:33:52 +00:00
node . wakuRelay . unsubscribeAll ( pubsubTopic )
node . topicSubscriptionQueue . emit ( ( kind : PubsubUnsub , topic : pubsubTopic ) )
proc publish * (
2024-03-15 23:08:47 +00:00
node : WakuNode , pubsubTopicOp : Option [ PubsubTopic ] , message : WakuMessage
) : Future [ Result [ void , string ] ] {. async , gcsafe . } =
2023-09-26 11:33:52 +00:00
## Publish a `WakuMessage`. Pubsub topic contains; none, a named or static shard.
## `WakuMessage` should contain a `contentTopic` field for light node functionality.
## It is also used to determine the shard.
2022-11-21 08:36:41 +00:00
2022-10-25 12:55:31 +00:00
if node . wakuRelay . isNil ( ) :
2024-03-15 23:08:47 +00:00
let msg =
" Invalid API call to `publish`. WakuRelay not mounted. Try `lightpush` instead. "
2024-08-14 14:40:08 +00:00
error " publish error " , err = msg
2022-10-25 12:55:31 +00:00
# TODO: Improve error handling
2024-01-18 12:49:13 +00:00
return err ( msg )
2022-10-18 14:05:53 +00:00
2023-09-26 11:33:52 +00:00
let pubsubTopic = pubsubTopicOp . valueOr :
2024-03-13 09:58:13 +00:00
node . wakuSharding . getShard ( message . contentTopic ) . valueOr :
2024-01-18 12:49:13 +00:00
let msg = " Autosharding error: " & error
2024-08-14 14:40:08 +00:00
error " publish error " , err = msg
2024-01-18 12:49:13 +00:00
return err ( msg )
2023-09-26 11:33:52 +00:00
#TODO instead of discard return error when 0 peers received the message
discard await node . wakuRelay . publish ( pubsubTopic , message )
2022-10-18 14:05:53 +00:00
2024-06-10 13:56:55 +00:00
notice " waku.relay published " ,
2024-03-15 23:08:47 +00:00
peerId = node . peerId ,
pubsubTopic = pubsubTopic ,
2024-06-10 13:56:55 +00:00
msg_hash = pubsubTopic . computeMessageHash ( message ) . to0xHex ( ) ,
2024-03-15 23:08:47 +00:00
publishTime = getNowInNanosecondTime ( )
2024-01-18 12:49:13 +00:00
return ok ( )
2023-02-03 08:06:21 +00:00
2022-10-27 15:29:09 +00:00
proc startRelay * ( node : WakuNode ) {. async . } =
2022-11-18 13:50:56 +00:00
## Setup and start relay protocol
info " starting relay protocol "
2022-10-27 15:29:09 +00:00
if node . wakuRelay . isNil ( ) :
2023-02-08 15:09:59 +00:00
error " Failed to start relay. Not mounted. "
2022-10-27 15:29:09 +00:00
return
2022-10-18 14:05:53 +00:00
2022-11-18 13:50:56 +00:00
## Setup relay protocol
2022-11-21 08:36:41 +00:00
2022-10-27 15:29:09 +00:00
# Resume previous relay connections
2022-11-24 13:11:23 +00:00
if node . peerManager . peerStore . hasPeers ( protocolMatcher ( WakuRelayCodec ) ) :
2022-10-27 15:29:09 +00:00
info " Found previous WakuRelay peers. Reconnecting. "
2022-11-21 08:36:41 +00:00
2022-10-27 15:29:09 +00:00
# Reconnect to previous relay peers. This will respect a backoff period, if necessary
2024-03-15 23:08:47 +00:00
let backoffPeriod =
node . wakuRelay . parameters . pruneBackoff + chronos . seconds ( BackoffSlackTime )
2022-10-18 14:05:53 +00:00
2024-03-15 23:08:47 +00:00
await node . peerManager . reconnectPeers ( WakuRelayCodec , backoffPeriod )
2022-11-21 08:36:41 +00:00
2022-10-27 15:29:09 +00:00
# Start the WakuRelay protocol
await node . wakuRelay . start ( )
2022-10-18 14:05:53 +00:00
2022-10-27 15:29:09 +00:00
info " relay started successfully "
2022-10-18 14:05:53 +00:00
2024-03-15 23:08:47 +00:00
proc mountRelay * (
node : WakuNode ,
2024-09-10 21:07:12 +00:00
shards : seq [ RelayShard ] = @ [ ] ,
2024-03-15 23:08:47 +00:00
peerExchangeHandler = none ( RoutingRecordsHandler ) ,
2024-04-20 03:40:52 +00:00
maxMessageSize = int ( DefaultMaxWakuMessageSize ) ,
2024-03-15 23:08:47 +00:00
) {. async , gcsafe . } =
2023-04-05 13:12:49 +00:00
if not node . wakuRelay . isNil ( ) :
error " wakuRelay already mounted, skipping "
return
2022-11-18 13:50:56 +00:00
## The default relay topics is the union of all configured topics plus default PubsubTopic(s)
info " mounting relay protocol "
2022-11-21 08:36:41 +00:00
2024-01-03 12:11:50 +00:00
let initRes = WakuRelay . new ( node . switch , maxMessageSize )
2022-11-18 13:50:56 +00:00
if initRes . isErr ( ) :
2024-03-15 23:08:47 +00:00
error " failed mounting relay protocol " , error = initRes . error
2022-11-18 13:50:56 +00:00
return
2022-10-18 14:05:53 +00:00
2022-11-18 13:50:56 +00:00
node . wakuRelay = initRes . value
2022-10-27 15:29:09 +00:00
## Add peer exchange handler
if peerExchangeHandler . isSome ( ) :
2024-03-15 23:08:47 +00:00
node . wakuRelay . parameters . enablePX = true
# Feature flag for peer exchange in nim-libp2p
2022-11-18 13:50:56 +00:00
node . wakuRelay . routingRecordsHandler . add ( peerExchangeHandler . get ( ) )
2022-10-27 15:29:09 +00:00
if node . started :
await node . startRelay ( )
2022-11-18 13:50:56 +00:00
node . switch . mount ( node . wakuRelay , protocolMatcher ( WakuRelayCodec ) )
2024-09-10 21:07:12 +00:00
info " relay mounted successfully " , shards = shards
2022-10-18 14:05:53 +00:00
2024-09-10 21:07:12 +00:00
# Subscribe to shards
for shard in shards :
node . subscribe ( ( kind : PubsubSub , topic : $ shard ) )
2023-02-10 14:17:50 +00:00
2022-10-27 15:29:09 +00:00
## Waku filter
2022-10-18 14:05:53 +00:00
2024-03-15 23:08:47 +00:00
proc mountFilter * (
node : WakuNode ,
subscriptionTimeout : Duration =
filter_subscriptions . DefaultSubscriptionTimeToLiveSec ,
maxFilterPeers : uint32 = filter_subscriptions . MaxFilterPeers ,
maxFilterCriteriaPerPeer : uint32 = filter_subscriptions . MaxFilterCriteriaPerPeer ,
2024-06-28 12:46:06 +00:00
messageCacheTTL : Duration = filter_subscriptions . MessageCacheTTL ,
2024-09-18 13:58:07 +00:00
rateLimitSetting : RateLimitSetting = FilterDefaultPerPeerRateLimit ,
2024-05-16 20:29:11 +00:00
) {. async : ( raises : [ ] ) . } =
2024-01-16 16:27:40 +00:00
## Mounting filter v2 protocol
2022-11-02 10:59:58 +00:00
info " mounting filter protocol "
2024-03-15 23:08:47 +00:00
node . wakuFilter = WakuFilter . new (
2024-07-16 13:46:21 +00:00
node . peerManager ,
subscriptionTimeout ,
maxFilterPeers ,
maxFilterCriteriaPerPeer ,
2024-06-28 12:46:06 +00:00
messageCacheTTL ,
2024-07-16 13:46:21 +00:00
some ( rateLimitSetting ) ,
2024-03-15 23:08:47 +00:00
)
2022-10-18 14:05:53 +00:00
if node . started :
2024-05-16 20:29:11 +00:00
try :
await node . wakuFilter . start ( )
except CatchableError :
error " failed to start wakuFilter " , error = getCurrentExceptionMsg ( )
2022-10-18 14:05:53 +00:00
2024-05-16 20:29:11 +00:00
try :
node . switch . mount ( node . wakuFilter , protocolMatcher ( WakuFilterSubscribeCodec ) )
except LPError :
error " failed to mount wakuFilter " , error = getCurrentExceptionMsg ( )
2023-09-14 19:28:57 +00:00
2024-03-15 23:08:47 +00:00
proc filterHandleMessage * (
node : WakuNode , pubsubTopic : PubsubTopic , message : WakuMessage
) {. async . } =
2024-03-25 18:07:56 +00:00
if node . wakuFilter . isNil ( ) :
2024-04-17 19:48:20 +00:00
error " cannot handle filter message " , error = " waku filter is required "
2022-10-27 15:29:09 +00:00
return
2024-03-25 18:07:56 +00:00
await node . wakuFilter . handleMessage ( pubsubTopic , message )
2022-10-27 15:29:09 +00:00
2024-05-16 20:29:11 +00:00
proc mountFilterClient * ( node : WakuNode ) {. async : ( raises : [ ] ) . } =
2024-03-25 18:07:56 +00:00
## Mounting both filter
2023-11-30 10:08:08 +00:00
## Giving option for application level to choose btw own push message handling or
2023-09-14 19:28:57 +00:00
## rely on node provided cache. - This only applies for v2 filter client
2022-11-02 10:59:58 +00:00
info " mounting filter client "
2023-09-14 19:28:57 +00:00
node . wakuFilterClient = WakuFilterClient . new ( node . peerManager , node . rng )
2022-11-02 10:59:58 +00:00
if node . started :
2024-05-16 20:29:11 +00:00
try :
await node . wakuFilterClient . start ( )
except CatchableError :
error " failed to start wakuFilterClient " , error = getCurrentExceptionMsg ( )
2022-11-02 10:59:58 +00:00
2024-05-16 20:29:11 +00:00
try :
node . switch . mount ( node . wakuFilterClient , protocolMatcher ( WakuFilterSubscribeCodec ) )
except LPError :
error " failed to mount wakuFilterClient " , error = getCurrentExceptionMsg ( )
2024-03-15 23:08:47 +00:00
proc filterSubscribe * (
node : WakuNode ,
pubsubTopic : Option [ PubsubTopic ] ,
contentTopics : ContentTopic | seq [ ContentTopic ] ,
peer : RemotePeerInfo | string ,
2024-05-16 20:29:11 +00:00
) : Future [ FilterSubscribeResult ] {. async : ( raises : [ ] ) . } =
2023-09-14 19:28:57 +00:00
## Registers for messages that match a specific filter. Triggers the handler whenever a message is received.
if node . wakuFilterClient . isNil ( ) :
2024-03-15 23:08:47 +00:00
error " cannot register filter subscription to topic " ,
error = " waku filter client is not set up "
2023-09-14 19:28:57 +00:00
return err ( FilterSubscribeError . serviceUnavailable ( ) )
let remotePeerRes = parsePeerInfo ( peer )
if remotePeerRes . isErr ( ) :
error " Couldn ' t parse the peer info properly " , error = remotePeerRes . error
return err ( FilterSubscribeError . serviceUnavailable ( " No peers available " ) )
let remotePeer = remotePeerRes . value
if pubsubTopic . isSome ( ) :
2024-03-15 23:08:47 +00:00
info " registering filter subscription to content " ,
pubsubTopic = pubsubTopic . get ( ) ,
contentTopics = contentTopics ,
peer = remotePeer . peerId
2024-03-19 15:18:52 +00:00
when ( contentTopics is ContentTopic ) :
let contentTopics = @ [ contentTopics ]
2024-03-15 23:08:47 +00:00
let subRes = await node . wakuFilterClient . subscribe (
remotePeer , pubsubTopic . get ( ) , contentTopics
)
2023-09-14 19:28:57 +00:00
if subRes . isOk ( ) :
2024-03-15 23:08:47 +00:00
info " v2 subscribed to topic " ,
pubsubTopic = pubsubTopic , contentTopics = contentTopics
2024-03-01 13:01:37 +00:00
# Purpose is to update Waku Metadata
node . topicSubscriptionQueue . emit ( ( kind : PubsubSub , topic : pubsubTopic . get ( ) ) )
2023-09-14 19:28:57 +00:00
else :
2024-03-15 23:08:47 +00:00
error " failed filter v2 subscription " , error = subRes . error
2023-09-14 19:28:57 +00:00
waku_node_errors . inc ( labelValues = [ " subscribe_filter_failure " ] )
return subRes
else :
2024-03-13 09:58:13 +00:00
let topicMapRes = node . wakuSharding . parseSharding ( pubsubTopic , contentTopics )
2023-09-14 19:28:57 +00:00
let topicMap =
if topicMapRes . isErr ( ) :
2024-03-15 23:08:47 +00:00
error " can ' t get shard " , error = topicMapRes . error
2023-09-14 19:28:57 +00:00
return err ( FilterSubscribeError . badResponse ( " can ' t get shard " ) )
2024-03-15 23:08:47 +00:00
else :
topicMapRes . get ( )
2023-09-14 19:28:57 +00:00
var futures = collect ( newSeq ) :
for pubsub , topics in topicMap . pairs :
2024-03-15 23:08:47 +00:00
info " registering filter subscription to content " ,
pubsubTopic = pubsub , contentTopics = topics , peer = remotePeer . peerId
2023-09-14 19:28:57 +00:00
let content = topics . mapIt ( $ it )
node . wakuFilterClient . subscribe ( remotePeer , $ pubsub , content )
var subRes : FilterSubscribeResult = FilterSubscribeResult . ok ( )
2024-05-16 20:29:11 +00:00
try :
let finished = await allFinished ( futures )
2023-08-17 12:11:18 +00:00
2024-05-16 20:29:11 +00:00
for fut in finished :
let res = fut . read ( )
2023-08-17 12:11:18 +00:00
2024-05-16 20:29:11 +00:00
if res . isErr ( ) :
error " failed filter subscription " , error = res . error
waku_node_errors . inc ( labelValues = [ " subscribe_filter_failure " ] )
subRes = FilterSubscribeResult . err ( res . error )
2022-10-27 15:29:09 +00:00
2024-05-16 20:29:11 +00:00
for pubsub , topics in topicMap . pairs :
info " subscribed to topic " , pubsubTopic = pubsub , contentTopics = topics
# Purpose is to update Waku Metadata
node . topicSubscriptionQueue . emit ( ( kind : PubsubSub , topic : $ pubsub ) )
except CatchableError :
let errMsg = " exception in filterSubscribe: " & getCurrentExceptionMsg ( )
error " exception in filterSubscribe " , error = getCurrentExceptionMsg ( )
waku_node_errors . inc ( labelValues = [ " subscribe_filter_failure " ] )
subRes =
FilterSubscribeResult . err ( FilterSubscribeError . serviceUnavailable ( errMsg ) )
2024-03-01 13:01:37 +00:00
2023-09-14 19:28:57 +00:00
# return the last error or ok
return subRes
2024-03-15 23:08:47 +00:00
proc filterUnsubscribe * (
node : WakuNode ,
pubsubTopic : Option [ PubsubTopic ] ,
2024-04-17 19:48:20 +00:00
contentTopics : ContentTopic | seq [ ContentTopic ] ,
2024-03-15 23:08:47 +00:00
peer : RemotePeerInfo | string ,
2024-05-16 20:29:11 +00:00
) : Future [ FilterSubscribeResult ] {. async : ( raises : [ ] ) . } =
2023-09-14 19:28:57 +00:00
## Unsubscribe from a content filter V2".
2022-11-21 08:36:41 +00:00
2023-09-14 19:28:57 +00:00
let remotePeerRes = parsePeerInfo ( peer )
if remotePeerRes . isErr ( ) :
error " couldn ' t parse remotePeerInfo " , error = remotePeerRes . error
return err ( FilterSubscribeError . serviceUnavailable ( " No peers available " ) )
let remotePeer = remotePeerRes . value
if pubsubTopic . isSome ( ) :
2024-03-15 23:08:47 +00:00
info " deregistering filter subscription to content " ,
pubsubTopic = pubsubTopic . get ( ) ,
contentTopics = contentTopics ,
peer = remotePeer . peerId
let unsubRes = await node . wakuFilterClient . unsubscribe (
remotePeer , pubsubTopic . get ( ) , contentTopics
)
2023-09-14 19:28:57 +00:00
if unsubRes . isOk ( ) :
2024-03-15 23:08:47 +00:00
info " unsubscribed from topic " ,
pubsubTopic = pubsubTopic . get ( ) , contentTopics = contentTopics
2024-03-01 13:01:37 +00:00
# Purpose is to update Waku Metadata
node . topicSubscriptionQueue . emit ( ( kind : PubsubUnsub , topic : pubsubTopic . get ( ) ) )
2023-09-14 19:28:57 +00:00
else :
2024-03-15 23:08:47 +00:00
error " failed filter unsubscription " , error = unsubRes . error
2023-09-14 19:28:57 +00:00
waku_node_errors . inc ( labelValues = [ " unsubscribe_filter_failure " ] )
return unsubRes
else : # pubsubTopic.isNone
2024-03-13 09:58:13 +00:00
let topicMapRes = node . wakuSharding . parseSharding ( pubsubTopic , contentTopics )
2023-09-14 19:28:57 +00:00
let topicMap =
if topicMapRes . isErr ( ) :
error " can ' t get shard " , error = topicMapRes . error
return err ( FilterSubscribeError . badResponse ( " can ' t get shard " ) )
2024-03-15 23:08:47 +00:00
else :
topicMapRes . get ( )
2022-11-21 08:36:41 +00:00
2023-09-14 19:28:57 +00:00
var futures = collect ( newSeq ) :
for pubsub , topics in topicMap . pairs :
2024-03-15 23:08:47 +00:00
info " deregistering filter subscription to content " ,
pubsubTopic = pubsub , contentTopics = topics , peer = remotePeer . peerId
2023-09-14 19:28:57 +00:00
let content = topics . mapIt ( $ it )
node . wakuFilterClient . unsubscribe ( remotePeer , $ pubsub , content )
2022-11-02 10:59:58 +00:00
2023-09-14 19:28:57 +00:00
var unsubRes : FilterSubscribeResult = FilterSubscribeResult . ok ( )
2024-05-16 20:29:11 +00:00
try :
let finished = await allFinished ( futures )
2023-09-14 19:28:57 +00:00
2024-05-16 20:29:11 +00:00
for fut in finished :
let res = fut . read ( )
2023-09-14 19:28:57 +00:00
2024-05-16 20:29:11 +00:00
if res . isErr ( ) :
error " failed filter unsubscription " , error = res . error
waku_node_errors . inc ( labelValues = [ " unsubscribe_filter_failure " ] )
unsubRes = FilterSubscribeResult . err ( res . error )
2023-09-14 19:28:57 +00:00
2024-05-16 20:29:11 +00:00
for pubsub , topics in topicMap . pairs :
info " unsubscribed from topic " , pubsubTopic = pubsub , contentTopics = topics
# Purpose is to update Waku Metadata
node . topicSubscriptionQueue . emit ( ( kind : PubsubUnsub , topic : $ pubsub ) )
except CatchableError :
let errMsg = " exception in filterUnsubscribe: " & getCurrentExceptionMsg ( )
error " exception in filterUnsubscribe " , error = getCurrentExceptionMsg ( )
waku_node_errors . inc ( labelValues = [ " unsubscribe_filter_failure " ] )
unsubRes =
FilterSubscribeResult . err ( FilterSubscribeError . serviceUnavailable ( errMsg ) )
2024-03-01 13:01:37 +00:00
2023-09-14 19:28:57 +00:00
# return the last error or ok
return unsubRes
2024-03-15 23:08:47 +00:00
proc filterUnsubscribeAll * (
node : WakuNode , peer : RemotePeerInfo | string
2024-05-16 20:29:11 +00:00
) : Future [ FilterSubscribeResult ] {. async : ( raises : [ ] ) . } =
2023-09-14 19:28:57 +00:00
## Unsubscribe from a content filter V2".
2022-11-21 08:36:41 +00:00
2023-09-14 19:28:57 +00:00
let remotePeerRes = parsePeerInfo ( peer )
if remotePeerRes . isErr ( ) :
error " couldn ' t parse remotePeerInfo " , error = remotePeerRes . error
return err ( FilterSubscribeError . serviceUnavailable ( " No peers available " ) )
let remotePeer = remotePeerRes . value
2024-03-15 23:08:47 +00:00
info " deregistering all filter subscription to content " , peer = remotePeer . peerId
2023-09-14 19:28:57 +00:00
let unsubRes = await node . wakuFilterClient . unsubscribeAll ( remotePeer )
if unsubRes . isOk ( ) :
2024-03-15 23:08:47 +00:00
info " unsubscribed from all content-topic " , peerId = remotePeer . peerId
2023-09-14 19:28:57 +00:00
else :
2024-03-15 23:08:47 +00:00
error " failed filter unsubscription from all content-topic " , error = unsubRes . error
2023-09-14 19:28:57 +00:00
waku_node_errors . inc ( labelValues = [ " unsubscribe_filter_failure " ] )
return unsubRes
2022-10-27 15:29:09 +00:00
2023-09-14 19:28:57 +00:00
# NOTICE: subscribe / unsubscribe methods are removed - they were already depricated
# yet incompatible to handle both type of filters - use specific filter registration instead
2022-10-27 15:29:09 +00:00
2022-11-23 09:08:00 +00:00
## Waku archive
2024-03-15 23:08:47 +00:00
proc mountArchive * (
2024-07-12 16:19:12 +00:00
node : WakuNode ,
driver : waku_archive . ArchiveDriver ,
retentionPolicy = none ( waku_archive . RetentionPolicy ) ,
2024-03-15 23:08:47 +00:00
) : Result [ void , string ] =
2024-07-12 16:19:12 +00:00
node . wakuArchive = waku_archive . WakuArchive . new (
driver = driver , retentionPolicy = retentionPolicy
) . valueOr :
2024-03-12 11:51:03 +00:00
return err ( " error in mountArchive: " & error )
2022-10-18 14:05:53 +00:00
2024-03-12 11:51:03 +00:00
node . wakuArchive . start ( )
2022-10-18 14:05:53 +00:00
2023-06-27 11:24:31 +00:00
return ok ( )
2022-10-18 14:05:53 +00:00
2024-07-12 16:19:12 +00:00
proc mountLegacyArchive * (
2024-07-30 12:05:23 +00:00
node : WakuNode , driver : waku_archive_legacy . ArchiveDriver
2024-07-12 16:19:12 +00:00
) : Result [ void , string ] =
2024-07-30 12:05:23 +00:00
node . wakuLegacyArchive = waku_archive_legacy . WakuArchive . new ( driver = driver ) . valueOr :
2024-07-12 16:19:12 +00:00
return err ( " error in mountLegacyArchive: " & error )
return ok ( )
2024-04-25 13:09:52 +00:00
## Legacy Waku Store
2022-11-23 09:08:00 +00:00
# TODO: Review this mapping logic. Maybe, move it to the appplication code
2024-07-12 16:19:12 +00:00
proc toArchiveQuery (
request : legacy_store_common . HistoryQuery
) : waku_archive_legacy . ArchiveQuery =
waku_archive_legacy . ArchiveQuery (
2022-11-23 09:08:00 +00:00
pubsubTopic : request . pubsubTopic ,
contentTopics : request . contentTopics ,
2024-03-15 23:08:47 +00:00
cursor : request . cursor . map (
2024-07-12 16:19:12 +00:00
proc ( cursor : HistoryCursor ) : waku_archive_legacy . ArchiveCursor =
waku_archive_legacy . ArchiveCursor (
2024-03-15 23:08:47 +00:00
pubsubTopic : cursor . pubsubTopic ,
senderTime : cursor . senderTime ,
storeTime : cursor . storeTime ,
digest : cursor . digest ,
)
) ,
2022-11-23 09:08:00 +00:00
startTime : request . startTime ,
endTime : request . endTime ,
pageSize : request . pageSize . uint ,
2024-03-15 23:08:47 +00:00
direction : request . direction ,
2024-08-29 20:56:14 +00:00
requestId : request . requestId ,
2022-10-18 14:05:53 +00:00
)
2022-11-23 09:08:00 +00:00
# TODO: Review this mapping logic. Maybe, move it to the appplication code
2024-07-12 16:19:12 +00:00
proc toHistoryResult * (
res : waku_archive_legacy . ArchiveResult
) : legacy_store_common . HistoryResult =
2022-11-23 09:08:00 +00:00
if res . isErr ( ) :
let error = res . error
2024-03-15 23:08:47 +00:00
case res . error . kind
2024-07-12 16:19:12 +00:00
of waku_archive_legacy . ArchiveErrorKind . DRIVER_ERROR ,
waku_archive_legacy . ArchiveErrorKind . INVALID_QUERY :
2024-03-15 23:08:47 +00:00
err ( HistoryError ( kind : HistoryErrorKind . BAD_REQUEST , cause : res . error . cause ) )
2022-11-23 09:08:00 +00:00
else :
err ( HistoryError ( kind : HistoryErrorKind . UNKNOWN ) )
else :
let response = res . get ( )
2024-03-15 23:08:47 +00:00
ok (
HistoryResponse (
messages : response . messages ,
cursor : response . cursor . map (
2024-07-12 16:19:12 +00:00
proc ( cursor : waku_archive_legacy . ArchiveCursor ) : HistoryCursor =
2024-03-15 23:08:47 +00:00
HistoryCursor (
pubsubTopic : cursor . pubsubTopic ,
senderTime : cursor . senderTime ,
storeTime : cursor . storeTime ,
digest : cursor . digest ,
)
) ,
)
)
2022-11-23 09:08:00 +00:00
2024-04-25 13:09:52 +00:00
proc mountLegacyStore * (
2024-04-15 13:28:35 +00:00
node : WakuNode , rateLimit : RateLimitSetting = DefaultGlobalNonRelayRateLimit
2024-04-25 13:09:52 +00:00
) {. async . } =
info " mounting waku legacy store protocol "
2022-11-23 09:08:00 +00:00
2024-07-12 16:19:12 +00:00
if node . wakuLegacyArchive . isNil ( ) :
2024-04-25 13:09:52 +00:00
error " failed to mount waku legacy store protocol " , error = " waku archive not set "
2022-11-23 09:08:00 +00:00
return
# TODO: Review this handler logic. Maybe, move it to the appplication code
2024-03-15 23:08:47 +00:00
let queryHandler : HistoryQueryHandler = proc (
request : HistoryQuery
2024-04-25 13:09:52 +00:00
) : Future [ legacy_store_common . HistoryResult ] {. async . } =
2024-03-15 23:08:47 +00:00
if request . cursor . isSome ( ) :
request . cursor . get ( ) . checkHistCursor ( ) . isOkOr :
return err ( error )
2023-11-22 08:32:39 +00:00
2024-03-15 23:08:47 +00:00
let request = request . toArchiveQuery ( )
2024-07-12 16:19:12 +00:00
let response = await node . wakuLegacyArchive . findMessagesV2 ( request )
2024-03-15 23:08:47 +00:00
return response . toHistoryResult ( )
2022-11-23 09:08:00 +00:00
2024-04-25 13:09:52 +00:00
node . wakuLegacyStore = legacy_store . WakuStore . new (
node . peerManager , node . rng , queryHandler , some ( rateLimit )
)
2022-11-23 09:08:00 +00:00
2022-10-18 14:05:53 +00:00
if node . started :
# Node has started already. Let's start store too.
2024-04-25 13:09:52 +00:00
await node . wakuLegacyStore . start ( )
2022-10-18 14:05:53 +00:00
2024-04-25 13:09:52 +00:00
node . switch . mount (
2024-05-09 18:07:49 +00:00
node . wakuLegacyStore , protocolMatcher ( legacy_store_common . WakuLegacyStoreCodec )
2024-04-25 13:09:52 +00:00
)
2022-10-18 14:05:53 +00:00
2024-04-25 13:09:52 +00:00
proc mountLegacyStoreClient * ( node : WakuNode ) =
info " mounting legacy store client "
2022-11-02 10:59:58 +00:00
2024-04-25 13:09:52 +00:00
node . wakuLegacyStoreClient =
legacy_store_client . WakuStoreClient . new ( node . peerManager , node . rng )
2022-11-02 10:59:58 +00:00
2024-03-15 23:08:47 +00:00
proc query * (
2024-04-25 13:09:52 +00:00
node : WakuNode , query : legacy_store_common . HistoryQuery , peer : RemotePeerInfo
) : Future [ legacy_store_common . WakuStoreResult [ legacy_store_common . HistoryResponse ] ] {.
async , gcsafe
. } =
2022-10-28 18:11:28 +00:00
## Queries known nodes for historical messages
2024-04-25 13:09:52 +00:00
if node . wakuLegacyStoreClient . isNil ( ) :
return err ( " waku legacy store client is nil " )
2022-10-28 18:11:28 +00:00
2024-04-25 13:09:52 +00:00
let queryRes = await node . wakuLegacyStoreClient . query ( query , peer )
2022-10-28 18:11:28 +00:00
if queryRes . isErr ( ) :
2024-04-25 13:09:52 +00:00
return err ( " legacy store client query error: " & $ queryRes . error )
2022-11-21 08:36:41 +00:00
2022-10-28 18:11:28 +00:00
let response = queryRes . get ( )
return ok ( response )
# TODO: Move to application module (e.g., wakunode2.nim)
2024-03-15 23:08:47 +00:00
proc query * (
2024-04-25 13:09:52 +00:00
node : WakuNode , query : legacy_store_common . HistoryQuery
) : Future [ legacy_store_common . WakuStoreResult [ legacy_store_common . HistoryResponse ] ] {.
2024-03-15 23:08:47 +00:00
async , gcsafe , deprecated : " Use ' node.query() ' with peer destination instead "
. } =
2022-10-27 15:29:09 +00:00
## Queries known nodes for historical messages
2024-04-25 13:09:52 +00:00
if node . wakuLegacyStoreClient . isNil ( ) :
return err ( " waku legacy store client is nil " )
2022-10-18 14:05:53 +00:00
2024-05-09 18:07:49 +00:00
let peerOpt = node . peerManager . selectPeer ( legacy_store_common . WakuLegacyStoreCodec )
2022-10-28 18:11:28 +00:00
if peerOpt . isNone ( ) :
error " no suitable remote peers "
return err ( " peer_not_found_failure " )
return await node . query ( query , peerOpt . get ( ) )
2022-10-18 14:05:53 +00:00
2022-11-23 09:08:00 +00:00
when defined ( waku_exp_store_resume ) :
# TODO: Move to application module (e.g., wakunode2.nim)
2024-03-15 23:08:47 +00:00
proc resume * (
node : WakuNode , peerList : Option [ seq [ RemotePeerInfo ] ] = none ( seq [ RemotePeerInfo ] )
) {. async , gcsafe . } =
2022-11-23 09:08:00 +00:00
## resume proc retrieves the history of waku messages published on the default waku pubsub topic since the last time the waku node has been online
## for resume to work properly the waku node must have the store protocol mounted in the full mode (i.e., persisting messages)
2023-11-30 10:08:08 +00:00
## messages are stored in the wakuStore's messages field and in the message db
2022-11-23 09:08:00 +00:00
## the offline time window is measured as the difference between the current time and the timestamp of the most recent persisted waku message
## an offset of 20 second is added to the time window to count for nodes asynchrony
## peerList indicates the list of peers to query from. The history is fetched from the first available peer in this list. Such candidates should be found through a discovery method (to be developed).
## if no peerList is passed, one of the peers in the underlying peer manager unit of the store protocol is picked randomly to fetch the history from.
## The history gets fetched successfully if the dialed peer has been online during the queried time window.
2024-04-25 13:09:52 +00:00
if node . wakuLegacyStoreClient . isNil ( ) :
2022-11-23 09:08:00 +00:00
return
2022-10-18 14:05:53 +00:00
2024-04-25 13:09:52 +00:00
let retrievedMessages = await node . wakuLegacyStoreClient . resume ( peerList )
2022-11-23 09:08:00 +00:00
if retrievedMessages . isErr ( ) :
2024-03-15 23:08:47 +00:00
error " failed to resume store " , error = retrievedMessages . error
2022-11-23 09:08:00 +00:00
return
2022-11-21 08:36:41 +00:00
2024-03-15 23:08:47 +00:00
info " the number of retrieved messages since the last online time: " ,
number = retrievedMessages . value
2022-10-18 14:05:53 +00:00
2024-04-25 13:09:52 +00:00
## Waku Store
2024-07-12 16:19:12 +00:00
proc toArchiveQuery ( request : StoreQueryRequest ) : waku_archive . ArchiveQuery =
var query = waku_archive . ArchiveQuery ( )
2024-04-25 13:09:52 +00:00
2024-05-01 18:47:06 +00:00
query . includeData = request . includeData
2024-04-25 13:09:52 +00:00
query . pubsubTopic = request . pubsubTopic
query . contentTopics = request . contentTopics
query . startTime = request . startTime
query . endTime = request . endTime
query . hashes = request . messageHashes
2024-07-12 16:19:12 +00:00
query . cursor = request . paginationCursor
2024-04-25 13:09:52 +00:00
query . direction = request . paginationForward
2024-08-29 20:56:14 +00:00
query . requestId = request . requestId
2024-04-25 13:09:52 +00:00
if request . paginationLimit . isSome ( ) :
query . pageSize = uint ( request . paginationLimit . get ( ) )
return query
2024-07-12 16:19:12 +00:00
proc toStoreResult ( res : waku_archive . ArchiveResult ) : StoreQueryResult =
2024-04-25 13:09:52 +00:00
let response = res . valueOr :
return err ( StoreError . new ( 300 , " archive error: " & $ error ) )
var res = StoreQueryResponse ( )
res . statusCode = 200
2024-04-25 19:43:21 +00:00
res . statusDesc = " OK "
2024-05-01 18:47:06 +00:00
for i in 0 .. < response . hashes . len :
let hash = response . hashes [ i ]
2024-05-08 19:35:56 +00:00
let kv = store_common . WakuMessageKeyValue ( messageHash : hash )
2024-05-01 18:47:06 +00:00
res . messages . add ( kv )
for i in 0 .. < response . messages . len :
res . messages [ i ] . message = some ( response . messages [ i ] )
2024-05-08 19:35:56 +00:00
res . messages [ i ] . pubsubTopic = some ( response . topics [ i ] )
2024-04-25 13:09:52 +00:00
2024-07-12 16:19:12 +00:00
res . paginationCursor = response . cursor
2024-04-25 13:09:52 +00:00
return ok ( res )
proc mountStore * (
node : WakuNode , rateLimit : RateLimitSetting = DefaultGlobalNonRelayRateLimit
) {. async . } =
if node . wakuArchive . isNil ( ) :
error " failed to mount waku store protocol " , error = " waku archive not set "
return
info " mounting waku store protocol "
let requestHandler : StoreQueryRequestHandler = proc (
request : StoreQueryRequest
) : Future [ StoreQueryResult ] {. async . } =
let request = request . toArchiveQuery ( )
let response = await node . wakuArchive . findMessages ( request )
return response . toStoreResult ( )
node . wakuStore =
store . WakuStore . new ( node . peerManager , node . rng , requestHandler , some ( rateLimit ) )
if node . started :
await node . wakuStore . start ( )
node . switch . mount ( node . wakuStore , protocolMatcher ( store_common . WakuStoreCodec ) )
proc mountStoreClient * ( node : WakuNode ) =
info " mounting store client "
node . wakuStoreClient = store_client . WakuStoreClient . new ( node . peerManager , node . rng )
proc query * (
node : WakuNode , request : store_common . StoreQueryRequest , peer : RemotePeerInfo
) : Future [ store_common . WakuStoreResult [ store_common . StoreQueryResponse ] ] {.
async , gcsafe
. } =
## Queries known nodes for historical messages
if node . wakuStoreClient . isNil ( ) :
return err ( " waku store v3 client is nil " )
let response = ( await node . wakuStoreClient . query ( request , peer ) ) . valueOr :
var res = StoreQueryResponse ( )
res . statusCode = uint32 ( error . kind )
res . statusDesc = $ error
return ok ( res )
return ok ( response )
2024-07-30 11:23:39 +00:00
proc setupStoreResume * ( node : WakuNode ) =
node . wakuStoreResume = StoreResume . new (
node . peerManager , node . wakuArchive , node . wakuStoreClient
) . valueOr :
error " Failed to setup Store Resume " , error = $ error
return
2022-10-27 15:29:09 +00:00
## Waku lightpush
2022-10-18 14:05:53 +00:00
2024-04-15 13:28:35 +00:00
proc mountLightPush * (
node : WakuNode , rateLimit : RateLimitSetting = DefaultGlobalNonRelayRateLimit
) {. async . } =
2022-10-18 14:05:53 +00:00
info " mounting light push "
2024-06-17 11:14:05 +00:00
var pushHandler =
2024-06-13 17:10:00 +00:00
if node . wakuRelay . isNil :
debug " mounting lightpush without relay (nil) "
getNilPushHandler ( )
else :
debug " mounting lightpush with relay "
2024-06-17 11:14:05 +00:00
let rlnPeer =
2024-06-13 17:10:00 +00:00
if isNil ( node . wakuRlnRelay ) :
debug " mounting lightpush without rln-relay "
none ( WakuRLNRelay )
else :
debug " mounting lightpush with rln-relay "
some ( node . wakuRlnRelay )
getRelayPushHandler ( node . wakuRelay , rlnPeer )
2022-10-18 14:05:53 +00:00
2024-04-15 13:28:35 +00:00
node . wakuLightPush =
WakuLightPush . new ( node . peerManager , node . rng , pushHandler , some ( rateLimit ) )
2022-10-25 12:55:31 +00:00
2022-10-18 14:05:53 +00:00
if node . started :
# Node has started already. Let's start lightpush too.
await node . wakuLightPush . start ( )
node . switch . mount ( node . wakuLightPush , protocolMatcher ( WakuLightPushCodec ) )
2022-11-02 10:59:58 +00:00
proc mountLightPushClient * ( node : WakuNode ) =
info " mounting light push client "
node . wakuLightpushClient = WakuLightPushClient . new ( node . peerManager , node . rng )
2024-03-15 23:08:47 +00:00
proc lightpushPublish * (
node : WakuNode ,
pubsubTopic : Option [ PubsubTopic ] ,
message : WakuMessage ,
peer : RemotePeerInfo ,
) : Future [ WakuLightPushResult [ void ] ] {. async , gcsafe . } =
2022-10-27 15:29:09 +00:00
## Pushes a `WakuMessage` to a node which relays it further on PubSub topic.
## Returns whether relaying was successful or not.
## `WakuMessage` should contain a `contentTopic` field for light node
## functionality.
2024-04-26 10:42:47 +00:00
if node . wakuLightpushClient . isNil ( ) and node . wakuLightPush . isNil ( ) :
error " failed to publish message as lightpush not available "
return err ( " Waku lightpush not available " )
let internalPublish = proc (
node : WakuNode ,
pubsubTopic : PubsubTopic ,
message : WakuMessage ,
peer : RemotePeerInfo ,
) : Future [ WakuLightPushResult [ void ] ] {. async , gcsafe . } =
2024-05-01 08:25:33 +00:00
let msgHash = pubsubTopic . computeMessageHash ( message ) . to0xHex ( )
2024-04-26 10:42:47 +00:00
if not node . wakuLightpushClient . isNil ( ) :
2024-06-10 13:56:55 +00:00
notice " publishing message with lightpush " ,
2024-04-26 10:42:47 +00:00
pubsubTopic = pubsubTopic ,
contentTopic = message . contentTopic ,
2024-05-01 08:25:33 +00:00
target_peer_id = peer . peerId ,
msg_hash = msgHash
2024-04-26 10:42:47 +00:00
return await node . wakuLightpushClient . publish ( pubsubTopic , message , peer )
if not node . wakuLightPush . isNil ( ) :
2024-06-10 13:56:55 +00:00
notice " publishing message with self hosted lightpush " ,
2024-05-01 08:25:33 +00:00
pubsubTopic = pubsubTopic ,
contentTopic = message . contentTopic ,
target_peer_id = peer . peerId ,
msg_hash = msgHash
2024-04-26 10:42:47 +00:00
return await node . wakuLightPush . handleSelfLightPushRequest ( pubsubTopic , message )
2022-10-28 14:30:01 +00:00
2023-08-17 12:11:18 +00:00
if pubsubTopic . isSome ( ) :
2024-04-26 10:42:47 +00:00
return await internalPublish ( node , pubsubTopic . get ( ) , message , peer )
2023-08-17 12:11:18 +00:00
2024-03-13 09:58:13 +00:00
let topicMapRes = node . wakuSharding . parseSharding ( pubsubTopic , message . contentTopic )
2023-08-17 12:11:18 +00:00
let topicMap =
if topicMapRes . isErr ( ) :
return err ( topicMapRes . error )
2024-03-15 23:08:47 +00:00
else :
topicMapRes . get ( )
2022-10-27 15:29:09 +00:00
2023-08-17 12:11:18 +00:00
for pubsub , _ in topicMap . pairs : # There's only one pair anyway
2024-04-26 10:42:47 +00:00
return await internalPublish ( node , $ pubsub , message , peer )
2022-10-28 14:30:01 +00:00
# TODO: Move to application module (e.g., wakunode2.nim)
2024-03-15 23:08:47 +00:00
proc lightpushPublish * (
node : WakuNode , pubsubTopic : Option [ PubsubTopic ] , message : WakuMessage
) : Future [ WakuLightPushResult [ void ] ] {.
async , gcsafe , deprecated : " Use ' node.lightpushPublish() ' instead "
. } =
2024-04-26 10:42:47 +00:00
if node . wakuLightpushClient . isNil ( ) and node . wakuLightPush . isNil ( ) :
error " failed to publish message as lightpush not available "
return err ( " waku lightpush not available " )
var peerOpt : Option [ RemotePeerInfo ] = none ( RemotePeerInfo )
if not node . wakuLightpushClient . isNil ( ) :
peerOpt = node . peerManager . selectPeer ( WakuLightPushCodec )
if peerOpt . isNone ( ) :
let msg = " no suitable remote peers "
2024-08-14 14:40:08 +00:00
error " failed to publish message " , err = msg
2024-04-26 10:42:47 +00:00
return err ( msg )
elif not node . wakuLightPush . isNil ( ) :
peerOpt = some ( RemotePeerInfo . init ( $ node . switch . peerInfo . peerId ) )
2022-10-28 14:30:01 +00:00
2024-03-15 23:08:47 +00:00
let publishRes =
await node . lightpushPublish ( pubsubTopic , message , peer = peerOpt . get ( ) )
2024-01-18 12:49:13 +00:00
if publishRes . isErr ( ) :
2024-03-15 23:08:47 +00:00
error " failed to publish message " , error = publishRes . error
2022-10-27 15:29:09 +00:00
2024-03-15 23:08:47 +00:00
return publishRes
2023-04-05 07:46:13 +00:00
2022-12-13 09:26:24 +00:00
## Waku RLN Relay
2024-03-15 23:08:47 +00:00
proc mountRlnRelay * (
node : WakuNode ,
rlnConf : WakuRlnConfig ,
spamHandler = none ( SpamHandler ) ,
registrationHandler = none ( RegistrationHandler ) ,
) {. async . } =
2023-09-11 06:32:31 +00:00
info " mounting rln relay "
if node . wakuRelay . isNil ( ) :
2024-03-15 23:08:47 +00:00
raise newException (
CatchableError , " WakuRelay protocol is not mounted, cannot mount WakuRlnRelay "
)
2023-09-11 06:32:31 +00:00
2024-03-15 23:08:47 +00:00
let rlnRelayRes = waitFor WakuRlnRelay . new ( rlnConf , registrationHandler )
2023-09-11 06:32:31 +00:00
if rlnRelayRes . isErr ( ) :
2024-03-15 23:08:47 +00:00
raise
newException ( CatchableError , " failed to mount WakuRlnRelay: " & rlnRelayRes . error )
2023-09-11 06:32:31 +00:00
let rlnRelay = rlnRelayRes . get ( )
2024-07-22 16:58:45 +00:00
if ( rlnConf . rlnRelayUserMessageLimit > rlnRelay . groupManager . rlnRelayMaxMessageLimit ) :
2024-07-26 11:27:34 +00:00
error " rln-relay-user-message-limit can ' t exceed the MAX_MESSAGE_LIMIT in the rln contract "
2023-09-11 06:32:31 +00:00
let validator = generateRlnValidator ( rlnRelay , spamHandler )
2024-01-29 15:11:26 +00:00
# register rln validator as default validator
debug " Registering RLN validator "
2024-02-01 17:16:10 +00:00
node . wakuRelay . addValidator ( validator , " RLN validation failed " )
2024-03-15 23:08:47 +00:00
2023-09-11 06:32:31 +00:00
node . wakuRlnRelay = rlnRelay
2023-01-26 10:18:30 +00:00
2022-10-27 15:29:09 +00:00
## Waku peer-exchange
2024-07-29 19:53:43 +00:00
proc mountPeerExchange * (
2024-09-18 13:58:07 +00:00
node : WakuNode ,
cluster : Option [ uint16 ] = none ( uint16 ) ,
rateLimit : RateLimitSetting = DefaultGlobalNonRelayRateLimit ,
2024-07-29 19:53:43 +00:00
) {. async : ( raises : [ ] ) . } =
2022-10-18 14:05:53 +00:00
info " mounting waku peer exchange "
2024-09-18 13:58:07 +00:00
node . wakuPeerExchange =
WakuPeerExchange . new ( node . peerManager , cluster , some ( rateLimit ) )
2022-10-18 14:05:53 +00:00
if node . started :
2024-05-16 20:29:11 +00:00
try :
await node . wakuPeerExchange . start ( )
except CatchableError :
error " failed to start wakuPeerExchange " , error = getCurrentExceptionMsg ( )
2022-10-18 14:05:53 +00:00
2024-05-16 20:29:11 +00:00
try :
node . switch . mount ( node . wakuPeerExchange , protocolMatcher ( WakuPeerExchangeCodec ) )
except LPError :
error " failed to mount wakuPeerExchange " , error = getCurrentExceptionMsg ( )
2022-10-18 14:05:53 +00:00
2024-03-14 16:48:09 +00:00
proc fetchPeerExchangePeers * (
node : Wakunode , amount : uint64
2024-09-18 13:58:07 +00:00
) : Future [ Result [ int , PeerExchangeResponseStatus ] ] {. async : ( raises : [ ] ) . } =
2023-02-09 15:59:29 +00:00
if node . wakuPeerExchange . isNil ( ) :
error " could not get peers from px, waku peer-exchange is nil "
2024-09-18 13:58:07 +00:00
return err (
(
status_code : PeerExchangeResponseStatusCode . SERVICE_UNAVAILABLE ,
status_desc : some ( " PeerExchange is not mounted " ) ,
)
)
2023-02-09 15:59:29 +00:00
info " Retrieving peer info via peer exchange protocol "
let pxPeersRes = await node . wakuPeerExchange . request ( amount )
if pxPeersRes . isOk :
var validPeers = 0
2023-04-19 14:12:00 +00:00
let peers = pxPeersRes . get ( ) . peerInfos
for pi in peers :
2023-02-09 15:59:29 +00:00
var record : enr . Record
if enr . fromBytes ( record , pi . enr ) :
2024-03-14 16:48:09 +00:00
node . peerManager . addPeer ( record . toRemotePeerInfo ( ) . get , PeerExchange )
2023-02-09 15:59:29 +00:00
validPeers + = 1
2024-03-14 16:48:09 +00:00
info " Retrieved peer info via peer exchange protocol " ,
validPeers = validPeers , totalPeers = peers . len
return ok ( validPeers )
2023-02-09 15:59:29 +00:00
else :
2024-03-14 16:48:09 +00:00
warn " failed to retrieve peer info via peer exchange protocol " ,
error = pxPeersRes . error
2024-09-18 13:58:07 +00:00
return err ( pxPeersRes . error )
2023-02-09 15:59:29 +00:00
2022-11-02 08:45:21 +00:00
# TODO: Move to application module (e.g., wakunode2.nim)
2024-03-15 23:08:47 +00:00
proc setPeerExchangePeer * (
node : WakuNode , peer : RemotePeerInfo | MultiAddress | string
) =
2022-10-27 15:29:09 +00:00
if node . wakuPeerExchange . isNil ( ) :
error " could not set peer, waku peer-exchange is nil "
return
2024-03-15 23:08:47 +00:00
info " Set peer-exchange peer " , peer = peer
2022-10-27 15:29:09 +00:00
2023-04-12 09:29:11 +00:00
let remotePeerRes = parsePeerInfo ( peer )
if remotePeerRes . isErr ( ) :
error " could not parse peer info " , error = remotePeerRes . error
return
2024-03-14 16:48:09 +00:00
node . peerManager . addPeer ( remotePeerRes . value , PeerExchange )
2022-11-02 08:45:21 +00:00
waku_px_peers . inc ( )
2022-10-27 15:29:09 +00:00
## Other protocols
2024-05-16 20:29:11 +00:00
proc mountLibp2pPing * ( node : WakuNode ) {. async : ( raises : [ ] ) . } =
2022-10-18 14:05:53 +00:00
info " mounting libp2p ping protocol "
try :
node . libp2pPing = Ping . new ( rng = node . rng )
except Exception as e :
2024-05-16 20:29:11 +00:00
error " failed to create ping " , error = getCurrentExceptionMsg ( )
2022-11-21 08:36:41 +00:00
2022-10-18 14:05:53 +00:00
if node . started :
# Node has started already. Let's start ping too.
2024-05-16 20:29:11 +00:00
try :
await node . libp2pPing . start ( )
except CatchableError :
error " failed to start libp2pPing " , error = getCurrentExceptionMsg ( )
2022-11-21 08:36:41 +00:00
2024-05-16 20:29:11 +00:00
try :
node . switch . mount ( node . libp2pPing )
except LPError :
error " failed to mount libp2pPing " , error = getCurrentExceptionMsg ( )
2022-10-18 14:05:53 +00:00
2022-11-24 13:11:23 +00:00
# TODO: Move this logic to PeerManager
2022-10-18 14:05:53 +00:00
proc keepaliveLoop ( node : WakuNode , keepalive : chronos . Duration ) {. async . } =
while node . started :
# Keep all connected peers alive while running
trace " Running keepalive "
# First get a list of connected peer infos
2024-03-15 23:08:47 +00:00
let peers =
node . peerManager . peerStore . peers ( ) . filterIt ( it . connectedness = = Connected )
2022-10-18 14:05:53 +00:00
for peer in peers :
2023-01-23 20:24:46 +00:00
try :
let conn = await node . switch . dial ( peer . peerId , peer . addrs , PingCodec )
let pingDelay = await node . libp2pPing . ping ( conn )
2024-05-13 10:07:57 +00:00
await conn . close ( )
2023-01-23 20:24:46 +00:00
except CatchableError as exc :
2022-10-18 14:05:53 +00:00
waku_node_errors . inc ( labelValues = [ " keep_alive_failure " ] )
2022-11-21 08:36:41 +00:00
2022-10-18 14:05:53 +00:00
await sleepAsync ( keepalive )
proc startKeepalive * ( node : WakuNode ) =
let defaultKeepalive = 2 . minutes # 20% of the default chronosstream timeout duration
2024-03-15 23:08:47 +00:00
info " starting keepalive " , keepalive = defaultKeepalive
2022-10-18 14:05:53 +00:00
asyncSpawn node . keepaliveLoop ( defaultKeepalive )
2024-05-16 20:29:11 +00:00
proc mountRendezvous * ( node : WakuNode ) {. async : ( raises : [ ] ) . } =
2023-06-01 19:43:10 +00:00
info " mounting rendezvous discovery protocol "
node . rendezvous = RendezVous . new ( node . switch )
if node . started :
2024-05-16 20:29:11 +00:00
try :
await node . rendezvous . start ( )
except CatchableError :
error " failed to start rendezvous " , error = getCurrentExceptionMsg ( )
2023-06-01 19:43:10 +00:00
2024-05-16 20:29:11 +00:00
try :
node . switch . mount ( node . rendezvous )
except LPError :
error " failed to mount rendezvous " , error = getCurrentExceptionMsg ( )
2023-06-01 19:43:10 +00:00
2023-10-27 07:11:47 +00:00
proc isBindIpWithZeroPort ( inputMultiAdd : MultiAddress ) : bool =
let inputStr = $ inputMultiAdd
if inputStr . contains ( " 0.0.0.0/tcp/0 " ) or inputStr . contains ( " 127.0.0.1/tcp/0 " ) :
return true
2022-10-27 15:29:09 +00:00
2023-10-27 07:11:47 +00:00
return false
2022-11-21 08:36:41 +00:00
2023-10-27 07:11:47 +00:00
proc printNodeNetworkInfo * ( node : WakuNode ) : void =
2022-10-18 14:05:53 +00:00
let peerInfo = node . switch . peerInfo
2023-11-16 16:15:27 +00:00
var announcedStr = " "
2022-10-18 14:05:53 +00:00
var listenStr = " "
2023-11-16 16:15:27 +00:00
var localIp = " "
try :
localIp = $ getPrimaryIPAddr ( )
except Exception as e :
2024-03-15 23:08:47 +00:00
warn " Could not retrieve localIp " , msg = e . msg
2023-10-27 07:11:47 +00:00
info " PeerInfo " , peerId = peerInfo . peerId , addrs = peerInfo . addrs
2022-10-18 14:05:53 +00:00
for address in node . announcedAddresses :
2022-11-21 08:36:41 +00:00
var fulladdr = " [ " & $ address & " /p2p/ " & $ peerInfo . peerId & " ] "
2023-11-16 16:15:27 +00:00
announcedStr & = fulladdr
for transport in node . switch . transports :
for address in transport . addrs :
var fulladdr = " [ " & $ address & " /p2p/ " & $ peerInfo . peerId & " ] "
listenStr & = fulladdr
2022-11-21 08:36:41 +00:00
2022-10-18 14:05:53 +00:00
## XXX: this should be /ip4..., / stripped?
2023-11-16 16:15:27 +00:00
info " Listening on " , full = listenStr , localIp = localIp
info " Announcing addresses " , full = announcedStr
2022-10-18 14:05:53 +00:00
info " DNS: discoverable ENR " , enr = node . enr . toUri ( )
2023-10-27 07:11:47 +00:00
proc start * ( node : WakuNode ) {. async . } =
## Starts a created Waku Node and
## all its mounted protocols.
2024-03-15 23:08:47 +00:00
waku_version . set ( 1 , labelValues = [ git_version ] )
info " Starting Waku node " , version = git_version
2023-10-27 07:11:47 +00:00
var zeroPortPresent = false
for address in node . announcedAddresses :
if isBindIpWithZeroPort ( address ) :
zeroPortPresent = true
2022-10-18 14:05:53 +00:00
# Perform relay-specific startup tasks TODO: this should be rethought
2022-10-27 15:29:09 +00:00
if not node . wakuRelay . isNil ( ) :
2022-10-18 14:05:53 +00:00
await node . startRelay ( )
2022-11-21 08:36:41 +00:00
2023-11-21 20:15:39 +00:00
if not node . wakuMetadata . isNil ( ) :
node . wakuMetadata . start ( )
2024-07-30 11:23:39 +00:00
if not node . wakuStoreResume . isNil ( ) :
await node . wakuStoreResume . start ( )
2024-08-13 11:27:34 +00:00
if not node . wakuSync . isNil ( ) :
node . wakuSync . start ( )
2022-10-28 09:51:46 +00:00
## The switch uses this mapper to update peer info addrs
## with announced addrs after start
2024-03-15 23:08:47 +00:00
let addressMapper = proc (
listenAddrs : seq [ MultiAddress ]
) : Future [ seq [ MultiAddress ] ] {. async . } =
return node . announcedAddresses
2022-10-28 09:51:46 +00:00
node . switch . peerInfo . addressMappers . add ( addressMapper )
## The switch will update addresses after start using the addressMapper
await node . switch . start ( )
2022-10-18 14:05:53 +00:00
node . started = true
2022-11-21 08:36:41 +00:00
2023-11-16 16:15:27 +00:00
if not zeroPortPresent :
printNodeNetworkInfo ( node )
else :
info " Listening port is dynamically allocated, address and ENR generation postponed "
2022-10-18 14:05:53 +00:00
info " Node started successfully "
proc stop * ( node : WakuNode ) {. async . } =
2024-04-30 10:52:11 +00:00
## By stopping the switch we are stopping all the underlying mounted protocols
await node . switch . stop ( )
2023-01-26 09:20:20 +00:00
node . peerManager . stop ( )
2022-10-18 14:05:53 +00:00
2023-09-11 06:32:31 +00:00
if not node . wakuRlnRelay . isNil ( ) :
2023-12-14 06:16:39 +00:00
try :
await node . wakuRlnRelay . stop ( ) ## this can raise an exception
except Exception :
2024-03-15 23:08:47 +00:00
error " exception stopping the node " , error = getCurrentExceptionMsg ( )
2023-07-27 11:51:21 +00:00
2023-12-11 07:50:40 +00:00
if not node . wakuArchive . isNil ( ) :
2024-03-12 11:51:03 +00:00
await node . wakuArchive . stopWait ( )
2023-12-11 07:50:40 +00:00
2024-07-30 11:23:39 +00:00
if not node . wakuStoreResume . isNil ( ) :
await node . wakuStoreResume . stopWait ( )
2022-11-21 08:36:41 +00:00
node . started = false
2023-09-06 08:46:19 +00:00
2023-12-14 06:16:39 +00:00
proc isReady * ( node : WakuNode ) : Future [ bool ] {. async : ( raises : [ Exception ] ) . } =
2023-09-11 06:32:31 +00:00
if node . wakuRlnRelay = = nil :
return true
return await node . wakuRlnRelay . isReady ( )
2023-09-06 08:46:19 +00:00
## TODO: add other protocol `isReady` checks
2024-09-18 13:58:07 +00:00
proc setRateLimits * ( node : WakuNode , limits : seq [ string ] ) : Result [ void , string ] =
let rateLimitConfig = ProtocolRateLimitSettings . parse ( limits )
if rateLimitConfig . isErr ( ) :
return err ( " invalid rate limit settings: " & rateLimitConfig . error )
node . rateLimitSettings = rateLimitConfig . get ( )
return ok ( )