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 ,
2020-05-21 12:16:00 +08:00
libp2p / crypto / crypto ,
libp2p / crypto / secp ,
2023-01-26 15:48:30 +05:30
libp2p / multiaddress ,
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
2025-10-01 16:31:34 +10:00
waku / factory / [ waku_conf , conf_builder / conf_builder , networks_config ] ,
waku / common / [ logging ] ,
waku / [
waku_enr ,
node / peer_manager ,
waku_core / topics / pubsub_topic ,
waku_core / message / default_values ,
] ,
2025-09-26 14:47:15 +05:30
.. / .. / tools / rln_keystore_generator / rln_keystore_generator
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-05-08 07:05:35 +10:00
export confTomlDefs , confTomlNet , confEnvvarDefs , confEnvvarNet , ProtectedShard
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 "
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
type WakuNodeConf * = object
configFile * {.
desc : " Loads configuration from a TOML file (cmd-line parameters take precedence) " ,
name : " config-file "
. } : Option [ InputFile ]
## 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
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
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
2025-04-01 09:28:18 +11:00
# TODO: Remove "Default is" when it's already visible on the CLI
2024-03-16 00:08:47 +01:00
rlnRelayUserMessageLimit * {.
desc :
" Set a user message limit for the rln membership registration. Must be a positive integer. Default is 1. " ,
defaultValue : 1 ,
name : " rln-relay-user-message-limit "
. } : uint64
rlnEpochSizeSec * {.
desc :
" Epoch size in seconds used to rate limit RLN memberships. Default is 1 second. " ,
defaultValue : 1 ,
name : " rln-relay-epoch-sec "
. } : uint64
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 ]
2024-03-16 00:08:47 +01:00
## General node config
2025-04-01 09:28:18 +11:00
preset * {.
desc :
2025-05-08 07:05:35 +10:00
" Network preset to use. ' twn ' is The RLN-protected Waku Network (cluster 1). Overrides other values. " ,
2025-04-01 09:28:18 +11:00
defaultValue : " " ,
name : " preset "
. } : string
2024-03-16 00:08:47 +01:00
clusterId * {.
desc :
" Cluster id that the node is running in. Node in a different cluster id is disconnected. " ,
defaultValue : 0 ,
name : " cluster-id "
2024-06-05 15:32:35 +02:00
. } : uint16
2024-03-16 00:08:47 +01:00
agentString * {.
2025-10-01 16:31:34 +10:00
defaultValue : " nwaku- " & cli_args . git_version ,
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>. " ,
defaultValue : " any "
. } : 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 * {.
desc : " Maximum allowed number of libp2p connections. " ,
defaultValue : 50 ,
name : " max-connections "
2025-01-21 11:29:52 +05:30
. } : int
maxRelayPeers * {.
desc :
" Deprecated. Use relay-service-ratio instead. It represents the maximum allowed number of relay peers. " ,
name : " max-relay-peers "
. } : Option [ 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.) " ,
name : " relay-service-ratio " ,
defaultValue : " 60:40 " # 60:40 ratio of relay to service peers
. } : 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. " ,
defaultValue : @ [ parseIpAddress ( " 1.1.1.1 " ) , parseIpAddress ( " 1.0.0.1 " ) ] ,
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
2024-10-28 09:17:46 +01:00
## Circuit-relay config
isRelayClient * {.
desc :
""" Set the node as a relay-client.
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 * {.
desc : " Enable relay protocol: true|false " , defaultValue : true , name : " relay "
. } : 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
rlnRelay * {.
2025-04-01 09:28:18 +11:00
desc : " Enable spam protection through rln-relay: true|false. " ,
2024-03-16 00:08:47 +01:00
defaultValue : false ,
name : " rln-relay "
. } : bool
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. " ,
2024-03-16 00:08:47 +01:00
defaultValue : false ,
name : " rln-relay-dynamic "
. } : bool
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 " ,
defaultValue : 1 ,
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
2024-07-12 12:19:12 -04:00
legacyStore * {.
2025-05-08 07:05:35 +10:00
desc : " Enable/disable support of Waku Store v2 as a service " ,
2025-07-02 17:22:51 +02:00
defaultValue : false ,
2024-07-12 12:19:12 -04:00
name : " legacy-store "
. } : bool
2024-03-16 00:08:47 +01:00
storenode * {.
desc : " Peer multiaddress to query for storage " ,
defaultValue : " " ,
name : " storenode "
. } : string
storeMessageRetentionPolicy * {.
desc :
" Message store retention policy. Time retention policy: ' time:<seconds> ' . Capacity retention policy: ' capacity:<count> ' . Size retention policy: ' size:<xMB/xGB> ' . Set to ' none ' to disable. " ,
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
reliabilityEnabled * {.
desc :
""" Adds an extra effort in the delivery/reception of messages by leveraging store-v3 requests.
2024-12-09 21:45:26 +08:00
with the drawback of consuming some more bandwidth . """ ,
2024-08-27 16:49:46 +02:00
defaultValue : false ,
name : " reliability "
. } : bool
2024-03-16 00:08:47 +01:00
## REST HTTP config
rest * {.
2024-04-23 10:23:13 +03:00
desc : " Enable Waku REST HTTP server: true|false " , defaultValue : true , name : " rest "
2024-03-16 00:08:47 +01:00
. } : bool
restAddress * {.
desc : " Listening address of the REST HTTP server. " ,
defaultValue : parseIpAddress ( " 127.0.0.1 " ) ,
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. " ,
defaultValue : parseIpAddress ( " 127.0.0.1 " ) ,
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
discv5Discovery * {.
2025-04-01 09:28:18 +11:00
desc : " Enable discovering nodes via Node Discovery v5. " ,
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 " ,
2025-09-12 12:16:59 +05:30
defaultValue : true ,
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 " ,
defaultValue : true ,
name : " rendezvous "
. } : bool
2025-09-11 20:40:01 +05:30
#Mix config
mix * {. desc : " Enable mix protocol: true|false " , defaultValue : false , name : " mix " . } :
bool
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 ]
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
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> " &
" Where ' protocol ' can be one of: <store|storev2|storev3|lightpush|px|filter> if not defined it means a global setting " &
" ' 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
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
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
)
2023-05-02 11:45:50 +02:00
let publicKey = secp256k1 . SkPublicKey . fromHex ( elements [ 1 ] )
if publicKey . isErr :
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 ] ) :
return ProtectedShard ( shard : uint16 . parseCmdArg ( elements [ 0 ] ) , key : publicKey . get ( ) )
# 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> " ,
)
return ProtectedShard ( shard : shard . shardId , key : publicKey . get ( ) )
2023-05-02 11:45:50 +02:00
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.
2023-12-14 07:16:39 +01:00
( static parseIpAddress ( " 0.0.0.0 " ) )
2022-12-07 12:30:32 +01:00
2024-01-02 14:01:18 +01:00
proc defaultColocationLimit * ( ) : int =
return DefaultColocationLimit
2022-11-02 14:55:48 +01:00
proc completeCmdArg * ( T : type Port , val : string ) : seq [ string ] =
2020-07-24 09:39:58 +08:00
return @ [ ]
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 ( ) )
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 ,
userMessageLimit : n . rlnRelayUserMessageLimit ,
ethPrivateKey : n . rlnRelayEthPrivateKey ,
credPath : n . rlnRelayCredPath ,
credPassword : n . rlnRelayCredPassword ,
)
2025-07-04 17:10:53 +10:00
proc toNetworkConf (
2025-05-08 07:05:35 +10:00
preset : string , clusterId : Option [ uint16 ]
2025-07-04 17:10:53 +10:00
) : ConfResult [ Option [ NetworkConf ] ] =
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 "
case lcPreset
of " " :
2025-07-04 17:10:53 +10:00
ok ( none ( NetworkConf ) )
2025-05-08 07:05:35 +10:00
of " twn " :
2025-07-04 17:10:53 +10:00
ok ( some ( NetworkConf . TheWakuNetworkConf ( ) ) )
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 ( )
b . withLogLevel ( n . logLevel )
b . withLogFormat ( n . logFormat )
b . rlnRelayConf . withEnabled ( n . rlnRelay )
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 )
b . rlnRelayConf . withUserMessageLimit ( n . rlnRelayUserMessageLimit )
b . rlnRelayConf . withEpochSizeSec ( n . rlnEpochSizeSec )
if n . rlnRelayCredIndex . isSome ( ) :
b . rlnRelayConf . withCredIndex ( n . rlnRelayCredIndex . get ( ) )
b . rlnRelayConf . withDynamic ( n . rlnRelayDynamic )
if n . maxMessageSize ! = " " :
b . withMaxMessageSize ( n . maxMessageSize )
b . withProtectedShards ( n . protectedShards )
b . withClusterId ( n . clusterId )
2025-07-04 17:10:53 +10:00
let networkConf = toNetworkConf ( n . preset , some ( n . clusterId ) ) . valueOr :
2025-05-08 07:05:35 +10:00
return err ( " Error determining cluster from preset: " & $ error )
2025-07-04 17:10:53 +10:00
if networkConf . isSome ( ) :
b . withNetworkConf ( networkConf . 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 . maxRelayPeers . isSome ( ) :
b . withMaxRelayPeers ( n . maxRelayPeers . get ( ) )
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 )
if n . numShardsInNetwork ! = 0 :
2025-07-04 17:10:53 +10:00
b . withNumShardsInCluster ( n . numShardsInNetwork )
b . withShardingConf ( AutoSharding )
else :
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 )
b . storeServiceConf . withSupportV2 ( n . legacyStore )
b . storeServiceConf . withRetentionPolicy ( n . storeMessageRetentionPolicy )
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 )
2025-09-11 20:40:01 +05:30
b . mixConf . withEnabled ( n . mix )
b . withMix ( n . mix )
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 )
b . withP2pReliability ( n . reliabilityEnabled )
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 )
2025-07-09 15:57:38 +10:00
b . rateLimitConf . withRateLimits ( n . rateLimits )
2025-05-08 07:05:35 +10:00
return b . build ( )