feat!: introduce `preset` option instead of deducing from cluster-id

This commit is contained in:
fryorcraken 2024-06-28 21:36:00 +10:00 committed by fryorcraken
parent c5887bd23c
commit 6c83ffb21a
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
6 changed files with 213 additions and 66 deletions

View File

@ -30,7 +30,7 @@ import
const os* {.strdefine.} = "" const os* {.strdefine.} = ""
when os == "Linux" and when os == "Linux" and
# GitHub only supports container actions on Linux # GitHub only supports container actions on Linux
# and we need to start a postgress database in a docker container # and we need to start a postgres database in a docker container
defined(postgres): defined(postgres):
import import
./waku_archive/test_driver_postgres_query, ./waku_archive/test_driver_postgres_query,
@ -102,3 +102,4 @@ import
import ./waku_rln_relay/test_all import ./waku_rln_relay/test_all
# Node Factory # Node Factory
import ./factory/test_config

View File

@ -0,0 +1,114 @@
{.used.}
import
std/options,
testutils/unittests,
chronos,
libp2p/crypto/[crypto, secp],
libp2p/multiaddress,
nimcrypto/utils,
secp256k1
import
../../waku/factory/external_config,
../../waku/factory/internal_config,
../../waku/factory/networks_config
suite "Waku config - apply preset":
test "Default preset is TWN":
## Setup
let twnConf = ClusterConf.TheWakuNetworkConf()
## Given
let preConfig = WakuNodeConf(cmd: noCommand, preset: "default")
## When
let res = applyPresetConfiguration(preConfig)
assert res.isOk(), $res.error
## Then
let conf = res.get()
assert conf.maxMessageSize == twnConf.maxMessageSize
assert conf.clusterId == twnConf.clusterId
assert conf.rlnRelay == twnConf.rlnRelay
assert conf.rlnRelayEthContractAddress == twnConf.rlnRelayEthContractAddress
assert conf.rlnRelayChainId == twnConf.rlnRelayChainId
assert conf.rlnRelayDynamic == twnConf.rlnRelayDynamic
assert conf.rlnRelayBandwidthThreshold == twnConf.rlnRelayBandwidthThreshold
assert conf.rlnEpochSizeSec == twnConf.rlnEpochSizeSec
assert conf.rlnRelayUserMessageLimit == twnConf.rlnRelayUserMessageLimit
assert conf.pubsubTopics == twnConf.pubsubTopics
assert conf.discv5Discovery == twnConf.discv5Discovery
assert conf.discv5BootstrapNodes == twnConf.discv5BootstrapNodes
test "Subscribes to all valid shards in default network":
## Setup
let twnConf = ClusterConf.TheWakuNetworkConf()
## Given
let shards: seq[uint16] = @[0, 1, 2, 3, 4, 5, 6, 7]
let preConfig = WakuNodeConf(cmd: noCommand, preset: "default", shards: shards)
## When
let res = applyPresetConfiguration(preConfig)
assert res.isOk(), $res.error
## Then
let conf = res.get()
assert conf.pubsubTopics == twnConf.pubsubTopics
test "Subscribes to some valid shards in default network":
## Setup
let twnConf = ClusterConf.TheWakuNetworkConf()
## Given
let shards: seq[uint16] = @[0, 4, 7]
let preConfig = WakuNodeConf(cmd: noCommand, preset: "default", shards: shards)
## When
let res = applyPresetConfiguration(preConfig)
assert res.isOk(), $res.error
## Then
let conf = res.get()
assert conf.pubsubTopics.len() == shards.len()
assert twnConf.pubsubTopics[0] in conf.pubsubTopics
assert twnConf.pubsubTopics[4] in conf.pubsubTopics
assert twnConf.pubsubTopics[7] in conf.pubsubTopics
test "Subscribes to invalid shards in default network":
## Setup
## Given
let shards: seq[uint16] = @[0, 4, 7, 10]
let preConfig = WakuNodeConf(cmd: noCommand, preset: "default", shards: shards)
## When
let res = applyPresetConfiguration(preConfig)
## Then
assert res.isErr(), "Invalid shard was accepted"
suite "Waku config - node key":
test "Passed node key is used":
## Setup
let nodekey = block:
let key = SkPrivateKey
.init(
utils.fromHex(
"0011223344556677889900aabbccddeeff0011223344556677889900aabbccddeeff"
)
)
.tryGet()
crypto.PrivateKey(scheme: Secp256k1, skkey: key)
## Given
let preConfig = WakuNodeConf(cmd: noCommand, nodekey: some(nodekey))
## When
let res = nodeKeyConfiguration(preConfig)
assert res.isOk(), $res.error
## Then
let resKey = res.get()
assert utils.toHex(resKey.getRawBytes().get()) ==
utils.toHex(nodekey.getRawBytes().get())

View File

@ -72,7 +72,7 @@ type WakuNodeConf* = object
.}: EthRpcUrl .}: EthRpcUrl
rlnRelayEthContractAddress* {. rlnRelayEthContractAddress* {.
desc: "Address of membership contract on an Ethereum testnet", desc: "Address of membership contract on an Ethereum testnet. Part of presets.",
defaultValue: "", defaultValue: "",
name: "rln-relay-eth-contract-address" name: "rln-relay-eth-contract-address"
.}: string .}: string
@ -98,14 +98,14 @@ type WakuNodeConf* = object
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 1. Part of presets.",
defaultValue: 1, defaultValue: 1,
name: "rln-relay-user-message-limit" name: "rln-relay-user-message-limit"
.}: uint64 .}: uint64
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 1 second. Part of presets.",
defaultValue: 1, defaultValue: 1,
name: "rln-relay-epoch-sec" name: "rln-relay-epoch-sec"
.}: uint64 .}: uint64
@ -134,9 +134,15 @@ type WakuNodeConf* = object
.}: seq[ProtectedTopic] .}: seq[ProtectedTopic]
## General node config ## General node config
preset* {.
desc: "Network preset to use." & "Must be one of 'default', ''",
defaultValue: "",
name: "preset"
.}: string
clusterId* {. clusterId* {.
desc: desc:
"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. Part of presets.",
defaultValue: 0, defaultValue: 0,
name: "cluster-id" name: "cluster-id"
.}: uint16 .}: uint16
@ -146,7 +152,7 @@ type WakuNodeConf* = object
maxMessageSize* {. maxMessageSize* {.
desc: desc:
"Maximum message size. Accepted units: KiB, KB, and B. e.g. 1024KiB; 1500 B; etc.", "Maximum message size. Accepted units: KiB, KB, and B. e.g. 1024KiB; 1500 B; etc. Part of presets.",
defaultValue: DefaultMaxWakuMessageSizeStr, defaultValue: DefaultMaxWakuMessageSizeStr,
name: "max-msg-size" name: "max-msg-size"
.}: string .}: string
@ -261,7 +267,9 @@ type WakuNodeConf* = object
.}: seq[string] .}: seq[string]
shards* {. shards* {.
desc: "Shards index to subscribe to [0.." & $MaxShardIndex & "]. Argument may be repeated.", desc:
"Shards index to subscribe to [0.." & $MaxShardIndex &
"]. Argument may be repeated.",
defaultValue: defaultValue:
@[ @[
uint16(0), uint16(0),
@ -283,7 +291,7 @@ type WakuNodeConf* = object
## RLN Relay config ## RLN Relay config
rlnRelay* {. rlnRelay* {.
desc: "Enable spam protection through rln-relay: true|false", desc: "Enable spam protection through rln-relay: true|false. Part of presets.",
defaultValue: false, defaultValue: false,
name: "rln-relay" name: "rln-relay"
.}: bool .}: bool
@ -294,7 +302,8 @@ type WakuNodeConf* = object
.}: Option[uint] .}: Option[uint]
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. Part of presets.",
defaultValue: false, defaultValue: false,
name: "rln-relay-dynamic" name: "rln-relay-dynamic"
.}: bool .}: bool
@ -318,7 +327,8 @@ type WakuNodeConf* = object
.}: string .}: string
rlnRelayBandwidthThreshold* {. rlnRelayBandwidthThreshold* {.
desc: "Message rate in bytes/sec after which verification of proofs should happen", desc:
"Message rate in bytes/sec after which verification of proofs should happen. Part of presets.",
defaultValue: 0, # to maintain backwards compatibility defaultValue: 0, # to maintain backwards compatibility
name: "rln-relay-bandwidth-threshold" name: "rln-relay-bandwidth-threshold"
.}: int .}: int
@ -546,7 +556,7 @@ type WakuNodeConf* = object
## Discovery v5 config ## Discovery v5 config
discv5Discovery* {. discv5Discovery* {.
desc: "Enable discovering nodes via Node Discovery v5", desc: "Enable discovering nodes via Node Discovery v5. Part of presets.",
defaultValue: false, defaultValue: false,
name: "discv5-discovery" name: "discv5-discovery"
.}: bool .}: bool
@ -559,7 +569,7 @@ type WakuNodeConf* = object
discv5BootstrapNodes* {. discv5BootstrapNodes* {.
desc: desc:
"Text-encoded ENR for bootstrap node. Used when connecting to the network. Argument may be repeated.", "Text-encoded ENR for bootstrap node. Used when connecting to the network. Argument may be repeated. Part of presets.",
name: "discv5-bootstrap-node" name: "discv5-bootstrap-node"
.}: seq[string] .}: seq[string]

View File

@ -12,7 +12,8 @@ import
../node/config, ../node/config,
../waku_enr/capabilities, ../waku_enr/capabilities,
../waku_enr, ../waku_enr,
../waku_core ../waku_core,
./networks_config
proc enrConfiguration*( proc enrConfiguration*(
conf: WakuNodeConf, netConfig: NetConfig, key: crypto.PrivateKey conf: WakuNodeConf, netConfig: NetConfig, key: crypto.PrivateKey
@ -178,3 +179,60 @@ proc networkConfiguration*(conf: WakuNodeConf, clientId: string): NetConfigResul
) )
return netConfigRes return netConfigRes
proc applyPresetConfiguration*(srcConf: WakuNodeConf): Result[WakuNodeConf, string] =
var resConf = srcConf
if resConf.clusterId == 1:
warn(
"TWN configuration will not be applied when `--cluster-id=1` is passed in future releases. Use `--preset=default` instead."
)
resConf.preset = "default"
case resConf.preset
of "default":
let twnClusterConf = ClusterConf.TheWakuNetworkConf()
for shard in resConf.shards:
if not (shard.int < twnClusterConf.pubsubTopics.len):
return err(
"Invalid shard received: " & $shard & " is not part of the available shards: " &
$toSeq(0 .. twnClusterConf.pubsubTopics.len - 1)
)
else:
resConf.pubsubTopics.add(twnClusterConf.pubsubTopics[shard.uint16])
# Override configuration
resConf.maxMessageSize = twnClusterConf.maxMessageSize
resConf.clusterId = twnClusterConf.clusterId
resConf.rlnRelay = twnClusterConf.rlnRelay
resConf.rlnRelayEthContractAddress = twnClusterConf.rlnRelayEthContractAddress
resConf.rlnRelayChainId = twnClusterConf.rlnRelayChainId
resConf.rlnRelayDynamic = twnClusterConf.rlnRelayDynamic
resConf.rlnRelayBandwidthThreshold = twnClusterConf.rlnRelayBandwidthThreshold
resConf.rlnEpochSizeSec = twnClusterConf.rlnEpochSizeSec
resConf.rlnRelayUserMessageLimit = twnClusterConf.rlnRelayUserMessageLimit
resConf.discv5Discovery = twnClusterConf.discv5Discovery
resConf.discv5BootstrapNodes =
resConf.discv5BootstrapNodes & twnClusterConf.discv5BootstrapNodes
else:
discard
return ok(resConf)
proc nodeKeyConfiguration*(
conf: WakuNodeConf, rng: Option[ref HmacDrbgContext] = none(ref HmacDrbgContext)
): Result[PrivateKey, string] =
if conf.nodeKey.isSome:
return ok(conf.nodeKey.get())
var nodeRng =
if rng.isSome():
rng.get()
else:
crypto.newRng()
let key = crypto.PrivateKey.random(Secp256k1, nodeRng[]).valueOr:
error "Failed to generate key", error = $error
return err("Failed to generate key: " & $error)
return ok(key)

View File

@ -399,15 +399,9 @@ proc setupNode*(
else: else:
crypto.newRng() crypto.newRng()
# Use provided key only if corresponding rng is also provided let key = nodeKeyConfiguration(conf).valueOr:
let key = error "Failed to generate key", error = error
if conf.nodeKey.isSome() and rng.isSome(): return err("Failed to generate key: " & error)
conf.nodeKey.get()
else:
warn "missing key or rng, generating new set"
crypto.PrivateKey.random(Secp256k1, nodeRng[]).valueOr:
error "Failed to generate key", error = error
return err("Failed to generate key: " & $error)
let netConfig = networkConfiguration(conf, clientId).valueOr: let netConfig = networkConfiguration(conf, clientId).valueOr:
error "failed to create internal config", error = error error "failed to create internal config", error = error

View File

@ -85,55 +85,25 @@ func version*(waku: Waku): string =
## Initialisation ## Initialisation
proc init*(T: type Waku, conf: WakuNodeConf): Result[Waku, string] = proc init*(T: type Waku, srcConf: WakuNodeConf): Result[Waku, string] =
var confCopy = conf
let rng = crypto.newRng() let rng = crypto.newRng()
logging.setupLog(conf.logLevel, conf.logFormat) logConfig(srcConf)
logging.setupLog(srcConf.logLevel, srcConf.logFormat)
case confCopy.clusterId # Why can't I replace this block with a concise `.valueOr`?
let finalConf = block:
# cluster-id=1 (aka The Waku Network) let res = applyPresetConfiguration(srcConf)
of 1: if res.isErr():
let twnClusterConf = ClusterConf.TheWakuNetworkConf() error "Failed to complete the config", error = res.error
if len(confCopy.shards) != 0: return err("Failed to complete the config:" & $res.error)
confCopy.pubsubTopics = res.get()
confCopy.shards.mapIt(twnClusterConf.pubsubTopics[it.uint16])
else:
confCopy.pubsubTopics = twnClusterConf.pubsubTopics
# Override configuration
confCopy.maxMessageSize = twnClusterConf.maxMessageSize
confCopy.clusterId = twnClusterConf.clusterId
confCopy.rlnRelayEthContractAddress = twnClusterConf.rlnRelayEthContractAddress
confCopy.rlnRelayChainId = twnClusterConf.rlnRelayChainId
confCopy.rlnRelayDynamic = twnClusterConf.rlnRelayDynamic
confCopy.rlnRelayBandwidthThreshold = twnClusterConf.rlnRelayBandwidthThreshold
confCopy.discv5Discovery = twnClusterConf.discv5Discovery
confCopy.discv5BootstrapNodes =
confCopy.discv5BootstrapNodes & twnClusterConf.discv5BootstrapNodes
confCopy.rlnEpochSizeSec = twnClusterConf.rlnEpochSizeSec
confCopy.rlnRelayUserMessageLimit = twnClusterConf.rlnRelayUserMessageLimit
# Only set rlnRelay to true if relay is configured
if confCopy.relay:
confCopy.rlnRelay = twnClusterConf.rlnRelay
else:
discard
info "Running nwaku node", version = git_version info "Running nwaku node", version = git_version
logConfig(confCopy)
if not confCopy.nodekey.isSome():
let keyRes = crypto.PrivateKey.random(Secp256k1, rng[])
if keyRes.isErr():
error "Failed to generate key", error = $keyRes.error
return err("Failed to generate key: " & $keyRes.error)
confCopy.nodekey = some(keyRes.get())
debug "Retrieve dynamic bootstrap nodes" debug "Retrieve dynamic bootstrap nodes"
let dynamicBootstrapNodesRes = waku_dnsdisc.retrieveDynamicBootstrapNodes( let dynamicBootstrapNodesRes = waku_dnsdisc.retrieveDynamicBootstrapNodes(
confCopy.dnsDiscovery, confCopy.dnsDiscoveryUrl, confCopy.dnsDiscoveryNameServers finalConf.dnsDiscovery, finalConf.dnsDiscoveryUrl, finalConf.dnsDiscoveryNameServers
) )
if dynamicBootstrapNodesRes.isErr(): if dynamicBootstrapNodesRes.isErr():
error "Retrieving dynamic bootstrap nodes failed", error "Retrieving dynamic bootstrap nodes failed",
@ -142,16 +112,16 @@ proc init*(T: type Waku, conf: WakuNodeConf): Result[Waku, string] =
"Retrieving dynamic bootstrap nodes failed: " & dynamicBootstrapNodesRes.error "Retrieving dynamic bootstrap nodes failed: " & dynamicBootstrapNodesRes.error
) )
let nodeRes = setupNode(confCopy, some(rng)) let nodeRes = setupNode(finalConf, some(rng))
if nodeRes.isErr(): if nodeRes.isErr():
error "Failed setting up node", error = nodeRes.error error "Failed setting up node", error = nodeRes.error
return err("Failed setting up node: " & nodeRes.error) return err("Failed setting up node: " & nodeRes.error)
var waku = Waku( var waku = Waku(
version: git_version, version: git_version,
conf: confCopy, conf: finalConf,
rng: rng, rng: rng,
key: confCopy.nodekey.get(), key: finalConf.nodekey.get(),
node: nodeRes.get(), node: nodeRes.get(),
dynamicBootstrapNodes: dynamicBootstrapNodesRes.get(), dynamicBootstrapNodes: dynamicBootstrapNodesRes.get(),
) )