mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-05-17 15:59:46 +00:00
Improve config
* Soft-deprecate --cluster-id=N triggering the associated preset selection * Rewrite applyNetworkConf to apply user-set fields over preset fields * Add createNode(preset, mode, overrides, additions) nim api * Generate WakuNodeConfOverlay (all Option fields) from WakuNodeConf * New parser for configJson handles new messaging shape and full conf shape * Change all confbuilder defaults from literal values to DefaultXXX consts * Change int/bool WakuNodeConf fields to Option to get user intent w/o sentinels * Make Option CLI default-value help mention defaults now owned by confbuilder * Misc refactors, fixes * Add tests
This commit is contained in:
parent
689ef70de9
commit
098c6f2a6d
@ -96,7 +96,7 @@ when isMainModule:
|
|||||||
|
|
||||||
wakuNodeConf.shards = @[conf.shard]
|
wakuNodeConf.shards = @[conf.shard]
|
||||||
wakuNodeConf.contentTopics = conf.contentTopics
|
wakuNodeConf.contentTopics = conf.contentTopics
|
||||||
wakuNodeConf.clusterId = conf.clusterId
|
wakuNodeConf.clusterId = some(conf.clusterId)
|
||||||
## TODO: Depending on the tester needs we might extend here with shards, clusterId, etc...
|
## TODO: Depending on the tester needs we might extend here with shards, clusterId, etc...
|
||||||
|
|
||||||
wakuNodeConf.metricsServer = true
|
wakuNodeConf.metricsServer = true
|
||||||
|
|||||||
@ -30,18 +30,18 @@ proc setup*(): Waku =
|
|||||||
|
|
||||||
# Override configuration
|
# Override configuration
|
||||||
conf.maxMessageSize = twnNetworkConf.maxMessageSize
|
conf.maxMessageSize = twnNetworkConf.maxMessageSize
|
||||||
conf.clusterId = twnNetworkConf.clusterId
|
conf.clusterId = some(twnNetworkConf.clusterId)
|
||||||
conf.rlnRelayEthContractAddress = twnNetworkConf.rlnRelayEthContractAddress
|
conf.rlnRelayEthContractAddress = twnNetworkConf.rlnRelayEthContractAddress
|
||||||
conf.rlnRelayDynamic = twnNetworkConf.rlnRelayDynamic
|
conf.rlnRelayDynamic = some(twnNetworkConf.rlnRelayDynamic)
|
||||||
conf.discv5Discovery = twnNetworkConf.discv5Discovery
|
conf.discv5Discovery = some(twnNetworkConf.discv5Discovery)
|
||||||
conf.discv5BootstrapNodes =
|
conf.discv5BootstrapNodes =
|
||||||
conf.discv5BootstrapNodes & twnNetworkConf.discv5BootstrapNodes
|
conf.discv5BootstrapNodes & twnNetworkConf.discv5BootstrapNodes
|
||||||
conf.rlnEpochSizeSec = twnNetworkConf.rlnEpochSizeSec
|
conf.rlnEpochSizeSec = some(twnNetworkConf.rlnEpochSizeSec)
|
||||||
conf.rlnRelayUserMessageLimit = twnNetworkConf.rlnRelayUserMessageLimit
|
conf.rlnRelayUserMessageLimit = some(twnNetworkConf.rlnRelayUserMessageLimit)
|
||||||
|
|
||||||
# Only set rlnRelay to true if relay is configured
|
# Only set rlnRelay to true if relay is configured
|
||||||
if conf.relay:
|
if conf.relay:
|
||||||
conf.rlnRelay = twnNetworkConf.rlnRelay
|
conf.rlnRelay = some(twnNetworkConf.rlnRelay)
|
||||||
|
|
||||||
info "Starting node"
|
info "Starting node"
|
||||||
var waku = (waitFor Waku.new(conf)).valueOr:
|
var waku = (waitFor Waku.new(conf)).valueOr:
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import std/[json, strutils, tables]
|
import std/json
|
||||||
import chronos, chronicles, results, confutils, confutils/std/net, ffi
|
import chronos, chronicles, results, ffi
|
||||||
import
|
import
|
||||||
waku/factory/waku,
|
waku/factory/waku,
|
||||||
waku/node/waku_node,
|
waku/node/waku_node,
|
||||||
waku/api/[api, types],
|
waku/api/[api, types],
|
||||||
waku/events/[message_events, health_events],
|
waku/events/[message_events, health_events],
|
||||||
tools/confutils/cli_args,
|
tools/confutils/conf_from_json,
|
||||||
../declare_lib,
|
../declare_lib,
|
||||||
../json_event
|
../json_event
|
||||||
|
|
||||||
@ -15,59 +15,11 @@ proc `%`*(id: RequestId): JsonNode =
|
|||||||
|
|
||||||
registerReqFFI(CreateNodeRequest, ctx: ptr FFIContext[Waku]):
|
registerReqFFI(CreateNodeRequest, ctx: ptr FFIContext[Waku]):
|
||||||
proc(configJson: cstring): Future[Result[string, string]] {.async.} =
|
proc(configJson: cstring): Future[Result[string, string]] {.async.} =
|
||||||
## Parse the JSON configuration using fieldPairs approach (WakuNodeConf)
|
let conf = parseConfJson($configJson).valueOr:
|
||||||
var conf = defaultWakuNodeConf().valueOr:
|
error "Failed to assemble WakuNodeConf from JSON",
|
||||||
return err("Failed creating default conf: " & error)
|
error = error, configJson = $configJson
|
||||||
|
return err(error)
|
||||||
|
|
||||||
var jsonNode: JsonNode
|
|
||||||
try:
|
|
||||||
jsonNode = parseJson($configJson)
|
|
||||||
except Exception:
|
|
||||||
let exceptionMsg = getCurrentExceptionMsg()
|
|
||||||
error "Failed to parse config JSON",
|
|
||||||
error = exceptionMsg, configJson = $configJson
|
|
||||||
return err(
|
|
||||||
"Failed to parse config JSON: " & exceptionMsg & " configJson string: " &
|
|
||||||
$configJson
|
|
||||||
)
|
|
||||||
|
|
||||||
var jsonFields: Table[string, (string, JsonNode)]
|
|
||||||
for key, value in jsonNode:
|
|
||||||
let lowerKey = key.toLowerAscii()
|
|
||||||
|
|
||||||
if jsonFields.hasKey(lowerKey):
|
|
||||||
error "Duplicate configuration option found when normalized to lowercase",
|
|
||||||
key = key
|
|
||||||
return err(
|
|
||||||
"Duplicate configuration option found when normalized to lowercase: '" & key &
|
|
||||||
"'"
|
|
||||||
)
|
|
||||||
|
|
||||||
jsonFields[lowerKey] = (key, value)
|
|
||||||
|
|
||||||
for confField, confValue in fieldPairs(conf):
|
|
||||||
let lowerField = confField.toLowerAscii()
|
|
||||||
if jsonFields.hasKey(lowerField):
|
|
||||||
let (jsonKey, jsonValue) = jsonFields[lowerField]
|
|
||||||
let formattedString = ($jsonValue).strip(chars = {'\"'})
|
|
||||||
try:
|
|
||||||
confValue = parseCmdArg(typeof(confValue), formattedString)
|
|
||||||
except Exception:
|
|
||||||
return err(
|
|
||||||
"Failed to parse field '" & confField & "' from JSON key '" & jsonKey & "': " &
|
|
||||||
getCurrentExceptionMsg() & ". Value: " & formattedString
|
|
||||||
)
|
|
||||||
|
|
||||||
jsonFields.del(lowerField)
|
|
||||||
|
|
||||||
if jsonFields.len > 0:
|
|
||||||
var unknownKeys = newSeq[string]()
|
|
||||||
for _, (jsonKey, _) in pairs(jsonFields):
|
|
||||||
unknownKeys.add(jsonKey)
|
|
||||||
error "Unrecognized configuration option(s) found", option = unknownKeys
|
|
||||||
return err("Unrecognized configuration option(s) found: " & $unknownKeys)
|
|
||||||
|
|
||||||
# Create the node
|
|
||||||
ctx.myLib[] = (await api.createNode(conf)).valueOr:
|
ctx.myLib[] = (await api.createNode(conf)).valueOr:
|
||||||
let errMsg = $error
|
let errMsg = $error
|
||||||
chronicles.error "CreateNodeRequest failed", err = errMsg
|
chronicles.error "CreateNodeRequest failed", err = errMsg
|
||||||
@ -96,7 +48,7 @@ proc logosdelivery_create_node(
|
|||||||
): pointer {.dynlib, exportc, cdecl.} =
|
): pointer {.dynlib, exportc, cdecl.} =
|
||||||
initializeLibrary()
|
initializeLibrary()
|
||||||
|
|
||||||
if isNil(callback):
|
if callback.isNil():
|
||||||
echo "error: missing callback in logosdelivery_create_node"
|
echo "error: missing callback in logosdelivery_create_node"
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
import
|
import
|
||||||
./test_entry_nodes,
|
./test_entry_nodes,
|
||||||
./test_node_conf,
|
./test_node_conf,
|
||||||
|
./test_messaging_conf,
|
||||||
./test_api_send,
|
./test_api_send,
|
||||||
./test_api_subscription,
|
./test_api_subscription,
|
||||||
./test_api_receive,
|
./test_api_receive,
|
||||||
|
|||||||
@ -96,7 +96,7 @@ suite "LM API health checking":
|
|||||||
conf.listenAddress = parseIpAddress("0.0.0.0")
|
conf.listenAddress = parseIpAddress("0.0.0.0")
|
||||||
conf.tcpPort = Port(0)
|
conf.tcpPort = Port(0)
|
||||||
conf.discv5UdpPort = Port(0)
|
conf.discv5UdpPort = Port(0)
|
||||||
conf.clusterId = 3'u16
|
conf.clusterId = some(3'u16)
|
||||||
conf.numShardsInNetwork = 1
|
conf.numShardsInNetwork = 1
|
||||||
conf.rest = false
|
conf.rest = false
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ suite "LM API health checking":
|
|||||||
edgeConf.listenAddress = parseIpAddress("0.0.0.0")
|
edgeConf.listenAddress = parseIpAddress("0.0.0.0")
|
||||||
edgeConf.tcpPort = Port(0)
|
edgeConf.tcpPort = Port(0)
|
||||||
edgeConf.discv5UdpPort = Port(0)
|
edgeConf.discv5UdpPort = Port(0)
|
||||||
edgeConf.clusterId = 3'u16
|
edgeConf.clusterId = some(3'u16)
|
||||||
edgeConf.maxMessageSize = "150 KiB"
|
edgeConf.maxMessageSize = "150 KiB"
|
||||||
edgeConf.rest = false
|
edgeConf.rest = false
|
||||||
|
|
||||||
|
|||||||
@ -67,9 +67,9 @@ proc createApiNodeConf(numShards: uint16 = 1): WakuNodeConf =
|
|||||||
conf.listenAddress = parseIpAddress("0.0.0.0")
|
conf.listenAddress = parseIpAddress("0.0.0.0")
|
||||||
conf.tcpPort = Port(0)
|
conf.tcpPort = Port(0)
|
||||||
conf.discv5UdpPort = Port(0)
|
conf.discv5UdpPort = Port(0)
|
||||||
conf.clusterId = 3'u16
|
conf.clusterId = some(3'u16)
|
||||||
conf.numShardsInNetwork = numShards
|
conf.numShardsInNetwork = numShards
|
||||||
conf.reliabilityEnabled = true
|
conf.reliabilityEnabled = some(true)
|
||||||
conf.rest = false
|
conf.rest = false
|
||||||
result = conf
|
result = conf
|
||||||
|
|
||||||
|
|||||||
@ -124,9 +124,9 @@ proc createApiNodeConf(mode: cli_args.WakuMode = cli_args.WakuMode.Core): WakuNo
|
|||||||
conf.listenAddress = parseIpAddress("0.0.0.0")
|
conf.listenAddress = parseIpAddress("0.0.0.0")
|
||||||
conf.tcpPort = Port(0)
|
conf.tcpPort = Port(0)
|
||||||
conf.discv5UdpPort = Port(0)
|
conf.discv5UdpPort = Port(0)
|
||||||
conf.clusterId = 3'u16
|
conf.clusterId = some(3'u16)
|
||||||
conf.numShardsInNetwork = 1
|
conf.numShardsInNetwork = 1
|
||||||
conf.reliabilityEnabled = true
|
conf.reliabilityEnabled = some(true)
|
||||||
conf.rest = false
|
conf.rest = false
|
||||||
result = conf
|
result = conf
|
||||||
|
|
||||||
|
|||||||
@ -75,9 +75,9 @@ proc createApiNodeConf(
|
|||||||
conf.listenAddress = parseIpAddress("0.0.0.0")
|
conf.listenAddress = parseIpAddress("0.0.0.0")
|
||||||
conf.tcpPort = Port(0)
|
conf.tcpPort = Port(0)
|
||||||
conf.discv5UdpPort = Port(0)
|
conf.discv5UdpPort = Port(0)
|
||||||
conf.clusterId = 3'u16
|
conf.clusterId = some(3'u16)
|
||||||
conf.numShardsInNetwork = numShards
|
conf.numShardsInNetwork = numShards
|
||||||
conf.reliabilityEnabled = true
|
conf.reliabilityEnabled = some(true)
|
||||||
conf.rest = false
|
conf.rest = false
|
||||||
result = conf
|
result = conf
|
||||||
|
|
||||||
|
|||||||
179
tests/api/test_messaging_conf.nim
Normal file
179
tests/api/test_messaging_conf.nim
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
{.used.}
|
||||||
|
|
||||||
|
import std/[algorithm, json, options, sequtils], results, testutils/unittests
|
||||||
|
import tools/confutils/conf_from_json, tools/confutils/cli_args
|
||||||
|
import tools/confutils/messaging_conf
|
||||||
|
|
||||||
|
suite "Messaging conf JSON parser":
|
||||||
|
test "Routes to messaging shape when mode and overrides are present":
|
||||||
|
let res = parseConfJson("""{"mode": "Core", "overrides": {}}""")
|
||||||
|
require res.isOk()
|
||||||
|
let conf = res.get()
|
||||||
|
check conf.mode == cli_args.WakuMode.Core
|
||||||
|
|
||||||
|
test "Routes to full conf shape when only mode key is present":
|
||||||
|
let res = parseConfJson("""{"mode": "Edge"}""")
|
||||||
|
require res.isOk()
|
||||||
|
let conf = res.get()
|
||||||
|
check conf.mode == cli_args.WakuMode.Edge
|
||||||
|
|
||||||
|
test "Messaging shape applies overrides":
|
||||||
|
let res = parseConfJson(
|
||||||
|
"""{"mode": "Core", "overrides": {"clusterId": 42, "tcpPort": 12345}}"""
|
||||||
|
)
|
||||||
|
require res.isOk()
|
||||||
|
let conf = res.get()
|
||||||
|
check:
|
||||||
|
conf.clusterId == some(42'u16)
|
||||||
|
conf.tcpPort == Port(12345)
|
||||||
|
|
||||||
|
test "Messaging shape applies preset":
|
||||||
|
let res = parseConfJson("""{"mode": "Core", "preset": "twn", "overrides": {}}""")
|
||||||
|
require res.isOk()
|
||||||
|
let conf = res.get()
|
||||||
|
check conf.preset == "twn"
|
||||||
|
|
||||||
|
test "Messaging shape applies additions to list fields":
|
||||||
|
let res = parseConfJson(
|
||||||
|
"""{"mode": "Core", "overrides": {}, "additions": {"staticnodes": ["/ip4/1.2.3.4/tcp/60000/p2p/16Uiu2HAmTUbnxLGT9JvV6mu9oPyDjqHK4Phs1VDJNUgESgNSkuby"]}}"""
|
||||||
|
)
|
||||||
|
require res.isOk()
|
||||||
|
let conf = res.get()
|
||||||
|
check conf.staticnodes.len == 1
|
||||||
|
|
||||||
|
test "Messaging shape: additions concat after overrides on same list field":
|
||||||
|
let res = parseConfJson(
|
||||||
|
"""{"mode": "Core", "additions": {"staticnodes": ["/ip4/1.2.3.4/tcp/60000/p2p/16Uiu2HAmTUbnxLGT9JvV6mu9oPyDjqHK4Phs1VDJNUgESgNSkuby"]}, "overrides": {"staticnodes": ["/ip4/5.6.7.8/tcp/60000/p2p/16Uiu2HAmTUbnxLGT9JvV6mu9oPyDjqHK4Phs1VDJNUgESgNSkuby"]}}"""
|
||||||
|
)
|
||||||
|
require res.isOk()
|
||||||
|
let conf = res.get()
|
||||||
|
check:
|
||||||
|
conf.staticnodes.len == 2
|
||||||
|
conf.staticnodes[0] ==
|
||||||
|
"/ip4/5.6.7.8/tcp/60000/p2p/16Uiu2HAmTUbnxLGT9JvV6mu9oPyDjqHK4Phs1VDJNUgESgNSkuby"
|
||||||
|
conf.staticnodes[1] ==
|
||||||
|
"/ip4/1.2.3.4/tcp/60000/p2p/16Uiu2HAmTUbnxLGT9JvV6mu9oPyDjqHK4Phs1VDJNUgESgNSkuby"
|
||||||
|
|
||||||
|
test "Messaging shape rejects missing mode":
|
||||||
|
let res = parseConfJson("""{"overrides": {}}""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Messaging shape rejects unknown override field":
|
||||||
|
let res = parseConfJson("""{"mode": "Core", "overrides": {"bogusField": 1}}""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Messaging shape rejects addition on non-list field":
|
||||||
|
let res = parseConfJson(
|
||||||
|
"""{"mode": "Core", "overrides": {}, "additions": {"clusterId": [1]}}"""
|
||||||
|
)
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Messaging shape rejects unknown top-level key":
|
||||||
|
let res = parseConfJson("""{"mode": "Core", "overrides": {}, "garbage": 1}""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Full conf shape parses arbitrary WakuNodeConf fields":
|
||||||
|
let res = parseConfJson("""{"clusterId": 7, "tcpPort": 22222}""")
|
||||||
|
require res.isOk()
|
||||||
|
let conf = res.get()
|
||||||
|
check:
|
||||||
|
conf.clusterId == some(7'u16)
|
||||||
|
conf.tcpPort == Port(22222)
|
||||||
|
|
||||||
|
test "Full conf shape rejects unknown field":
|
||||||
|
let res = parseConfJson("""{"completelyMadeUp": 1}""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Malformed JSON returns error":
|
||||||
|
let res = parseConfJson("{ not json }")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Rejects top-level JSON array":
|
||||||
|
let res = parseConfJson("""[1, 2]""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Rejects top-level scalar":
|
||||||
|
let res = parseConfJson("""42""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Rejects top-level null":
|
||||||
|
let res = parseConfJson("""null""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Messaging shape rejects 'mode' inside 'overrides'":
|
||||||
|
let res = parseConfJson("""{"mode": "Core", "overrides": {"mode": "Edge"}}""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Messaging shape rejects 'preset' inside 'overrides'":
|
||||||
|
let res = parseConfJson(
|
||||||
|
"""{"mode": "Core", "preset": "twn", "overrides": {"preset": "logos.dev"}}"""
|
||||||
|
)
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Messaging shape rejects 'mode' inside 'additions'":
|
||||||
|
let res = parseConfJson(
|
||||||
|
"""{"mode": "Core", "overrides": {}, "additions": {"mode": "Edge"}}"""
|
||||||
|
)
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Messaging shape rejects 'preset' inside 'additions'":
|
||||||
|
let res = parseConfJson(
|
||||||
|
"""{"mode": "Core", "overrides": {}, "additions": {"preset": "twn"}}"""
|
||||||
|
)
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Rejects duplicate normalized keys":
|
||||||
|
let res = parseConfJson("""{"clusterId": 1, "ClusterId": 2}""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Case-insensitive override matching":
|
||||||
|
let res = parseConfJson("""{"mode": "Core", "overrides": {"CLUSTERID": 99}}""")
|
||||||
|
require res.isOk()
|
||||||
|
let conf = res.get()
|
||||||
|
check conf.clusterId == some(99'u16)
|
||||||
|
|
||||||
|
test "Rejects 'overrides' that isn't a JSON object":
|
||||||
|
let res = parseConfJson("""{"mode": "Core", "overrides": "not an object"}""")
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "Rejects 'additions' that isn't a JSON object":
|
||||||
|
let res = parseConfJson(
|
||||||
|
"""{"mode": "Core", "overrides": {}, "additions": ["not an object"]}"""
|
||||||
|
)
|
||||||
|
check res.isErr()
|
||||||
|
|
||||||
|
test "JBool maps to Option[bool] field":
|
||||||
|
let res = parseConfJson("""{"mode": "Core", "overrides": {"rlnRelay": true}}""")
|
||||||
|
require res.isOk()
|
||||||
|
let conf = res.get()
|
||||||
|
check conf.rlnRelay == some(true)
|
||||||
|
|
||||||
|
suite "WakuNodeConfOverlay structure":
|
||||||
|
proc fieldNamesOfWakuNodeConf(): seq[string] =
|
||||||
|
var c: WakuNodeConf
|
||||||
|
for name, _ in fieldPairs(c):
|
||||||
|
result.add(name)
|
||||||
|
|
||||||
|
proc fieldNamesOfOverlay(): seq[string] =
|
||||||
|
var o: WakuNodeConfOverlay
|
||||||
|
for name, _ in fieldPairs(o):
|
||||||
|
result.add(name)
|
||||||
|
|
||||||
|
test "Overlay field names match WakuNodeConf minus excludes":
|
||||||
|
let expected =
|
||||||
|
fieldNamesOfWakuNodeConf().filterIt(it notin WakuNodeConfOverlayExcludes)
|
||||||
|
let actual = fieldNamesOfOverlay()
|
||||||
|
check sorted(actual) == sorted(expected)
|
||||||
|
|
||||||
|
test "Every overlay field is Option-typed":
|
||||||
|
var o: WakuNodeConfOverlay
|
||||||
|
var allOption = true
|
||||||
|
for _, value in fieldPairs(o):
|
||||||
|
when typeof(value) isnot Option:
|
||||||
|
allOption = false
|
||||||
|
check allOption
|
||||||
|
|
||||||
|
test "Excluded names are absent from overlay":
|
||||||
|
let actual = fieldNamesOfOverlay()
|
||||||
|
for excluded in WakuNodeConfOverlayExcludes:
|
||||||
|
check excluded notin actual
|
||||||
@ -37,7 +37,7 @@ suite "WakuNodeConf - mode-driven toWakuConf":
|
|||||||
var conf = defaultWakuNodeConf().valueOr:
|
var conf = defaultWakuNodeConf().valueOr:
|
||||||
raiseAssert error
|
raiseAssert error
|
||||||
conf.mode = Core
|
conf.mode = Core
|
||||||
conf.clusterId = 1
|
conf.clusterId = some(1'u16)
|
||||||
|
|
||||||
## When
|
## When
|
||||||
let wakuConfRes = conf.toWakuConf()
|
let wakuConfRes = conf.toWakuConf()
|
||||||
@ -58,7 +58,7 @@ suite "WakuNodeConf - mode-driven toWakuConf":
|
|||||||
var conf = defaultWakuNodeConf().valueOr:
|
var conf = defaultWakuNodeConf().valueOr:
|
||||||
raiseAssert error
|
raiseAssert error
|
||||||
conf.mode = Edge
|
conf.mode = Edge
|
||||||
conf.clusterId = 1
|
conf.clusterId = some(1'u16)
|
||||||
|
|
||||||
## When
|
## When
|
||||||
let wakuConfRes = conf.toWakuConf()
|
let wakuConfRes = conf.toWakuConf()
|
||||||
@ -81,7 +81,7 @@ suite "WakuNodeConf - mode-driven toWakuConf":
|
|||||||
conf.mode = cli_args.WakuMode.noMode
|
conf.mode = cli_args.WakuMode.noMode
|
||||||
conf.relay = true
|
conf.relay = true
|
||||||
conf.lightpush = false
|
conf.lightpush = false
|
||||||
conf.clusterId = 5
|
conf.clusterId = some(5'u16)
|
||||||
|
|
||||||
## When
|
## When
|
||||||
let wakuConfRes = conf.toWakuConf()
|
let wakuConfRes = conf.toWakuConf()
|
||||||
@ -122,7 +122,7 @@ suite "WakuNodeConf - JSON parsing with fieldPairs":
|
|||||||
let conf = confRes.get()
|
let conf = confRes.get()
|
||||||
check:
|
check:
|
||||||
conf.mode == cli_args.WakuMode.noMode
|
conf.mode == cli_args.WakuMode.noMode
|
||||||
conf.clusterId == 0
|
conf.clusterId.isNone()
|
||||||
conf.logLevel == logging.LogLevel.INFO
|
conf.logLevel == logging.LogLevel.INFO
|
||||||
|
|
||||||
test "JSON with mode and clusterId":
|
test "JSON with mode and clusterId":
|
||||||
@ -134,7 +134,7 @@ suite "WakuNodeConf - JSON parsing with fieldPairs":
|
|||||||
let conf = confRes.get()
|
let conf = confRes.get()
|
||||||
check:
|
check:
|
||||||
conf.mode == Core
|
conf.mode == Core
|
||||||
conf.clusterId == 42
|
conf.clusterId == some(42'u16)
|
||||||
|
|
||||||
test "JSON with Edge mode":
|
test "JSON with Edge mode":
|
||||||
## Given / When
|
## Given / When
|
||||||
@ -165,7 +165,7 @@ suite "WakuNodeConf - JSON parsing with fieldPairs":
|
|||||||
require confRes.isOk()
|
require confRes.isOk()
|
||||||
let conf = confRes.get()
|
let conf = confRes.get()
|
||||||
check:
|
check:
|
||||||
conf.clusterId == 99
|
conf.clusterId == some(99'u16)
|
||||||
conf.numShardsInNetwork == 16
|
conf.numShardsInNetwork == 16
|
||||||
|
|
||||||
test "JSON with unknown fields is silently ignored":
|
test "JSON with unknown fields is silently ignored":
|
||||||
@ -177,7 +177,7 @@ suite "WakuNodeConf - JSON parsing with fieldPairs":
|
|||||||
require confRes.isOk()
|
require confRes.isOk()
|
||||||
let conf = confRes.get()
|
let conf = confRes.get()
|
||||||
check:
|
check:
|
||||||
conf.clusterId == 5
|
conf.clusterId == some(5'u16)
|
||||||
|
|
||||||
test "Invalid JSON syntax returns error":
|
test "Invalid JSON syntax returns error":
|
||||||
## Given / When
|
## Given / When
|
||||||
|
|||||||
@ -206,8 +206,9 @@ suite "Waku Conf - build with cluster conf":
|
|||||||
assert conf.rlnRelayConf.isSome
|
assert conf.rlnRelayConf.isSome
|
||||||
|
|
||||||
let rlnRelayConf = conf.rlnRelayConf.get()
|
let rlnRelayConf = conf.rlnRelayConf.get()
|
||||||
check rlnRelayConf.ethContractAddress.string ==
|
# actually match the explicit contractAddress, which is the value set on the builder above
|
||||||
networkConf.rlnRelayEthContractAddress
|
# this proves that an explicit builder call wins over the same field set via the preset
|
||||||
|
check rlnRelayConf.ethContractAddress.string == contractAddress
|
||||||
check rlnRelayConf.dynamic == networkConf.rlnRelayDynamic
|
check rlnRelayConf.dynamic == networkConf.rlnRelayDynamic
|
||||||
check rlnRelayConf.chainId == networkConf.rlnRelayChainId
|
check rlnRelayConf.chainId == networkConf.rlnRelayChainId
|
||||||
check rlnRelayConf.epochSizeSec == networkConf.rlnEpochSizeSec
|
check rlnRelayConf.epochSizeSec == networkConf.rlnEpochSizeSec
|
||||||
@ -247,10 +248,6 @@ suite "Waku Conf - build with cluster conf":
|
|||||||
let networkConf = NetworkConf.LogosDevConf()
|
let networkConf = NetworkConf.LogosDevConf()
|
||||||
var builder = WakuConfBuilder.init()
|
var builder = WakuConfBuilder.init()
|
||||||
builder.withNetworkConf(networkConf)
|
builder.withNetworkConf(networkConf)
|
||||||
# Note: builder.withNumShardsInCluster() is not called when the
|
|
||||||
# value that comes from the CLI path is 0 (which means it was
|
|
||||||
# either set to 0 or was left unset).
|
|
||||||
builder.withShardingConf(StaticSharding)
|
|
||||||
|
|
||||||
## When
|
## When
|
||||||
let conf = builder.build().expect("build should succeed")
|
let conf = builder.build().expect("build should succeed")
|
||||||
|
|||||||
@ -4,21 +4,22 @@ import chronos, testutils/unittests, std/options
|
|||||||
|
|
||||||
import waku
|
import waku
|
||||||
import tools/confutils/cli_args
|
import tools/confutils/cli_args
|
||||||
|
import waku/factory/networks_config
|
||||||
|
|
||||||
suite "Waku API - Create node":
|
suite "Waku API - Create node":
|
||||||
asyncTest "Create node with minimal configuration":
|
asyncTest "Create node with minimal configuration":
|
||||||
## Given
|
## Given
|
||||||
var nodeConf = defaultWakuNodeConf().valueOr:
|
var nodeConf = defaultWakuNodeConf().valueOr:
|
||||||
raiseAssert error
|
raiseAssert "defaultWakuNodeConf failed: " & error
|
||||||
nodeConf.mode = Core
|
nodeConf.mode = Core
|
||||||
nodeConf.clusterId = 3'u16
|
nodeConf.clusterId = some(3'u16)
|
||||||
nodeConf.rest = false
|
nodeConf.rest = false
|
||||||
|
|
||||||
# This is the actual minimal config but as the node auto-start, it is not suitable for tests
|
# This is the actual minimal config but as the node auto-start, it is not suitable for tests
|
||||||
|
|
||||||
## When
|
## When
|
||||||
let node = (await createNode(nodeConf)).valueOr:
|
let node = (await createNode(nodeConf)).valueOr:
|
||||||
raiseAssert error
|
raiseAssert "createNode (minimal config) failed: " & error
|
||||||
|
|
||||||
## Then
|
## Then
|
||||||
check:
|
check:
|
||||||
@ -29,9 +30,9 @@ suite "Waku API - Create node":
|
|||||||
asyncTest "Create node with full configuration":
|
asyncTest "Create node with full configuration":
|
||||||
## Given
|
## Given
|
||||||
var nodeConf = defaultWakuNodeConf().valueOr:
|
var nodeConf = defaultWakuNodeConf().valueOr:
|
||||||
raiseAssert error
|
raiseAssert "defaultWakuNodeConf failed: " & error
|
||||||
nodeConf.mode = Core
|
nodeConf.mode = Core
|
||||||
nodeConf.clusterId = 99'u16
|
nodeConf.clusterId = some(99'u16)
|
||||||
nodeConf.rest = false
|
nodeConf.rest = false
|
||||||
nodeConf.numShardsInNetwork = 16
|
nodeConf.numShardsInNetwork = 16
|
||||||
nodeConf.maxMessageSize = "1024 KiB"
|
nodeConf.maxMessageSize = "1024 KiB"
|
||||||
@ -44,7 +45,7 @@ suite "Waku API - Create node":
|
|||||||
|
|
||||||
## When
|
## When
|
||||||
let node = (await createNode(nodeConf)).valueOr:
|
let node = (await createNode(nodeConf)).valueOr:
|
||||||
raiseAssert error
|
raiseAssert "createNode (full config) failed: " & error
|
||||||
|
|
||||||
## Then
|
## Then
|
||||||
check:
|
check:
|
||||||
@ -61,9 +62,9 @@ suite "Waku API - Create node":
|
|||||||
asyncTest "Create node with mixed entry nodes (enrtree, multiaddr)":
|
asyncTest "Create node with mixed entry nodes (enrtree, multiaddr)":
|
||||||
## Given
|
## Given
|
||||||
var nodeConf = defaultWakuNodeConf().valueOr:
|
var nodeConf = defaultWakuNodeConf().valueOr:
|
||||||
raiseAssert error
|
raiseAssert "defaultWakuNodeConf failed: " & error
|
||||||
nodeConf.mode = Core
|
nodeConf.mode = Core
|
||||||
nodeConf.clusterId = 42'u16
|
nodeConf.clusterId = some(42'u16)
|
||||||
nodeConf.rest = false
|
nodeConf.rest = false
|
||||||
nodeConf.entryNodes = @[
|
nodeConf.entryNodes = @[
|
||||||
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im",
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im",
|
||||||
@ -72,7 +73,7 @@ suite "Waku API - Create node":
|
|||||||
|
|
||||||
## When
|
## When
|
||||||
let node = (await createNode(nodeConf)).valueOr:
|
let node = (await createNode(nodeConf)).valueOr:
|
||||||
raiseAssert error
|
raiseAssert "createNode (mixed entry nodes) failed: " & error
|
||||||
|
|
||||||
## Then
|
## Then
|
||||||
check:
|
check:
|
||||||
@ -86,3 +87,89 @@ suite "Waku API - Create node":
|
|||||||
node.conf.staticNodes.len == 1
|
node.conf.staticNodes.len == 1
|
||||||
node.conf.staticNodes[0] ==
|
node.conf.staticNodes[0] ==
|
||||||
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
||||||
|
|
||||||
|
asyncTest "Create node via messaging API with overrides":
|
||||||
|
let
|
||||||
|
clusterId = 3'u16
|
||||||
|
numShards = 1'u16
|
||||||
|
let overrides = WakuNodeConfOverlay(
|
||||||
|
clusterId: some(clusterId), rest: some(false), numShardsInNetwork: some(numShards)
|
||||||
|
)
|
||||||
|
|
||||||
|
let node = (await createNode(mode = cli_args.WakuMode.Core, overrides = overrides)).valueOr:
|
||||||
|
raiseAssert "createNode (overrides only) failed: " & error
|
||||||
|
|
||||||
|
check:
|
||||||
|
not node.isNil()
|
||||||
|
node.conf.clusterId == clusterId
|
||||||
|
node.conf.shardingConf.numShardsInCluster == numShards
|
||||||
|
|
||||||
|
asyncTest "Create node via messaging API with overrides + additions":
|
||||||
|
let
|
||||||
|
clusterId = 7'u16
|
||||||
|
staticnode =
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
||||||
|
let overrides = WakuNodeConfOverlay(
|
||||||
|
clusterId: some(clusterId), rest: some(false), numShardsInNetwork: some(1'u16)
|
||||||
|
)
|
||||||
|
let additions = WakuNodeConfOverlay(staticnodes: some(@[staticnode]))
|
||||||
|
|
||||||
|
let node = (
|
||||||
|
await createNode(
|
||||||
|
mode = cli_args.WakuMode.Core, overrides = overrides, additions = additions
|
||||||
|
)
|
||||||
|
).valueOr:
|
||||||
|
raiseAssert "createNode (overrides + additions) failed: " & error
|
||||||
|
|
||||||
|
check:
|
||||||
|
not node.isNil()
|
||||||
|
node.conf.clusterId == clusterId
|
||||||
|
node.conf.staticNodes.len == 1
|
||||||
|
node.conf.staticNodes[0] == staticnode
|
||||||
|
|
||||||
|
asyncTest "Create node via messaging API with preset":
|
||||||
|
let
|
||||||
|
preset = "twn"
|
||||||
|
twn = NetworkConf.TheWakuNetworkConf()
|
||||||
|
let overrides = WakuNodeConfOverlay(rest: some(false))
|
||||||
|
|
||||||
|
let node = (
|
||||||
|
await createNode(
|
||||||
|
preset = preset, mode = cli_args.WakuMode.Edge, overrides = overrides
|
||||||
|
)
|
||||||
|
).valueOr:
|
||||||
|
raiseAssert "createNode (preset = " & preset & ") failed: " & error
|
||||||
|
|
||||||
|
check:
|
||||||
|
not node.isNil()
|
||||||
|
node.conf.clusterId == twn.clusterId
|
||||||
|
node.conf.shardingConf.kind == twn.shardingConf.kind
|
||||||
|
node.conf.shardingConf.numShardsInCluster == twn.shardingConf.numShardsInCluster
|
||||||
|
node.conf.discv5Conf.isSome()
|
||||||
|
node.conf.discv5Conf.get().bootstrapNodes.len == twn.discv5BootstrapNodes.len
|
||||||
|
|
||||||
|
asyncTest "Create node via messaging API: additions concat with preset's bootstrap nodes":
|
||||||
|
let
|
||||||
|
preset = "twn"
|
||||||
|
twn = NetworkConf.TheWakuNetworkConf()
|
||||||
|
addedBootstrapNode =
|
||||||
|
"enr:-QESuED0qW1BCmF-oH_ARGPr97Nv767bl_43uoy70vrbah3EaCAdK3Q0iRQ6wkSTTpdrg_dU_NC2ydO8leSlRpBX4pxiAYJpZIJ2NIJpcIRA4VDAim11bHRpYWRkcnO4XAArNiZub2RlLTAxLmRvLWFtczMud2FrdS5zYW5kYm94LnN0YXR1cy5pbQZ2XwAtNiZub2RlLTAxLmRvLWFtczMud2FrdS5zYW5kYm94LnN0YXR1cy5pbQYfQN4DgnJzkwABCAAAAAEAAgADAAQABQAGAAeJc2VjcDI1NmsxoQOTd-h5owwj-cx7xrmbvQKU8CV3Fomfdvcv1MBc-67T5oN0Y3CCdl-DdWRwgiMohXdha3UyDw"
|
||||||
|
let overrides = WakuNodeConfOverlay(rest: some(false))
|
||||||
|
let additions =
|
||||||
|
WakuNodeConfOverlay(discv5BootstrapNodes: some(@[addedBootstrapNode]))
|
||||||
|
|
||||||
|
let node = (
|
||||||
|
await createNode(
|
||||||
|
preset = preset,
|
||||||
|
mode = cli_args.WakuMode.Edge,
|
||||||
|
overrides = overrides,
|
||||||
|
additions = additions,
|
||||||
|
)
|
||||||
|
).valueOr:
|
||||||
|
raiseAssert "createNode (preset = " & preset & " + additions) failed: " & error
|
||||||
|
|
||||||
|
check:
|
||||||
|
not node.isNil()
|
||||||
|
node.conf.discv5Conf.isSome()
|
||||||
|
node.conf.discv5Conf.get().bootstrapNodes.len == twn.discv5BootstrapNodes.len + 1
|
||||||
|
node.conf.discv5Conf.get().bootstrapNodes.contains(addedBootstrapNode)
|
||||||
|
|||||||
@ -43,7 +43,7 @@ logScope:
|
|||||||
topics = "waku cli args"
|
topics = "waku cli args"
|
||||||
|
|
||||||
# Git version in git describe format (defined at compile time)
|
# Git version in git describe format (defined at compile time)
|
||||||
const git_version* {.strdefine.} = "n/a"
|
const git_version* {.strdefine.} = "(unknown)"
|
||||||
|
|
||||||
type ConfResult*[T] = Result[T, string]
|
type ConfResult*[T] = Result[T, string]
|
||||||
|
|
||||||
@ -117,20 +117,23 @@ type WakuNodeConf* = object
|
|||||||
name: "rln-relay-eth-private-key"
|
name: "rln-relay-eth-private-key"
|
||||||
.}: string
|
.}: string
|
||||||
|
|
||||||
# TODO: Remove "Default is" when it's already visible on the CLI
|
# Option-typed; desc states the default since the CLI can't auto-show it for none().
|
||||||
rlnRelayUserMessageLimit* {.
|
rlnRelayUserMessageLimit* {.
|
||||||
desc:
|
desc:
|
||||||
"Set a user message limit for the rln membership registration. Must be a positive integer. Default is 1.",
|
"Set a user message limit for the rln membership registration. Must be a positive integer. Default is " &
|
||||||
defaultValue: 1,
|
$DefaultRlnRelayUserMessageLimit & ".",
|
||||||
|
defaultValue: none(uint64),
|
||||||
name: "rln-relay-user-message-limit"
|
name: "rln-relay-user-message-limit"
|
||||||
.}: uint64
|
.}: Option[uint64]
|
||||||
|
|
||||||
|
# Option-typed; desc states the default since the CLI can't auto-show it for none().
|
||||||
rlnEpochSizeSec* {.
|
rlnEpochSizeSec* {.
|
||||||
desc:
|
desc:
|
||||||
"Epoch size in seconds used to rate limit RLN memberships. Default is 1 second.",
|
"Epoch size in seconds used to rate limit RLN memberships. Default is " &
|
||||||
defaultValue: 1,
|
$DefaultRlnRelayEpochSizeSec & " second.",
|
||||||
|
defaultValue: none(uint64),
|
||||||
name: "rln-relay-epoch-sec"
|
name: "rln-relay-epoch-sec"
|
||||||
.}: uint64
|
.}: Option[uint64]
|
||||||
|
|
||||||
maxMessageSize* {.
|
maxMessageSize* {.
|
||||||
desc:
|
desc:
|
||||||
@ -170,15 +173,18 @@ type WakuNodeConf* = object
|
|||||||
name: "preset"
|
name: "preset"
|
||||||
.}: string
|
.}: string
|
||||||
|
|
||||||
|
# Option-typed; desc states the default since the CLI can't auto-show it for none().
|
||||||
clusterId* {.
|
clusterId* {.
|
||||||
desc:
|
desc: static(
|
||||||
"Cluster id that the node is running in. Node in a different cluster id is disconnected.",
|
"Cluster id that the node is running in. Node in a different cluster id is disconnected. Default is " &
|
||||||
defaultValue: 0,
|
$DefaultClusterId & "."
|
||||||
|
),
|
||||||
|
defaultValue: none(uint16),
|
||||||
name: "cluster-id"
|
name: "cluster-id"
|
||||||
.}: uint16
|
.}: Option[uint16]
|
||||||
|
|
||||||
agentString* {.
|
agentString* {.
|
||||||
defaultValue: "logos-delivery-" & cli_args.git_version,
|
defaultValue: "logos-delivery " & cli_args.git_version,
|
||||||
desc: "Node agent string which is used as identifier in network",
|
desc: "Node agent string which is used as identifier in network",
|
||||||
name: "agent-string"
|
name: "agent-string"
|
||||||
.}: string
|
.}: string
|
||||||
@ -291,11 +297,14 @@ hence would have reachability issues.""",
|
|||||||
name: "relay-shard-manager"
|
name: "relay-shard-manager"
|
||||||
.}: bool
|
.}: bool
|
||||||
|
|
||||||
|
# Option-typed; desc states the default since the CLI can't auto-show it for none().
|
||||||
rlnRelay* {.
|
rlnRelay* {.
|
||||||
desc: "Enable spam protection through rln-relay: true|false.",
|
desc:
|
||||||
defaultValue: false,
|
"Enable spam protection through rln-relay: true|false. Default is " &
|
||||||
|
$DefaultRlnRelayEnabled & ".",
|
||||||
|
defaultValue: none(bool),
|
||||||
name: "rln-relay"
|
name: "rln-relay"
|
||||||
.}: bool
|
.}: Option[bool]
|
||||||
|
|
||||||
rlnRelayCredIndex* {.
|
rlnRelayCredIndex* {.
|
||||||
desc: "the index of the onchain commitment to use",
|
desc: "the index of the onchain commitment to use",
|
||||||
@ -304,9 +313,9 @@ hence would have reachability issues.""",
|
|||||||
|
|
||||||
rlnRelayDynamic* {.
|
rlnRelayDynamic* {.
|
||||||
desc: "Enable waku-rln-relay with on-chain dynamic group management: true|false.",
|
desc: "Enable waku-rln-relay with on-chain dynamic group management: true|false.",
|
||||||
defaultValue: false,
|
defaultValue: none(bool),
|
||||||
name: "rln-relay-dynamic"
|
name: "rln-relay-dynamic"
|
||||||
.}: bool
|
.}: Option[bool]
|
||||||
|
|
||||||
entryNodes* {.
|
entryNodes* {.
|
||||||
desc:
|
desc:
|
||||||
@ -466,13 +475,14 @@ hence would have reachability issues.""",
|
|||||||
.}: string
|
.}: string
|
||||||
|
|
||||||
## Reliability config
|
## Reliability config
|
||||||
|
# Option-typed; desc states the default since the CLI can't auto-show it for none().
|
||||||
reliabilityEnabled* {.
|
reliabilityEnabled* {.
|
||||||
desc:
|
desc:
|
||||||
"""Adds an extra effort in the delivery/reception of messages by leveraging store-v3 requests.
|
"""Adds an extra effort in the delivery/reception of messages by leveraging store-v3 requests, with the drawback of consuming some more bandwidth. Default is """ &
|
||||||
with the drawback of consuming some more bandwidth.""",
|
$DefaultP2pReliability & ".",
|
||||||
defaultValue: true,
|
defaultValue: none(bool),
|
||||||
name: "reliability"
|
name: "reliability"
|
||||||
.}: bool
|
.}: Option[bool]
|
||||||
|
|
||||||
## REST HTTP config
|
## REST HTTP config
|
||||||
rest* {.
|
rest* {.
|
||||||
@ -557,8 +567,11 @@ with the drawback of consuming some more bandwidth.""",
|
|||||||
.}: string
|
.}: string
|
||||||
|
|
||||||
## Discovery v5 config
|
## Discovery v5 config
|
||||||
|
# Option-typed; desc states the default since the CLI can't auto-show it for none().
|
||||||
discv5Discovery* {.
|
discv5Discovery* {.
|
||||||
desc: "Enable discovering nodes via Node Discovery v5.",
|
desc:
|
||||||
|
"Enable discovering nodes via Node Discovery v5. Default is " &
|
||||||
|
$DefaultDiscv5Enabled & ".",
|
||||||
defaultValue: none(bool),
|
defaultValue: none(bool),
|
||||||
name: "discv5-discovery"
|
name: "discv5-discovery"
|
||||||
.}: Option[bool]
|
.}: Option[bool]
|
||||||
@ -627,8 +640,12 @@ with the drawback of consuming some more bandwidth.""",
|
|||||||
.}: bool
|
.}: bool
|
||||||
|
|
||||||
#Mix config
|
#Mix config
|
||||||
mix* {.desc: "Enable mix protocol: true|false", defaultValue: false, name: "mix".}:
|
# Option-typed; desc states the default since the CLI can't auto-show it for none().
|
||||||
bool
|
mix* {.
|
||||||
|
desc: "Enable mix protocol: true|false. Default is " & $DefaultMix & ".",
|
||||||
|
defaultValue: none(bool),
|
||||||
|
name: "mix"
|
||||||
|
.}: Option[bool]
|
||||||
|
|
||||||
mixkey* {.
|
mixkey* {.
|
||||||
desc:
|
desc:
|
||||||
@ -643,12 +660,14 @@ with the drawback of consuming some more bandwidth.""",
|
|||||||
.}: seq[MixNodePubInfo]
|
.}: seq[MixNodePubInfo]
|
||||||
|
|
||||||
# Kademlia Discovery config
|
# Kademlia Discovery config
|
||||||
|
# Option-typed; desc states the default since the CLI can't auto-show it for none().
|
||||||
enableKadDiscovery* {.
|
enableKadDiscovery* {.
|
||||||
desc:
|
desc:
|
||||||
"Enable extended kademlia discovery. Can be enabled without bootstrap nodes for the first node in the network.",
|
"Enable extended kademlia discovery. Can be enabled without bootstrap nodes for the first node in the network. Default is " &
|
||||||
defaultValue: false,
|
$DefaultKadEnabled & ".",
|
||||||
|
defaultValue: none(bool),
|
||||||
name: "enable-kad-discovery"
|
name: "enable-kad-discovery"
|
||||||
.}: bool
|
.}: Option[bool]
|
||||||
|
|
||||||
kadBootstrapNodes* {.
|
kadBootstrapNodes* {.
|
||||||
desc:
|
desc:
|
||||||
@ -913,7 +932,7 @@ proc toKeystoreGeneratorConf*(n: WakuNodeConf): RlnKeystoreGeneratorConf =
|
|||||||
chainId: UInt256.fromBytesBE(n.rlnRelayChainId.toBytesBE()),
|
chainId: UInt256.fromBytesBE(n.rlnRelayChainId.toBytesBE()),
|
||||||
ethClientUrls: n.ethClientUrls.mapIt(string(it)),
|
ethClientUrls: n.ethClientUrls.mapIt(string(it)),
|
||||||
ethContractAddress: n.rlnRelayEthContractAddress,
|
ethContractAddress: n.rlnRelayEthContractAddress,
|
||||||
userMessageLimit: n.rlnRelayUserMessageLimit,
|
userMessageLimit: n.rlnRelayUserMessageLimit.get(DefaultRlnRelayUserMessageLimit),
|
||||||
ethPrivateKey: n.rlnRelayEthPrivateKey,
|
ethPrivateKey: n.rlnRelayEthPrivateKey,
|
||||||
credPath: n.rlnRelayCredPath,
|
credPath: n.rlnRelayCredPath,
|
||||||
credPassword: n.rlnRelayCredPassword,
|
credPassword: n.rlnRelayCredPassword,
|
||||||
@ -947,7 +966,7 @@ proc toNetworkConf(
|
|||||||
proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
|
proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
|
||||||
var b = WakuConfBuilder.init()
|
var b = WakuConfBuilder.init()
|
||||||
|
|
||||||
let networkConf = toNetworkConf(n.preset, some(n.clusterId)).valueOr:
|
let networkConf = toNetworkConf(n.preset, n.clusterId).valueOr:
|
||||||
return err("Error determining cluster from preset: " & $error)
|
return err("Error determining cluster from preset: " & $error)
|
||||||
|
|
||||||
if networkConf.isSome():
|
if networkConf.isSome():
|
||||||
@ -956,7 +975,8 @@ proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
|
|||||||
b.withLogLevel(n.logLevel)
|
b.withLogLevel(n.logLevel)
|
||||||
b.withLogFormat(n.logFormat)
|
b.withLogFormat(n.logFormat)
|
||||||
|
|
||||||
b.rlnRelayConf.withEnabled(n.rlnRelay)
|
if n.rlnRelay.isSome():
|
||||||
|
b.rlnRelayConf.withEnabled(n.rlnRelay.get())
|
||||||
if n.rlnRelayCredPath != "":
|
if n.rlnRelayCredPath != "":
|
||||||
b.rlnRelayConf.withCredPath(n.rlnRelayCredPath)
|
b.rlnRelayConf.withCredPath(n.rlnRelayCredPath)
|
||||||
if n.rlnRelayCredPassword != "":
|
if n.rlnRelayCredPassword != "":
|
||||||
@ -968,18 +988,22 @@ proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
|
|||||||
|
|
||||||
if n.rlnRelayChainId != 0:
|
if n.rlnRelayChainId != 0:
|
||||||
b.rlnRelayConf.withChainId(n.rlnRelayChainId)
|
b.rlnRelayConf.withChainId(n.rlnRelayChainId)
|
||||||
b.rlnRelayConf.withUserMessageLimit(n.rlnRelayUserMessageLimit)
|
if n.rlnRelayUserMessageLimit.isSome():
|
||||||
b.rlnRelayConf.withEpochSizeSec(n.rlnEpochSizeSec)
|
b.rlnRelayConf.withUserMessageLimit(n.rlnRelayUserMessageLimit.get())
|
||||||
|
if n.rlnEpochSizeSec.isSome():
|
||||||
|
b.rlnRelayConf.withEpochSizeSec(n.rlnEpochSizeSec.get())
|
||||||
|
|
||||||
if n.rlnRelayCredIndex.isSome():
|
if n.rlnRelayCredIndex.isSome():
|
||||||
b.rlnRelayConf.withCredIndex(n.rlnRelayCredIndex.get())
|
b.rlnRelayConf.withCredIndex(n.rlnRelayCredIndex.get())
|
||||||
b.rlnRelayConf.withDynamic(n.rlnRelayDynamic)
|
if n.rlnRelayDynamic.isSome():
|
||||||
|
b.rlnRelayConf.withDynamic(n.rlnRelayDynamic.get())
|
||||||
|
|
||||||
if n.maxMessageSize != "":
|
if n.maxMessageSize != "":
|
||||||
b.withMaxMessageSize(n.maxMessageSize)
|
b.withMaxMessageSize(n.maxMessageSize)
|
||||||
|
|
||||||
b.withProtectedShards(n.protectedShards)
|
b.withProtectedShards(n.protectedShards)
|
||||||
b.withClusterId(n.clusterId)
|
if n.clusterId.isSome():
|
||||||
|
b.withClusterId(n.clusterId.get())
|
||||||
|
|
||||||
b.withAgentString(n.agentString)
|
b.withAgentString(n.agentString)
|
||||||
|
|
||||||
@ -1033,7 +1057,7 @@ proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
|
|||||||
if n.numShardsInNetwork != 0:
|
if n.numShardsInNetwork != 0:
|
||||||
b.withNumShardsInCluster(n.numShardsInNetwork)
|
b.withNumShardsInCluster(n.numShardsInNetwork)
|
||||||
b.withShardingConf(AutoSharding)
|
b.withShardingConf(AutoSharding)
|
||||||
else:
|
elif networkConf.isNone():
|
||||||
b.withShardingConf(StaticSharding)
|
b.withShardingConf(StaticSharding)
|
||||||
|
|
||||||
# It is not possible to pass an empty sequence on the CLI
|
# It is not possible to pass an empty sequence on the CLI
|
||||||
@ -1066,9 +1090,10 @@ proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
|
|||||||
b.storeServiceConf.storeSyncConf.withRangeSec(n.storeSyncRange)
|
b.storeServiceConf.storeSyncConf.withRangeSec(n.storeSyncRange)
|
||||||
b.storeServiceConf.storeSyncConf.withRelayJitterSec(n.storeSyncRelayJitter)
|
b.storeServiceConf.storeSyncConf.withRelayJitterSec(n.storeSyncRelayJitter)
|
||||||
|
|
||||||
b.mixConf.withEnabled(n.mix)
|
if n.mix.isSome():
|
||||||
|
b.mixConf.withEnabled(n.mix.get())
|
||||||
|
b.withMix(n.mix.get())
|
||||||
b.mixConf.withMixNodes(n.mixnodes)
|
b.mixConf.withMixNodes(n.mixnodes)
|
||||||
b.withMix(n.mix)
|
|
||||||
if n.mixkey.isSome():
|
if n.mixkey.isSome():
|
||||||
b.mixConf.withMixKey(n.mixkey.get())
|
b.mixConf.withMixKey(n.mixkey.get())
|
||||||
|
|
||||||
@ -1078,7 +1103,8 @@ proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
|
|||||||
b.filterServiceConf.withMaxCriteria(n.filterMaxCriteria)
|
b.filterServiceConf.withMaxCriteria(n.filterMaxCriteria)
|
||||||
|
|
||||||
b.withLightPush(n.lightpush)
|
b.withLightPush(n.lightpush)
|
||||||
b.withP2pReliability(n.reliabilityEnabled)
|
if n.reliabilityEnabled.isSome():
|
||||||
|
b.withP2pReliability(n.reliabilityEnabled.get())
|
||||||
|
|
||||||
b.restServerConf.withEnabled(n.rest)
|
b.restServerConf.withEnabled(n.rest)
|
||||||
b.restServerConf.withListenAddress(n.restAddress)
|
b.restServerConf.withListenAddress(n.restAddress)
|
||||||
@ -1119,7 +1145,8 @@ proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
|
|||||||
if n.rateLimits.len > 0:
|
if n.rateLimits.len > 0:
|
||||||
b.rateLimitConf.withRateLimits(n.rateLimits)
|
b.rateLimitConf.withRateLimits(n.rateLimits)
|
||||||
|
|
||||||
b.kademliaDiscoveryConf.withEnabled(n.enableKadDiscovery)
|
if n.enableKadDiscovery.isSome():
|
||||||
|
b.kademliaDiscoveryConf.withEnabled(n.enableKadDiscovery.get())
|
||||||
b.kademliaDiscoveryConf.withBootstrapNodes(n.kadBootstrapNodes)
|
b.kademliaDiscoveryConf.withBootstrapNodes(n.kadBootstrapNodes)
|
||||||
|
|
||||||
# Mode-driven configuration overrides
|
# Mode-driven configuration overrides
|
||||||
|
|||||||
243
tools/confutils/conf_from_json.nim
Normal file
243
tools/confutils/conf_from_json.nim
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
import std/[json, strutils, tables]
|
||||||
|
import confutils, confutils/std/net, results
|
||||||
|
import ./cli_args
|
||||||
|
|
||||||
|
const
|
||||||
|
KeyMode = "mode"
|
||||||
|
KeyPreset = "preset"
|
||||||
|
KeyOverrides = "overrides"
|
||||||
|
KeyAdditions = "additions"
|
||||||
|
|
||||||
|
const TopLevelOnlyKeys = [KeyMode, KeyPreset]
|
||||||
|
## Keys that the messaging shape requires at the top-level of the JSON input.
|
||||||
|
## They must not appear inside `overrides` or `additions`.
|
||||||
|
|
||||||
|
proc collectJsonFields*(
|
||||||
|
jsonNode: JsonNode
|
||||||
|
): Result[Table[string, (string, JsonNode)], string] =
|
||||||
|
## Walk the top-level JSON object and key it by lowercased names.
|
||||||
|
if jsonNode.kind != JObject:
|
||||||
|
return err("config JSON must be a JSON object, got " & $jsonNode.kind)
|
||||||
|
var jsonFields: Table[string, (string, JsonNode)]
|
||||||
|
for key, value in jsonNode:
|
||||||
|
let lowerKey = key.toLowerAscii()
|
||||||
|
if jsonFields.hasKey(lowerKey):
|
||||||
|
let firstKey = jsonFields[lowerKey][0]
|
||||||
|
return err(
|
||||||
|
"Duplicate configuration option (case-insensitive): '" & firstKey & "' and '" &
|
||||||
|
key & "'"
|
||||||
|
)
|
||||||
|
jsonFields[lowerKey] = (key, value)
|
||||||
|
return ok(jsonFields)
|
||||||
|
|
||||||
|
proc unknownKeysError(
|
||||||
|
jsonFields: Table[string, (string, JsonNode)], prefix: string
|
||||||
|
): string =
|
||||||
|
## Format leftover JSON keys as an error message.
|
||||||
|
var keys = newSeq[string]()
|
||||||
|
for _, (jsonKey, _) in pairs(jsonFields):
|
||||||
|
keys.add(jsonKey)
|
||||||
|
return prefix & ": " & $keys
|
||||||
|
|
||||||
|
proc rejectTopLevelOnlyKeysInside(
|
||||||
|
node: JsonNode, blockName: string
|
||||||
|
): Result[void, string] =
|
||||||
|
## Error if `node` contains any key from `TopLevelOnlyKeys`.
|
||||||
|
for k, _ in node:
|
||||||
|
if k.toLowerAscii() in TopLevelOnlyKeys:
|
||||||
|
return err("'" & k & "' must be a top-level key, not inside '" & blockName & "'")
|
||||||
|
return ok()
|
||||||
|
|
||||||
|
proc jsonScalarToString(node: JsonNode): Result[string, string] =
|
||||||
|
## Convert a scalar JSON value to its string form.
|
||||||
|
case node.kind
|
||||||
|
of JString:
|
||||||
|
return ok(node.getStr())
|
||||||
|
of JInt:
|
||||||
|
return ok($node.getInt())
|
||||||
|
of JFloat:
|
||||||
|
return ok($node.getFloat())
|
||||||
|
of JBool:
|
||||||
|
return ok($node.getBool())
|
||||||
|
of JNull:
|
||||||
|
return ok("")
|
||||||
|
else:
|
||||||
|
return err("expected scalar JSON value, got " & $node.kind)
|
||||||
|
|
||||||
|
proc applyJsonFieldsToConf(
|
||||||
|
conf: var WakuNodeConf,
|
||||||
|
jsonFields: var Table[string, (string, JsonNode)],
|
||||||
|
parseErrPrefix: string,
|
||||||
|
unknownErrPrefix: string,
|
||||||
|
): Result[void, string] =
|
||||||
|
## Walk `conf`'s fields and write each one matched (case-insensitive) by
|
||||||
|
## `jsonFields`. seq fields take a JArray (full replace); scalar fields
|
||||||
|
## take any scalar JSON kind. Errors on leftover unknown keys.
|
||||||
|
for confField, confValue in fieldPairs(conf):
|
||||||
|
let lowerField = confField.toLowerAscii()
|
||||||
|
if jsonFields.hasKey(lowerField):
|
||||||
|
let (jsonKey, jsonValue) = jsonFields[lowerField]
|
||||||
|
when confValue is seq:
|
||||||
|
if jsonValue.kind != JArray:
|
||||||
|
return err(
|
||||||
|
parseErrPrefix & " '" & confField & "' from JSON key '" & jsonKey &
|
||||||
|
"' must be a JSON array"
|
||||||
|
)
|
||||||
|
var newSeq: typeof(confValue) = @[]
|
||||||
|
for item in jsonValue:
|
||||||
|
let formattedItem = jsonScalarToString(item).valueOr:
|
||||||
|
return err(
|
||||||
|
parseErrPrefix & " '" & confField & "' from JSON key '" & jsonKey & "': " &
|
||||||
|
error
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
type ElemType = typeof(confValue[0])
|
||||||
|
newSeq.add(parseCmdArg(ElemType, formattedItem))
|
||||||
|
except CatchableError as e:
|
||||||
|
return err(
|
||||||
|
parseErrPrefix & " '" & confField & "' from JSON key '" & jsonKey & "': " &
|
||||||
|
e.msg & ". Value: " & formattedItem
|
||||||
|
)
|
||||||
|
confValue = newSeq
|
||||||
|
else:
|
||||||
|
let formattedString = jsonScalarToString(jsonValue).valueOr:
|
||||||
|
return err(
|
||||||
|
parseErrPrefix & " '" & confField & "' from JSON key '" & jsonKey & "': " &
|
||||||
|
error
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
confValue = parseCmdArg(typeof(confValue), formattedString)
|
||||||
|
except CatchableError as e:
|
||||||
|
return err(
|
||||||
|
parseErrPrefix & " '" & confField & "' from JSON key '" & jsonKey & "': " &
|
||||||
|
e.msg & ". Value: " & formattedString
|
||||||
|
)
|
||||||
|
jsonFields.del(lowerField)
|
||||||
|
if jsonFields.len > 0:
|
||||||
|
return err(unknownKeysError(jsonFields, unknownErrPrefix))
|
||||||
|
return ok()
|
||||||
|
|
||||||
|
proc applyJsonAsOverride*(
|
||||||
|
conf: var WakuNodeConf, overrides: JsonNode
|
||||||
|
): Result[void, string] =
|
||||||
|
## Apply `overrides` JSON onto `conf` with replace semantics for both scalars and lists.
|
||||||
|
var jsonFields = ?collectJsonFields(overrides)
|
||||||
|
return applyJsonFieldsToConf(
|
||||||
|
conf, jsonFields, "Failed to parse override field",
|
||||||
|
"Unrecognized override field(s) found",
|
||||||
|
)
|
||||||
|
|
||||||
|
proc applyJsonAsAddition*(
|
||||||
|
conf: var WakuNodeConf, additions: JsonNode
|
||||||
|
): Result[void, string] =
|
||||||
|
## Append JSON array in `additions` to `conf` seq fields.
|
||||||
|
var jsonFields = ?collectJsonFields(additions)
|
||||||
|
for confField, confValue in fieldPairs(conf):
|
||||||
|
let lowerField = confField.toLowerAscii()
|
||||||
|
if jsonFields.hasKey(lowerField):
|
||||||
|
let (jsonKey, jsonValue) = jsonFields[lowerField]
|
||||||
|
when confValue is seq:
|
||||||
|
if jsonValue.kind != JArray:
|
||||||
|
return err(
|
||||||
|
"Addition field '" & confField & "' from JSON key '" & jsonKey &
|
||||||
|
"' must be a JSON array"
|
||||||
|
)
|
||||||
|
for item in jsonValue:
|
||||||
|
let formattedItem = jsonScalarToString(item).valueOr:
|
||||||
|
return err(
|
||||||
|
"Failed to parse addition item for field '" & confField & "': " & error
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
type ElemType = typeof(confValue[0])
|
||||||
|
confValue.add(parseCmdArg(ElemType, formattedItem))
|
||||||
|
except CatchableError as e:
|
||||||
|
return err(
|
||||||
|
"Failed to parse addition item for field '" & confField & "': " & e.msg &
|
||||||
|
". Value: " & formattedItem
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return err(
|
||||||
|
"Field '" & confField & "' from JSON key '" & jsonKey &
|
||||||
|
"' is not a list and cannot be in additions"
|
||||||
|
)
|
||||||
|
jsonFields.del(lowerField)
|
||||||
|
if jsonFields.len > 0:
|
||||||
|
return err(unknownKeysError(jsonFields, "Unrecognized addition field(s) found"))
|
||||||
|
return ok()
|
||||||
|
|
||||||
|
proc assembleMessagingConf*(
|
||||||
|
jsonFields: Table[string, (string, JsonNode)]
|
||||||
|
): Result[WakuNodeConf, string] =
|
||||||
|
## Build a WakuNodeConf from the messaging shape
|
||||||
|
## `{mode, overrides, preset?, additions?}`. `mode` and `overrides` are
|
||||||
|
## required. Order: overrides applied first, then additions concat.
|
||||||
|
var conf = ?defaultWakuNodeConf()
|
||||||
|
var fields = jsonFields
|
||||||
|
|
||||||
|
if not fields.hasKey(KeyMode):
|
||||||
|
return err("messaging shape requires '" & KeyMode & "' key")
|
||||||
|
if not fields.hasKey(KeyOverrides):
|
||||||
|
return err("messaging shape requires '" & KeyOverrides & "' key")
|
||||||
|
|
||||||
|
let modeStr = jsonScalarToString(fields[KeyMode][1]).valueOr:
|
||||||
|
return err("Failed to parse '" & KeyMode & "': " & error)
|
||||||
|
try:
|
||||||
|
conf.mode = parseCmdArg(WakuMode, modeStr)
|
||||||
|
except CatchableError as e:
|
||||||
|
return err("Failed to parse '" & KeyMode & "': " & e.msg & ". Value: " & modeStr)
|
||||||
|
fields.del(KeyMode)
|
||||||
|
|
||||||
|
if fields.hasKey(KeyPreset):
|
||||||
|
let presetStr = jsonScalarToString(fields[KeyPreset][1]).valueOr:
|
||||||
|
return err("Failed to parse '" & KeyPreset & "': " & error)
|
||||||
|
conf.preset = presetStr
|
||||||
|
fields.del(KeyPreset)
|
||||||
|
|
||||||
|
let overridesNode = fields[KeyOverrides][1]
|
||||||
|
if overridesNode.kind != JObject:
|
||||||
|
return err("'" & KeyOverrides & "' must be a JSON object")
|
||||||
|
?rejectTopLevelOnlyKeysInside(overridesNode, KeyOverrides)
|
||||||
|
?applyJsonAsOverride(conf, overridesNode)
|
||||||
|
fields.del(KeyOverrides)
|
||||||
|
|
||||||
|
if fields.hasKey(KeyAdditions):
|
||||||
|
let additionsNode = fields[KeyAdditions][1]
|
||||||
|
if additionsNode.kind != JObject:
|
||||||
|
return err("'" & KeyAdditions & "' must be a JSON object")
|
||||||
|
?rejectTopLevelOnlyKeysInside(additionsNode, KeyAdditions)
|
||||||
|
?applyJsonAsAddition(conf, additionsNode)
|
||||||
|
fields.del(KeyAdditions)
|
||||||
|
|
||||||
|
if fields.len > 0:
|
||||||
|
return
|
||||||
|
err(unknownKeysError(fields, "Unrecognized top-level key(s) in messaging shape"))
|
||||||
|
|
||||||
|
return ok(conf)
|
||||||
|
|
||||||
|
proc assembleFullConf*(
|
||||||
|
jsonFields: Table[string, (string, JsonNode)]
|
||||||
|
): Result[WakuNodeConf, string] =
|
||||||
|
## Build a WakuNodeConf from a flat JSON object whose keys are WakuNodeConf field names.
|
||||||
|
var conf = ?defaultWakuNodeConf()
|
||||||
|
var fields = jsonFields
|
||||||
|
?applyJsonFieldsToConf(
|
||||||
|
conf, fields, "Failed to parse field", "Unrecognized configuration option(s) found"
|
||||||
|
)
|
||||||
|
return ok(conf)
|
||||||
|
|
||||||
|
proc parseConfJson*(jsonStr: string): Result[WakuNodeConf, string] =
|
||||||
|
## Parse a JSON config, route to messaging or full-config shape based on
|
||||||
|
## whether `overrides` or `additions` fields are in the config object top-level.
|
||||||
|
var jsonNode: JsonNode
|
||||||
|
try:
|
||||||
|
jsonNode = parseJson(jsonStr)
|
||||||
|
except CatchableError as e:
|
||||||
|
return err("Failed to parse config JSON: " & e.msg)
|
||||||
|
|
||||||
|
let jsonFields = ?collectJsonFields(jsonNode)
|
||||||
|
let isMessagingShape =
|
||||||
|
jsonFields.hasKey(KeyOverrides) or jsonFields.hasKey(KeyAdditions)
|
||||||
|
if isMessagingShape:
|
||||||
|
return assembleMessagingConf(jsonFields)
|
||||||
|
else:
|
||||||
|
return assembleFullConf(jsonFields)
|
||||||
37
tools/confutils/messaging_conf.nim
Normal file
37
tools/confutils/messaging_conf.nim
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import std/options
|
||||||
|
import results
|
||||||
|
import ./cli_args
|
||||||
|
import ./optionalize
|
||||||
|
|
||||||
|
const WakuNodeConfOverlayExcludes* = ["cmd", "execute", "mode", "preset"]
|
||||||
|
|
||||||
|
# Generates the WakuNodeConfOverlay type from the WakuNodeConf type.
|
||||||
|
# The generated type converts fields from type T to Option[T] if T != Option.
|
||||||
|
# Skips fields that are in WakuNodeConfOverlayExcludes.
|
||||||
|
optionalizeType(WakuNodeConfOverlay, WakuNodeConf, WakuNodeConfOverlayExcludes)
|
||||||
|
|
||||||
|
proc init*(T: type WakuNodeConfOverlay): WakuNodeConfOverlay =
|
||||||
|
## Default config overlay where every field is `none`.
|
||||||
|
return WakuNodeConfOverlay()
|
||||||
|
|
||||||
|
proc applyAsOverride*(conf: var WakuNodeConf, overlay: WakuNodeConfOverlay) =
|
||||||
|
## For all fields, overlay.some() overrides field of same name in conf.
|
||||||
|
for confName, confValue in fieldPairs(conf):
|
||||||
|
for ovName, ovValue in fieldPairs(overlay):
|
||||||
|
when confName == ovName:
|
||||||
|
if ovValue.isSome():
|
||||||
|
when typeof(confValue) is Option:
|
||||||
|
confValue = ovValue
|
||||||
|
else:
|
||||||
|
confValue = ovValue.get()
|
||||||
|
|
||||||
|
proc applyAsAddition*(conf: var WakuNodeConf, overlay: WakuNodeConfOverlay) =
|
||||||
|
## For all seq fields, overlay.some() concats to field of same name in conf.
|
||||||
|
for confName, confValue in fieldPairs(conf):
|
||||||
|
for ovName, ovValue in fieldPairs(overlay):
|
||||||
|
when confName == ovName:
|
||||||
|
when typeof(confValue) is seq:
|
||||||
|
if ovValue.isSome() and ovValue.get().len > 0:
|
||||||
|
confValue = confValue & ovValue.get()
|
||||||
74
tools/confutils/optionalize.nim
Normal file
74
tools/confutils/optionalize.nim
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import std/[macros, options]
|
||||||
|
|
||||||
|
proc isOptionType(n: NimNode): bool =
|
||||||
|
if n.kind == nnkBracketExpr and n.len >= 1:
|
||||||
|
let head = n[0]
|
||||||
|
return head.eqIdent("Option")
|
||||||
|
return false
|
||||||
|
|
||||||
|
proc unwrapName(n: NimNode): NimNode =
|
||||||
|
var cur = n
|
||||||
|
if cur.kind == nnkPragmaExpr:
|
||||||
|
cur = cur[0]
|
||||||
|
if cur.kind == nnkPostfix:
|
||||||
|
cur = cur[1]
|
||||||
|
return cur
|
||||||
|
|
||||||
|
proc collectFields(rec: NimNode, target: NimNode, excluded: seq[string]) =
|
||||||
|
for child in rec:
|
||||||
|
case child.kind
|
||||||
|
of nnkIdentDefs:
|
||||||
|
let nameNode = child[0]
|
||||||
|
let fieldType = child[^2]
|
||||||
|
let plainName = unwrapName(nameNode)
|
||||||
|
if plainName.kind notin {nnkIdent, nnkSym}:
|
||||||
|
continue
|
||||||
|
if $plainName in excluded:
|
||||||
|
continue
|
||||||
|
let newType =
|
||||||
|
if isOptionType(fieldType):
|
||||||
|
fieldType
|
||||||
|
else:
|
||||||
|
nnkBracketExpr.newTree(ident("Option"), fieldType)
|
||||||
|
let exported = postfix(ident($plainName), "*")
|
||||||
|
target.add(newIdentDefs(exported, newType, newEmptyNode()))
|
||||||
|
of nnkRecCase:
|
||||||
|
for branch in child[1 ..^ 1]:
|
||||||
|
case branch.kind
|
||||||
|
of nnkOfBranch:
|
||||||
|
collectFields(branch[^1], target, excluded)
|
||||||
|
of nnkElse:
|
||||||
|
collectFields(branch[0], target, excluded)
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
of nnkRecList:
|
||||||
|
collectFields(child, target, excluded)
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
|
macro optionalizeType*(
|
||||||
|
newName: untyped, source: typedesc, exclude: static[openArray[string]] = []
|
||||||
|
): untyped =
|
||||||
|
var typImpl = source.getTypeImpl
|
||||||
|
if typImpl.kind == nnkBracketExpr and typImpl.len >= 2:
|
||||||
|
typImpl = typImpl[1].getTypeImpl
|
||||||
|
if typImpl.kind != nnkObjectTy:
|
||||||
|
error("optionalizeType: expected object type, got " & $typImpl.kind, source)
|
||||||
|
|
||||||
|
var excluded: seq[string] = @[]
|
||||||
|
for e in exclude:
|
||||||
|
excluded.add(e)
|
||||||
|
|
||||||
|
let recList = typImpl[2]
|
||||||
|
let newRecList = newNimNode(nnkRecList)
|
||||||
|
collectFields(recList, newRecList, excluded)
|
||||||
|
|
||||||
|
let typeDef = nnkTypeDef.newTree(
|
||||||
|
postfix(newName, "*"),
|
||||||
|
newEmptyNode(),
|
||||||
|
nnkObjectTy.newTree(newEmptyNode(), newEmptyNode(), newRecList),
|
||||||
|
)
|
||||||
|
|
||||||
|
result = nnkTypeSection.newTree(typeDef)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import chronicles, chronos, results
|
import chronicles, chronos, results, std/options
|
||||||
|
|
||||||
import waku/factory/waku
|
import waku/factory/waku
|
||||||
import waku/[requests/health_requests, waku_core, waku_node]
|
import waku/[requests/health_requests, waku_core, waku_node]
|
||||||
@ -6,9 +6,10 @@ import waku/node/delivery_service/send_service
|
|||||||
import waku/node/delivery_service/subscription_manager
|
import waku/node/delivery_service/subscription_manager
|
||||||
import libp2p/peerid
|
import libp2p/peerid
|
||||||
import ../../tools/confutils/cli_args
|
import ../../tools/confutils/cli_args
|
||||||
|
import ../../tools/confutils/messaging_conf
|
||||||
import ./[api_conf, types]
|
import ./[api_conf, types]
|
||||||
|
|
||||||
export cli_args
|
export cli_args, messaging_conf
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "api"
|
topics = "api"
|
||||||
@ -24,6 +25,20 @@ proc createNode*(conf: WakuNodeConf): Future[Result[Waku, string]] {.async.} =
|
|||||||
|
|
||||||
return ok(wakuRes)
|
return ok(wakuRes)
|
||||||
|
|
||||||
|
proc createNode*(
|
||||||
|
preset = "",
|
||||||
|
mode = cli_args.WakuMode.Core,
|
||||||
|
overrides = WakuNodeConfOverlay.init(),
|
||||||
|
additions = WakuNodeConfOverlay.init(),
|
||||||
|
): Future[Result[Waku, string]] {.async.} =
|
||||||
|
var conf = defaultWakuNodeConf().valueOr:
|
||||||
|
return err("Failed creating default conf: " & error)
|
||||||
|
conf.mode = mode
|
||||||
|
conf.preset = preset
|
||||||
|
applyAsOverride(conf, overrides)
|
||||||
|
applyAsAddition(conf, additions)
|
||||||
|
return await createNode(conf)
|
||||||
|
|
||||||
proc checkApiAvailability(w: Waku): Result[void, string] =
|
proc checkApiAvailability(w: Waku): Result[void, string] =
|
||||||
if w.isNil():
|
if w.isNil():
|
||||||
return err("Waku node is not initialized")
|
return err("Waku node is not initialized")
|
||||||
|
|||||||
@ -4,6 +4,14 @@ import ../waku_conf
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder discv5"
|
topics = "waku conf builder discv5"
|
||||||
|
|
||||||
|
const
|
||||||
|
DefaultDiscv5Enabled*: bool = false
|
||||||
|
DefaultDiscv5BitsPerHop*: int = 1
|
||||||
|
DefaultDiscv5BucketIpLimit*: uint = 2
|
||||||
|
DefaultDiscv5EnrAutoUpdate*: bool = true
|
||||||
|
DefaultDiscv5TableIpLimit*: uint = 10
|
||||||
|
DefaultDiscv5UdpPort*: Port = Port(0)
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
## Discv5 Config Builder ##
|
## Discv5 Config Builder ##
|
||||||
###########################
|
###########################
|
||||||
@ -46,18 +54,18 @@ proc withBootstrapNodes*(b: var Discv5ConfBuilder, bootstrapNodes: seq[string])
|
|||||||
b.bootstrapNodes = concat(b.bootstrapNodes, bootstrapNodes)
|
b.bootstrapNodes = concat(b.bootstrapNodes, bootstrapNodes)
|
||||||
|
|
||||||
proc build*(b: Discv5ConfBuilder): Result[Option[Discv5Conf], string] =
|
proc build*(b: Discv5ConfBuilder): Result[Option[Discv5Conf], string] =
|
||||||
if not b.enabled.get(false):
|
if not b.enabled.get(DefaultDiscv5Enabled):
|
||||||
return ok(none(Discv5Conf))
|
return ok(none(Discv5Conf))
|
||||||
|
|
||||||
return ok(
|
return ok(
|
||||||
some(
|
some(
|
||||||
Discv5Conf(
|
Discv5Conf(
|
||||||
bootstrapNodes: b.bootstrapNodes,
|
bootstrapNodes: b.bootstrapNodes,
|
||||||
bitsPerHop: b.bitsPerHop.get(1),
|
bitsPerHop: b.bitsPerHop.get(DefaultDiscv5BitsPerHop),
|
||||||
bucketIpLimit: b.bucketIpLimit.get(2),
|
bucketIpLimit: b.bucketIpLimit.get(DefaultDiscv5BucketIpLimit),
|
||||||
enrAutoUpdate: b.enrAutoUpdate.get(true),
|
enrAutoUpdate: b.enrAutoUpdate.get(DefaultDiscv5EnrAutoUpdate),
|
||||||
tableIpLimit: b.tableIpLimit.get(10),
|
tableIpLimit: b.tableIpLimit.get(DefaultDiscv5TableIpLimit),
|
||||||
udpPort: b.udpPort.get(Port(0)),
|
udpPort: b.udpPort.get(DefaultDiscv5UdpPort),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -4,6 +4,12 @@ import ../waku_conf
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder filter service"
|
topics = "waku conf builder filter service"
|
||||||
|
|
||||||
|
const
|
||||||
|
DefaultFilterEnabled*: bool = false
|
||||||
|
DefaultFilterMaxPeersToServe*: uint32 = 500
|
||||||
|
DefaultFilterSubscriptionTimeout*: uint16 = 300
|
||||||
|
DefaultFilterMaxCriteria*: uint32 = 1000
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
## Filter Service Config Builder ##
|
## Filter Service Config Builder ##
|
||||||
###################################
|
###################################
|
||||||
@ -37,15 +43,15 @@ proc withMaxCriteria*(b: var FilterServiceConfBuilder, maxCriteria: uint32) =
|
|||||||
b.maxCriteria = some(maxCriteria)
|
b.maxCriteria = some(maxCriteria)
|
||||||
|
|
||||||
proc build*(b: FilterServiceConfBuilder): Result[Option[FilterServiceConf], string] =
|
proc build*(b: FilterServiceConfBuilder): Result[Option[FilterServiceConf], string] =
|
||||||
if not b.enabled.get(false):
|
if not b.enabled.get(DefaultFilterEnabled):
|
||||||
return ok(none(FilterServiceConf))
|
return ok(none(FilterServiceConf))
|
||||||
|
|
||||||
return ok(
|
return ok(
|
||||||
some(
|
some(
|
||||||
FilterServiceConf(
|
FilterServiceConf(
|
||||||
maxPeersToServe: b.maxPeersToServe.get(500),
|
maxPeersToServe: b.maxPeersToServe.get(DefaultFilterMaxPeersToServe),
|
||||||
subscriptionTimeout: b.subscriptionTimeout.get(300),
|
subscriptionTimeout: b.subscriptionTimeout.get(DefaultFilterSubscriptionTimeout),
|
||||||
maxCriteria: b.maxCriteria.get(1000),
|
maxCriteria: b.maxCriteria.get(DefaultFilterMaxCriteria),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -5,18 +5,20 @@ import waku/factory/waku_conf
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder kademlia discovery"
|
topics = "waku conf builder kademlia discovery"
|
||||||
|
|
||||||
|
const DefaultKadEnabled*: bool = false
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
## Kademlia Discovery Config Builder ##
|
## Kademlia Discovery Config Builder ##
|
||||||
#######################################
|
#######################################
|
||||||
type KademliaDiscoveryConfBuilder* = object
|
type KademliaDiscoveryConfBuilder* = object
|
||||||
enabled*: bool
|
enabled*: Option[bool]
|
||||||
bootstrapNodes*: seq[string]
|
bootstrapNodes*: seq[string]
|
||||||
|
|
||||||
proc init*(T: type KademliaDiscoveryConfBuilder): KademliaDiscoveryConfBuilder =
|
proc init*(T: type KademliaDiscoveryConfBuilder): KademliaDiscoveryConfBuilder =
|
||||||
KademliaDiscoveryConfBuilder()
|
KademliaDiscoveryConfBuilder()
|
||||||
|
|
||||||
proc withEnabled*(b: var KademliaDiscoveryConfBuilder, enabled: bool) =
|
proc withEnabled*(b: var KademliaDiscoveryConfBuilder, enabled: bool) =
|
||||||
b.enabled = enabled
|
b.enabled = some(enabled)
|
||||||
|
|
||||||
proc withBootstrapNodes*(
|
proc withBootstrapNodes*(
|
||||||
b: var KademliaDiscoveryConfBuilder, bootstrapNodes: seq[string]
|
b: var KademliaDiscoveryConfBuilder, bootstrapNodes: seq[string]
|
||||||
@ -27,7 +29,7 @@ proc build*(
|
|||||||
b: KademliaDiscoveryConfBuilder
|
b: KademliaDiscoveryConfBuilder
|
||||||
): Result[Option[KademliaDiscoveryConf], string] =
|
): Result[Option[KademliaDiscoveryConf], string] =
|
||||||
# Kademlia is enabled if explicitly enabled OR if bootstrap nodes are provided
|
# Kademlia is enabled if explicitly enabled OR if bootstrap nodes are provided
|
||||||
let enabled = b.enabled or b.bootstrapNodes.len > 0
|
let enabled = b.enabled.get(DefaultKadEnabled) or b.bootstrapNodes.len > 0
|
||||||
if not enabled:
|
if not enabled:
|
||||||
return ok(none(KademliaDiscoveryConf))
|
return ok(none(KademliaDiscoveryConf))
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,12 @@ import ../waku_conf
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder metrics server"
|
topics = "waku conf builder metrics server"
|
||||||
|
|
||||||
|
const
|
||||||
|
DefaultMetricsEnabled*: bool = false
|
||||||
|
DefaultMetricsHttpAddress*: IpAddress = static parseIpAddress("127.0.0.1")
|
||||||
|
DefaultMetricsHttpPort*: Port = Port(0)
|
||||||
|
DefaultMetricsLogging*: bool = false
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
## Metrics Server Config Builder ##
|
## Metrics Server Config Builder ##
|
||||||
###################################
|
###################################
|
||||||
@ -33,15 +39,15 @@ proc withLogging*(b: var MetricsServerConfBuilder, logging: bool) =
|
|||||||
b.logging = some(logging)
|
b.logging = some(logging)
|
||||||
|
|
||||||
proc build*(b: MetricsServerConfBuilder): Result[Option[MetricsServerConf], string] =
|
proc build*(b: MetricsServerConfBuilder): Result[Option[MetricsServerConf], string] =
|
||||||
if not b.enabled.get(false):
|
if not b.enabled.get(DefaultMetricsEnabled):
|
||||||
return ok(none(MetricsServerConf))
|
return ok(none(MetricsServerConf))
|
||||||
|
|
||||||
return ok(
|
return ok(
|
||||||
some(
|
some(
|
||||||
MetricsServerConf(
|
MetricsServerConf(
|
||||||
httpAddress: b.httpAddress.get(static parseIpAddress("127.0.0.1")),
|
httpAddress: b.httpAddress.get(DefaultMetricsHttpAddress),
|
||||||
httpPort: b.httpPort.get(Port(0)),
|
httpPort: b.httpPort.get(DefaultMetricsHttpPort),
|
||||||
logging: b.logging.get(false),
|
logging: b.logging.get(DefaultMetricsLogging),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import ../waku_conf, waku/waku_mix
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder mix"
|
topics = "waku conf builder mix"
|
||||||
|
|
||||||
|
const DefaultMixEnabled*: bool = false
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
## Mix Config Builder ##
|
## Mix Config Builder ##
|
||||||
##################################
|
##################################
|
||||||
@ -26,7 +28,7 @@ proc withMixNodes*(b: var MixConfBuilder, mixNodes: seq[MixNodePubInfo]) =
|
|||||||
b.mixNodes = mixNodes
|
b.mixNodes = mixNodes
|
||||||
|
|
||||||
proc build*(b: MixConfBuilder): Result[Option[MixConf], string] =
|
proc build*(b: MixConfBuilder): Result[Option[MixConf], string] =
|
||||||
if not b.enabled.get(false):
|
if not b.enabled.get(DefaultMixEnabled):
|
||||||
return ok(none[MixConf]())
|
return ok(none[MixConf]())
|
||||||
else:
|
else:
|
||||||
if b.mixKey.isSome():
|
if b.mixKey.isSome():
|
||||||
|
|||||||
@ -4,6 +4,11 @@ import ../waku_conf
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder rest server"
|
topics = "waku conf builder rest server"
|
||||||
|
|
||||||
|
const
|
||||||
|
DefaultRestEnabled*: bool = false
|
||||||
|
DefaultRestPort*: Port = Port(0)
|
||||||
|
DefaultRestAdmin*: bool = false
|
||||||
|
|
||||||
################################
|
################################
|
||||||
## REST Server Config Builder ##
|
## REST Server Config Builder ##
|
||||||
################################
|
################################
|
||||||
@ -41,7 +46,7 @@ proc withRelayCacheCapacity*(b: var RestServerConfBuilder, relayCacheCapacity: u
|
|||||||
b.relayCacheCapacity = some(relayCacheCapacity)
|
b.relayCacheCapacity = some(relayCacheCapacity)
|
||||||
|
|
||||||
proc build*(b: RestServerConfBuilder): Result[Option[RestServerConf], string] =
|
proc build*(b: RestServerConfBuilder): Result[Option[RestServerConf], string] =
|
||||||
if not b.enabled.get(false):
|
if not b.enabled.get(DefaultRestEnabled):
|
||||||
return ok(none(RestServerConf))
|
return ok(none(RestServerConf))
|
||||||
|
|
||||||
if b.listenAddress.isNone():
|
if b.listenAddress.isNone():
|
||||||
@ -54,8 +59,8 @@ proc build*(b: RestServerConfBuilder): Result[Option[RestServerConf], string] =
|
|||||||
RestServerConf(
|
RestServerConf(
|
||||||
allowOrigin: b.allowOrigin,
|
allowOrigin: b.allowOrigin,
|
||||||
listenAddress: b.listenAddress.get(),
|
listenAddress: b.listenAddress.get(),
|
||||||
port: b.port.get(Port(0)),
|
port: b.port.get(DefaultRestPort),
|
||||||
admin: b.admin.get(false),
|
admin: b.admin.get(DefaultRestAdmin),
|
||||||
relayCacheCapacity: b.relayCacheCapacity.get(),
|
relayCacheCapacity: b.relayCacheCapacity.get(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -4,6 +4,11 @@ import ../waku_conf
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder rln relay"
|
topics = "waku conf builder rln relay"
|
||||||
|
|
||||||
|
const
|
||||||
|
DefaultRlnRelayEnabled*: bool = false
|
||||||
|
DefaultRlnRelayEpochSizeSec*: uint64 = 1
|
||||||
|
DefaultRlnRelayUserMessageLimit*: uint64 = 1
|
||||||
|
|
||||||
##############################
|
##############################
|
||||||
## RLN Relay Config Builder ##
|
## RLN Relay Config Builder ##
|
||||||
##############################
|
##############################
|
||||||
@ -56,7 +61,7 @@ proc withUserMessageLimit*(b: var RlnRelayConfBuilder, userMessageLimit: uint64)
|
|||||||
b.userMessageLimit = some(userMessageLimit)
|
b.userMessageLimit = some(userMessageLimit)
|
||||||
|
|
||||||
proc build*(b: RlnRelayConfBuilder): Result[Option[RlnRelayConf], string] =
|
proc build*(b: RlnRelayConfBuilder): Result[Option[RlnRelayConf], string] =
|
||||||
if not b.enabled.get(false):
|
if not b.enabled.get(DefaultRlnRelayEnabled):
|
||||||
return ok(none(RlnRelayConf))
|
return ok(none(RlnRelayConf))
|
||||||
|
|
||||||
if b.chainId.isNone():
|
if b.chainId.isNone():
|
||||||
@ -78,11 +83,6 @@ proc build*(b: RlnRelayConfBuilder): Result[Option[RlnRelayConf], string] =
|
|||||||
return err("rlnRelay.ethClientUrls is not specified")
|
return err("rlnRelay.ethClientUrls is not specified")
|
||||||
if b.ethContractAddress.get("") == "":
|
if b.ethContractAddress.get("") == "":
|
||||||
return err("rlnRelay.ethContractAddress is not specified")
|
return err("rlnRelay.ethContractAddress is not specified")
|
||||||
if b.epochSizeSec.isNone():
|
|
||||||
return err("rlnRelay.epochSizeSec is not specified")
|
|
||||||
if b.userMessageLimit.isNone():
|
|
||||||
return err("rlnRelay.userMessageLimit is not specified")
|
|
||||||
|
|
||||||
return ok(
|
return ok(
|
||||||
some(
|
some(
|
||||||
RlnRelayConf(
|
RlnRelayConf(
|
||||||
@ -92,8 +92,8 @@ proc build*(b: RlnRelayConfBuilder): Result[Option[RlnRelayConf], string] =
|
|||||||
dynamic: b.dynamic.get(),
|
dynamic: b.dynamic.get(),
|
||||||
ethClientUrls: b.ethClientUrls.get(),
|
ethClientUrls: b.ethClientUrls.get(),
|
||||||
ethContractAddress: b.ethContractAddress.get(),
|
ethContractAddress: b.ethContractAddress.get(),
|
||||||
epochSizeSec: b.epochSizeSec.get(),
|
epochSizeSec: b.epochSizeSec.get(DefaultRlnRelayEpochSizeSec),
|
||||||
userMessageLimit: b.userMessageLimit.get(),
|
userMessageLimit: b.userMessageLimit.get(DefaultRlnRelayUserMessageLimit),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -5,6 +5,14 @@ import ../waku_conf, ./store_sync_conf_builder
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder store service"
|
topics = "waku conf builder store service"
|
||||||
|
|
||||||
|
const
|
||||||
|
DefaultStoreEnabled*: bool = false
|
||||||
|
DefaultStoreDbMigration*: bool = true
|
||||||
|
DefaultStoreDbVacuum*: bool = false
|
||||||
|
DefaultStoreMaxNumDbConnections*: int = 50
|
||||||
|
DefaultStoreResume*: bool = false
|
||||||
|
DefaultStoreRetentionPolicy*: string = "time:" & $2.days.seconds
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
## Store Service Config Builder ##
|
## Store Service Config Builder ##
|
||||||
##################################
|
##################################
|
||||||
@ -77,7 +85,7 @@ proc validateRetentionPolicies(policies: seq[string]): Result[void, string] =
|
|||||||
return ok()
|
return ok()
|
||||||
|
|
||||||
proc build*(b: StoreServiceConfBuilder): Result[Option[StoreServiceConf], string] =
|
proc build*(b: StoreServiceConfBuilder): Result[Option[StoreServiceConf], string] =
|
||||||
if not b.enabled.get(false):
|
if not b.enabled.get(DefaultStoreEnabled):
|
||||||
return ok(none(StoreServiceConf))
|
return ok(none(StoreServiceConf))
|
||||||
|
|
||||||
if b.dbUrl.get("") == "":
|
if b.dbUrl.get("") == "":
|
||||||
@ -88,7 +96,7 @@ proc build*(b: StoreServiceConfBuilder): Result[Option[StoreServiceConf], string
|
|||||||
|
|
||||||
let retentionPolicies =
|
let retentionPolicies =
|
||||||
if b.retentionPolicies.len == 0:
|
if b.retentionPolicies.len == 0:
|
||||||
@["time:" & $2.days.seconds]
|
@[DefaultStoreRetentionPolicy]
|
||||||
else:
|
else:
|
||||||
validateRetentionPolicies(b.retentionPolicies).isOkOr:
|
validateRetentionPolicies(b.retentionPolicies).isOkOr:
|
||||||
return err("invalid retention policies: " & error)
|
return err("invalid retention policies: " & error)
|
||||||
@ -97,12 +105,12 @@ proc build*(b: StoreServiceConfBuilder): Result[Option[StoreServiceConf], string
|
|||||||
return ok(
|
return ok(
|
||||||
some(
|
some(
|
||||||
StoreServiceConf(
|
StoreServiceConf(
|
||||||
dbMigration: b.dbMigration.get(true),
|
dbMigration: b.dbMigration.get(DefaultStoreDbMigration),
|
||||||
dbURl: b.dbUrl.get(),
|
dbURl: b.dbUrl.get(),
|
||||||
dbVacuum: b.dbVacuum.get(false),
|
dbVacuum: b.dbVacuum.get(DefaultStoreDbVacuum),
|
||||||
maxNumDbConnections: b.maxNumDbConnections.get(50),
|
maxNumDbConnections: b.maxNumDbConnections.get(DefaultStoreMaxNumDbConnections),
|
||||||
retentionPolicies: retentionPolicies,
|
retentionPolicies: retentionPolicies,
|
||||||
resume: b.resume.get(false),
|
resume: b.resume.get(DefaultStoreResume),
|
||||||
storeSyncConf: storeSyncConf,
|
storeSyncConf: storeSyncConf,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import ../waku_conf
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder store sync"
|
topics = "waku conf builder store sync"
|
||||||
|
|
||||||
|
const DefaultStoreSyncEnabled*: bool = false
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
## Store Sync Config Builder ##
|
## Store Sync Config Builder ##
|
||||||
##################################
|
##################################
|
||||||
@ -30,7 +32,7 @@ proc withRelayJitterSec*(b: var StoreSyncConfBuilder, relayJitterSec: uint32) =
|
|||||||
b.relayJitterSec = some(relayJitterSec)
|
b.relayJitterSec = some(relayJitterSec)
|
||||||
|
|
||||||
proc build*(b: StoreSyncConfBuilder): Result[Option[StoreSyncConf], string] =
|
proc build*(b: StoreSyncConfBuilder): Result[Option[StoreSyncConf], string] =
|
||||||
if not b.enabled.get(false):
|
if not b.enabled.get(DefaultStoreSyncEnabled):
|
||||||
return ok(none(StoreSyncConf))
|
return ok(none(StoreSyncConf))
|
||||||
|
|
||||||
if b.rangeSec.isNone():
|
if b.rangeSec.isNone():
|
||||||
|
|||||||
@ -13,6 +13,9 @@ import
|
|||||||
factory/networks_config,
|
factory/networks_config,
|
||||||
common/logging,
|
common/logging,
|
||||||
common/utils/parse_size_units,
|
common/utils/parse_size_units,
|
||||||
|
node/peer_manager,
|
||||||
|
waku_core/message/default_values,
|
||||||
|
waku_core/topics/pubsub_topic,
|
||||||
waku_enr/capabilities,
|
waku_enr/capabilities,
|
||||||
],
|
],
|
||||||
tools/confutils/entry_nodes
|
tools/confutils/entry_nodes
|
||||||
@ -34,7 +37,35 @@ import
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder"
|
topics = "waku conf builder"
|
||||||
|
|
||||||
const DefaultMaxConnections* = 150
|
# Picks up the same -d:git_version=... build flag that cli_args.nim defines.
|
||||||
|
const git_version {.strdefine.} = "(unknown)"
|
||||||
|
|
||||||
|
const
|
||||||
|
DefaultMaxConnections* = 150
|
||||||
|
DefaultRelay*: bool = false
|
||||||
|
DefaultLightPush*: bool = false
|
||||||
|
DefaultPeerExchange*: bool = false
|
||||||
|
DefaultStoreSyncMount*: bool = false
|
||||||
|
DefaultRendezvous*: bool = false
|
||||||
|
DefaultMix*: bool = false
|
||||||
|
DefaultRelayPeerExchange*: bool = false
|
||||||
|
DefaultLogLevel*: logging.LogLevel = logging.LogLevel.INFO
|
||||||
|
DefaultLogFormat*: logging.LogFormat = logging.LogFormat.TEXT
|
||||||
|
DefaultNatStrategy*: string = "none"
|
||||||
|
DefaultP2pTcpPort*: Port = Port(0)
|
||||||
|
DefaultP2pListenAddress*: IpAddress = static parseIpAddress("0.0.0.0")
|
||||||
|
DefaultPortsShift*: uint16 = 0
|
||||||
|
DefaultExtMultiAddrsOnly*: bool = false
|
||||||
|
DefaultDnsAddrsNameServers*: seq[IpAddress] =
|
||||||
|
@[static parseIpAddress("1.1.1.1"), static parseIpAddress("1.0.0.1")]
|
||||||
|
DefaultPeerPersistence*: bool = false
|
||||||
|
DefaultAgentString*: string = "logos-delivery " & git_version
|
||||||
|
DefaultRelayShardedPeerManagement*: bool = false
|
||||||
|
DefaultRelayServiceRatio*: string = "50:50"
|
||||||
|
DefaultCircuitRelayClient*: bool = false
|
||||||
|
DefaultP2pReliability*: bool = true
|
||||||
|
DefaultNumShardsInCluster*: uint16 = 1
|
||||||
|
DefaultShardingConfKind*: ShardingConfKind = AutoSharding
|
||||||
|
|
||||||
type MaxMessageSizeKind* = enum
|
type MaxMessageSizeKind* = enum
|
||||||
mmskNone
|
mmskNone
|
||||||
@ -301,117 +332,124 @@ proc buildShardingConf(
|
|||||||
bNumShardsInCluster: Option[uint16],
|
bNumShardsInCluster: Option[uint16],
|
||||||
bSubscribeShards: Option[seq[uint16]],
|
bSubscribeShards: Option[seq[uint16]],
|
||||||
): (ShardingConf, seq[uint16]) =
|
): (ShardingConf, seq[uint16]) =
|
||||||
case bShardingConfKind.get(AutoSharding)
|
case bShardingConfKind.get(DefaultShardingConfKind)
|
||||||
of StaticSharding:
|
of StaticSharding:
|
||||||
(ShardingConf(kind: StaticSharding), bSubscribeShards.get(@[]))
|
(ShardingConf(kind: StaticSharding), bSubscribeShards.get(@[]))
|
||||||
of AutoSharding:
|
of AutoSharding:
|
||||||
let numShardsInCluster = bNumShardsInCluster.get(1)
|
let numShardsInCluster = bNumShardsInCluster.get(DefaultNumShardsInCluster)
|
||||||
let shardingConf =
|
let shardingConf =
|
||||||
ShardingConf(kind: AutoSharding, numShardsInCluster: numShardsInCluster)
|
ShardingConf(kind: AutoSharding, numShardsInCluster: numShardsInCluster)
|
||||||
let upperShard = uint16(numShardsInCluster - 1)
|
let upperShard = uint16(numShardsInCluster - 1)
|
||||||
(shardingConf, bSubscribeShards.get(toSeq(0.uint16 .. upperShard)))
|
(shardingConf, bSubscribeShards.get(toSeq(0.uint16 .. upperShard)))
|
||||||
|
|
||||||
|
template checkSetPresetValueToField[T](
|
||||||
|
field: var Option[T], presetVal: T, msg: static string
|
||||||
|
) =
|
||||||
|
## Set the field to the preset's value, unless the field is already set
|
||||||
|
## (explicit wins). Warn iff the field's existing value differs from the
|
||||||
|
## preset's. No-op if they agree.
|
||||||
|
|
||||||
|
if field.isSome():
|
||||||
|
if field.get() != presetVal:
|
||||||
|
warn msg, used = field.get(), discarded = presetVal
|
||||||
|
else:
|
||||||
|
field = some(presetVal)
|
||||||
|
|
||||||
|
proc checkAddPresetValueToField[T](field: var seq[T], presetVals: seq[T]) =
|
||||||
|
## Append the preset's list values to the field's existing list. Lists
|
||||||
|
## concat rather than override; both the user's and the preset's entries
|
||||||
|
## end up in the final list.
|
||||||
|
|
||||||
|
field = field & presetVals
|
||||||
|
|
||||||
proc applyNetworkConf(builder: var WakuConfBuilder) =
|
proc applyNetworkConf(builder: var WakuConfBuilder) =
|
||||||
# Apply network conf, overrides most values passed individually
|
## NetworkConf = network presets.
|
||||||
# If you want to tweak values, don't use networkConf
|
## Cascade the chosen preset's values onto builder fields the user hasn't set.
|
||||||
# TODO: networkconf should be one field of the conf builder so that this function becomes unnecessary
|
## User-set fields stay; preset fills the gaps and warns on conflict (explicit wins).
|
||||||
|
## List fields concat (preset's nodes appended to user's).
|
||||||
|
|
||||||
if builder.networkConf.isNone():
|
if builder.networkConf.isNone():
|
||||||
return
|
return # If there is no preset given, then nothing to do.
|
||||||
|
|
||||||
let networkConf = builder.networkConf.get()
|
let networkConf = builder.networkConf.get()
|
||||||
|
|
||||||
if builder.clusterId.isSome():
|
checkSetPresetValueToField(
|
||||||
warn "Cluster id was provided alongside a network conf",
|
builder.clusterId, networkConf.clusterId,
|
||||||
used = networkConf.clusterId, discarded = builder.clusterId.get()
|
"Cluster id was provided alongside a network conf",
|
||||||
builder.clusterId = some(networkConf.clusterId)
|
)
|
||||||
|
|
||||||
# Apply relay parameters
|
# Apply relay parameters
|
||||||
if builder.relay.get(false) and networkConf.rlnRelay:
|
if builder.relay.get(DefaultRelay) and networkConf.rlnRelay:
|
||||||
if builder.rlnRelayConf.enabled.isSome():
|
checkSetPresetValueToField(
|
||||||
warn "RLN Relay was provided alongside a network conf",
|
builder.rlnRelayConf.enabled,
|
||||||
used = networkConf.rlnRelay, discarded = builder.rlnRelayConf.enabled
|
networkConf.rlnRelay, # true
|
||||||
builder.rlnRelayConf.withEnabled(true)
|
"RLN Relay was provided alongside a network conf",
|
||||||
|
)
|
||||||
if builder.rlnRelayConf.ethContractAddress.get("") != "":
|
checkSetPresetValueToField(
|
||||||
warn "RLN Relay ETH Contract Address was provided alongside a network conf",
|
builder.rlnRelayConf.ethContractAddress, networkConf.rlnRelayEthContractAddress,
|
||||||
used = networkConf.rlnRelayEthContractAddress.string,
|
"RLN Relay ETH Contract Address was provided alongside a network conf",
|
||||||
discarded = builder.rlnRelayConf.ethContractAddress.get().string
|
)
|
||||||
builder.rlnRelayConf.withEthContractAddress(networkConf.rlnRelayEthContractAddress)
|
checkSetPresetValueToField(
|
||||||
|
builder.rlnRelayConf.chainId, networkConf.rlnRelayChainId,
|
||||||
if builder.rlnRelayConf.chainId.isSome():
|
"RLN Relay Chain Id was provided alongside a network conf",
|
||||||
warn "RLN Relay Chain Id was provided alongside a network conf",
|
)
|
||||||
used = networkConf.rlnRelayChainId, discarded = builder.rlnRelayConf.chainId
|
checkSetPresetValueToField(
|
||||||
builder.rlnRelayConf.withChainId(networkConf.rlnRelayChainId)
|
builder.rlnRelayConf.dynamic, networkConf.rlnRelayDynamic,
|
||||||
|
"RLN Relay Dynamic was provided alongside a network conf",
|
||||||
if builder.rlnRelayConf.dynamic.isSome():
|
)
|
||||||
warn "RLN Relay Dynamic was provided alongside a network conf",
|
checkSetPresetValueToField(
|
||||||
used = networkConf.rlnRelayDynamic, discarded = builder.rlnRelayConf.dynamic
|
builder.rlnRelayConf.epochSizeSec, networkConf.rlnEpochSizeSec,
|
||||||
builder.rlnRelayConf.withDynamic(networkConf.rlnRelayDynamic)
|
"RLN Epoch Size in Seconds was provided alongside a network conf",
|
||||||
|
)
|
||||||
if builder.rlnRelayConf.epochSizeSec.isSome():
|
checkSetPresetValueToField(
|
||||||
warn "RLN Epoch Size in Seconds was provided alongside a network conf",
|
builder.rlnRelayConf.userMessageLimit, networkConf.rlnRelayUserMessageLimit,
|
||||||
used = networkConf.rlnEpochSizeSec,
|
"RLN Relay User Message Limit was provided alongside a network conf",
|
||||||
discarded = builder.rlnRelayConf.epochSizeSec
|
)
|
||||||
builder.rlnRelayConf.withEpochSizeSec(networkConf.rlnEpochSizeSec)
|
|
||||||
|
|
||||||
if builder.rlnRelayConf.userMessageLimit.isSome():
|
|
||||||
warn "RLN Relay User Message Limit was provided alongside a network conf",
|
|
||||||
used = networkConf.rlnRelayUserMessageLimit,
|
|
||||||
discarded = builder.rlnRelayConf.userMessageLimit
|
|
||||||
if builder.rlnRelayConf.userMessageLimit.get(0) == 0:
|
|
||||||
## only override with the "preset" value if there was not explicit set value
|
|
||||||
builder.rlnRelayConf.withUserMessageLimit(networkConf.rlnRelayUserMessageLimit)
|
|
||||||
|
|
||||||
# End Apply relay parameters
|
# End Apply relay parameters
|
||||||
|
|
||||||
case builder.maxMessageSize.kind
|
case builder.maxMessageSize.kind
|
||||||
of mmskNone:
|
of mmskNone:
|
||||||
discard
|
builder.withMaxMessageSize(parseCorrectMsgSize(networkConf.maxMessageSize))
|
||||||
of mmskStr, mmskInt:
|
of mmskStr, mmskInt:
|
||||||
warn "Max Message Size was provided alongside a network conf",
|
warn "Max Message Size was provided alongside a network conf",
|
||||||
used = networkConf.maxMessageSize, discarded = $builder.maxMessageSize
|
used = $builder.maxMessageSize, discarded = networkConf.maxMessageSize
|
||||||
builder.withMaxMessageSize(parseCorrectMsgSize(networkConf.maxMessageSize))
|
|
||||||
|
|
||||||
if builder.shardingConf.isSome():
|
|
||||||
warn "Sharding Conf was provided alongside a network conf",
|
|
||||||
used = networkConf.shardingConf.kind, discarded = builder.shardingConf
|
|
||||||
|
|
||||||
|
checkSetPresetValueToField(
|
||||||
|
builder.shardingConf, networkConf.shardingConf.kind,
|
||||||
|
"Sharding Conf was provided alongside a network conf",
|
||||||
|
)
|
||||||
case networkConf.shardingConf.kind
|
case networkConf.shardingConf.kind
|
||||||
of StaticSharding:
|
|
||||||
builder.shardingConf = some(StaticSharding)
|
|
||||||
of AutoSharding:
|
of AutoSharding:
|
||||||
builder.shardingConf = some(AutoSharding)
|
checkSetPresetValueToField(
|
||||||
if builder.numShardsInCluster.isSome():
|
builder.numShardsInCluster, networkConf.shardingConf.numShardsInCluster,
|
||||||
warn "Num Shards In Cluster overrides network conf preset",
|
"Num Shards In Cluster overrides network conf preset",
|
||||||
used = builder.numShardsInCluster.get(),
|
)
|
||||||
ignored = networkConf.shardingConf.numShardsInCluster
|
of StaticSharding:
|
||||||
else:
|
discard
|
||||||
builder.numShardsInCluster = some(networkConf.shardingConf.numShardsInCluster)
|
|
||||||
|
|
||||||
if networkConf.discv5Discovery:
|
checkSetPresetValueToField(
|
||||||
if builder.discv5Conf.enabled.isNone:
|
builder.discv5Conf.enabled, networkConf.discv5Discovery,
|
||||||
builder.discv5Conf.withEnabled(networkConf.discv5Discovery)
|
"Discv5 Discovery was provided alongside a network conf",
|
||||||
|
)
|
||||||
|
checkAddPresetValueToField(
|
||||||
|
builder.discv5Conf.bootstrapNodes, networkConf.discv5BootstrapNodes
|
||||||
|
)
|
||||||
|
|
||||||
if builder.discv5Conf.bootstrapNodes.len == 0 and
|
checkSetPresetValueToField(
|
||||||
networkConf.discv5BootstrapNodes.len > 0:
|
builder.kademliaDiscoveryConf.enabled, networkConf.enableKadDiscovery,
|
||||||
warn "Discv5 Bootstrap nodes were provided alongside a network conf",
|
"Kademlia Discovery was provided alongside a network conf",
|
||||||
used = networkConf.discv5BootstrapNodes,
|
)
|
||||||
discarded = builder.discv5Conf.bootstrapNodes
|
checkAddPresetValueToField(
|
||||||
builder.discv5Conf.withBootstrapNodes(networkConf.discv5BootstrapNodes)
|
builder.kademliaDiscoveryConf.bootstrapNodes, networkConf.kadBootstrapNodes
|
||||||
|
)
|
||||||
|
|
||||||
if networkConf.enableKadDiscovery:
|
checkSetPresetValueToField(
|
||||||
if not builder.kademliaDiscoveryConf.enabled:
|
builder.mix, networkConf.mix, "Mix was provided alongside a network conf"
|
||||||
builder.kademliaDiscoveryConf.withEnabled(networkConf.enableKadDiscovery)
|
)
|
||||||
|
checkSetPresetValueToField(
|
||||||
if builder.kademliaDiscoveryConf.bootstrapNodes.len == 0 and
|
builder.p2pReliability, networkConf.p2pReliability,
|
||||||
networkConf.kadBootstrapNodes.len > 0:
|
"P2P Reliability was provided alongside a network conf",
|
||||||
builder.kademliaDiscoveryConf.withBootstrapNodes(networkConf.kadBootstrapNodes)
|
)
|
||||||
|
|
||||||
if networkConf.mix:
|
|
||||||
if builder.mix.isNone:
|
|
||||||
builder.mix = some(networkConf.mix)
|
|
||||||
|
|
||||||
if builder.p2pReliability.isNone:
|
|
||||||
builder.withP2pReliability(networkConf.p2pReliability)
|
|
||||||
|
|
||||||
# Process entry nodes from network config - classify and distribute
|
# Process entry nodes from network config - classify and distribute
|
||||||
if networkConf.entryNodes.len > 0:
|
if networkConf.entryNodes.len > 0:
|
||||||
@ -449,44 +487,44 @@ proc build*(
|
|||||||
builder.relay.get()
|
builder.relay.get()
|
||||||
else:
|
else:
|
||||||
warn "whether to mount relay is not specified, defaulting to not mounting"
|
warn "whether to mount relay is not specified, defaulting to not mounting"
|
||||||
false
|
DefaultRelay
|
||||||
|
|
||||||
let lightPush =
|
let lightPush =
|
||||||
if builder.lightPush.isSome():
|
if builder.lightPush.isSome():
|
||||||
builder.lightPush.get()
|
builder.lightPush.get()
|
||||||
else:
|
else:
|
||||||
warn "whether to mount lightPush is not specified, defaulting to not mounting"
|
warn "whether to mount lightPush is not specified, defaulting to not mounting"
|
||||||
false
|
DefaultLightPush
|
||||||
|
|
||||||
let peerExchange =
|
let peerExchange =
|
||||||
if builder.peerExchange.isSome():
|
if builder.peerExchange.isSome():
|
||||||
builder.peerExchange.get()
|
builder.peerExchange.get()
|
||||||
else:
|
else:
|
||||||
warn "whether to mount peerExchange is not specified, defaulting to not mounting"
|
warn "whether to mount peerExchange is not specified, defaulting to not mounting"
|
||||||
false
|
DefaultPeerExchange
|
||||||
|
|
||||||
let storeSync =
|
let storeSync =
|
||||||
if builder.storeSync.isSome():
|
if builder.storeSync.isSome():
|
||||||
builder.storeSync.get()
|
builder.storeSync.get()
|
||||||
else:
|
else:
|
||||||
warn "whether to mount storeSync is not specified, defaulting to not mounting"
|
warn "whether to mount storeSync is not specified, defaulting to not mounting"
|
||||||
false
|
DefaultStoreSyncMount
|
||||||
|
|
||||||
let rendezvous =
|
let rendezvous =
|
||||||
if builder.rendezvous.isSome():
|
if builder.rendezvous.isSome():
|
||||||
builder.rendezvous.get()
|
builder.rendezvous.get()
|
||||||
else:
|
else:
|
||||||
warn "whether to mount rendezvous is not specified, defaulting to not mounting"
|
warn "whether to mount rendezvous is not specified, defaulting to not mounting"
|
||||||
false
|
DefaultRendezvous
|
||||||
|
|
||||||
let mix =
|
let mix =
|
||||||
if builder.mix.isSome():
|
if builder.mix.isSome():
|
||||||
builder.mix.get()
|
builder.mix.get()
|
||||||
else:
|
else:
|
||||||
warn "whether to mount mix is not specified, defaulting to not mounting"
|
warn "whether to mount mix is not specified, defaulting to not mounting"
|
||||||
false
|
DefaultMix
|
||||||
|
|
||||||
let relayPeerExchange = builder.relayPeerExchange.get(false)
|
let relayPeerExchange = builder.relayPeerExchange.get(DefaultRelayPeerExchange)
|
||||||
|
|
||||||
let nodeKey = ?nodeKey(builder, rng)
|
let nodeKey = ?nodeKey(builder, rng)
|
||||||
|
|
||||||
@ -495,7 +533,7 @@ proc build*(
|
|||||||
# TODO: ClusterId should never be defaulted, instead, presets
|
# TODO: ClusterId should never be defaulted, instead, presets
|
||||||
# should be defined and used
|
# should be defined and used
|
||||||
warn("Cluster Id was not specified, defaulting to 0")
|
warn("Cluster Id was not specified, defaulting to 0")
|
||||||
0.uint16
|
DefaultClusterId
|
||||||
else:
|
else:
|
||||||
builder.clusterId.get().uint16
|
builder.clusterId.get().uint16
|
||||||
|
|
||||||
@ -514,8 +552,9 @@ proc build*(
|
|||||||
of mmskStr:
|
of mmskStr:
|
||||||
?parseMsgSize(builder.maxMessageSize.str)
|
?parseMsgSize(builder.maxMessageSize.str)
|
||||||
else:
|
else:
|
||||||
warn "Max Message Size not specified, defaulting to 150KiB"
|
warn "Max Message Size not specified, defaulting to DefaultMaxWakuMessageSize",
|
||||||
parseCorrectMsgSize("150KiB")
|
default = DefaultMaxWakuMessageSizeStr
|
||||||
|
DefaultMaxWakuMessageSize
|
||||||
|
|
||||||
let contentTopics = builder.contentTopics.get(@[])
|
let contentTopics = builder.contentTopics.get(@[])
|
||||||
|
|
||||||
@ -560,37 +599,37 @@ proc build*(
|
|||||||
builder.logLevel.get()
|
builder.logLevel.get()
|
||||||
else:
|
else:
|
||||||
warn "Log Level not specified, defaulting to INFO"
|
warn "Log Level not specified, defaulting to INFO"
|
||||||
logging.LogLevel.INFO
|
DefaultLogLevel
|
||||||
|
|
||||||
let logFormat =
|
let logFormat =
|
||||||
if builder.logFormat.isSome():
|
if builder.logFormat.isSome():
|
||||||
builder.logFormat.get()
|
builder.logFormat.get()
|
||||||
else:
|
else:
|
||||||
warn "Log Format not specified, defaulting to TEXT"
|
warn "Log Format not specified, defaulting to TEXT"
|
||||||
logging.LogFormat.TEXT
|
DefaultLogFormat
|
||||||
|
|
||||||
let natStrategy =
|
let natStrategy =
|
||||||
if builder.natStrategy.isSome():
|
if builder.natStrategy.isSome():
|
||||||
builder.natStrategy.get()
|
builder.natStrategy.get()
|
||||||
else:
|
else:
|
||||||
warn "Nat Strategy is not specified, defaulting to none"
|
warn "Nat Strategy is not specified, defaulting to none"
|
||||||
"none"
|
DefaultNatStrategy
|
||||||
|
|
||||||
let p2pTcpPort = builder.p2pTcpPort.get(Port(0))
|
let p2pTcpPort = builder.p2pTcpPort.get(DefaultP2pTcpPort)
|
||||||
|
|
||||||
let p2pListenAddress =
|
let p2pListenAddress =
|
||||||
if builder.p2pListenAddress.isSome():
|
if builder.p2pListenAddress.isSome():
|
||||||
builder.p2pListenAddress.get()
|
builder.p2pListenAddress.get()
|
||||||
else:
|
else:
|
||||||
warn "P2P listening address not specified, listening on 0.0.0.0"
|
warn "P2P listening address not specified, listening on 0.0.0.0"
|
||||||
(static parseIpAddress("0.0.0.0"))
|
DefaultP2pListenAddress
|
||||||
|
|
||||||
let portsShift =
|
let portsShift =
|
||||||
if builder.portsShift.isSome():
|
if builder.portsShift.isSome():
|
||||||
builder.portsShift.get()
|
builder.portsShift.get()
|
||||||
else:
|
else:
|
||||||
warn "Ports Shift is not specified, defaulting to 0"
|
warn "Ports Shift is not specified, defaulting to 0"
|
||||||
0.uint16
|
DefaultPortsShift
|
||||||
|
|
||||||
let dns4DomainName =
|
let dns4DomainName =
|
||||||
if builder.dns4DomainName.isSome():
|
if builder.dns4DomainName.isSome():
|
||||||
@ -613,21 +652,21 @@ proc build*(
|
|||||||
builder.extMultiAddrsOnly.get()
|
builder.extMultiAddrsOnly.get()
|
||||||
else:
|
else:
|
||||||
warn "Whether to only announce external multiaddresses is not specified, defaulting to false"
|
warn "Whether to only announce external multiaddresses is not specified, defaulting to false"
|
||||||
false
|
DefaultExtMultiAddrsOnly
|
||||||
|
|
||||||
let dnsAddrsNameServers =
|
let dnsAddrsNameServers =
|
||||||
if builder.dnsAddrsNameServers.len != 0:
|
if builder.dnsAddrsNameServers.len != 0:
|
||||||
builder.dnsAddrsNameServers
|
builder.dnsAddrsNameServers
|
||||||
else:
|
else:
|
||||||
warn "DNS name servers IPs not provided, defaulting to Cloudflare's."
|
warn "DNS name servers IPs not provided, defaulting to Cloudflare's."
|
||||||
@[static parseIpAddress("1.1.1.1"), static parseIpAddress("1.0.0.1")]
|
DefaultDnsAddrsNameServers
|
||||||
|
|
||||||
let peerPersistence =
|
let peerPersistence =
|
||||||
if builder.peerPersistence.isSome():
|
if builder.peerPersistence.isSome():
|
||||||
builder.peerPersistence.get()
|
builder.peerPersistence.get()
|
||||||
else:
|
else:
|
||||||
warn "Peer persistence not specified, defaulting to false"
|
warn "Peer persistence not specified, defaulting to false"
|
||||||
false
|
DefaultPeerPersistence
|
||||||
|
|
||||||
let maxConnections =
|
let maxConnections =
|
||||||
if builder.maxConnections.isSome():
|
if builder.maxConnections.isSome():
|
||||||
@ -641,15 +680,13 @@ proc build*(
|
|||||||
warn "max-connections less than DefaultMaxConnections; we suggest using DefaultMaxConnections or more for better connectivity",
|
warn "max-connections less than DefaultMaxConnections; we suggest using DefaultMaxConnections or more for better connectivity",
|
||||||
provided = maxConnections, recommended = DefaultMaxConnections
|
provided = maxConnections, recommended = DefaultMaxConnections
|
||||||
|
|
||||||
# TODO: Do the git version thing here
|
let agentString = builder.agentString.get(DefaultAgentString)
|
||||||
let agentString = builder.agentString.get("logos-delivery")
|
|
||||||
|
|
||||||
# TODO: use `DefaultColocationLimit`. the user of this value should
|
let colocationLimit = builder.colocationLimit.get(DefaultColocationLimit)
|
||||||
# probably be defining a config object
|
|
||||||
let colocationLimit = builder.colocationLimit.get(5)
|
|
||||||
|
|
||||||
# TODO: is there a strategy for experimental features? delete vs promote
|
# TODO: is there a strategy for experimental features? delete vs promote
|
||||||
let relayShardedPeerManagement = builder.relayShardedPeerManagement.get(false)
|
let relayShardedPeerManagement =
|
||||||
|
builder.relayShardedPeerManagement.get(DefaultRelayShardedPeerManagement)
|
||||||
|
|
||||||
let wakuFlags = CapabilitiesBitfield.init(
|
let wakuFlags = CapabilitiesBitfield.init(
|
||||||
lightpush = lightPush and relay,
|
lightpush = lightPush and relay,
|
||||||
@ -710,12 +747,12 @@ proc build*(
|
|||||||
agentString: agentString,
|
agentString: agentString,
|
||||||
colocationLimit: colocationLimit,
|
colocationLimit: colocationLimit,
|
||||||
maxRelayPeers: builder.maxRelayPeers,
|
maxRelayPeers: builder.maxRelayPeers,
|
||||||
relayServiceRatio: builder.relayServiceRatio.get("50:50"),
|
relayServiceRatio: builder.relayServiceRatio.get(DefaultRelayServiceRatio),
|
||||||
rateLimit: rateLimit,
|
rateLimit: rateLimit,
|
||||||
circuitRelayClient: builder.circuitRelayClient.get(false),
|
circuitRelayClient: builder.circuitRelayClient.get(DefaultCircuitRelayClient),
|
||||||
staticNodes: builder.staticNodes,
|
staticNodes: builder.staticNodes,
|
||||||
relayShardedPeerManagement: relayShardedPeerManagement,
|
relayShardedPeerManagement: relayShardedPeerManagement,
|
||||||
p2pReliability: builder.p2pReliability.get(false),
|
p2pReliability: builder.p2pReliability.get(DefaultP2pReliability),
|
||||||
wakuFlags: wakuFlags,
|
wakuFlags: wakuFlags,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,11 @@ import waku/factory/waku_conf
|
|||||||
logScope:
|
logScope:
|
||||||
topics = "waku conf builder websocket"
|
topics = "waku conf builder websocket"
|
||||||
|
|
||||||
|
const
|
||||||
|
DefaultWebSocketEnabled*: bool = false
|
||||||
|
DefaultWebSocketSecureEnabled*: bool = false
|
||||||
|
DefaultWebSocketPort*: Port = Port(0)
|
||||||
|
|
||||||
##############################
|
##############################
|
||||||
## WebSocket Config Builder ##
|
## WebSocket Config Builder ##
|
||||||
##############################
|
##############################
|
||||||
@ -38,14 +43,15 @@ proc withCertPath*(b: var WebSocketConfBuilder, certPath: string) =
|
|||||||
b.certPath = some(certPath)
|
b.certPath = some(certPath)
|
||||||
|
|
||||||
proc build*(b: WebSocketConfBuilder): Result[Option[WebSocketConf], string] =
|
proc build*(b: WebSocketConfBuilder): Result[Option[WebSocketConf], string] =
|
||||||
if not b.enabled.get(false):
|
if not b.enabled.get(DefaultWebSocketEnabled):
|
||||||
return ok(none(WebSocketConf))
|
return ok(none(WebSocketConf))
|
||||||
|
|
||||||
if not b.secureEnabled.get(false):
|
if not b.secureEnabled.get(DefaultWebSocketSecureEnabled):
|
||||||
return ok(
|
return ok(
|
||||||
some(
|
some(
|
||||||
WebSocketConf(
|
WebSocketConf(
|
||||||
port: b.webSocketPort.get(Port(0)), secureConf: none(WebSocketSecureConf)
|
port: b.webSocketPort.get(DefaultWebSocketPort),
|
||||||
|
secureConf: none(WebSocketSecureConf),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -58,7 +64,7 @@ proc build*(b: WebSocketConfBuilder): Result[Option[WebSocketConf], string] =
|
|||||||
return ok(
|
return ok(
|
||||||
some(
|
some(
|
||||||
WebSocketConf(
|
WebSocketConf(
|
||||||
port: b.webSocketPort.get(Port(0)),
|
port: b.webSocketPort.get(DefaultWebSocketPort),
|
||||||
secureConf: some(
|
secureConf: some(
|
||||||
WebSocketSecureConf(keyPath: b.keyPath.get(), certPath: b.certPath.get())
|
WebSocketSecureConf(keyPath: b.keyPath.get(), certPath: b.certPath.get())
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import chronicles, results, stint
|
import chronicles, results, stint
|
||||||
|
import waku/waku_core/message/default_values
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "waku networks conf"
|
topics = "waku networks conf"
|
||||||
@ -17,7 +18,7 @@ type
|
|||||||
of StaticSharding:
|
of StaticSharding:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
type NetworkConf* = object
|
type NetworkConf* = object ## A network "preset" (--preset=twn, --preset=logos.dev).
|
||||||
maxMessageSize*: string # TODO: static convert to a uint64
|
maxMessageSize*: string # TODO: static convert to a uint64
|
||||||
clusterId*: uint16
|
clusterId*: uint16
|
||||||
rlnRelay*: bool
|
rlnRelay*: bool
|
||||||
@ -41,7 +42,7 @@ type NetworkConf* = object
|
|||||||
proc TheWakuNetworkConf*(T: type NetworkConf): NetworkConf =
|
proc TheWakuNetworkConf*(T: type NetworkConf): NetworkConf =
|
||||||
const RelayChainId = 59141'u256
|
const RelayChainId = 59141'u256
|
||||||
return NetworkConf(
|
return NetworkConf(
|
||||||
maxMessageSize: "150KiB",
|
maxMessageSize: DefaultMaxWakuMessageSizeStr,
|
||||||
clusterId: 1,
|
clusterId: 1,
|
||||||
rlnRelay: true,
|
rlnRelay: true,
|
||||||
rlnRelayEthContractAddress: "0xB9cd878C90E49F797B4431fBF4fb333108CB90e6",
|
rlnRelayEthContractAddress: "0xB9cd878C90E49F797B4431fBF4fb333108CB90e6",
|
||||||
@ -68,7 +69,7 @@ proc TheWakuNetworkConf*(T: type NetworkConf): NetworkConf =
|
|||||||
proc LogosDevConf*(T: type NetworkConf): NetworkConf =
|
proc LogosDevConf*(T: type NetworkConf): NetworkConf =
|
||||||
const ZeroChainId = 0'u256
|
const ZeroChainId = 0'u256
|
||||||
return NetworkConf(
|
return NetworkConf(
|
||||||
maxMessageSize: "150KiB",
|
maxMessageSize: DefaultMaxWakuMessageSizeStr,
|
||||||
clusterId: 2,
|
clusterId: 2,
|
||||||
rlnRelay: false,
|
rlnRelay: false,
|
||||||
rlnRelayEthContractAddress: "",
|
rlnRelayEthContractAddress: "",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user