mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-01-26 01:33:10 +00:00
split builder and conf
This commit is contained in:
parent
08be11834a
commit
98114bde20
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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),
|
||||
)
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
476
waku/factory/waku_conf_builder.nim
Normal file
476
waku/factory/waku_conf_builder.nim
Normal 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,
|
||||
)
|
||||
)
|
||||
Loading…
x
Reference in New Issue
Block a user