2020-04-29 12:49:27 +08:00
import
2025-05-12 10:57:13 +02:00
std /[ strutils , strformat , sequtils ] ,
2024-07-09 13:14:28 +02:00
results ,
2025-05-08 07:05:35 +10:00
chronicles ,
2022-10-26 17:10:30 +02:00
chronos ,
2022-11-02 15:55:09 +01:00
regex ,
2025-05-26 21:58:02 +02:00
stew / endians2 ,
stint ,
2022-11-03 10:45:06 +01:00
confutils ,
confutils / defs ,
2022-10-18 07:06:54 -05:00
confutils / std / net ,
2022-05-17 17:48:08 +02:00
confutils / toml / defs as confTomlDefs ,
confutils / toml / std / net as confTomlNet ,
2025-10-08 10:18:54 +05:30
libp2p / crypto / curve25519 ,
2020-05-21 12:16:00 +08:00
libp2p / crypto / crypto ,
libp2p / crypto / secp ,
2023-01-26 15:48:30 +05:30
libp2p / multiaddress ,
2025-10-08 10:18:54 +05:30
libp2p / multicodec ,
2023-05-02 11:45:50 +02:00
nimcrypto / utils ,
2024-05-10 10:56:17 +02:00
secp256k1 ,
json
2025-05-08 07:05:35 +10:00
2022-11-03 17:58:48 +01:00
import
2026-06-08 13:37:53 +02:00
logos_delivery / waku / factory /[ waku_conf , conf_builder / conf_builder , networks_config ] ,
logos_delivery / waku / common /[ logging ] ,
logos_delivery / waku /[
2025-10-01 16:31:34 +10:00
waku_enr ,
node / peer_manager ,
waku_core / topics / pubsub_topic ,
waku_core / message / default_values ,
2025-10-08 10:18:54 +05:30
waku_mix ,
2025-10-01 16:31:34 +10:00
] ,
2026-03-03 19:17:54 +01:00
.. / .. / tools / rln_keystore_generator / rln_keystore_generator ,
. / entry_nodes
2022-05-17 17:48:08 +02:00
2025-10-01 16:31:34 +10:00
import . / envvar as confEnvvarDefs , . / envvar_net as confEnvvarNet
2024-01-03 13:11:50 +01:00
2025-11-15 23:31:09 +01:00
export
confTomlDefs , confTomlNet , confEnvvarDefs , confEnvvarNet , ProtectedShard ,
2026-06-10 09:09:22 -03:00
DefaultMaxWakuMessageSizeStr , DefaultAgentString
2025-05-08 07:05:35 +10:00
logScope :
2025-10-01 16:31:34 +10:00
topics = "waku cli args"
2022-10-26 17:10:30 +02:00
2024-09-25 11:52:02 +02:00
# Git version in git describe format (defined at compile time)
const git_version * {. strdefine .} = "n/a"
2026-06-10 09:09:22 -03:00
# CLI defaults that differ from confbuilder defaults
const
DefaultCLIRelay * = true
DefaultCLIPeerExchange * = true
DefaultCLIRendezvous * = true
DefaultCLINat * = "any"
2022-10-26 17:10:30 +02:00
type ConfResult *[ T ] = Result [ T , string ]
2022-11-23 10:08:00 +01:00
2024-03-27 10:08:53 -04:00
type EthRpcUrl * = distinct string
2024-02-16 18:36:31 +05:30
2023-11-09 15:18:39 +05:30
type StartUpCommand * = enum
2024-03-16 00:08:47 +01:00
noCommand # default, runs waku
generateRlnKeystore # generates a new RLN keystore
2023-11-09 15:18:39 +05:30
2026-03-03 19:17:54 +01:00
type WakuMode * {. pure .} = enum
noMode # default - use explicit CLI flags as-is
Core # full service node
Edge # client-only node
2024-03-16 00:08:47 +01:00
type WakuNodeConf * = object
configFile * {.
desc : "Loads configuration from a TOML file (cmd-line parameters take precedence)" ,
name : "config-file"
.}: Option [ InputFile ]
2022-05-17 17:48:08 +02:00
2024-03-16 00:08:47 +01:00
## Log configuration
logLevel * {.
desc :
"Sets the log level for process. Supported levels: TRACE, DEBUG, INFO, NOTICE, WARN, ERROR or FATAL" ,
defaultValue : logging . LogLevel . INFO ,
name : "log-level"
.}: logging . LogLevel
2022-05-17 22:11:07 +02:00
2024-03-16 00:08:47 +01:00
logFormat * {.
desc :
2024-12-09 21:45:26 +08:00
"Specifies what kind of logs should be written to stdout. Supported formats: TEXT, JSON" ,
2024-03-16 00:08:47 +01:00
defaultValue : logging . LogFormat . TEXT ,
name : "log-format"
.}: logging . LogFormat
2022-10-28 15:12:06 +02:00
2024-03-16 00:08:47 +01:00
rlnRelayCredPath * {.
2025-05-13 09:13:28 +02:00
desc : "The path for persisting rln-relay credential" ,
2024-03-16 00:08:47 +01:00
defaultValue : "" ,
name : "rln-relay-cred-path"
.}: string
2025-05-12 10:57:13 +02:00
ethClientUrls * {.
desc :
"HTTP address of an Ethereum testnet client e.g., http://localhost:8540/. Argument may be repeated." ,
defaultValue : @[ EthRpcUrl ( "http://localhost:8540/" ) ] ,
2024-03-16 00:08:47 +01:00
name : "rln-relay-eth-client-address"
2025-05-12 10:57:13 +02:00
.}: seq [ EthRpcUrl ]
2024-03-16 00:08:47 +01:00
rlnRelayEthContractAddress * {.
2025-04-01 09:28:18 +11:00
desc : "Address of membership contract on an Ethereum testnet." ,
2024-03-16 00:08:47 +01:00
defaultValue : "" ,
name : "rln-relay-eth-contract-address"
.}: string
2024-06-28 14:49:16 +05:30
rlnRelayChainId * {.
2024-07-09 13:14:28 +02:00
desc :
"Chain ID of the provided contract (optional, will fetch from RPC provider if not used)" ,
2024-06-28 14:49:16 +05:30
defaultValue : 0 ,
name : "rln-relay-chain-id"
.}: uint
2024-03-16 00:08:47 +01:00
rlnRelayCredPassword * {.
desc : "Password for encrypting RLN credentials" ,
defaultValue : "" ,
name : "rln-relay-cred-password"
.}: string
rlnRelayEthPrivateKey * {.
desc : "Private key for broadcasting transactions" ,
defaultValue : "" ,
name : "rln-relay-eth-private-key"
.}: string
2026-06-10 09:09:22 -03:00
# Option-typed; desc states the default since the CLI can't auto-show it for none().
2024-03-16 00:08:47 +01:00
rlnRelayUserMessageLimit * {.
desc :
2026-06-10 09:09:22 -03:00
"Set a user message limit for the rln membership registration. Must be a positive integer. Default is " &
$ DefaultRlnRelayUserMessageLimit & "." ,
defaultValue : none ( uint64 ),
2024-03-16 00:08:47 +01:00
name : "rln-relay-user-message-limit"
2026-06-10 09:09:22 -03:00
.}: Option [ uint64 ]
2024-03-16 00:08:47 +01:00
2026-06-10 09:09:22 -03:00
# Option-typed; desc states the default since the CLI can't auto-show it for none().
2024-03-16 00:08:47 +01:00
rlnEpochSizeSec * {.
desc :
2026-06-10 09:09:22 -03:00
"Epoch size in seconds used to rate limit RLN memberships. Default is " &
$ DefaultRlnRelayEpochSizeSec & " second." ,
defaultValue : none ( uint64 ),
2024-03-16 00:08:47 +01:00
name : "rln-relay-epoch-sec"
2026-06-10 09:09:22 -03:00
.}: Option [ uint64 ]
2024-03-16 00:08:47 +01:00
maxMessageSize * {.
desc :
"Maximum message size. Accepted units: KiB, KB, and B. e.g. 1024KiB; 1500 B; etc." ,
defaultValue : DefaultMaxWakuMessageSizeStr ,
name : "max-msg-size"
.}: string
case cmd * {. command , defaultValue : noCommand .}: StartUpCommand
of generateRlnKeystore :
execute * {.
desc : "Runs the registration function on-chain. By default, a dry-run will occur" ,
defaultValue : false ,
name : "execute"
.}: bool
of noCommand :
## Application-level configuration
2024-08-19 12:56:22 +02:00
protectedShards * {.
desc :
"Shards and its public keys to be used for message validation, shard:pubkey. Argument may be repeated." ,
defaultValue : newSeq [ ProtectedShard ] ( 0 ),
name : "protected-shard"
.}: seq [ ProtectedShard ]
2022-08-18 10:35:02 -07:00
2024-03-16 00:08:47 +01:00
## General node config
2026-03-03 19:17:54 +01:00
mode * {.
desc :
"Node operation mode. 'Core' enables relay+service protocols. 'Edge' enables client-only protocols. Default: explicit CLI flags used." ,
defaultValue : WakuMode . noMode ,
name : "mode"
.}: WakuMode
2025-04-01 09:28:18 +11:00
preset * {.
desc :
2026-05-21 18:29:33 +01:00
"Network preset to use. 'twn' is The RLN-protected Waku Network (cluster 1). 'logos.dev' is the Logos Dev Network (cluster 2). 'logos.test' is the Logos Test Network (cluster 2). Overrides other values." ,
2025-04-01 09:28:18 +11:00
defaultValue : "" ,
name : "preset"
.}: string
2026-06-10 09:09:22 -03:00
# Option-typed; desc states the default since the CLI can't auto-show it for none().
2024-03-16 00:08:47 +01:00
clusterId * {.
2026-06-10 09:09:22 -03:00
desc : static (
"Cluster id that the node is running in. Node in a different cluster id is disconnected. Default is " &
$ DefaultClusterId & "."
),
defaultValue : none ( uint16 ),
2024-03-16 00:08:47 +01:00
name : "cluster-id"
2026-06-10 09:09:22 -03:00
.}: Option [ uint16 ]
2022-11-23 10:08:00 +01:00
2024-03-16 00:08:47 +01:00
agentString * {.
2026-06-10 09:09:22 -03:00
defaultValue : DefaultAgentString ,
2024-03-16 00:08:47 +01:00
desc : "Node agent string which is used as identifier in network" ,
name : "agent-string"
.}: string
nodekey * {. desc : "P2P node private key as 64 char hex string." , name : "nodekey" .}:
Option [ PrivateKey ]
listenAddress * {.
defaultValue : defaultListenAddress (),
desc : "Listening address for LibP2P (and Discovery v5, if enabled) traffic." ,
name : "listen-address"
.}: IpAddress
tcpPort * {. desc : "TCP listening port." , defaultValue : 60000 , name : "tcp-port" .}:
Port
portsShift * {.
desc : "Add a shift to all port numbers." , defaultValue : 0 , name : "ports-shift"
.}: uint16
nat * {.
desc :
"Specify method to use for determining public address. " &
"Must be one of: any, none, upnp, pmp, extip:<IP>." ,
2026-06-11 05:31:33 -03:00
defaultValue : DefaultCLINat ,
name : "nat"
2024-03-16 00:08:47 +01:00
.}: string
extMultiAddrs * {.
desc :
"External multiaddresses to advertise to the network. Argument may be repeated." ,
name : "ext-multiaddr"
.}: seq [ string ]
extMultiAddrsOnly * {.
2025-05-08 07:05:35 +10:00
desc : "Only announce external multiaddresses setup with --ext-multiaddr" ,
2024-03-16 00:08:47 +01:00
defaultValue : false ,
name : "ext-multiaddr-only"
.}: bool
maxConnections * {.
2026-01-17 17:05:25 +05:30
desc :
"Maximum allowed number of libp2p connections. (Default: 150) that's recommended value for better connectivity" ,
defaultValue : 150 ,
2024-03-16 00:08:47 +01:00
name : "max-connections"
2025-01-21 11:29:52 +05:30
.}: int
relayServiceRatio * {.
desc :
"This percentage ratio represents the relay peers to service peers. For example, 60:40, tells that 60% of the max-connections will be used for relay protocol and the other 40% of max-connections will be reserved for other service protocols (e.g., filter, lightpush, store, metadata, etc.)" ,
2026-01-17 17:05:25 +05:30
defaultValue : "50:50" ,
name : "relay-service-ratio"
2025-01-21 11:29:52 +05:30
.}: string
2024-03-16 00:08:47 +01:00
colocationLimit * {.
desc :
"Max num allowed peers from the same IP. Set it to 0 to remove the limitation." ,
defaultValue : defaultColocationLimit (),
name : "ip-colocation-limit"
.}: int
peerStoreCapacity * {.
desc : "Maximum stored peers in the peerstore." , name : "peer-store-capacity"
.}: Option [ int ]
peerPersistence * {.
desc : "Enable peer persistence." , defaultValue : false , name : "peer-persistence"
.}: bool
## DNS addrs config
dnsAddrsNameServers * {.
desc :
"DNS name server IPs to query for DNS multiaddrs resolution. Argument may be repeated." ,
2026-04-08 12:42:14 +02:00
defaultValue : @[
IpAddress ( family : IpAddressFamily . IPv4 , address_v4 : [ 1'u8 , 1 , 1 , 1 ] ),
IpAddress ( family : IpAddressFamily . IPv4 , address_v4 : [ 1'u8 , 0 , 0 , 1 ] ),
] ,
2024-03-16 00:08:47 +01:00
name : "dns-addrs-name-server"
.}: seq [ IpAddress ]
dns4DomainName * {.
desc : "The domain name resolving to the node's public IPv4 address" ,
2023-11-09 15:18:39 +05:30
defaultValue : "" ,
2024-03-16 00:08:47 +01:00
name : "dns4-domain-name"
.}: string
2022-10-28 11:13:05 +02:00
2024-10-28 09:17:46 +01:00
## Circuit-relay config
isRelayClient * {.
2026-03-17 10:15:35 -03:00
desc : """Set the node as a relay-client.
2024-10-28 09:17:46 +01:00
Set it to true for nodes that run behind a NAT or firewall and
hence would have reachability issues.""" ,
defaultValue : false ,
name : "relay-client"
.}: bool
2024-03-16 00:08:47 +01:00
## Relay config
relay * {.
2026-06-10 09:09:22 -03:00
desc : "Enable relay protocol: true|false" ,
defaultValue : DefaultCLIRelay ,
name : "relay"
2024-03-16 00:08:47 +01:00
.}: bool
relayPeerExchange * {.
desc : "Enable gossipsub peer exchange in relay protocol: true|false" ,
defaultValue : false ,
name : "relay-peer-exchange"
.}: bool
relayShardedPeerManagement * {.
desc :
"Enable experimental shard aware peer manager for relay protocol: true|false" ,
defaultValue : false ,
name : "relay-shard-manager"
.}: bool
2026-06-10 09:09:22 -03:00
# Option-typed; desc states the default since the CLI can't auto-show it for none().
2024-03-16 00:08:47 +01:00
rlnRelay * {.
2026-06-10 09:09:22 -03:00
desc :
"Enable spam protection through rln-relay: true|false. Default is " &
$ DefaultRlnRelayEnabled & "." ,
defaultValue : none ( bool ),
2024-03-16 00:08:47 +01:00
name : "rln-relay"
2026-06-10 09:09:22 -03:00
.}: Option [ bool ]
2024-03-16 00:08:47 +01:00
rlnRelayCredIndex * {.
desc : "the index of the onchain commitment to use" ,
name : "rln-relay-membership-index"
.}: Option [ uint ]
rlnRelayDynamic * {.
2025-04-01 09:28:18 +11:00
desc : "Enable waku-rln-relay with on-chain dynamic group management: true|false." ,
2026-06-10 09:09:22 -03:00
defaultValue : none ( bool ),
2024-03-16 00:08:47 +01:00
name : "rln-relay-dynamic"
2026-06-10 09:09:22 -03:00
.}: Option [ bool ]
2024-03-16 00:08:47 +01:00
2026-03-03 19:17:54 +01:00
entryNodes * {.
desc :
"Entry node address (enrtree:, enr:, or multiaddr). " &
"Automatically classified and distributed to DNS discovery, discv5 bootstrap, " &
"and static nodes. Argument may be repeated." ,
name : "entry-node"
.}: seq [ string ]
2024-03-16 00:08:47 +01:00
staticnodes * {.
desc : "Peer multiaddr to directly connect with. Argument may be repeated." ,
name : "staticnode"
.}: seq [ string ]
2025-07-16 15:26:59 +02:00
keepAlive * {.
2025-07-18 15:34:14 +02:00
desc :
"Deprecated since >=v0.37. This param is ignored and keep alive is always active" ,
2025-07-16 15:26:59 +02:00
defaultValue : true ,
name : "keep-alive"
.}: bool
2024-09-10 15:07:12 -06:00
numShardsInNetwork * {.
2025-07-04 17:10:53 +10:00
desc :
"Enables autosharding and set number of shards in the cluster, set to `0` to use static sharding" ,
2026-04-08 15:33:16 +02:00
defaultValue : 0 ,
2024-09-10 15:07:12 -06:00
name : "num-shards-in-network"
2025-07-04 17:10:53 +10:00
.}: uint16
2024-09-10 15:07:12 -06:00
2024-03-16 00:08:47 +01:00
shards * {.
2024-09-10 15:07:12 -06:00
desc :
2025-07-04 17:10:53 +10:00
"Shards index to subscribe to [0..NUM_SHARDS_IN_NETWORK-1]. Argument may be repeated. Subscribes to all shards by default in auto-sharding, no shard for static sharding" ,
2024-03-16 00:08:47 +01:00
name : "shard"
2024-06-05 15:32:35 +02:00
.}: seq [ uint16 ]
2024-03-16 00:08:47 +01:00
contentTopics * {.
desc : "Default content topic to subscribe to. Argument may be repeated." ,
name : "content-topic"
.}: seq [ string ]
## Store and message store config
store * {.
desc : "Enable/disable waku store protocol" , defaultValue : false , name : "store"
.}: bool
storenode * {.
desc : "Peer multiaddress to query for storage" ,
defaultValue : "" ,
name : "storenode"
.}: string
storeMessageRetentionPolicy * {.
desc :
2026-03-19 21:37:04 +01:00
"Message store retention policy. Multiple policies may be provided as a semicolon-separated string and are applied as a union. Time retention policy: 'time:<seconds>'. Capacity retention policy: 'capacity:<count>'. Size retention policy: 'size:<xMB/xGB>'. Set to 'none' to disable. Example: 'time:3600;size:1GB;capacity:100'." ,
2024-03-16 00:08:47 +01:00
defaultValue : "time:" & $ 2. days . seconds ,
name : "store-message-retention-policy"
.}: string
storeMessageDbUrl * {.
desc : "The database connection URL for peristent storage." ,
defaultValue : "sqlite://store.sqlite3" ,
name : "store-message-db-url"
.}: string
storeMessageDbVacuum * {.
desc :
"Enable database vacuuming at start. Only supported by SQLite database engine." ,
defaultValue : false ,
name : "store-message-db-vacuum"
.}: bool
storeMessageDbMigration * {.
desc : "Enable database migration at start." ,
defaultValue : true ,
name : "store-message-db-migration"
.}: bool
storeMaxNumDbConnections * {.
desc : "Maximum number of simultaneous Postgres connections." ,
defaultValue : 50 ,
name : "store-max-num-db-connections"
.}: int
2024-07-30 07:23:39 -04:00
storeResume * {.
desc : "Enable store resume functionality" ,
defaultValue : false ,
name : "store-resume"
.}: bool
2024-08-13 07:27:34 -04:00
## Sync config
storeSync * {.
desc : "Enable store sync protocol: true|false" ,
defaultValue : false ,
name : "store-sync"
.}: bool
storeSyncInterval * {.
desc : "Interval between store sync attempts. In seconds." ,
2024-08-28 10:26:38 -04:00
defaultValue : 300 , # 5 minutes
2024-08-13 07:27:34 -04:00
name : "store-sync-interval"
2025-05-08 07:05:35 +10:00
.}: uint32
2024-08-13 07:27:34 -04:00
storeSyncRange * {.
desc : "Amount of time to sync. In seconds." ,
2024-08-28 10:26:38 -04:00
defaultValue : 3600 , # 1 hours
2024-08-13 07:27:34 -04:00
name : "store-sync-range"
2025-05-08 07:05:35 +10:00
.}: uint32
2024-08-13 07:27:34 -04:00
storeSyncRelayJitter * {.
hidden ,
desc : "Time offset to account for message propagation jitter. In seconds." ,
defaultValue : 20 ,
name : "store-sync-relay-jitter"
2025-05-08 07:05:35 +10:00
.}: uint32
2024-08-13 07:27:34 -04:00
2024-03-16 00:08:47 +01:00
## Filter config
filter * {.
desc : "Enable filter protocol: true|false" , defaultValue : false , name : "filter"
.}: bool
filternode * {.
desc : "Peer multiaddr to request content filtering of messages." ,
defaultValue : "" ,
name : "filternode"
.}: string
filterSubscriptionTimeout * {.
desc :
"Timeout for filter subscription without ping or refresh it, in seconds. Only for v2 filter protocol." ,
defaultValue : 300 , # 5 minutes
name : "filter-subscription-timeout"
2025-05-08 07:05:35 +10:00
.}: uint16
2024-03-16 00:08:47 +01:00
filterMaxPeersToServe * {.
desc : "Maximum number of peers to serve at a time. Only for v2 filter protocol." ,
defaultValue : 1000 ,
name : "filter-max-peers-to-serve"
.}: uint32
filterMaxCriteria * {.
desc :
"Maximum number of pubsub- and content topic combination per peers at a time. Only for v2 filter protocol." ,
defaultValue : 1000 ,
name : "filter-max-criteria"
.}: uint32
## Lightpush config
lightpush * {.
desc : "Enable lightpush protocol: true|false" ,
defaultValue : false ,
name : "lightpush"
.}: bool
lightpushnode * {.
desc : "Peer multiaddr to request lightpush of published messages." ,
defaultValue : "" ,
name : "lightpushnode"
.}: string
2024-08-27 16:49:46 +02:00
## Reliability config
2026-06-10 09:09:22 -03:00
# Option-typed; desc states the default since the CLI can't auto-show it for none().
2024-08-27 16:49:46 +02:00
reliabilityEnabled * {.
desc :
2026-06-10 09:09:22 -03:00
"""Adds an extra effort in the delivery/reception of messages by leveraging store-v3 requests, with the drawback of consuming some more bandwidth. Default is """ &
$ DefaultP2pReliability & "." ,
defaultValue : none ( bool ),
2024-08-27 16:49:46 +02:00
name : "reliability"
2026-06-10 09:09:22 -03:00
.}: Option [ bool ]
2024-08-27 16:49:46 +02:00
2024-03-16 00:08:47 +01:00
## REST HTTP config
rest * {.
2026-03-03 23:48:00 +01:00
desc : "Enable Waku REST HTTP server: true|false" ,
defaultValue : false ,
name : "rest"
2024-03-16 00:08:47 +01:00
.}: bool
restAddress * {.
desc : "Listening address of the REST HTTP server." ,
2026-04-08 12:42:14 +02:00
defaultValue :
IpAddress ( family : IpAddressFamily . IPv4 , address_v4 : [ 127'u8 , 0 , 0 , 1 ] ),
2024-03-16 00:08:47 +01:00
name : "rest-address"
.}: IpAddress
restPort * {.
desc : "Listening port of the REST HTTP server." ,
defaultValue : 8645 ,
name : "rest-port"
.}: uint16
restRelayCacheCapacity * {.
desc : "Capacity of the Relay REST API message cache." ,
2025-06-13 15:08:47 +05:30
defaultValue : 50 ,
2024-03-16 00:08:47 +01:00
name : "rest-relay-cache-capacity"
.}: uint32
restAdmin * {.
desc : "Enable access to REST HTTP Admin API: true|false" ,
defaultValue : false ,
name : "rest-admin"
.}: bool
restAllowOrigin * {.
desc :
"Allow cross-origin requests from the specified origin." &
"Argument may be repeated." & "Wildcards: * or ? allowed." &
"Ex.: \" localhost:* \" or \" 127.0.0.1:8080 \" " ,
defaultValue : newSeq [ string ] (),
name : "rest-allow-origin"
.}: seq [ string ]
## Metrics config
metricsServer * {.
desc : "Enable the metrics server: true|false" ,
defaultValue : false ,
name : "metrics-server"
.}: bool
metricsServerAddress * {.
desc : "Listening address of the metrics server." ,
2026-04-08 12:42:14 +02:00
defaultValue :
IpAddress ( family : IpAddressFamily . IPv4 , address_v4 : [ 127'u8 , 0 , 0 , 1 ] ),
2024-03-16 00:08:47 +01:00
name : "metrics-server-address"
.}: IpAddress
metricsServerPort * {.
desc : "Listening HTTP port of the metrics server." ,
defaultValue : 8008 ,
name : "metrics-server-port"
.}: uint16
metricsLogging * {.
desc : "Enable metrics logging: true|false" ,
defaultValue : true ,
name : "metrics-logging"
.}: bool
## DNS discovery config
dnsDiscovery * {.
2025-02-24 22:06:48 +02:00
desc :
"Deprecated, please set dns-discovery-url instead. Enable discovering nodes via DNS" ,
2024-03-16 00:08:47 +01:00
defaultValue : false ,
name : "dns-discovery"
.}: bool
dnsDiscoveryUrl * {.
2025-07-03 11:56:43 +10:00
desc :
"URL for DNS node list in format 'enrtree://<key>@<fqdn>', enables DNS Discovery" ,
2024-03-16 00:08:47 +01:00
defaultValue : "" ,
name : "dns-discovery-url"
.}: string
## Discovery v5 config
2026-06-10 09:09:22 -03:00
# Option-typed; desc states the default since the CLI can't auto-show it for none().
2024-03-16 00:08:47 +01:00
discv5Discovery * {.
2026-06-10 09:09:22 -03:00
desc :
"Enable discovering nodes via Node Discovery v5. Default is " &
$ DefaultDiscv5Enabled & "." ,
2025-05-08 07:05:35 +10:00
defaultValue : none ( bool ),
2024-03-16 00:08:47 +01:00
name : "discv5-discovery"
2025-05-08 07:05:35 +10:00
.}: Option [ bool ]
2024-03-16 00:08:47 +01:00
discv5UdpPort * {.
desc : "Listening UDP port for Node Discovery v5." ,
defaultValue : 9000 ,
name : "discv5-udp-port"
.}: Port
discv5BootstrapNodes * {.
desc :
"Text-encoded ENR for bootstrap node. Used when connecting to the network. Argument may be repeated." ,
name : "discv5-bootstrap-node"
.}: seq [ string ]
discv5EnrAutoUpdate * {.
desc :
"Discovery can automatically update its ENR with the IP address " &
"and UDP port as seen by other nodes it communicates with. " &
"This option allows to enable/disable this functionality" ,
defaultValue : false ,
name : "discv5-enr-auto-update"
.}: bool
discv5TableIpLimit * {.
hidden ,
desc : "Maximum amount of nodes with the same IP in discv5 routing tables" ,
defaultValue : 10 ,
name : "discv5-table-ip-limit"
.}: uint
discv5BucketIpLimit * {.
hidden ,
desc : "Maximum amount of nodes with the same IP in discv5 routing table buckets" ,
defaultValue : 2 ,
name : "discv5-bucket-ip-limit"
.}: uint
discv5BitsPerHop * {.
hidden ,
desc : "Kademlia's b variable, increase for less hops per lookup" ,
2024-02-09 16:31:45 +05:30
defaultValue : 1 ,
2024-03-16 00:08:47 +01:00
name : "discv5-bits-per-hop"
.}: int
## waku peer exchange config
peerExchange * {.
desc : "Enable waku peer exchange protocol (responder side): true|false" ,
2026-06-10 09:09:22 -03:00
defaultValue : DefaultCLIPeerExchange ,
2024-03-16 00:08:47 +01:00
name : "peer-exchange"
.}: bool
peerExchangeNode * {.
desc :
"Peer multiaddr to send peer exchange requests to. (enables peer exchange protocol requester side)" ,
defaultValue : "" ,
name : "peer-exchange-node"
.}: string
2024-12-09 15:22:36 -05:00
## Rendez vous
rendezvous * {.
desc : "Enable waku rendezvous discovery server" ,
2026-06-10 09:09:22 -03:00
defaultValue : DefaultCLIRendezvous ,
2024-12-09 15:22:36 -05:00
name : "rendezvous"
.}: bool
2025-09-11 20:40:01 +05:30
#Mix config
2026-06-10 09:09:22 -03:00
# Option-typed; desc states the default since the CLI can't auto-show it for none().
mix * {.
desc : "Enable mix protocol: true|false. Default is " & $ DefaultMix & "." ,
defaultValue : none ( bool ),
name : "mix"
.}: Option [ bool ]
2025-09-11 20:40:01 +05:30
mixkey * {.
desc :
"ED25519 private key as 64 char hex string , without 0x. If not provided, a random key will be generated." ,
name : "mixkey"
.}: Option [ string ]
2025-10-08 10:18:54 +05:30
mixnodes * {.
desc :
"Multiaddress and mix-key of mix node to be statically specified in format multiaddr:mixPubKey. Argument may be repeated." ,
name : "mixnode"
.}: seq [ MixNodePubInfo ]
2026-02-19 10:26:17 +05:30
# Kademlia Discovery config
2026-06-10 09:09:22 -03:00
# Option-typed; desc states the default since the CLI can't auto-show it for none().
2026-02-19 10:26:17 +05:30
enableKadDiscovery * {.
desc :
2026-06-10 09:09:22 -03:00
"Enable extended kademlia discovery. Can be enabled without bootstrap nodes for the first node in the network. Default is " &
$ DefaultKadEnabled & "." ,
defaultValue : none ( bool ),
2026-02-19 10:26:17 +05:30
name : "enable-kad-discovery"
2026-06-10 09:09:22 -03:00
.}: Option [ bool ]
2026-02-19 10:26:17 +05:30
kadBootstrapNodes * {.
desc :
"Peer multiaddr for kademlia discovery bootstrap node (must include /p2p/<peerID>). Argument may be repeated." ,
name : "kad-bootstrap-node"
.}: seq [ string ]
2026-06-18 12:51:27 -04:00
kadRandomLookupIntervalSec * {.
desc : "Interval seconds between random kademlia lookups." ,
defaultValue : 60 ,
name : "kad-random-lookup-interval"
.}: uint32
kadServiceLookupIntervalSec * {.
desc : "Interval seconds between service-specific kademlia lookups." ,
defaultValue : 60 ,
name : "kad-service-lookup-interval"
.}: uint32
2024-03-16 00:08:47 +01:00
## websocket config
websocketSupport * {.
desc : "Enable websocket: true|false" ,
defaultValue : false ,
name : "websocket-support"
.}: bool
websocketPort * {.
desc : "WebSocket listening port." , defaultValue : 8000 , name : "websocket-port"
.}: Port
websocketSecureSupport * {.
desc : "Enable secure websocket: true|false" ,
defaultValue : false ,
name : "websocket-secure-support"
.}: bool
websocketSecureKeyPath * {.
desc : "Secure websocket key path: '/path/to/key.txt' " ,
defaultValue : "" ,
name : "websocket-secure-key-path"
.}: string
websocketSecureCertPath * {.
desc : "Secure websocket Certificate path: '/path/to/cert.txt' " ,
defaultValue : "" ,
name : "websocket-secure-cert-path"
.}: string
2021-11-02 10:29:11 +00:00
2026-06-17 07:55:45 -03:00
## quic config
quicSupport * {.
desc : "Enable QUIC transport: true|false" ,
defaultValue : false ,
name : "quic-support"
.}: bool
quicPort * {.
desc : "QUIC (UDP) listening port." , defaultValue : 60000 , name : "quic-port"
.}: Port
2024-09-18 15:58:07 +02:00
## Rate limitation config, if not set, rate limit checks will not be performed
rateLimits * {.
2024-04-15 15:28:35 +02:00
desc :
2024-09-18 15:58:07 +02:00
"Rate limit settings for different protocols." &
"Format: protocol:volume/period<unit>" &
2026-03-30 00:08:08 +02:00
" Where 'protocol' can be one of: <store|storev3|lightpush|px|filter> if not defined it means a global setting" &
2024-09-18 15:58:07 +02:00
" 'volume' and period must be an integer value. " &
" 'unit' must be one of <h|m|s|ms> - hours, minutes, seconds, milliseconds respectively. " &
"Argument may be repeated." ,
defaultValue : newSeq [ string ] ( 0 ),
name : "rate-limit"
.}: seq [ string ]
2024-04-15 15:28:35 +02:00
2026-05-16 00:09:07 +02:00
localStoragePath * {.
desc : "Path to store local data." ,
defaultValue : "./data" ,
name : "local-storage-path"
.}: string
2022-12-07 12:30:32 +01:00
## Parsing
2020-05-21 12:16:00 +08:00
# NOTE: Keys are different in nim-libp2p
2022-11-02 14:55:48 +01:00
proc parseCmdArg * ( T : type crypto . PrivateKey , p : string ): T =
2020-04-29 12:49:27 +08:00
try :
2020-05-26 11:55:53 +08:00
let key = SkPrivateKey . init ( utils . fromHex ( p )). tryGet ()
2022-11-03 10:45:06 +01:00
crypto . PrivateKey ( scheme : Secp256k1 , skkey : key )
2023-04-04 15:34:53 +02:00
except CatchableError :
2023-09-21 13:12:14 +02:00
raise newException ( ValueError , "Invalid private key" )
2020-04-29 12:49:27 +08:00
2024-05-10 10:56:17 +02:00
proc parseCmdArg *[ T ] ( _ : type seq [ T ] , s : string ): seq [ T ] {. raises : [ ValueError ] .} =
var
inputSeq : JsonNode
res : seq [ T ] = @[]
try :
inputSeq = s . parseJson ()
except Exception :
raise newException ( ValueError , fmt"Could not parse sequence: {s}" )
for entry in inputSeq :
let formattedString = ( $ entry ). strip ( chars = { ' \" ' })
res . add ( parseCmdArg ( T , formattedString ))
return res
2022-11-02 14:55:48 +01:00
proc completeCmdArg * ( T : type crypto . PrivateKey , val : string ): seq [ string ] =
2020-04-29 12:49:27 +08:00
return @[]
2024-08-19 12:56:22 +02:00
# TODO: Remove when removing protected-topic configuration
proc isNumber ( x : string ): bool =
try :
discard parseInt ( x )
result = true
except ValueError :
result = false
2025-10-08 10:18:54 +05:30
proc parseCmdArg * ( T : type MixNodePubInfo , p : string ): T =
let elements = p . split ( ":" )
if elements . len != 2 :
raise newException (
ValueError , "Invalid format for mix node expected multiaddr:mixPublicKey"
)
let multiaddr = MultiAddress . init ( elements [ 0 ] ). valueOr :
raise newException ( ValueError , "Invalid multiaddress format" )
if not multiaddr . contains ( multiCodec ( "ip4" )). get ():
raise newException (
ValueError , "Invalid format for ip address, expected a ipv4 multiaddress"
)
return MixNodePubInfo (
multiaddr : elements [ 0 ] , pubKey : intoCurve25519Key ( ncrutils . fromHex ( elements [ 1 ] ))
)
2024-08-19 12:56:22 +02:00
proc parseCmdArg * ( T : type ProtectedShard , p : string ): T =
2023-05-02 11:45:50 +02:00
let elements = p . split ( ":" )
if elements . len != 2 :
2024-03-16 00:08:47 +01:00
raise newException (
2024-08-19 12:56:22 +02:00
ValueError , "Invalid format for protected shard expected shard:publickey"
2024-03-16 00:08:47 +01:00
)
2025-10-27 14:07:06 -03:00
let publicKey = secp256k1 . SkPublicKey . fromHex ( elements [ 1 ] ). valueOr :
2023-09-21 13:12:14 +02:00
raise newException ( ValueError , "Invalid public key" )
2023-05-02 11:45:50 +02:00
2024-08-19 12:56:22 +02:00
if isNumber ( elements [ 0 ] ):
2025-10-27 14:07:06 -03:00
return ProtectedShard ( shard : uint16 . parseCmdArg ( elements [ 0 ] ), key : publicKey )
2023-05-02 11:45:50 +02:00
2024-08-19 12:56:22 +02:00
# TODO: Remove when removing protected-topic configuration
let shard = RelayShard . parse ( elements [ 0 ] ). valueOr :
raise newException (
ValueError ,
"Invalid pubsub topic. Pubsub topics must be in the format /waku/2/rs/<cluster-id>/<shard-id>" ,
)
2025-10-27 14:07:06 -03:00
return ProtectedShard ( shard : shard . shardId , key : publicKey )
2024-08-19 12:56:22 +02:00
proc completeCmdArg * ( T : type ProtectedShard , val : string ): seq [ string ] =
2023-05-02 11:45:50 +02:00
return @[]
2022-12-07 12:30:32 +01:00
2023-12-14 07:16:39 +01:00
proc completeCmdArg * ( T : type IpAddress , val : string ): seq [ string ] =
2020-04-29 12:49:27 +08:00
return @[]
2020-07-24 09:39:58 +08:00
2023-12-14 07:16:39 +01:00
proc defaultListenAddress * (): IpAddress =
2025-05-08 07:05:35 +10:00
# TODO: Should probably listen on both ipv4 and ipv6 by default.
2026-04-08 12:42:14 +02:00
( static IpAddress ( family : IpAddressFamily . IPv4 , address_v4 : [ 0'u8 , 0 , 0 , 0 ] ))
2022-05-17 17:48:08 +02:00
2024-01-02 14:01:18 +01:00
proc defaultColocationLimit * (): int =
return DefaultColocationLimit
2022-12-07 12:30:32 +01:00
proc completeCmdArg * ( T : type Port , val : string ): seq [ string ] =
return @[]
2022-05-17 17:48:08 +02:00
2024-02-16 18:36:31 +05:30
proc completeCmdArg * ( T : type EthRpcUrl , val : string ): seq [ string ] =
return @[]
proc parseCmdArg * ( T : type EthRpcUrl , s : string ): T =
## allowed patterns:
## http://url:port
## https://url:port
## http://url:port/path
## https://url:port/path
## http://url/with/path
## http://url:port/path?query
## https://url:port/path?query
2025-07-31 23:17:29 +05:30
## https://username:password@url:port/path
## https://username:password@url:port/path?query
## supports IPv4, IPv6, URL-encoded credentials
2024-02-16 18:36:31 +05:30
## disallowed patterns:
## any valid/invalid ws or wss url
2024-03-16 00:08:47 +01:00
var httpPattern =
2025-07-31 23:17:29 +05:30
re2"^(https?):\/\/(([^\s:@]*(?:%[0-9A-Fa-f]{2})*):([^\s:@]*(?:%[0-9A-Fa-f]{2})*)@)?((?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|\[[0-9a-fA-F:]+\])(?::([0-9]{1,5}))?(\/[^\s?#]*)?(\?[^\s#]*)?(#[^\s]*)?$"
2024-03-16 00:08:47 +01:00
var wsPattern =
2024-04-02 15:14:55 +02:00
re2"^(wss?):\/\/([\w-]+(\.[\w-]+)+)(:[0-9]{1,5})?(\/[\w.,@?^=%&:\/~+#-]*)?$"
2024-02-16 18:36:31 +05:30
if regex . match ( s , wsPattern ):
2024-03-16 00:08:47 +01:00
raise newException (
ValueError , "Websocket RPC URL is not supported, Please use an HTTP URL"
)
2024-02-16 18:36:31 +05:30
if not regex . match ( s , httpPattern ):
raise newException ( ValueError , "Invalid HTTP RPC URL" )
return EthRpcUrl ( s )
2022-11-03 10:45:06 +01:00
## Load
2024-03-16 00:08:47 +01:00
proc readValue * (
r : var TomlReader , value : var crypto . PrivateKey
) {. raises : [ SerializationError ] .} =
2022-11-23 10:08:00 +01:00
try :
2022-11-03 10:45:06 +01:00
value = parseCmdArg ( crypto . PrivateKey , r . readValue ( string ))
except CatchableError :
raise newException ( SerializationError , getCurrentExceptionMsg ())
2024-03-16 00:08:47 +01:00
proc readValue * (
r : var EnvvarReader , value : var crypto . PrivateKey
) {. raises : [ SerializationError ] .} =
2022-11-23 10:08:00 +01:00
try :
2022-11-03 17:58:48 +01:00
value = parseCmdArg ( crypto . PrivateKey , r . readValue ( string ))
except CatchableError :
raise newException ( SerializationError , getCurrentExceptionMsg ())
2025-10-08 10:18:54 +05:30
proc readValue * (
r : var TomlReader , value : var MixNodePubInfo
) {. raises : [ SerializationError ] .} =
try :
value = parseCmdArg ( MixNodePubInfo , r . readValue ( string ))
except CatchableError :
raise newException ( SerializationError , getCurrentExceptionMsg ())
proc readValue * (
r : var EnvvarReader , value : var MixNodePubInfo
) {. raises : [ SerializationError ] .} =
try :
value = parseCmdArg ( MixNodePubInfo , r . readValue ( string ))
except CatchableError :
raise newException ( SerializationError , getCurrentExceptionMsg ())
2024-03-16 00:08:47 +01:00
proc readValue * (
2024-08-19 12:56:22 +02:00
r : var TomlReader , value : var ProtectedShard
2024-03-16 00:08:47 +01:00
) {. raises : [ SerializationError ] .} =
2023-05-02 11:45:50 +02:00
try :
2024-08-19 12:56:22 +02:00
value = parseCmdArg ( ProtectedShard , r . readValue ( string ))
2023-05-02 11:45:50 +02:00
except CatchableError :
raise newException ( SerializationError , getCurrentExceptionMsg ())
2024-03-16 00:08:47 +01:00
proc readValue * (
2024-08-19 12:56:22 +02:00
r : var EnvvarReader , value : var ProtectedShard
2024-03-16 00:08:47 +01:00
) {. raises : [ SerializationError ] .} =
2023-05-02 11:45:50 +02:00
try :
2024-08-19 12:56:22 +02:00
value = parseCmdArg ( ProtectedShard , r . readValue ( string ))
2023-05-02 11:45:50 +02:00
except CatchableError :
raise newException ( SerializationError , getCurrentExceptionMsg ())
2022-11-03 10:45:06 +01:00
2024-03-16 00:08:47 +01:00
proc readValue * (
r : var TomlReader , value : var EthRpcUrl
) {. raises : [ SerializationError ] .} =
2024-02-16 18:36:31 +05:30
try :
value = parseCmdArg ( EthRpcUrl , r . readValue ( string ))
except CatchableError :
raise newException ( SerializationError , getCurrentExceptionMsg ())
2024-03-16 00:08:47 +01:00
proc readValue * (
r : var EnvvarReader , value : var EthRpcUrl
) {. raises : [ SerializationError ] .} =
2024-02-16 18:36:31 +05:30
try :
value = parseCmdArg ( EthRpcUrl , r . readValue ( string ))
except CatchableError :
raise newException ( SerializationError , getCurrentExceptionMsg ())
2024-03-16 00:08:47 +01:00
proc load * ( T : type WakuNodeConf , version = "" ): ConfResult [ T ] =
2022-11-03 10:45:06 +01:00
try :
let conf = WakuNodeConf . load (
2024-03-16 00:08:47 +01:00
version = version ,
secondarySources = proc (
conf : WakuNodeConf , sources : auto
) {. gcsafe , raises : [ ConfigurationError ] .} =
2022-11-03 17:58:48 +01:00
sources . addConfigFile ( Envvar , InputFile ( "wakunode2" ))
2022-11-03 10:45:06 +01:00
if conf . configFile . isSome ():
sources . addConfigFile ( Toml , conf . configFile . get ())
2024-03-16 00:08:47 +01:00
,
2022-11-03 10:45:06 +01:00
)
2024-09-18 15:58:07 +02:00
2022-11-03 10:45:06 +01:00
ok ( conf )
except CatchableError :
err ( getCurrentExceptionMsg ())
2024-05-10 10:56:17 +02:00
proc defaultWakuNodeConf * (): ConfResult [ WakuNodeConf ] =
try :
let conf = WakuNodeConf . load ( version = "" , cmdLine = @[] )
return ok ( conf )
except CatchableError :
return err ( "exception in defaultWakuNodeConf: " & getCurrentExceptionMsg ())
2025-05-08 07:05:35 +10:00
proc toKeystoreGeneratorConf * ( n : WakuNodeConf ): RlnKeystoreGeneratorConf =
RlnKeystoreGeneratorConf (
execute : n . execute ,
2025-05-26 21:58:02 +02:00
chainId : UInt256 . fromBytesBE ( n . rlnRelayChainId . toBytesBE ()),
2025-05-12 10:57:13 +02:00
ethClientUrls : n . ethClientUrls . mapIt ( string ( it )),
2025-05-08 07:05:35 +10:00
ethContractAddress : n . rlnRelayEthContractAddress ,
2026-06-10 09:09:22 -03:00
userMessageLimit : n . rlnRelayUserMessageLimit . get ( DefaultRlnRelayUserMessageLimit ),
2025-05-08 07:05:35 +10:00
ethPrivateKey : n . rlnRelayEthPrivateKey ,
credPath : n . rlnRelayCredPath ,
credPassword : n . rlnRelayCredPassword ,
)
2026-06-10 09:09:22 -03:00
proc toNetworkPresetConf (
2025-05-08 07:05:35 +10:00
preset : string , clusterId : Option [ uint16 ]
2026-06-10 09:09:22 -03:00
): ConfResult [ Option [ NetworkPresetConf ]] =
2025-05-08 07:05:35 +10:00
var lcPreset = toLowerAscii ( preset )
if clusterId . isSome () and clusterId . get () == 1 :
warn (
"TWN - The Waku Network configuration will not be applied when `--cluster-id=1` is passed in future releases. Use `--preset=twn` instead."
)
lcPreset = "twn"
2026-03-03 19:17:54 +01:00
if clusterId . isSome () and clusterId . get () == 2 :
warn (
"Logos.dev - Logos.dev configuration will not be applied when `--cluster-id=2` is passed in future releases. Use `--preset=logos.dev` instead."
)
lcPreset = "logos.dev"
2025-05-08 07:05:35 +10:00
case lcPreset
of "" :
2026-06-10 09:09:22 -03:00
ok ( none ( NetworkPresetConf ))
2025-05-08 07:05:35 +10:00
of "twn" :
2026-06-10 09:09:22 -03:00
ok ( some ( NetworkPresetConf . TheWakuNetworkConf ()))
2026-03-03 19:17:54 +01:00
of "logos.dev" , "logosdev" :
2026-06-10 09:09:22 -03:00
ok ( some ( NetworkPresetConf . LogosDevConf ()))
2026-05-21 18:29:33 +01:00
of "logos.test" , "logostest" :
2026-06-10 09:09:22 -03:00
ok ( some ( NetworkPresetConf . LogosTestConf ()))
2025-05-08 07:05:35 +10:00
else :
err ( "Invalid --preset value passed: " & lcPreset )
proc toWakuConf * ( n : WakuNodeConf ): ConfResult [ WakuConf ] =
var b = WakuConfBuilder . init ()
2026-06-10 09:09:22 -03:00
let networkPresetConf = toNetworkPresetConf ( n . preset , n . clusterId ). valueOr :
2026-03-25 13:23:20 +01:00
return err ( "Error determining cluster from preset: " & $ error )
2026-06-10 09:09:22 -03:00
if networkPresetConf . isSome ():
b . withNetworkPresetConf ( networkPresetConf . get ())
2026-03-25 13:23:20 +01:00
2025-05-08 07:05:35 +10:00
b . withLogLevel ( n . logLevel )
b . withLogFormat ( n . logFormat )
2026-06-10 09:09:22 -03:00
if n . rlnRelay . isSome ():
b . rlnRelayConf . withEnabled ( n . rlnRelay . get ())
2025-05-08 07:05:35 +10:00
if n . rlnRelayCredPath != "" :
b . rlnRelayConf . withCredPath ( n . rlnRelayCredPath )
if n . rlnRelayCredPassword != "" :
b . rlnRelayConf . withCredPassword ( n . rlnRelayCredPassword )
2025-05-12 10:57:13 +02:00
if n . ethClientUrls . len > 0 :
b . rlnRelayConf . withEthClientUrls ( n . ethClientUrls . mapIt ( string ( it )))
2025-05-08 07:05:35 +10:00
if n . rlnRelayEthContractAddress != "" :
b . rlnRelayConf . withEthContractAddress ( n . rlnRelayEthContractAddress )
if n . rlnRelayChainId != 0 :
b . rlnRelayConf . withChainId ( n . rlnRelayChainId )
2026-06-10 09:09:22 -03:00
if n . rlnRelayUserMessageLimit . isSome ():
b . rlnRelayConf . withUserMessageLimit ( n . rlnRelayUserMessageLimit . get ())
if n . rlnEpochSizeSec . isSome ():
b . rlnRelayConf . withEpochSizeSec ( n . rlnEpochSizeSec . get ())
2025-05-08 07:05:35 +10:00
if n . rlnRelayCredIndex . isSome ():
b . rlnRelayConf . withCredIndex ( n . rlnRelayCredIndex . get ())
2026-06-10 09:09:22 -03:00
if n . rlnRelayDynamic . isSome ():
b . rlnRelayConf . withDynamic ( n . rlnRelayDynamic . get ())
2025-05-08 07:05:35 +10:00
if n . maxMessageSize != "" :
b . withMaxMessageSize ( n . maxMessageSize )
b . withProtectedShards ( n . protectedShards )
2026-06-10 09:09:22 -03:00
if n . clusterId . isSome ():
b . withClusterId ( n . clusterId . get ())
2025-05-08 07:05:35 +10:00
b . withAgentString ( n . agentString )
if n . nodeKey . isSome ():
b . withNodeKey ( n . nodeKey . get ())
b . withP2pListenAddress ( n . listenAddress )
b . withP2pTcpPort ( n . tcpPort )
b . withPortsShift ( n . portsShift )
b . withNatStrategy ( n . nat )
b . withExtMultiAddrs ( n . extMultiAddrs )
b . withExtMultiAddrsOnly ( n . extMultiAddrsOnly )
b . withMaxConnections ( n . maxConnections )
if n . relayServiceRatio != "" :
b . withRelayServiceRatio ( n . relayServiceRatio )
b . withColocationLimit ( n . colocationLimit )
if n . peerStoreCapacity . isSome :
b . withPeerStoreCapacity ( n . peerStoreCapacity . get ())
b . withPeerPersistence ( n . peerPersistence )
b . withDnsAddrsNameServers ( n . dnsAddrsNameServers )
b . withDns4DomainName ( n . dns4DomainName )
b . withCircuitRelayClient ( n . isRelayClient )
b . withRelay ( n . relay )
b . withRelayPeerExchange ( n . relayPeerExchange )
b . withRelayShardedPeerManagement ( n . relayShardedPeerManagement )
b . withStaticNodes ( n . staticNodes )
2026-03-03 19:17:54 +01:00
# Process entry nodes - supports enrtree:, enr:, and multiaddress formats
if n . entryNodes . len > 0 :
let ( enrTreeUrls , bootstrapEnrs , staticNodesFromEntry ) = processEntryNodes (
n . entryNodes
). valueOr :
return err ( "Failed to process entry nodes: " & error )
# Set ENRTree URLs for DNS discovery
if enrTreeUrls . len > 0 :
for url in enrTreeUrls :
b . dnsDiscoveryConf . withEnrTreeUrl ( url )
# Set ENR records as bootstrap nodes for discv5
if bootstrapEnrs . len > 0 :
b . discv5Conf . withBootstrapNodes ( bootstrapEnrs )
# Add static nodes (multiaddrs and those extracted from ENR entries)
if staticNodesFromEntry . len > 0 :
b . withStaticNodes ( staticNodesFromEntry )
2025-05-08 07:05:35 +10:00
if n . numShardsInNetwork != 0 :
2025-07-04 17:10:53 +10:00
b . withNumShardsInCluster ( n . numShardsInNetwork )
b . withShardingConf ( AutoSharding )
2026-06-10 09:09:22 -03:00
elif networkPresetConf . isNone ():
2025-07-04 17:10:53 +10:00
b . withShardingConf ( StaticSharding )
# It is not possible to pass an empty sequence on the CLI
# If this is empty, it means the user did not specify any shards
if n . shards . len != 0 :
b . withSubscribeShards ( n . shards )
2025-05-08 07:05:35 +10:00
b . withContentTopics ( n . contentTopics )
b . storeServiceConf . withEnabled ( n . store )
2026-03-19 21:37:04 +01:00
b . storeServiceConf . withRetentionPolicies ( n . storeMessageRetentionPolicy )
2025-05-08 07:05:35 +10:00
b . storeServiceConf . withDbUrl ( n . storeMessageDbUrl )
b . storeServiceConf . withDbVacuum ( n . storeMessageDbVacuum )
b . storeServiceConf . withDbMigration ( n . storeMessageDbMigration )
b . storeServiceConf . withMaxNumDbConnections ( n . storeMaxNumDbConnections )
b . storeServiceConf . withResume ( n . storeResume )
# TODO: can we just use `Option` on the CLI?
if n . storenode != "" :
b . withRemoteStoreNode ( n . storenode )
if n . filternode != "" :
b . withRemoteFilterNode ( n . filternode )
if n . lightpushnode != "" :
b . withRemoteLightPushNode ( n . lightpushnode )
if n . peerExchangeNode != "" :
b . withRemotePeerExchangeNode ( n . peerExchangeNode )
b . storeServiceConf . storeSyncConf . withEnabled ( n . storeSync )
b . storeServiceConf . storeSyncConf . withIntervalSec ( n . storeSyncInterval )
b . storeServiceConf . storeSyncConf . withRangeSec ( n . storeSyncRange )
b . storeServiceConf . storeSyncConf . withRelayJitterSec ( n . storeSyncRelayJitter )
2026-06-10 09:09:22 -03:00
if n . mix . isSome ():
b . mixConf . withEnabled ( n . mix . get ())
b . withMix ( n . mix . get ())
2025-10-08 10:18:54 +05:30
b . mixConf . withMixNodes ( n . mixnodes )
2025-09-11 20:40:01 +05:30
if n . mixkey . isSome ():
b . mixConf . withMixKey ( n . mixkey . get ())
2025-05-08 07:05:35 +10:00
b . filterServiceConf . withEnabled ( n . filter )
b . filterServiceConf . withSubscriptionTimeout ( n . filterSubscriptionTimeout )
b . filterServiceConf . withMaxPeersToServe ( n . filterMaxPeersToServe )
b . filterServiceConf . withMaxCriteria ( n . filterMaxCriteria )
b . withLightPush ( n . lightpush )
2026-06-10 09:09:22 -03:00
if n . reliabilityEnabled . isSome ():
b . withP2pReliability ( n . reliabilityEnabled . get ())
2025-05-08 07:05:35 +10:00
b . restServerConf . withEnabled ( n . rest )
b . restServerConf . withListenAddress ( n . restAddress )
b . restServerConf . withPort ( n . restPort )
b . restServerConf . withRelayCacheCapacity ( n . restRelayCacheCapacity )
b . restServerConf . withAdmin ( n . restAdmin )
b . restServerConf . withAllowOrigin ( n . restAllowOrigin )
b . metricsServerConf . withEnabled ( n . metricsServer )
b . metricsServerConf . withHttpAddress ( n . metricsServerAddress )
b . metricsServerConf . withHttpPort ( n . metricsServerPort )
b . metricsServerConf . withLogging ( n . metricsLogging )
2025-07-03 11:56:43 +10:00
if n . dnsDiscoveryUrl != "" :
b . dnsDiscoveryConf . withEnrTreeUrl ( n . dnsDiscoveryUrl )
2025-06-18 22:55:18 +02:00
b . dnsDiscoveryConf . withNameServers ( n . dnsAddrsNameServers )
2025-05-08 07:05:35 +10:00
if n . discv5Discovery . isSome ():
b . discv5Conf . withEnabled ( n . discv5Discovery . get ())
b . discv5Conf . withUdpPort ( n . discv5UdpPort )
b . discv5Conf . withBootstrapNodes ( n . discv5BootstrapNodes )
b . discv5Conf . withEnrAutoUpdate ( n . discv5EnrAutoUpdate )
b . discv5Conf . withTableIpLimit ( n . discv5TableIpLimit )
b . discv5Conf . withBucketIpLimit ( n . discv5BucketIpLimit )
b . discv5Conf . withBitsPerHop ( n . discv5BitsPerHop )
b . withPeerExchange ( n . peerExchange )
b . withRendezvous ( n . rendezvous )
b . webSocketConf . withEnabled ( n . websocketSupport )
b . webSocketConf . withWebSocketPort ( n . websocketPort )
b . webSocketConf . withSecureEnabled ( n . websocketSecureSupport )
b . webSocketConf . withKeyPath ( n . websocketSecureKeyPath )
b . webSocketConf . withCertPath ( n . websocketSecureCertPath )
2026-06-17 07:55:45 -03:00
b . quicConf . withEnabled ( n . quicSupport )
b . quicConf . withQuicPort ( n . quicPort )
2026-03-03 19:17:54 +01:00
if n . rateLimits . len > 0 :
b . rateLimitConf . withRateLimits ( n . rateLimits )
2025-05-08 07:05:35 +10:00
2026-05-16 00:09:07 +02:00
b . withLocalStoragePath ( n . localStoragePath )
2026-06-10 09:09:22 -03:00
if n . enableKadDiscovery . isSome ():
b . kademliaDiscoveryConf . withEnabled ( n . enableKadDiscovery . get ())
2026-02-19 10:26:17 +05:30
b . kademliaDiscoveryConf . withBootstrapNodes ( n . kadBootstrapNodes )
2026-06-18 12:51:27 -04:00
if n . kadRandomLookupIntervalSec > 0 :
b . kademliaDiscoveryConf . withRandomLookupInterval (
chronos . seconds ( n . kadRandomLookupIntervalSec . int64 )
)
if n . kadServiceLookupIntervalSec > 0 :
b . kademliaDiscoveryConf . withServiceLookupInterval (
chronos . seconds ( n . kadServiceLookupIntervalSec . int64 )
)
2026-03-03 19:17:54 +01:00
# Mode-driven configuration overrides
case n . mode
of WakuMode . Core :
b . withRelay ( true )
b . filterServiceConf . withEnabled ( true )
b . withLightPush ( true )
b . discv5Conf . withEnabled ( true )
b . withPeerExchange ( true )
b . withRendezvous ( true )
b . rateLimitConf . withRateLimitsIfNotAssigned (
@[ "filter:100/1s" , "lightpush:5/1s" , "px:5/1s" ]
)
of WakuMode . Edge :
b . withPeerExchange ( true )
b . withRelay ( false )
b . filterServiceConf . withEnabled ( false )
b . withLightPush ( false )
b . storeServiceConf . withEnabled ( false )
of WakuMode . noMode :
discard # use explicit CLI flags as-is
2025-05-08 07:05:35 +10:00
return b . build ()