252 lines
7.7 KiB
Nim
Raw Normal View History

2025-04-07 15:42:34 +10:00
import
std/[net, options, strutils],
chronicles,
libp2p/crypto/crypto,
libp2p/multiaddress,
2025-04-10 11:10:48 +10:00
secp256k1,
2025-04-11 16:23:18 +10:00
results
2025-04-04 16:14:04 +11:00
2025-04-11 16:23:18 +10:00
import
../waku_rln_relay/rln_relay,
../waku_api/rest/builder,
../discovery/waku_discv5,
../node/waku_metrics,
../common/logging,
2025-04-11 20:11:00 +10:00
./networks_config,
../waku_enr/capabilities
2025-04-04 16:14:04 +11:00
2025-04-11 16:23:18 +10:00
export RlnRelayConf, RlnRelayCreds, RestServerConf, Discv5Conf, MetricsServerConf
2025-04-10 12:29:36 +10:00
2025-04-04 16:14:04 +11:00
logScope:
2025-04-07 15:42:34 +10:00
topics = "waku conf"
2025-04-04 16:14:04 +11:00
2025-04-10 11:10:48 +10:00
# TODO: should be defined in validator_signed.nim and imported here
2025-04-11 16:23:18 +10:00
type ProtectedShard* {.requiresInit.} = object
2025-04-10 11:10:48 +10:00
shard*: uint16
key*: secp256k1.SkPublicKey
2025-04-11 16:23:18 +10:00
type DnsDiscoveryConf* {.requiresInit.} = object
enrTreeUrl*: string
# TODO: should probably only have one set of name servers (see dnsaddrs)
nameServers*: seq[IpAddress]
2025-04-04 16:14:04 +11:00
2025-04-11 16:23:18 +10:00
type StoreSyncConf* {.requiresInit.} = object
rangeSec*: uint32
intervalSec*: uint32
relayJitterSec*: uint32
type StoreServiceConf* {.requiresInit.} = object
dbMigration*: bool
2025-04-10 11:10:48 +10:00
dbURl*: string
dbVacuum*: bool
2025-04-11 16:23:18 +10:00
legacy*: bool
2025-04-10 11:10:48 +10:00
maxNumDbConnections*: int
retentionPolicy*: string
resume*: bool
2025-04-11 16:23:18 +10:00
storeSyncConf*: Option[StoreSyncConf]
2025-04-09 13:09:34 +10:00
2025-04-11 16:23:18 +10:00
type FilterServiceConf* {.requiresInit.} = object
maxPeersToServe*: uint32
subscriptionTimeout*: uint16
maxCriteria*: uint32
2025-04-11 16:23:18 +10:00
type WebSocketSecureConf* {.requiresInit.} = object
2025-04-08 15:10:26 +10:00
keyPath*: string
certPath*: string
2025-04-08 11:01:39 +10:00
2025-04-11 16:23:18 +10:00
type WebSocketConf* = object
2025-04-08 15:10:26 +10:00
port*: Port
secureConf*: Option[WebSocketSecureConf]
2025-04-08 11:01:39 +10:00
2025-04-11 20:11:00 +10:00
type NetworkConfig* = object # TODO: make enum
natStrategy*: string
p2pTcpPort*: Port
dns4DomainName*: Option[string]
p2pListenAddress*: IpAddress
extMultiAddrs*: seq[MultiAddress]
extMultiAddrsOnly*: bool
2025-04-07 15:45:52 +10:00
## `WakuConf` is a valid configuration for a Waku node
## All information needed by a waku node should be contained
## In this object. A convenient `validate` method enables doing
## sanity checks beyond type enforcement.
## If `Option` is `some` it means the related protocol is enabled.
2025-04-11 16:23:18 +10:00
type WakuConf* {.requiresInit.} = ref object
# ref because `getRunningNetConfig` modifies it
nodeKey*: crypto.PrivateKey
2025-04-04 16:14:04 +11:00
clusterId*: uint16
shards*: seq[uint16]
2025-04-10 11:10:48 +10:00
protectedShards*: seq[ProtectedShard]
# TODO: move to an autoShardingConf
2025-04-10 11:10:48 +10:00
numShardsInNetwork*: uint32
contentTopics*: seq[string]
2025-04-04 16:14:04 +11:00
relay*: bool
lightPush*: bool
peerExchange*: bool
2025-04-11 16:23:18 +10:00
2025-04-08 15:10:26 +10:00
# TODO: remove relay peer exchange
relayPeerExchange*: bool
2025-04-10 11:10:48 +10:00
rendezvous*: bool
circuitRelayClient*: bool
keepAlive*: bool
2025-04-04 16:14:04 +11:00
2025-04-07 15:42:34 +10:00
discv5Conf*: Option[Discv5Conf]
dnsDiscoveryConf*: Option[DnsDiscoveryConf]
filterServiceConf*: Option[FilterServiceConf]
2025-04-10 11:10:48 +10:00
storeServiceConf*: Option[StoreServiceConf]
2025-04-04 16:14:04 +11:00
rlnRelayConf*: Option[RlnRelayConf]
restServerConf*: Option[RestServerConf]
2025-04-11 16:23:18 +10:00
metricsServerConf*: Option[MetricsServerConf]
2025-04-11 20:11:00 +10:00
webSocketConf*: Option[WebSocketConf]
portsShift*: uint16
dnsAddrs*: bool
dnsAddrsNameServers*: seq[IpAddress]
networkConf*: NetworkConfig
wakuFlags*: CapabilitiesBitfield
# TODO: could probably make it a `PeerRemoteInfo`
staticNodes*: seq[string]
2025-04-10 11:10:48 +10:00
remoteStoreNode*: Option[string]
remoteLightPushNode*: Option[string]
remoteFilterNode*: Option[string]
remotePeerExchangeNode*: Option[string]
2025-04-10 11:10:48 +10:00
2025-04-11 16:23:18 +10:00
maxMessageSizeBytes*: uint64
2025-04-04 16:14:04 +11:00
logLevel*: logging.LogLevel
logFormat*: logging.LogFormat
2025-04-08 11:01:39 +10:00
peerPersistence*: bool
# TODO: should clearly be a uint
peerStoreCapacity*: Option[int]
# TODO: should clearly be a uint
maxConnections*: int
2025-04-04 17:07:53 +11:00
2025-04-08 15:49:12 +10:00
agentString*: string
colocationLimit*: int
2025-04-10 12:29:36 +10:00
# TODO: use proper type
2025-04-08 15:49:12 +10:00
rateLimits*: seq[string]
# TODO: those could be in a relay conf object
maxRelayPeers*: Option[int]
relayShardedPeerManagement*: bool
2025-04-10 12:29:36 +10:00
# TODO: use proper type
2025-04-08 15:49:12 +10:00
relayServiceRatio*: string
2025-04-11 20:11:00 +10:00
p2pReliability*: bool
2025-04-04 16:14:04 +11:00
proc log*(conf: WakuConf) =
info "Configuration: Enabled protocols",
relay = conf.relay,
rlnRelay = conf.rlnRelayConf.isSome,
2025-04-10 11:10:48 +10:00
store = conf.storeServiceConf.isSome,
filter = conf.filterServiceConf.isSome,
2025-04-04 16:14:04 +11:00
lightPush = conf.lightPush,
peerExchange = conf.peerExchange
info "Configuration. Network", cluster = conf.clusterId
for shard in conf.shards:
info "Configuration. Shards", shard = shard
2025-04-07 15:42:34 +10:00
if conf.discv5Conf.isSome():
for i in conf.discv5Conf.get().bootstrapNodes:
info "Configuration. Bootstrap nodes", node = i.string
2025-04-04 16:14:04 +11:00
2025-04-11 16:23:18 +10:00
if conf.rlnRelayConf.isSome():
var rlnRelayConf = conf.rlnRelayConf.get()
2025-04-07 15:42:34 +10:00
if rlnRelayConf.dynamic:
2025-04-04 16:14:04 +11:00
info "Configuration. Validation",
mechanism = "onchain rln",
2025-04-07 15:42:34 +10:00
contract = rlnRelayConf.ethContractAddress.string,
2025-04-04 16:14:04 +11:00
maxMessageSize = conf.maxMessageSizeBytes,
2025-04-07 15:42:34 +10:00
rlnEpochSizeSec = rlnRelayConf.epochSizeSec,
rlnRelayUserMessageLimit = rlnRelayConf.userMessageLimit,
rlnRelayEthClientAddress = string(rlnRelayConf.ethClientAddress)
2025-04-04 16:14:04 +11:00
proc validateNodeKey(wakuConf: WakuConf): Result[void, string] =
# TODO
return ok()
2025-04-07 15:42:34 +10:00
proc validateShards(wakuConf: WakuConf): Result[void, string] =
2025-04-04 16:14:04 +11:00
let numShardsInNetwork = wakuConf.numShardsInNetwork
for shard in wakuConf.shards:
if shard >= numShardsInNetwork:
let msg =
"validateShards invalid shard: " & $shard & " when numShardsInNetwork: " &
$numShardsInNetwork # fmt doesn't work
error "validateShards failed", error = msg
return err(msg)
return ok()
2025-04-07 15:42:34 +10:00
proc validateNoEmptyStrings(wakuConf: WakuConf): Result[void, string] =
2025-04-11 20:11:00 +10:00
if wakuConf.networkConf.dns4DomainName.isSome and
isEmptyOrWhiteSpace(wakuConf.networkConf.dns4DomainName.get().string):
2025-04-10 11:10:48 +10:00
return err("dns4DomainName is an empty string, set it to none(string) instead")
2025-04-04 16:14:04 +11:00
2025-04-09 13:09:34 +10:00
if isEmptyOrWhiteSpace(wakuConf.relayServiceRatio):
return err("relayServiceRatio is an empty string")
for sn in wakuConf.staticNodes:
if isEmptyOrWhiteSpace(sn):
return err("staticNodes contain an empty string")
2025-04-10 11:10:48 +10:00
if wakuConf.remoteStoreNode.isSome and
isEmptyOrWhiteSpace(wakuConf.remoteStoreNode.get()):
return err("remoteStoreNode is an empty string, set it to none(string) instead")
if wakuConf.remoteLightPushNode.isSome and
isEmptyOrWhiteSpace(wakuConf.remoteLightPushNode.get()):
return err("remoteLightPushNode is an empty string, set it to none(string) instead")
if wakuConf.remotePeerExchangeNode.isSome and
isEmptyOrWhiteSpace(wakuConf.remotePeerExchangeNode.get()):
return
err("remotePeerExchangeNode is an empty string, set it to none(string) instead")
if wakuConf.remoteFilterNode.isSome and
isEmptyOrWhiteSpace(wakuConf.remoteFilterNode.get()):
return
err("remotePeerExchangeNode is an empty string, set it to none(string) instead")
if wakuConf.dnsDiscoveryConf.isSome and
isEmptyOrWhiteSpace(wakuConf.dnsDiscoveryConf.get().enrTreeUrl):
return err ("dnsDiscoveryConf.enrTreeUrl is an empty string")
# TODO: rln relay config should validate itself
2025-04-11 16:23:18 +10:00
if wakuConf.rlnRelayConf.isSome():
let rlnRelayConf = wakuConf.rlnRelayConf.get()
if isEmptyOrWhiteSpace(rlnRelayConf.treePath):
return err("rlnRelayConf.treepath is an empty string")
if isEmptyOrWhiteSpace(rlnRelayConf.ethClientAddress):
return err("rlnRelayConf.ethClientAddress is an empty string")
if isEmptyOrWhiteSpace(rlnRelayConf.ethContractAddress):
return err("rlnRelayConf.ethContractAddress is an empty string")
if rlnRelayConf.creds.isSome():
let creds = rlnRelayConf.creds.get()
if isEmptyOrWhiteSpace(creds.path):
return err (
"rlnRelayConf.creds.path is an empty string, set rlnRelayConf.creds it to none instead"
)
if isEmptyOrWhiteSpace(creds.password):
return err (
"rlnRelayConf.creds.password is an empty string, set rlnRelayConf.creds to none instead"
)
2025-04-10 11:10:48 +10:00
2025-04-04 16:14:04 +11:00
return ok()
2025-04-07 15:42:34 +10:00
proc validate*(wakuConf: WakuConf): Result[void, string] =
?wakuConf.validateNodeKey()
2025-04-07 15:42:34 +10:00
?wakuConf.validateShards()
?wakuConf.validateNoEmptyStrings()