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.} = ""
when os == "Linux" and
# 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):
import
./waku_archive/test_driver_postgres_query,
@ -102,3 +102,4 @@ import
import ./waku_rln_relay/test_all
# 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
rlnRelayEthContractAddress* {.
desc: "Address of membership contract on an Ethereum testnet",
desc: "Address of membership contract on an Ethereum testnet. Part of presets.",
defaultValue: "",
name: "rln-relay-eth-contract-address"
.}: string
@ -98,14 +98,14 @@ type WakuNodeConf* = object
rlnRelayUserMessageLimit* {.
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,
name: "rln-relay-user-message-limit"
.}: uint64
rlnEpochSizeSec* {.
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,
name: "rln-relay-epoch-sec"
.}: uint64
@ -134,9 +134,15 @@ type WakuNodeConf* = object
.}: seq[ProtectedTopic]
## General node config
preset* {.
desc: "Network preset to use." & "Must be one of 'default', ''",
defaultValue: "",
name: "preset"
.}: string
clusterId* {.
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,
name: "cluster-id"
.}: uint16
@ -146,7 +152,7 @@ type WakuNodeConf* = object
maxMessageSize* {.
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,
name: "max-msg-size"
.}: string
@ -261,7 +267,9 @@ type WakuNodeConf* = object
.}: seq[string]
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:
@[
uint16(0),
@ -283,7 +291,7 @@ type WakuNodeConf* = object
## RLN Relay config
rlnRelay* {.
desc: "Enable spam protection through rln-relay: true|false",
desc: "Enable spam protection through rln-relay: true|false. Part of presets.",
defaultValue: false,
name: "rln-relay"
.}: bool
@ -294,7 +302,8 @@ type WakuNodeConf* = object
.}: Option[uint]
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,
name: "rln-relay-dynamic"
.}: bool
@ -318,7 +327,8 @@ type WakuNodeConf* = object
.}: string
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
name: "rln-relay-bandwidth-threshold"
.}: int
@ -546,7 +556,7 @@ type WakuNodeConf* = object
## Discovery v5 config
discv5Discovery* {.
desc: "Enable discovering nodes via Node Discovery v5",
desc: "Enable discovering nodes via Node Discovery v5. Part of presets.",
defaultValue: false,
name: "discv5-discovery"
.}: bool
@ -559,7 +569,7 @@ type WakuNodeConf* = object
discv5BootstrapNodes* {.
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"
.}: seq[string]

View File

@ -12,7 +12,8 @@ import
../node/config,
../waku_enr/capabilities,
../waku_enr,
../waku_core
../waku_core,
./networks_config
proc enrConfiguration*(
conf: WakuNodeConf, netConfig: NetConfig, key: crypto.PrivateKey
@ -178,3 +179,60 @@ proc networkConfiguration*(conf: WakuNodeConf, clientId: string): NetConfigResul
)
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:
crypto.newRng()
# Use provided key only if corresponding rng is also provided
let key =
if conf.nodeKey.isSome() and rng.isSome():
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 key = nodeKeyConfiguration(conf).valueOr:
error "Failed to generate key", error = error
return err("Failed to generate key: " & error)
let netConfig = networkConfiguration(conf, clientId).valueOr:
error "failed to create internal config", error = error

View File

@ -85,55 +85,25 @@ func version*(waku: Waku): string =
## Initialisation
proc init*(T: type Waku, conf: WakuNodeConf): Result[Waku, string] =
var confCopy = conf
proc init*(T: type Waku, srcConf: WakuNodeConf): Result[Waku, string] =
let rng = crypto.newRng()
logging.setupLog(conf.logLevel, conf.logFormat)
logConfig(srcConf)
logging.setupLog(srcConf.logLevel, srcConf.logFormat)
case confCopy.clusterId
# cluster-id=1 (aka The Waku Network)
of 1:
let twnClusterConf = ClusterConf.TheWakuNetworkConf()
if len(confCopy.shards) != 0:
confCopy.pubsubTopics =
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
# Why can't I replace this block with a concise `.valueOr`?
let finalConf = block:
let res = applyPresetConfiguration(srcConf)
if res.isErr():
error "Failed to complete the config", error = res.error
return err("Failed to complete the config:" & $res.error)
res.get()
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"
let dynamicBootstrapNodesRes = waku_dnsdisc.retrieveDynamicBootstrapNodes(
confCopy.dnsDiscovery, confCopy.dnsDiscoveryUrl, confCopy.dnsDiscoveryNameServers
finalConf.dnsDiscovery, finalConf.dnsDiscoveryUrl, finalConf.dnsDiscoveryNameServers
)
if dynamicBootstrapNodesRes.isErr():
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
)
let nodeRes = setupNode(confCopy, some(rng))
let nodeRes = setupNode(finalConf, some(rng))
if nodeRes.isErr():
error "Failed setting up node", error = nodeRes.error
return err("Failed setting up node: " & nodeRes.error)
var waku = Waku(
version: git_version,
conf: confCopy,
conf: finalConf,
rng: rng,
key: confCopy.nodekey.get(),
key: finalConf.nodekey.get(),
node: nodeRes.get(),
dynamicBootstrapNodes: dynamicBootstrapNodesRes.get(),
)