Sergei Tikhomirov 7d1c6abaac
chore: do not mount lightpush without relay (fixes #2808) (#3540)
* chore: do not mount lightpush without relay (fixes #2808)

- Change mountLightPush signature to return Result[void, string]
- Return error when relay is not mounted
- Update all call sites to handle Result return type
- Add test verifying mounting fails without relay
- Only advertise lightpush capability when relay is enabled

* chore: don't mount legacy lightpush without relay
2025-12-11 10:51:47 +01:00

678 lines
23 KiB
Nim

import
libp2p/crypto/crypto,
libp2p/multiaddress,
std/[net, options, sequtils],
stint,
chronicles,
chronos,
results
import
../waku_conf,
../networks_config,
../../common/logging,
../../common/utils/parse_size_units,
../../waku_enr/capabilities
import
./filter_service_conf_builder,
./store_sync_conf_builder,
./store_service_conf_builder,
./rest_server_conf_builder,
./dns_discovery_conf_builder,
./discv5_conf_builder,
./web_socket_conf_builder,
./metrics_server_conf_builder,
./rate_limit_conf_builder,
./rln_relay_conf_builder,
./mix_conf_builder
logScope:
topics = "waku conf builder"
type MaxMessageSizeKind* = enum
mmskNone
mmskStr
mmskInt
type MaxMessageSize* = object
case kind*: MaxMessageSizeKind
of mmskNone:
discard
of mmskStr:
str*: string
of mmskInt:
bytes*: uint64
## `WakuConfBuilder` is a convenient tool to accumulate
## Config parameters to build a `WakuConfig`.
## It provides some type conversion, as well as applying
## defaults in an agnostic manner (for any usage of Waku node)
#
# TODO: Sub protocol builder (eg `StoreServiceConfBuilder`
# is be better defined in the protocol module (eg store)
# and apply good defaults from this protocol PoV and make the
# decision when the dev must specify a value vs when a default
# is fine to have.
#
# TODO: Add default to most values so that when a developer uses
# the builder, it works out-of-the-box
type WakuConfBuilder* = object
nodeKey: Option[crypto.PrivateKey]
clusterId: Option[uint16]
shardingConf: Option[ShardingConfKind]
numShardsInCluster: Option[uint16]
subscribeShards: Option[seq[uint16]]
protectedShards: Option[seq[ProtectedShard]]
contentTopics: Option[seq[string]]
# Conf builders
dnsDiscoveryConf*: DnsDiscoveryConfBuilder
discv5Conf*: Discv5ConfBuilder
filterServiceConf*: FilterServiceConfBuilder
metricsServerConf*: MetricsServerConfBuilder
restServerConf*: RestServerConfBuilder
rlnRelayConf*: RlnRelayConfBuilder
storeServiceConf*: StoreServiceConfBuilder
mixConf*: MixConfBuilder
webSocketConf*: WebSocketConfBuilder
rateLimitConf*: RateLimitConfBuilder
# End conf builders
relay: Option[bool]
lightPush: Option[bool]
peerExchange: Option[bool]
storeSync: Option[bool]
relayPeerExchange: Option[bool]
mix: Option[bool]
# TODO: move within a relayConf
rendezvous: Option[bool]
networkConf: Option[NetworkConf]
staticNodes: seq[string]
remoteStoreNode: Option[string]
remoteLightPushNode: Option[string]
remoteFilterNode: Option[string]
remotePeerExchangeNode: Option[string]
maxMessageSize: MaxMessageSize
logLevel: Option[logging.LogLevel]
logFormat: Option[logging.LogFormat]
natStrategy: Option[string]
p2pTcpPort: Option[Port]
p2pListenAddress: Option[IpAddress]
portsShift: Option[uint16]
dns4DomainName: Option[string]
extMultiAddrs: seq[string]
extMultiAddrsOnly: Option[bool]
dnsAddrsNameServers: seq[IpAddress]
peerPersistence: Option[bool]
peerStoreCapacity: Option[int]
maxConnections: Option[int]
colocationLimit: Option[int]
agentString: Option[string]
maxRelayPeers: Option[int]
relayShardedPeerManagement: Option[bool]
relayServiceRatio: Option[string]
circuitRelayClient: Option[bool]
p2pReliability: Option[bool]
proc init*(T: type WakuConfBuilder): WakuConfBuilder =
WakuConfBuilder(
dnsDiscoveryConf: DnsDiscoveryConfBuilder.init(),
discv5Conf: Discv5ConfBuilder.init(),
filterServiceConf: FilterServiceConfBuilder.init(),
metricsServerConf: MetricsServerConfBuilder.init(),
restServerConf: RestServerConfBuilder.init(),
rlnRelayConf: RlnRelayConfBuilder.init(),
storeServiceConf: StoreServiceConfBuilder.init(),
webSocketConf: WebSocketConfBuilder.init(),
rateLimitConf: RateLimitConfBuilder.init(),
)
proc withNetworkConf*(b: var WakuConfBuilder, networkConf: NetworkConf) =
b.networkConf = some(networkConf)
proc withNodeKey*(b: var WakuConfBuilder, nodeKey: crypto.PrivateKey) =
b.nodeKey = some(nodeKey)
proc withClusterId*(b: var WakuConfBuilder, clusterId: uint16) =
b.clusterId = some(clusterId)
proc withShardingConf*(b: var WakuConfBuilder, shardingConf: ShardingConfKind) =
b.shardingConf = some(shardingConf)
proc withNumShardsInCluster*(b: var WakuConfBuilder, numShardsInCluster: uint16) =
b.numShardsInCluster = some(numShardsInCluster)
proc withSubscribeShards*(b: var WakuConfBuilder, shards: seq[uint16]) =
b.subscribeShards = some(shards)
proc withProtectedShards*(
b: var WakuConfBuilder, protectedShards: seq[ProtectedShard]
) =
b.protectedShards = some(protectedShards)
proc withContentTopics*(b: var WakuConfBuilder, contentTopics: seq[string]) =
b.contentTopics = some(contentTopics)
proc withRelay*(b: var WakuConfBuilder, relay: bool) =
b.relay = some(relay)
proc withLightPush*(b: var WakuConfBuilder, lightPush: bool) =
b.lightPush = some(lightPush)
proc withStoreSync*(b: var WakuConfBuilder, storeSync: bool) =
b.storeSync = some(storeSync)
proc withPeerExchange*(b: var WakuConfBuilder, peerExchange: bool) =
b.peerExchange = some(peerExchange)
proc withRelayPeerExchange*(b: var WakuConfBuilder, relayPeerExchange: bool) =
b.relayPeerExchange = some(relayPeerExchange)
proc withRendezvous*(b: var WakuConfBuilder, rendezvous: bool) =
b.rendezvous = some(rendezvous)
proc withMix*(builder: var WakuConfBuilder, mix: bool) =
builder.mix = some(mix)
proc withRemoteStoreNode*(b: var WakuConfBuilder, remoteStoreNode: string) =
b.remoteStoreNode = some(remoteStoreNode)
proc withRemoteLightPushNode*(b: var WakuConfBuilder, remoteLightPushNode: string) =
b.remoteLightPushNode = some(remoteLightPushNode)
proc withRemoteFilterNode*(b: var WakuConfBuilder, remoteFilterNode: string) =
b.remoteFilterNode = some(remoteFilterNode)
proc withRemotePeerExchangeNode*(
b: var WakuConfBuilder, remotePeerExchangeNode: string
) =
b.remotePeerExchangeNode = some(remotePeerExchangeNode)
proc withPeerPersistence*(b: var WakuConfBuilder, peerPersistence: bool) =
b.peerPersistence = some(peerPersistence)
proc withPeerStoreCapacity*(b: var WakuConfBuilder, peerStoreCapacity: int) =
b.peerStoreCapacity = some(peerStoreCapacity)
proc withMaxConnections*(b: var WakuConfBuilder, maxConnections: int) =
b.maxConnections = some(maxConnections)
proc withDnsAddrsNameServers*(
b: var WakuConfBuilder, dnsAddrsNameServers: seq[IpAddress]
) =
b.dnsAddrsNameServers.insert(dnsAddrsNameServers)
proc withLogLevel*(b: var WakuConfBuilder, logLevel: logging.LogLevel) =
b.logLevel = some(logLevel)
proc withLogFormat*(b: var WakuConfBuilder, logFormat: logging.LogFormat) =
b.logFormat = some(logFormat)
proc withP2pTcpPort*(b: var WakuConfBuilder, p2pTcpPort: Port) =
b.p2pTcpPort = some(p2pTcpPort)
proc withP2pTcpPort*(b: var WakuConfBuilder, p2pTcpPort: uint16) =
b.p2pTcpPort = some(Port(p2pTcpPort))
proc withPortsShift*(b: var WakuConfBuilder, portsShift: uint16) =
b.portsShift = some(portsShift)
proc withP2pListenAddress*(b: var WakuConfBuilder, p2pListenAddress: IpAddress) =
b.p2pListenAddress = some(p2pListenAddress)
proc withExtMultiAddrsOnly*(b: var WakuConfBuilder, extMultiAddrsOnly: bool) =
b.extMultiAddrsOnly = some(extMultiAddrsOnly)
proc withDns4DomainName*(b: var WakuConfBuilder, dns4DomainName: string) =
b.dns4DomainName = some(dns4DomainName)
proc withNatStrategy*(b: var WakuConfBuilder, natStrategy: string) =
b.natStrategy = some(natStrategy)
proc withAgentString*(b: var WakuConfBuilder, agentString: string) =
b.agentString = some(agentString)
proc withColocationLimit*(b: var WakuConfBuilder, colocationLimit: int) =
b.colocationLimit = some(colocationLimit)
proc withMaxRelayPeers*(b: var WakuConfBuilder, maxRelayPeers: int) =
b.maxRelayPeers = some(maxRelayPeers)
proc withRelayServiceRatio*(b: var WakuConfBuilder, relayServiceRatio: string) =
b.relayServiceRatio = some(relayServiceRatio)
proc withCircuitRelayClient*(b: var WakuConfBuilder, circuitRelayClient: bool) =
b.circuitRelayClient = some(circuitRelayClient)
proc withRelayShardedPeerManagement*(
b: var WakuConfBuilder, relayShardedPeerManagement: bool
) =
b.relayShardedPeerManagement = some(relayShardedPeerManagement)
proc withP2pReliability*(b: var WakuConfBuilder, p2pReliability: bool) =
b.p2pReliability = some(p2pReliability)
proc withExtMultiAddrs*(builder: var WakuConfBuilder, extMultiAddrs: seq[string]) =
builder.extMultiAddrs = concat(builder.extMultiAddrs, extMultiAddrs)
proc withMaxMessageSize*(builder: var WakuConfBuilder, maxMessageSizeBytes: uint64) =
builder.maxMessageSize = MaxMessageSize(kind: mmskInt, bytes: maxMessageSizeBytes)
proc withMaxMessageSize*(builder: var WakuConfBuilder, maxMessageSize: string) =
builder.maxMessageSize = MaxMessageSize(kind: mmskStr, str: maxMessageSize)
proc withStaticNodes*(builder: var WakuConfBuilder, staticNodes: seq[string]) =
builder.staticNodes = concat(builder.staticNodes, staticNodes)
## Building
proc nodeKey(
builder: WakuConfBuilder, rng: ref HmacDrbgContext
): Result[crypto.PrivateKey, string] =
if builder.nodeKey.isSome():
return ok(builder.nodeKey.get())
else:
warn "missing node key, generating new set"
let nodeKey = crypto.PrivateKey.random(Secp256k1, rng[]).valueOr:
error "Failed to generate key", error = error
return err("Failed to generate key: " & $error)
return ok(nodeKey)
proc buildShardingConf(
bShardingConfKind: Option[ShardingConfKind],
bNumShardsInCluster: Option[uint16],
bSubscribeShards: Option[seq[uint16]],
): (ShardingConf, seq[uint16]) =
echo "bSubscribeShards: ", bSubscribeShards
case bShardingConfKind.get(AutoSharding)
of StaticSharding:
(ShardingConf(kind: StaticSharding), bSubscribeShards.get(@[]))
of AutoSharding:
let numShardsInCluster = bNumShardsInCluster.get(1)
let shardingConf =
ShardingConf(kind: AutoSharding, numShardsInCluster: numShardsInCluster)
let upperShard = uint16(numShardsInCluster - 1)
(shardingConf, bSubscribeShards.get(toSeq(0.uint16 .. upperShard)))
proc applyNetworkConf(builder: var WakuConfBuilder) =
# Apply network conf, overrides most values passed individually
# If you want to tweak values, don't use networkConf
# TODO: networkconf should be one field of the conf builder so that this function becomes unnecessary
if builder.networkConf.isNone():
return
let networkConf = builder.networkConf.get()
if builder.clusterId.isSome():
warn "Cluster id was provided alongside a network conf",
used = networkConf.clusterId, discarded = builder.clusterId.get()
builder.clusterId = some(networkConf.clusterId)
# Apply relay parameters
if builder.relay.get(false) and networkConf.rlnRelay:
if builder.rlnRelayConf.enabled.isSome():
warn "RLN Relay was provided alongside a network conf",
used = networkConf.rlnRelay, discarded = builder.rlnRelayConf.enabled
builder.rlnRelayConf.withEnabled(true)
if builder.rlnRelayConf.ethContractAddress.get("") != "":
warn "RLN Relay ETH Contract Address was provided alongside a network conf",
used = networkConf.rlnRelayEthContractAddress.string,
discarded = builder.rlnRelayConf.ethContractAddress.get().string
builder.rlnRelayConf.withEthContractAddress(networkConf.rlnRelayEthContractAddress)
if builder.rlnRelayConf.chainId.isSome():
warn "RLN Relay Chain Id was provided alongside a network conf",
used = networkConf.rlnRelayChainId, discarded = builder.rlnRelayConf.chainId
builder.rlnRelayConf.withChainId(networkConf.rlnRelayChainId)
if builder.rlnRelayConf.dynamic.isSome():
warn "RLN Relay Dynamic was provided alongside a network conf",
used = networkConf.rlnRelayDynamic, discarded = builder.rlnRelayConf.dynamic
builder.rlnRelayConf.withDynamic(networkConf.rlnRelayDynamic)
if builder.rlnRelayConf.epochSizeSec.isSome():
warn "RLN Epoch Size in Seconds was provided alongside a network conf",
used = networkConf.rlnEpochSizeSec,
discarded = builder.rlnRelayConf.epochSizeSec
builder.rlnRelayConf.withEpochSizeSec(networkConf.rlnEpochSizeSec)
if builder.rlnRelayConf.userMessageLimit.isSome():
warn "RLN Relay Dynamic was provided alongside a network conf",
used = networkConf.rlnRelayUserMessageLimit,
discarded = builder.rlnRelayConf.userMessageLimit
builder.rlnRelayConf.withUserMessageLimit(networkConf.rlnRelayUserMessageLimit)
# End Apply relay parameters
case builder.maxMessageSize.kind
of mmskNone:
discard
of mmskStr, mmskInt:
warn "Max Message Size was provided alongside a network conf",
used = networkConf.maxMessageSize, discarded = $builder.maxMessageSize
builder.withMaxMessageSize(parseCorrectMsgSize(networkConf.maxMessageSize))
if builder.shardingConf.isSome():
warn "Sharding Conf was provided alongside a network conf",
used = networkConf.shardingConf.kind, discarded = builder.shardingConf
if builder.numShardsInCluster.isSome():
warn "Num Shards In Cluster was provided alongside a network conf",
used = networkConf.shardingConf.numShardsInCluster,
discarded = builder.numShardsInCluster
case networkConf.shardingConf.kind
of StaticSharding:
builder.shardingConf = some(StaticSharding)
of AutoSharding:
builder.shardingConf = some(AutoSharding)
builder.numShardsInCluster = some(networkConf.shardingConf.numShardsInCluster)
if networkConf.discv5Discovery:
if builder.discv5Conf.enabled.isNone:
builder.discv5Conf.withEnabled(networkConf.discv5Discovery)
if builder.discv5Conf.bootstrapNodes.len == 0 and
networkConf.discv5BootstrapNodes.len > 0:
warn "Discv5 Bootstrap nodes were provided alongside a network conf",
used = networkConf.discv5BootstrapNodes,
discarded = builder.discv5Conf.bootstrapNodes
builder.discv5Conf.withBootstrapNodes(networkConf.discv5BootstrapNodes)
proc build*(
builder: var WakuConfBuilder, rng: ref HmacDrbgContext = crypto.newRng()
): Result[WakuConf, string] =
## Return a WakuConf that contains all mandatory parameters
## Applies some sane defaults that are applicable across any usage
## of libwaku. It aims to be agnostic so it does not apply a
## default when it is opinionated.
applyNetworkConf(builder)
let relay =
if builder.relay.isSome():
builder.relay.get()
else:
warn "whether to mount relay is not specified, defaulting to not mounting"
false
let lightPush =
if builder.lightPush.isSome():
builder.lightPush.get()
else:
warn "whether to mount lightPush is not specified, defaulting to not mounting"
false
let peerExchange =
if builder.peerExchange.isSome():
builder.peerExchange.get()
else:
warn "whether to mount peerExchange is not specified, defaulting to not mounting"
false
let storeSync =
if builder.storeSync.isSome():
builder.storeSync.get()
else:
warn "whether to mount storeSync is not specified, defaulting to not mounting"
false
let rendezvous =
if builder.rendezvous.isSome():
builder.rendezvous.get()
else:
warn "whether to mount rendezvous is not specified, defaulting to not mounting"
false
let mix =
if builder.mix.isSome():
builder.mix.get()
else:
warn "whether to mount mix is not specified, defaulting to not mounting"
false
let relayPeerExchange = builder.relayPeerExchange.get(false)
let nodeKey = ?nodeKey(builder, rng)
let clusterId =
if builder.clusterId.isNone():
# TODO: ClusterId should never be defaulted, instead, presets
# should be defined and used
warn("Cluster Id was not specified, defaulting to 0")
0.uint16
else:
builder.clusterId.get().uint16
let (shardingConf, subscribeShards) = buildShardingConf(
builder.shardingConf, builder.numShardsInCluster, builder.subscribeShards
)
let protectedShards = builder.protectedShards.get(@[])
info "Sharding configuration: ",
shardingConf = $shardingConf, subscribeShards = $subscribeShards
let maxMessageSizeBytes =
case builder.maxMessageSize.kind
of mmskInt:
builder.maxMessageSize.bytes
of mmskStr:
?parseMsgSize(builder.maxMessageSize.str)
else:
warn "Max Message Size not specified, defaulting to 150KiB"
parseCorrectMsgSize("150KiB")
let contentTopics = builder.contentTopics.get(@[])
# Build sub-configs
let discv5Conf = builder.discv5Conf.build().valueOr:
return err("Discv5 Conf building failed: " & $error)
let dnsDiscoveryConf = builder.dnsDiscoveryConf.build().valueOr:
return err("DNS Discovery Conf building failed: " & $error)
let filterServiceConf = builder.filterServiceConf.build().valueOr:
return err("Filter Service Conf building failed: " & $error)
let metricsServerConf = builder.metricsServerConf.build().valueOr:
return err("Metrics Server Conf building failed: " & $error)
let restServerConf = builder.restServerConf.build().valueOr:
return err("REST Server Conf building failed: " & $error)
let rlnRelayConf = builder.rlnRelayConf.build().valueOr:
return err("RLN Relay Conf building failed: " & $error)
let storeServiceConf = builder.storeServiceConf.build().valueOr:
return err("Store Conf building failed: " & $error)
let mixConf = builder.mixConf.build().valueOr:
return err("Mix Conf building failed: " & $error)
let webSocketConf = builder.webSocketConf.build().valueOr:
return err("WebSocket Conf building failed: " & $error)
let rateLimit = builder.rateLimitConf.build().valueOr:
return err("Rate limits Conf building failed: " & $error)
# End - Build sub-configs
let logLevel =
if builder.logLevel.isSome():
builder.logLevel.get()
else:
warn "Log Level not specified, defaulting to INFO"
logging.LogLevel.INFO
let logFormat =
if builder.logFormat.isSome():
builder.logFormat.get()
else:
warn "Log Format not specified, defaulting to TEXT"
logging.LogFormat.TEXT
let natStrategy =
if builder.natStrategy.isSome():
builder.natStrategy.get()
else:
warn "Nat Strategy is not specified, defaulting to none"
"none"
let p2pTcpPort =
if builder.p2pTcpPort.isSome():
builder.p2pTcpPort.get()
else:
warn "P2P Listening TCP Port is not specified, listening on 60000"
60000.Port
let p2pListenAddress =
if builder.p2pListenAddress.isSome():
builder.p2pListenAddress.get()
else:
warn "P2P listening address not specified, listening on 0.0.0.0"
(static parseIpAddress("0.0.0.0"))
let portsShift =
if builder.portsShift.isSome():
builder.portsShift.get()
else:
warn "Ports Shift is not specified, defaulting to 0"
0.uint16
let dns4DomainName =
if builder.dns4DomainName.isSome():
let d = builder.dns4DomainName.get()
if d.string != "":
some(d)
else:
none(string)
else:
none(string)
var extMultiAddrs: seq[MultiAddress] = @[]
for s in builder.extMultiAddrs:
let m = MultiAddress.init(s).valueOr:
return err("Invalid multiaddress provided: " & s)
extMultiAddrs.add(m)
let extMultiAddrsOnly =
if builder.extMultiAddrsOnly.isSome():
builder.extMultiAddrsOnly.get()
else:
warn "Whether to only announce external multiaddresses is not specified, defaulting to false"
false
let dnsAddrsNameServers =
if builder.dnsAddrsNameServers.len != 0:
builder.dnsAddrsNameServers
else:
warn "DNS name servers IPs not provided, defaulting to Cloudflare's."
@[static parseIpAddress("1.1.1.1"), static parseIpAddress("1.0.0.1")]
let peerPersistence =
if builder.peerPersistence.isSome():
builder.peerPersistence.get()
else:
warn "Peer persistence not specified, defaulting to false"
false
let maxConnections =
if builder.maxConnections.isSome():
builder.maxConnections.get()
else:
warn "Max Connections was not specified, defaulting to 300"
300
# TODO: Do the git version thing here
let agentString = builder.agentString.get("nwaku")
# TODO: use `DefaultColocationLimit`. the user of this value should
# probably be defining a config object
let colocationLimit = builder.colocationLimit.get(5)
# TODO: is there a strategy for experimental features? delete vs promote
let relayShardedPeerManagement = builder.relayShardedPeerManagement.get(false)
let wakuFlags = CapabilitiesBitfield.init(
lightpush = lightPush and relay,
filter = filterServiceConf.isSome,
store = storeServiceConf.isSome,
relay = relay,
sync = storeServiceConf.isSome() and storeServiceConf.get().storeSyncConf.isSome,
mix = mix,
)
let wakuConf = WakuConf(
# confs
storeServiceConf: storeServiceConf,
filterServiceConf: filterServiceConf,
discv5Conf: discv5Conf,
rlnRelayConf: rlnRelayConf,
metricsServerConf: metricsServerConf,
restServerConf: restServerConf,
dnsDiscoveryConf: dnsDiscoveryConf,
mixConf: mixConf,
# end confs
nodeKey: nodeKey,
clusterId: clusterId,
shardingConf: shardingConf,
contentTopics: contentTopics,
subscribeShards: subscribeShards,
protectedShards: protectedShards,
relay: relay,
lightPush: lightPush,
peerExchangeService: peerExchange,
rendezvous: rendezvous,
peerExchangeDiscovery: true,
# enabling peer exchange client by default for quicker bootstrapping
remoteStoreNode: builder.remoteStoreNode,
remoteLightPushNode: builder.remoteLightPushNode,
remoteFilterNode: builder.remoteFilterNode,
remotePeerExchangeNode: builder.remotePeerExchangeNode,
relayPeerExchange: relayPeerExchange,
maxMessageSizeBytes: maxMessageSizeBytes,
logLevel: logLevel,
logFormat: logFormat,
# TODO: Separate builders
endpointConf: EndpointConf(
natStrategy: natStrategy,
p2pTcpPort: p2pTcpPort,
dns4DomainName: dns4DomainName,
p2pListenAddress: p2pListenAddress,
extMultiAddrs: extMultiAddrs,
extMultiAddrsOnly: extMultiAddrsOnly,
),
portsShift: portsShift,
webSocketConf: webSocketConf,
dnsAddrsNameServers: dnsAddrsNameServers,
peerPersistence: peerPersistence,
peerStoreCapacity: builder.peerStoreCapacity,
maxConnections: maxConnections,
agentString: agentString,
colocationLimit: colocationLimit,
maxRelayPeers: builder.maxRelayPeers,
relayServiceRatio: builder.relayServiceRatio.get("60:40"),
rateLimit: rateLimit,
circuitRelayClient: builder.circuitRelayClient.get(false),
staticNodes: builder.staticNodes,
relayShardedPeerManagement: relayShardedPeerManagement,
p2pReliability: builder.p2pReliability.get(false),
wakuFlags: wakuFlags,
)
?wakuConf.validate()
return ok(wakuConf)