split builder and conf

This commit is contained in:
fryorcraken 2025-04-07 15:42:34 +10:00
parent 08be11834a
commit 98114bde20
6 changed files with 612 additions and 491 deletions

View File

@ -63,9 +63,11 @@ when isMainModule:
let restServer = rest_server_builder.startRestServerEsentials(
nodeHealthMonitor, confCopy
).valueOr:
error "Starting esential REST server failed.", error = $error
error "Starting essential REST server failed.", error = $error
quit(QuitFailure)
# applyPresetConfiguration(wakuNodeConf, confBuilder)
var waku = Waku.new(confCopy).valueOr:
error "Waku initialization failed", error = error
quit(QuitFailure)

View File

@ -2,12 +2,14 @@
import
libp2p/crypto/[crypto, secp],
libp2p/multiaddress,
nimcrypto/utils,
std/[options, sequtils],
results,
testutils/unittests
import
waku/factory/waku_conf,
waku/factory/waku_conf_builder,
waku/factory/networks_config,
waku/common/utils/parse_size_units
@ -16,12 +18,13 @@ suite "Waku Conf - build with cluster conf":
## Setup
let clusterConf = ClusterConf.TheWakuNetworkConf()
var builder = WakuConfBuilder.init()
builder.withTcpPort(3000)
builder.withTcpPort(60000)
builder.discv5Conf.withUdpPort(9000)
# Mount all shards in network
let expectedShards = toSeq[0.uint16 .. 7.uint16]
## Given
builder.withRlnRelayEthClientAddress("https://my_eth_rpc_url/")
builder.rlnRelayConf.withEthClientAddress("https://my_eth_rpc_url/")
builder.withClusterConf(clusterConf)
builder.withRelay(true)
@ -31,13 +34,14 @@ suite "Waku Conf - build with cluster conf":
## Then
let conf = res.get()
assert conf.validate().isOk()
assert conf.clusterId == clusterConf.clusterId
assert conf.numShardsInNetwork == clusterConf.numShardsInNetwork
assert conf.shards == expectedShards
assert conf.maxMessageSizeBytes ==
int(parseCorrectMsgSize(clusterConf.maxMessageSize))
assert conf.discv5BootstrapNodes.map(
assert conf.discv5Conf.get().bootstrapNodes.map(
proc(e: TextEnr): string =
e.string
) == clusterConf.discv5BootstrapNodes
@ -46,26 +50,25 @@ suite "Waku Conf - build with cluster conf":
assert conf.rlnRelayConf.isSome
let rlnRelayConf = conf.rlnRelayConf.get()
assert rlnRelayConf.rlnRelayEthContractAddress.string ==
assert rlnRelayConf.ethContractAddress.string ==
clusterConf.rlnRelayEthContractAddress
assert rlnRelayConf.rlnRelayDynamic == clusterConf.rlnRelayDynamic
assert rlnRelayConf.rlnRelayChainId == clusterConf.rlnRelayChainId
assert rlnRelayConf.rlnRelayBandwidthThreshold ==
clusterConf.rlnRelayBandwidthThreshold
assert rlnRelayConf.rlnEpochSizeSec == clusterConf.rlnEpochSizeSec
assert rlnRelayConf.rlnRelayUserMessageLimit ==
clusterConf.rlnRelayUserMessageLimit
assert rlnRelayConf.dynamic == clusterConf.rlnRelayDynamic
assert rlnRelayConf.chainId == clusterConf.rlnRelayChainId
assert rlnRelayConf.bandwidthThreshold == clusterConf.rlnRelayBandwidthThreshold
assert rlnRelayConf.epochSizeSec == clusterConf.rlnEpochSizeSec
assert rlnRelayConf.userMessageLimit == clusterConf.rlnRelayUserMessageLimit
test "Cluster Conf is passed, but relay is disabled":
## Setup
let clusterConf = ClusterConf.TheWakuNetworkConf()
var builder = WakuConfBuilder.init()
builder.withTcpPort(3000)
builder.withTcpPort(60000)
builder.discv5Conf.withUdpPort(9000)
# Mount all shards in network
let expectedShards = toSeq[0.uint16 .. 7.uint16]
## Given
builder.withRlnRelayEthClientAddress("https://my_eth_rpc_url/")
builder.rlnRelayConf.withEthClientAddress("https://my_eth_rpc_url/")
builder.withClusterConf(clusterConf)
builder.withRelay(false)
@ -75,12 +78,13 @@ suite "Waku Conf - build with cluster conf":
## Then
let conf = res.get()
assert conf.validate().isOk()
assert conf.clusterId == clusterConf.clusterId
assert conf.numShardsInNetwork == clusterConf.numShardsInNetwork
assert conf.shards == expectedShards
assert conf.maxMessageSizeBytes ==
int(parseCorrectMsgSize(clusterConf.maxMessageSize))
assert conf.discv5BootstrapNodes.map(
assert conf.discv5Conf.get().bootstrapNodes.map(
proc(e: TextEnr): string =
e.string
) == clusterConf.discv5BootstrapNodes
@ -91,15 +95,16 @@ suite "Waku Conf - build with cluster conf":
## Setup
let clusterConf = ClusterConf.TheWakuNetworkConf()
var builder = WakuConfBuilder.init()
builder.withTcpPort(3000)
builder.withTcpPort(60000)
builder.discv5Conf.withUdpPort(9000)
let # Mount all shards in network
expectedShards = toSeq[0.uint16 .. 7.uint16]
## Given
builder.withRlnRelayEthClientAddress("https://my_eth_rpc_url/")
builder.rlnRelayConf.withEthClientAddress("https://my_eth_rpc_url/")
builder.withClusterConf(clusterConf)
builder.withRlnRelay(false)
builder.rlnRelayConf.withRlnRelay(false)
## When
let res = builder.build()
@ -107,12 +112,13 @@ suite "Waku Conf - build with cluster conf":
## Then
let conf = res.get()
assert conf.validate().isOk()
assert conf.clusterId == clusterConf.clusterId
assert conf.numShardsInNetwork == clusterConf.numShardsInNetwork
assert conf.shards == expectedShards
assert conf.maxMessageSizeBytes ==
int(parseCorrectMsgSize(clusterConf.maxMessageSize))
assert conf.discv5BootstrapNodes.map(
assert conf.discv5Conf.get().bootstrapNodes.map(
proc(e: TextEnr): string =
e.string
) == clusterConf.discv5BootstrapNodes
@ -123,11 +129,12 @@ suite "Waku Conf - build with cluster conf":
## Setup
let clusterConf = ClusterConf.TheWakuNetworkConf()
var builder = WakuConfBuilder.init()
builder.withTcpPort(3000)
builder.withTcpPort(60000)
builder.discv5Conf.withUdpPort(9000)
let shards = @[2.uint16, 3.uint16]
## Given
builder.withRlnRelayEthClientAddress("https://my_eth_rpc_url/")
builder.rlnRelayConf.withEthClientAddress("https://my_eth_rpc_url/")
builder.withClusterConf(clusterConf)
builder.withShards(shards)
@ -137,12 +144,13 @@ suite "Waku Conf - build with cluster conf":
## Then
let conf = res.get()
assert conf.validate().isOk()
assert conf.clusterId == clusterConf.clusterId
assert conf.numShardsInNetwork == clusterConf.numShardsInNetwork
assert conf.shards == shards
assert conf.maxMessageSizeBytes ==
int(parseCorrectMsgSize(clusterConf.maxMessageSize))
assert conf.discv5BootstrapNodes.map(
assert conf.discv5Conf.get().bootstrapNodes.map(
proc(e: TextEnr): string =
e.string
) == clusterConf.discv5BootstrapNodes
@ -151,33 +159,37 @@ suite "Waku Conf - build with cluster conf":
## Setup
let clusterConf = ClusterConf.TheWakuNetworkConf()
var builder = WakuConfBuilder.init()
builder.withTcpPort(3000)
builder.withTcpPort(60000)
builder.discv5Conf.withUdpPort(9000)
let shards = @[2.uint16, 10.uint16]
## Given
builder.withRlnRelayEthClientAddress("https://my_eth_rpc_url/")
builder.rlnRelayConf.withEthClientAddress("https://my_eth_rpc_url/")
builder.withClusterConf(clusterConf)
builder.withShards(shards)
## When
let res = builder.build()
assert res.isOk(), $res.error
## Then
assert res.isErr(), "Invalid shard was accepted"
let conf = res.get()
assert conf.validate().isErr(), "Invalid shard was accepted"
test "Cluster Conf is passed and RLN contract is overridden":
## Setup
let clusterConf = ClusterConf.TheWakuNetworkConf()
var builder = WakuConfBuilder.init()
builder.withTcpPort(3000)
builder.withRlnRelayEthClientAddress("https://my_eth_rpc_url/")
builder.withTcpPort(60000)
builder.discv5Conf.withUdpPort(9000)
builder.rlnRelayConf.withEthClientAddress("https://my_eth_rpc_url/")
# Mount all shards in network
let expectedShards = toSeq[0.uint16 .. 7.uint16]
let contractAddress = "0x0123456789ABCDEF"
## Given
builder.withRlnRelayEthContractAddress(contractAddress)
builder.rlnRelayConf.withEthContractAddress(contractAddress)
builder.withClusterConf(clusterConf)
builder.withRelay(true)
@ -187,13 +199,14 @@ suite "Waku Conf - build with cluster conf":
## Then
let conf = res.get()
assert conf.validate().isOk()
assert conf.clusterId == clusterConf.clusterId
assert conf.numShardsInNetwork == clusterConf.numShardsInNetwork
assert conf.shards == expectedShards
assert conf.maxMessageSizeBytes ==
int(parseCorrectMsgSize(clusterConf.maxMessageSize))
assert conf.discv5BootstrapNodes.map(
assert conf.discv5Conf.get().bootstrapNodes.map(
proc(e: TextEnr): string =
e.string
) == clusterConf.discv5BootstrapNodes
@ -202,14 +215,12 @@ suite "Waku Conf - build with cluster conf":
assert conf.rlnRelayConf.isSome
let rlnRelayConf = conf.rlnRelayConf.get()
assert rlnRelayConf.rlnRelayEthContractAddress.string == contractAddress
assert rlnRelayConf.rlnRelayDynamic == clusterConf.rlnRelayDynamic
assert rlnRelayConf.rlnRelayChainId == clusterConf.rlnRelayChainId
assert rlnRelayConf.rlnRelayBandwidthThreshold ==
clusterConf.rlnRelayBandwidthThreshold
assert rlnRelayConf.rlnEpochSizeSec == clusterConf.rlnEpochSizeSec
assert rlnRelayConf.rlnRelayUserMessageLimit ==
clusterConf.rlnRelayUserMessageLimit
assert rlnRelayConf.ethContractAddress.string == contractAddress
assert rlnRelayConf.dynamic == clusterConf.rlnRelayDynamic
assert rlnRelayConf.chainId == clusterConf.rlnRelayChainId
assert rlnRelayConf.bandwidthThreshold == clusterConf.rlnRelayBandwidthThreshold
assert rlnRelayConf.epochSizeSec == clusterConf.rlnEpochSizeSec
assert rlnRelayConf.userMessageLimit == clusterConf.rlnRelayUserMessageLimit
suite "Waku Conf - node key":
test "Node key is generated":
@ -217,7 +228,8 @@ suite "Waku Conf - node key":
var builder = WakuConfBuilder.init()
builder.withClusterId(1)
builder.withMaxMessageSizeBytes(1)
builder.withTcpPort(3000)
builder.withTcpPort(60000)
builder.discv5Conf.withUdpPort(9000)
## Given
@ -227,6 +239,7 @@ suite "Waku Conf - node key":
let conf = res.get()
## Then
assert conf.validate().isOk()
let pubkey = getPublicKey(conf.nodeKey)
assert pubkey.isOk()
@ -240,7 +253,8 @@ suite "Waku Conf - node key":
var builder = WakuConfBuilder.init()
builder.withClusterId(1)
builder.withMaxMessageSizeBytes(1)
builder.withTcpPort(3000)
builder.withTcpPort(60000)
builder.discv5Conf.withUdpPort(9000)
## Given
builder.withNodeKey(nodeKey)
@ -251,6 +265,37 @@ suite "Waku Conf - node key":
let conf = res.get()
## Then
assert conf.validate().isOk()
assert utils.toHex(conf.nodeKey.getRawBytes().get()) ==
utils.toHex(nodeKey.getRawBytes().get()),
"Passed node key isn't in config:" & $nodeKey & $conf.nodeKey
suite "Waku Conf - extMultiaddrs":
test "Valid multiaddresses are passed and accepted":
## Setup
var builder = WakuConfBuilder.init()
builder.withClusterId(1)
builder.withMaxMessageSizeBytes(1)
builder.withTcpPort(60000)
builder.discv5Conf.withUdpPort(9000)
## Given
let multiaddrs =
@["/ip4/127.0.0.1/udp/9090/quic", "/ip6/::1/tcp/3217", "/dns4/foo.com/tcp/80"]
for m in multiaddrs:
builder.withExtMultiAddr(m)
## When
let res = builder.build()
assert res.isOk(), $res.error
let conf = res.get()
## Then
assert conf.validate().isOk()
assert multiaddrs.len == conf.extMultiaddrs.len
let resMultiaddrs = conf.extMultiaddrs.map(
proc(m: MultiAddress): string =
$m
)
for m in multiaddrs:
assert m in resMultiaddrs

View File

@ -45,13 +45,6 @@ proc enrConfiguration*(
return ok(record)
proc validateExtMultiAddrs*(vals: seq[string]): Result[seq[MultiAddress], string] =
var multiaddrs: seq[MultiAddress]
for val in vals:
let multiaddr = ?MultiAddress.init(val)
multiaddrs.add(multiaddr)
return ok(multiaddrs)
proc dnsResolve*(
domain: string, conf: WakuNodeConf
): Future[Result[string, string]] {.async.} =
@ -85,15 +78,9 @@ proc networkConfiguration*(conf: WakuConf, clientId: string): NetConfigResult =
var (extIp, extTcpPort, _) = natRes.get()
let
dns4DomainName =
if conf.dns4DomainName != "":
some(conf.dns4DomainName)
else:
none(string)
discv5UdpPort =
if conf.discv5Discovery:
some(Port(uint16(conf.discv5UdpPort) + conf.portsShift))
if conf.discv5Conf.isSome:
some(Port(uint16(conf.discv5Conf.get().udpPort) + conf.portsShift))
else:
none(Port)
@ -102,22 +89,11 @@ proc networkConfiguration*(conf: WakuConf, clientId: string): NetConfigResult =
## extPort as well. The following heuristic assumes that, in absence of
## manual config, the external port is the same as the bind port.
extPort =
if (extIp.isSome() or dns4DomainName.isSome()) and extTcpPort.isNone():
if (extIp.isSome() or conf.dns4DomainName.isSome()) and extTcpPort.isNone():
some(Port(uint16(conf.tcpPort) + conf.portsShift))
else:
extTcpPort
extMultiAddrs =
if (conf.extMultiAddrs.len > 0):
let extMultiAddrsValidationRes = validateExtMultiAddrs(conf.extMultiAddrs)
if extMultiAddrsValidationRes.isErr():
return
err("invalid external multiaddress: " & $extMultiAddrsValidationRes.error)
else:
extMultiAddrsValidationRes.get()
else:
@[]
wakuFlags = CapabilitiesBitfield.init(
lightpush = conf.lightpush,
filter = conf.filter,
@ -127,7 +103,7 @@ proc networkConfiguration*(conf: WakuConf, clientId: string): NetConfigResult =
)
# Resolve and use DNS domain IP
if dns4DomainName.isSome() and extIp.isNone():
if conf.dns4DomainName.isSome() and extIp.isNone():
try:
let dnsRes = waitFor dnsResolve(conf.dns4DomainName, conf)
@ -148,12 +124,12 @@ proc networkConfiguration*(conf: WakuConf, clientId: string): NetConfigResult =
bindPort = Port(uint16(conf.tcpPort) + conf.portsShift),
extIp = extIp,
extPort = extPort,
extMultiAddrs = extMultiAddrs,
extMultiAddrs = conf.extMultiAddrs,
extMultiAddrsOnly = conf.extMultiAddrsOnly,
wsBindPort = Port(uint16(conf.websocketPort) + conf.portsShift),
wsEnabled = conf.websocketSupport,
wssEnabled = conf.websocketSecureSupport,
dns4DomainName = dns4DomainName,
dns4DomainName = conf.dns4DomainName,
discv5UdpPort = discv5UdpPort,
wakuFlags = some(wakuFlags),
)

View File

@ -144,18 +144,14 @@ proc setupAppCallbacks(
return ok()
# TODO: This should probably accept a `WakuConf` instead, and have the caller use `WakuConfBuilder`
# Or whatever they prefer to build a valid conf
proc new*(
T: type Waku, wakuNodeConf: WakuNodeConf, appCallbacks: AppCallbacks = nil
T: type Waku, wakuConf: WakuConf, appCallbacks: AppCallbacks = nil
): Result[Waku, string] =
let rng = crypto.newRng()
logging.setupLog(wakuNodeConf.logLevel, wakuNodeConf.logFormat)
logging.setupLog(wakuConf.logLevel, wakuConf.logFormat)
var confBuilder = WakuConfBuilder.init()
applyPresetConfiguration(wakuNodeConf, confBuilder)
?wakuConf.validate()
info "Running nwaku node", version = git_version

View File

@ -1,27 +1,36 @@
import std/[options, sequtils, net], chronicles, libp2p/crypto/crypto, results
import
std/[net, options, strutils],
chronicles,
libp2p/crypto/crypto,
libp2p/multiaddress,
results
import ../common/logging, ../common/utils/parse_size_units
import waku/factory/networks_config
import ../common/logging
logScope:
topics = "wakunode conf"
topics = "waku conf"
type
TextEnr* = distinct string
ContractAddress* = distinct string
EthRpcUrl* = distinct string
NatStrategy* = distinct string
DomainName* = distinct string
# TODO: this should come from discv5 discovery module
type Discv5Conf* = ref object
bootstrapNodes*: seq[TextEnr]
udpPort*: Port
# TODO: this should come from RLN relay module
type RlnRelayConf* = ref object
rlnRelayEthContractAddress*: ContractAddress
rlnRelayChainId*: uint
rlnRelayDynamic*: bool
rlnRelayBandwidthThreshold*: int
rlnEpochSizeSec*: uint64
rlnRelayUserMessageLimit*: uint64
rlnRelayEthClientAddress*: EthRpcUrl
ethContractAddress*: ContractAddress
chainId*: uint
dynamic*: bool
bandwidthThreshold*: int
epochSizeSec*: uint64
userMessageLimit*: uint64
ethClientAddress*: EthRpcUrl
type WakuConf* = ref object
nodeKey*: PrivateKey
@ -36,7 +45,7 @@ type WakuConf* = ref object
lightPush*: bool
peerExchange*: bool
discv5BootstrapNodes*: seq[TextEnr]
discv5Conf*: Option[Discv5Conf]
rlnRelayConf*: Option[RlnRelayConf]
@ -49,6 +58,8 @@ type WakuConf* = ref object
tcpPort*: Port
portsShift*: uint16
dns4DomainName*: Option[DomainName]
extMultiAddrs*: seq[MultiAddress]
proc log*(conf: WakuConf) =
info "Configuration: Enabled protocols",
@ -64,176 +75,22 @@ proc log*(conf: WakuConf) =
for shard in conf.shards:
info "Configuration. Shards", shard = shard
for i in conf.discv5BootstrapNodes:
info "Configuration. Bootstrap nodes", node = i.string
if conf.discv5Conf.isSome():
for i in conf.discv5Conf.get().bootstrapNodes:
info "Configuration. Bootstrap nodes", node = i.string
if conf.rlnRelayConf.isSome:
var rlnRelayConf = conf.rlnRelayConf.geT()
if rlnRelayConf.rlnRelayDynamic:
if rlnRelayConf.dynamic:
info "Configuration. Validation",
mechanism = "onchain rln",
contract = rlnRelayConf.rlnRelayEthContractAddress.string,
contract = rlnRelayConf.ethContractAddress.string,
maxMessageSize = conf.maxMessageSizeBytes,
rlnEpochSizeSec = rlnRelayConf.rlnEpochSizeSec,
rlnRelayUserMessageLimit = rlnRelayConf.rlnRelayUserMessageLimit,
rlnRelayEthClientAddress = string(rlnRelayConf.rlnRelayEthClientAddress)
rlnEpochSizeSec = rlnRelayConf.epochSizeSec,
rlnRelayUserMessageLimit = rlnRelayConf.userMessageLimit,
rlnRelayEthClientAddress = string(rlnRelayConf.ethClientAddress)
type RlnRelayConfBuilder = ref object
rlnRelay: Option[bool]
rlnRelayEthContractAddress: Option[ContractAddress]
rlnRelayChainId: Option[uint]
rlnRelayDynamic: Option[bool]
rlnRelayBandwidthThreshold: Option[int]
rlnEpochSizeSec: Option[uint64]
rlnRelayUserMessageLimit: Option[uint64]
rlnRelayEthClientAddress: Option[EthRpcUrl]
proc init(T: type RlnRelayConfBuilder): RlnRelayConfBuilder =
RlnRelayConfBuilder()
proc withRlnRelay(builder: var RlnRelayConfBuilder, rlnRelay: bool) =
builder.rlnRelay = some(rlnRelay)
proc withRlnRelayEthClientAddress(
builder: var RlnRelayConfBuilder, rlnRelayEthClientAddress: EthRpcUrl
) =
builder.rlnRelayEthClientAddress = some(rlnRelayEthClientAddress)
proc withRlnRelayEthContractAddress(
builder: var RlnRelayConfBuilder, withRlnRelayEthContractAddress: ContractAddress
) =
builder.rlnRelayEthContractAddress = some(withRlnRelayEthContractAddress)
proc build(builder: RlnRelayConfBuilder): Result[Option[RlnRelayConf], string] =
if builder.rlnRelay.isNone or not builder.rlnRelay.get():
info "RLN Relay is disabled"
return ok(none(RlnRelayConf))
let rlnRelayEthContractAddress =
if builder.rlnRelayEthContractAddress.isSome:
builder.rlnRelayEthContractAddress.get()
else:
return err("RLN Eth Contract Address was not specified")
let rlnRelayChainId =
if builder.rlnRelayChainId.isSome:
builder.rlnRelayChainId.get()
else:
return err("RLN Relay Chain Id was not specified")
let rlnRelayDynamic =
if builder.rlnRelayDynamic.isSome:
builder.rlnRelayDynamic.get()
else:
return err("RLN Relay Dynamic was not specified")
let rlnRelayBandwidthThreshold =
if builder.rlnRelayBandwidthThreshold.isSome:
builder.rlnRelayBandwidthThreshold.get()
else:
return err("RLN Relay Bandwidth Threshold was not specified")
let rlnEpochSizeSec =
if builder.rlnEpochSizeSec.isSome:
builder.rlnEpochSizeSec.get()
else:
return err("RLN Epoch Size was not specified")
let rlnRelayUserMessageLimit =
if builder.rlnRelayUserMessageLimit.isSome:
builder.rlnRelayUserMessageLimit.get()
else:
return err("RLN Relay User Message Limit was not specified")
let rlnRelayEthClientAddress =
if builder.rlnRelayEthClientAddress.isSome:
builder.rlnRelayEthClientAddress.get()
else:
return err("RLN Relay Eth Client Address was not specified")
return ok(
some(
RlnRelayConf(
rlnRelayChainId: rlnRelayChainId,
rlnRelayDynamic: rlnRelayDynamic,
rlnRelayEthContractAddress: rlnRelayEthContractAddress,
rlnEpochSizeSec: rlnEpochSizeSec,
rlnRelayUserMessageLimit: rlnRelayUserMessageLimit,
rlnRelayEthClientAddress: rlnRelayEthClientAddress,
)
)
)
type WakuConfBuilder* = ref object
nodeKey*: Option[PrivateKey]
clusterId: Option[uint16]
numShardsInNetwork: Option[uint32]
shards: Option[seq[uint16]]
relay: Option[bool]
store: Option[bool]
filter: Option[bool]
lightPush: Option[bool]
peerExchange: Option[bool]
clusterConf: Option[ClusterConf]
rlnRelayConf: RlnRelayConfBuilder
maxMessageSizeBytes: Option[int]
discv5Discovery: Option[bool]
discv5BootstrapNodes: Option[seq[TextEnr]]
logLevel: Option[logging.LogLevel]
logFormat: Option[logging.LogFormat]
natStrategy: Option[NatStrategy]
tcpPort: Option[Port]
portsShift: Option[uint16]
proc init*(T: type WakuConfBuilder): WakuConfBuilder =
WakuConfBuilder(rlnRelayConf: RlnRelayConfBuilder.init())
proc withClusterConf*(builder: var WakuConfBuilder, clusterConf: ClusterConf) =
builder.clusterConf = some(clusterConf)
proc withNodeKey*(builder: var WakuConfBuilder, nodeKey: PrivateKey) =
builder.nodeKey = some(nodeKey)
proc withClusterId*(builder: var WakuConfBuilder, clusterId: uint16) =
builder.clusterid = some(clusterId)
proc withShards*(builder: var WakuConfBuilder, shards: seq[uint16]) =
builder.shards = some(shards)
proc withRelay*(builder: var WakuConfBuilder, relay: bool) =
builder.relay = some(relay)
proc withRlnRelay*(builder: var WakuConfBuilder, rlnRelay: bool) =
builder.rlnRelayConf.withRlnRelay(rlnRelay)
proc withRlnRelayEthClientAddress*(
builder: var WakuConfBuilder, rlnRelayEthClientAddress: string
) =
builder.rlnRelayConf.withRlnRelayEthClientAddress(rlnRelayEthClientAddress.EthRpcUrl)
proc withRlnRelayEthContractAddress*(
builder: var WakuConfBuilder, rlnRelayEthContractAddress: string
) =
builder.rlnRelayConf.withRlnRelayEthContractAddress(
rlnRelayEthContractAddress.ContractAddress
)
proc withMaxMessageSizeBytes*(builder: WakuConfBuilder, maxMessageSizeBytes: int) =
builder.maxMessageSizeBytes = some(maxMessageSizeBytes)
proc withTcpPort*(builder: WakuConfBuilder, tcpPort: uint16) =
builder.tcpPort = some(tcpPort.Port)
proc validateShards*(wakuConf: WakuConf): Result[void, string] =
proc validateShards(wakuConf: WakuConf): Result[void, string] =
let numShardsInNetwork = wakuConf.numShardsInNetwork
for shard in wakuConf.shards:
@ -246,246 +103,15 @@ proc validateShards*(wakuConf: WakuConf): Result[void, string] =
return ok()
proc validate(wakuConf: WakuConf): Result[void, string] =
?validateShards(wakuConf)
proc validateNoEmptyStrings(wakuConf: WakuConf): Result[void, string] =
if wakuConf.dns4DomainName.isSome():
if isEmptyOrWhiteSpace(wakuConf.dns4DomainName.get().string):
return err("dns4DomainName is an empty string, set it to none(string) instead")
return ok()
proc nodeKey(
builder: WakuConfBuilder, rng: ref HmacDrbgContext
): Result[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 validate*(wakuConf: WakuConf): Result[void, string] =
?wakuConf.validateShards()
?wakuConf.validateNoEmptyStrings()
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.
let relay =
if builder.relay.isSome:
builder.relay.get()
else:
warn "whether to mount relay is not specified, defaulting to not mounting"
false
let store =
if builder.store.isSome:
builder.store.get()
else:
warn "whether to mount store is not specified, defaulting to not mounting"
false
let filter =
if builder.filter.isSome:
builder.filter.get()
else:
warn "whether to mount filter 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
# Apply cluster conf - values passed manually override cluster conf
# Should be applied **first**, before individual values are pulled
if builder.clusterConf.isSome:
var clusterConf = builder.clusterConf.get()
if builder.clusterId.isNone:
builder.clusterId = some(clusterConf.clusterId)
else:
warn "Cluster id was manually provided alongside a cluster conf",
used = builder.clusterId, discarded = clusterConf.clusterId
if relay and clusterConf.rlnRelay:
var rlnRelayConf = builder.rlnRelayConf
if rlnRelayConf.rlnRelay.isNone:
rlnRelayConf.rlnRelay = some(true)
else:
warn "RLN Relay was manually provided alongside a cluster conf",
used = rlnRelayConf.rlnRelay, discarded = clusterConf.rlnRelay
if rlnRelayConf.rlnRelayEthContractAddress.isNone:
rlnRelayConf.rlnRelayEthContractAddress =
some(clusterConf.rlnRelayEthContractAddress.ContractAddress)
else:
warn "RLN Relay ETH Contract Address was manually provided alongside a cluster conf",
used = rlnRelayConf.rlnRelayEthContractAddress.get().string,
discarded = clusterConf.rlnRelayEthContractAddress.string
if rlnRelayConf.rlnRelayChainId.isNone:
rlnRelayConf.rlnRelayChainId = some(clusterConf.rlnRelayChainId)
else:
warn "RLN Relay Chain Id was manually provided alongside a cluster conf",
used = rlnRelayConf.rlnRelayChainId, discarded = clusterConf.rlnRelayChainId
if rlnRelayConf.rlnRelayDynamic.isNone:
rlnRelayConf.rlnRelayDynamic = some(clusterConf.rlnRelayDynamic)
else:
warn "RLN Relay Dynamic was manually provided alongside a cluster conf",
used = rlnRelayConf.rlnRelayDynamic, discarded = clusterConf.rlnRelayDynamic
if rlnRelayConf.rlnRelayBandwidthThreshold.isNone:
rlnRelayConf.rlnRelayBandwidthThreshold =
some(clusterConf.rlnRelayBandwidthThreshold)
else:
warn "RLN Relay Bandwidth Threshold was manually provided alongside a cluster conf",
used = rlnRelayConf.rlnRelayBandwidthThreshold,
discarded = clusterConf.rlnRelayBandwidthThreshold
if rlnRelayConf.rlnEpochSizeSec.isNone:
rlnRelayConf.rlnEpochSizeSec = some(clusterConf.rlnEpochSizeSec)
else:
warn "RLN Epoch Size in Seconds was manually provided alongside a cluster conf",
used = rlnRelayConf.rlnEpochSizeSec, discarded = clusterConf.rlnEpochSizeSec
if rlnRelayConf.rlnRelayUserMessageLimit.isNone:
rlnRelayConf.rlnRelayUserMessageLimit =
some(clusterConf.rlnRelayUserMessageLimit)
else:
warn "RLN Relay Dynamic was manually provided alongside a cluster conf",
used = rlnRelayConf.rlnRelayUserMessageLimit,
discarded = clusterConf.rlnRelayUserMessageLimit
if builder.maxMessageSizeBytes.isNone:
builder.maxMessageSizeBytes =
some(int(parseCorrectMsgSize(clusterConf.maxMessageSize)))
else:
warn "Max Message Size was manually provided alongside a cluster conf",
used = builder.maxMessageSizeBytes, discarded = clusterConf.maxMessageSize
if builder.numShardsInNetwork.isNone:
builder.numShardsInNetwork = some(clusterConf.numShardsInNetwork)
else:
warn "Num Shards In Network was manually provided alongside a cluster conf",
used = builder.numShardsInNetwork, discarded = clusterConf.numShardsInNetwork
if builder.discv5Discovery.isNone:
builder.discv5Discovery = some(clusterConf.discv5Discovery)
if builder.discv5BootstrapNodes.isNone:
builder.discv5BootstrapNodes = some(
clusterConf.discv5BootstrapNodes.map(
proc(e: string): TextEnr =
e.TextEnr
)
)
# Apply preset - end
let nodeKey = ?nodeKey(builder, rng)
let clusterId =
if builder.clusterId.isSome:
builder.clusterId.get()
else:
return err("Cluster Id is missing")
let numShardsInNetwork =
if builder.numShardsInNetwork.isSome:
builder.numShardsInNetwork.get()
else:
warn "Number of shards in network not specified, defaulting to one shard"
1
let shards =
if builder.shards.isSome:
builder.shards.get()
else:
warn "shards not specified, defaulting to all shards in network"
# TODO: conversion should not be needed
let upperShard: uint16 = uint16(numShardsInNetwork - 1)
toSeq(0.uint16 .. upperShard)
let discv5BootstrapNodes =
if builder.discv5BootstrapNodes.isSome:
builder.discv5BootstrapNodes.get()
else:
@[]
let rlnRelayConf = builder.rlnRelayConf.build().valueOr:
return err("RLN Relay Conf building failed: " & $error)
let maxMessageSizeBytes =
if builder.maxMessageSizeBytes.isSome:
builder.maxMessageSizeBytes.get()
else:
return err("Max Message Size is missing")
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".NatStrategy
let tcpPort =
if builder.tcpPort.isSome:
builder.tcpPort.get()
else:
return err("TCP Port is missing")
let portsShift =
if builder.portsShift.isSome:
builder.portsShift.get()
else:
warn "Ports Shift is not specified, defaulting to 0"
0.uint16
let wakuConf = WakuConf(
nodeKey: nodeKey,
clusterId: clusterId,
numShardsInNetwork: numShardsInNetwork,
shards: shards,
relay: relay,
store: store,
filter: filter,
lightPush: lightPush,
peerExchange: peerExchange,
discv5BootstrapNodes: discv5BootstrapNodes,
rlnRelayConf: rlnRelayConf,
maxMessageSizeBytes: maxMessageSizeBytes,
logLevel: logLevel,
logFormat: logFormat,
natStrategy: natStrategy,
tcpPort: tcpPort,
portsShift: portsShift,
)
?validate(wakuConf)
return ok(wakuConf)
return ok()

View File

@ -0,0 +1,476 @@
import
libp2p/crypto/crypto,
libp2p/multiaddress,
std/[net, options, sequtils],
chronicles,
results
import
./waku_conf, ./networks_config, ../common/logging, ../common/utils/parse_size_units
logScope:
topics = "waku conf builder"
##############################
## RLN Relay Config Builder ##
##############################
type RlnRelayConfBuilder = ref object
rlnRelay: Option[bool]
ethContractAddress: Option[ContractAddress]
chainId: Option[uint]
dynamic: Option[bool]
bandwidthThreshold: Option[int]
epochSizeSec: Option[uint64]
userMessageLimit: Option[uint64]
ethClientAddress: Option[EthRpcUrl]
proc init*(T: type RlnRelayConfBuilder): RlnRelayConfBuilder =
RlnRelayConfBuilder()
proc withRlnRelay*(builder: var RlnRelayConfBuilder, rlnRelay: bool) =
builder.rlnRelay = some(rlnRelay)
proc withEthContractAddress*(
builder: var RlnRelayConfBuilder, ethContractAddress: string
) =
builder.ethContractAddress = some(ethContractAddress.ContractAddress)
proc withChainId*(builder: var RlnRelayConfBuilder, chainId: uint) =
builder.chainId = some(chainId)
proc withDynamic*(builder: var RlnRelayConfBuilder, dynamic: bool) =
builder.dynamic = some(dynamic)
proc withBandwidthThreshold*(
builder: var RlnRelayConfBuilder, bandwidthThreshold: int
) =
builder.bandwidthThreshold = some(bandwidthThreshold)
proc withEpochSizeSec*(builder: var RlnRelayConfBuilder, epochSizeSec: uint64) =
builder.epochSizeSec = some(epochSizeSec)
proc withUserMessageLimit*(builder: var RlnRelayConfBuilder, userMessageLimit: uint64) =
builder.userMessageLimit = some(userMessageLimit)
proc withEthClientAddress*(builder: var RlnRelayConfBuilder, ethClientAddress: string) =
builder.ethClientAddress = some(ethClientAddress.EthRpcUrl)
proc build*(builder: RlnRelayConfBuilder): Result[Option[RlnRelayConf], string] =
if builder.rlnRelay.isNone or not builder.rlnRelay.get():
info "RLN Relay is disabled"
return ok(none(RlnRelayConf))
let ethContractAddress =
if builder.ethContractAddress.isSome:
builder.ethContractAddress.get()
else:
return err("RLN Eth Contract Address was not specified")
let chainId =
if builder.chainId.isSome:
builder.chainId.get()
else:
return err("RLN Relay Chain Id was not specified")
let dynamic =
if builder.dynamic.isSome:
builder.dynamic.get()
else:
return err("RLN Relay Dynamic was not specified")
let bandwidthThreshold =
if builder.bandwidthThreshold.isSome:
builder.bandwidthThreshold.get()
else:
return err("RLN Relay Bandwidth Threshold was not specified")
let epochSizeSec =
if builder.epochSizeSec.isSome:
builder.epochSizeSec.get()
else:
return err("RLN Epoch Size was not specified")
let userMessageLimit =
if builder.userMessageLimit.isSome:
builder.userMessageLimit.get()
else:
return err("RLN Relay User Message Limit was not specified")
let ethClientAddress =
if builder.ethClientAddress.isSome:
builder.ethClientAddress.get()
else:
return err("RLN Relay Eth Client Address was not specified")
return ok(
some(
RlnRelayConf(
chainId: chainId,
dynamic: dynamic,
ethContractAddress: ethContractAddress,
epochSizeSec: epochSizeSec,
userMessageLimit: userMessageLimit,
ethClientAddress: ethClientAddress,
)
)
)
###########################
## Discv5 Config Builder ##
###########################
type Discv5ConfBuilder = ref object
discv5*: Option[bool]
bootstrapNodes*: Option[seq[TextEnr]]
udpPort*: Option[Port]
proc init(T: type Discv5ConfBuilder): Discv5ConfBuilder =
Discv5ConfBuilder()
proc withDiscv5(builder: var Discv5ConfBuilder, discv5: bool) =
builder.discv5 = some(discv5)
proc withBootstrapNodes(builder: var Discv5ConfBuilder, bootstrapNodes: seq[string]) =
# TODO: validate ENRs?
builder.bootstrapNodes = some(
bootstrapNodes.map(
proc(e: string): TextEnr =
e.TextEnr
)
)
proc withUdpPort*(builder: var Discv5ConfBuilder, udpPort: uint16) =
builder.udpPort = some (udpPort.Port)
proc build(builder: Discv5ConfBuilder): Result[Option[Discv5Conf], string] =
if builder.discv5.isNone or not builder.discv5.get():
return ok(none(Discv5Conf))
# TODO: Do we need to ensure there are bootstrap nodes?
# Not sure discv5 is of any use without bootstrap nodes
# Confirmed: discv5 is useless without bootstrap node - config valid function?
let bootstrapNodes = builder.bootstrapNodes.get(@[])
let udpPort =
if builder.udpPort.isSome:
builder.udpPort.get()
else:
return err("Discv5 UDP Port was not specified")
return ok(some(Discv5Conf(bootstrapNodes: bootstrapNodes, udpPort: udpPort)))
#########################
## Waku Config Builder ##
#########################
type WakuConfBuilder* = ref object
nodeKey*: Option[PrivateKey]
clusterId: Option[uint16]
numShardsInNetwork: Option[uint32]
shards: Option[seq[uint16]]
relay: Option[bool]
store: Option[bool]
filter: Option[bool]
lightPush: Option[bool]
peerExchange: Option[bool]
clusterConf: Option[ClusterConf]
rlnRelayConf*: RlnRelayConfBuilder
maxMessageSizeBytes: Option[int]
discv5Conf*: Discv5ConfBuilder
logLevel: Option[logging.LogLevel]
logFormat: Option[logging.LogFormat]
natStrategy: Option[NatStrategy]
tcpPort: Option[Port]
portsShift: Option[uint16]
dns4DomainName: Option[DomainName]
extMultiAddrs: seq[string]
proc init*(T: type WakuConfBuilder): WakuConfBuilder =
WakuConfBuilder(
rlnRelayConf: RlnRelayConfBuilder.init(), discv5Conf: Discv5ConfBuilder.init()
)
proc withClusterConf*(builder: var WakuConfBuilder, clusterConf: ClusterConf) =
builder.clusterConf = some(clusterConf)
proc withNodeKey*(builder: var WakuConfBuilder, nodeKey: PrivateKey) =
builder.nodeKey = some(nodeKey)
proc withClusterId*(builder: var WakuConfBuilder, clusterId: uint16) =
builder.clusterid = some(clusterId)
proc withShards*(builder: var WakuConfBuilder, shards: seq[uint16]) =
builder.shards = some(shards)
proc withRelay*(builder: var WakuConfBuilder, relay: bool) =
builder.relay = some(relay)
proc withMaxMessageSizeBytes*(builder: var WakuConfBuilder, maxMessageSizeBytes: int) =
builder.maxMessageSizeBytes = some(maxMessageSizeBytes)
proc withDiscv5*(builder: var WakuConfBuilder, discv5: bool) =
builder.discv5Conf.withDiscv5(discv5)
proc withTcpPort*(builder: var WakuConfBuilder, tcpPort: uint16) =
builder.tcpPort = some(tcpPort.Port)
proc withDns4DomainName*(builder: var WakuConfBuilder, dns4DomainName: string) =
builder.dns4DomainName = some(dns4DomainName.DomainName)
proc withExtMultiAddr*(builder: var WakuConfBuilder, extMultiAddr: string) =
builder.extMultiAddrs.add(extMultiAddr)
proc nodeKey(
builder: WakuConfBuilder, rng: ref HmacDrbgContext
): Result[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 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.
let relay =
if builder.relay.isSome:
builder.relay.get()
else:
warn "whether to mount relay is not specified, defaulting to not mounting"
false
let store =
if builder.store.isSome:
builder.store.get()
else:
warn "whether to mount store is not specified, defaulting to not mounting"
false
let filter =
if builder.filter.isSome:
builder.filter.get()
else:
warn "whether to mount filter 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
# Apply cluster conf - values passed manually override cluster conf
# Should be applied **first**, before individual values are pulled
if builder.clusterConf.isSome:
var clusterConf = builder.clusterConf.get()
if builder.clusterId.isNone:
builder.clusterId = some(clusterConf.clusterId)
else:
warn "Cluster id was manually provided alongside a cluster conf",
used = builder.clusterId, discarded = clusterConf.clusterId
if relay and clusterConf.rlnRelay:
var rlnRelayConf = builder.rlnRelayConf
if rlnRelayConf.rlnRelay.isNone:
rlnRelayConf.withRlnRelay(true)
else:
warn "RLN Relay was manually provided alongside a cluster conf",
used = rlnRelayConf.rlnRelay, discarded = clusterConf.rlnRelay
if rlnRelayConf.ethContractAddress.isNone:
rlnRelayConf.withEthContractAddress(clusterConf.rlnRelayEthContractAddress)
else:
warn "RLN Relay ETH Contract Address was manually provided alongside a cluster conf",
used = rlnRelayConf.ethContractAddress.get().string,
discarded = clusterConf.rlnRelayEthContractAddress.string
if rlnRelayConf.chainId.isNone:
rlnRelayConf.withChainId(clusterConf.rlnRelayChainId)
else:
warn "RLN Relay Chain Id was manually provided alongside a cluster conf",
used = rlnRelayConf.chainId, discarded = clusterConf.rlnRelayChainId
if rlnRelayConf.dynamic.isNone:
rlnRelayConf.withDynamic(clusterConf.rlnRelayDynamic)
else:
warn "RLN Relay Dynamic was manually provided alongside a cluster conf",
used = rlnRelayConf.dynamic, discarded = clusterConf.rlnRelayDynamic
if rlnRelayConf.bandwidthThreshold.isNone:
rlnRelayConf.withBandwidthThreshold(clusterConf.rlnRelayBandwidthThreshold)
else:
warn "RLN Relay Bandwidth Threshold was manually provided alongside a cluster conf",
used = rlnRelayConf.bandwidthThreshold,
discarded = clusterConf.rlnRelayBandwidthThreshold
if rlnRelayConf.epochSizeSec.isNone:
rlnRelayConf.withEpochSizeSec(clusterConf.rlnEpochSizeSec)
else:
warn "RLN Epoch Size in Seconds was manually provided alongside a cluster conf",
used = rlnRelayConf.epochSizeSec, discarded = clusterConf.rlnEpochSizeSec
if rlnRelayConf.userMessageLimit.isNone:
rlnRelayConf.withUserMessageLimit(clusterConf.rlnRelayUserMessageLimit)
else:
warn "RLN Relay Dynamic was manually provided alongside a cluster conf",
used = rlnRelayConf.userMessageLimit,
discarded = clusterConf.rlnRelayUserMessageLimit
if builder.maxMessageSizeBytes.isNone:
builder.maxMessageSizeBytes =
some(int(parseCorrectMsgSize(clusterConf.maxMessageSize)))
else:
warn "Max Message Size was manually provided alongside a cluster conf",
used = builder.maxMessageSizeBytes, discarded = clusterConf.maxMessageSize
if builder.numShardsInNetwork.isNone:
builder.numShardsInNetwork = some(clusterConf.numShardsInNetwork)
else:
warn "Num Shards In Network was manually provided alongside a cluster conf",
used = builder.numShardsInNetwork, discarded = clusterConf.numShardsInNetwork
if clusterConf.discv5Discovery:
var discv5ConfBuilder = builder.discv5Conf
if discv5ConfBuilder.discv5.isNone:
discv5ConfBuilder.withDiscv5(clusterConf.discv5Discovery)
if discv5ConfBuilder.bootstrapNodes.isNone and
clusterConf.discv5BootstrapNodes.len > 0:
discv5ConfBuilder.withBootstrapNodes(clusterConf.discv5BootstrapNodes)
# Apply preset - end
let nodeKey = ?nodeKey(builder, rng)
let clusterId =
if builder.clusterId.isSome:
builder.clusterId.get()
else:
return err("Cluster Id is missing")
let numShardsInNetwork =
if builder.numShardsInNetwork.isSome:
builder.numShardsInNetwork.get()
else:
warn "Number of shards in network not specified, defaulting to one shard"
1
let shards =
if builder.shards.isSome:
builder.shards.get()
else:
warn "shards not specified, defaulting to all shards in network"
# TODO: conversion should not be needed
let upperShard: uint16 = uint16(numShardsInNetwork - 1)
toSeq(0.uint16 .. upperShard)
let discv5Conf = builder.discv5Conf.build().valueOr:
return err("Discv5 Conf building failed: " & $error)
let rlnRelayConf = builder.rlnRelayConf.build().valueOr:
return err("RLN Relay Conf building failed: " & $error)
let maxMessageSizeBytes =
if builder.maxMessageSizeBytes.isSome:
builder.maxMessageSizeBytes.get()
else:
return err("Max Message Size is missing")
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".NatStrategy
let tcpPort =
if builder.tcpPort.isSome:
builder.tcpPort.get()
else:
return err("TCP Port is missing")
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(DomainName)
else:
none(DomainName)
var extMultiAddrs: seq[MultiAddress] = @[]
for s in builder.extMultiAddrs:
let m = MultiAddress.init(s).valueOr:
return err("Invalid multiaddress provided: " & s)
extMultiAddrs.add(m)
return ok(
WakuConf(
nodeKey: nodeKey,
clusterId: clusterId,
numShardsInNetwork: numShardsInNetwork,
shards: shards,
relay: relay,
store: store,
filter: filter,
lightPush: lightPush,
peerExchange: peerExchange,
discv5Conf: discv5Conf,
rlnRelayConf: rlnRelayConf,
maxMessageSizeBytes: maxMessageSizeBytes,
logLevel: logLevel,
logFormat: logFormat,
natStrategy: natStrategy,
tcpPort: tcpPort,
portsShift: portsShift,
dns4DomainName: dns4DomainName,
extMultiAddrs: extMultiAddrs,
)
)