mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-01-02 14:03:06 +00:00
feat: Waku API create node (#3580)
* introduce createNode # Conflicts: # apps/wakunode2/cli_args.nim * remove confutils dependency on the library * test: remove websocket in default test config * update to latest specs * test: cli_args * align to spec changes (sovereign, message conf, entrypoints * accept enr, entree and multiaddr as entry points * post rebase * format * change from "sovereign" to "core" * add example * get example to continue running * nitpicks * idiomatic constructors * fix enum naming * replace procs with consts * remove messageConfirmation * use pure enum * rename example file
This commit is contained in:
parent
08d14fb082
commit
bc8acf7611
@ -14,8 +14,8 @@ import
|
|||||||
libp2p/wire
|
libp2p/wire
|
||||||
|
|
||||||
import
|
import
|
||||||
|
../../tools/confutils/cli_args,
|
||||||
waku/[
|
waku/[
|
||||||
factory/external_config,
|
|
||||||
node/peer_manager,
|
node/peer_manager,
|
||||||
waku_lightpush/common,
|
waku_lightpush/common,
|
||||||
waku_relay,
|
waku_relay,
|
||||||
|
|||||||
@ -11,11 +11,11 @@ import
|
|||||||
confutils
|
confutils
|
||||||
|
|
||||||
import
|
import
|
||||||
|
../../tools/confutils/cli_args,
|
||||||
waku/[
|
waku/[
|
||||||
common/enr,
|
common/enr,
|
||||||
common/logging,
|
common/logging,
|
||||||
factory/waku as waku_factory,
|
factory/waku as waku_factory,
|
||||||
factory/external_config,
|
|
||||||
waku_node,
|
waku_node,
|
||||||
node/waku_metrics,
|
node/waku_metrics,
|
||||||
node/peer_manager,
|
node/peer_manager,
|
||||||
|
|||||||
@ -11,8 +11,8 @@ import
|
|||||||
libp2p/wire
|
libp2p/wire
|
||||||
|
|
||||||
import
|
import
|
||||||
|
../wakunode2/cli_args,
|
||||||
waku/[
|
waku/[
|
||||||
factory/external_config,
|
|
||||||
common/enr,
|
common/enr,
|
||||||
waku_node,
|
waku_node,
|
||||||
node/peer_manager,
|
node/peer_manager,
|
||||||
|
|||||||
@ -12,14 +12,9 @@ import
|
|||||||
secp256k1
|
secp256k1
|
||||||
|
|
||||||
import
|
import
|
||||||
waku/[
|
../../tools/confutils/
|
||||||
common/confutils/envvar/defs as confEnvvarDefs,
|
[cli_args, envvar as confEnvvarDefs, envvar_net as confEnvvarNet],
|
||||||
common/confutils/envvar/std/net as confEnvvarNet,
|
waku/[common/logging, waku_core, waku_core/topics/pubsub_topic]
|
||||||
common/logging,
|
|
||||||
factory/external_config,
|
|
||||||
waku_core,
|
|
||||||
waku_core/topics/pubsub_topic,
|
|
||||||
]
|
|
||||||
|
|
||||||
export confTomlDefs, confTomlNet, confEnvvarDefs, confEnvvarNet
|
export confTomlDefs, confTomlNet, confEnvvarDefs, confEnvvarNet
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import results, options, chronos
|
import results, options, chronos
|
||||||
import waku/[waku_node, waku_core, waku_lightpush]
|
import waku/[waku_node, waku_core, waku_lightpush, waku_lightpush/common]
|
||||||
import publisher_base
|
import publisher_base
|
||||||
|
|
||||||
type V3Publisher* = ref object of PublisherBase
|
type V3Publisher* = ref object of PublisherBase
|
||||||
|
|||||||
@ -9,13 +9,13 @@ import
|
|||||||
system/ansi_c,
|
system/ansi_c,
|
||||||
libp2p/crypto/crypto
|
libp2p/crypto/crypto
|
||||||
import
|
import
|
||||||
../../tools/rln_keystore_generator/rln_keystore_generator,
|
../../tools/[rln_keystore_generator/rln_keystore_generator, confutils/cli_args],
|
||||||
waku/[
|
waku/[
|
||||||
common/logging,
|
common/logging,
|
||||||
factory/external_config,
|
|
||||||
factory/waku,
|
factory/waku,
|
||||||
node/health_monitor,
|
node/health_monitor,
|
||||||
waku_api/rest/builder as rest_server_builder,
|
waku_api/rest/builder as rest_server_builder,
|
||||||
|
waku_core/message/default_values,
|
||||||
]
|
]
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
|
|||||||
@ -7,9 +7,21 @@ Make all examples.
|
|||||||
make example2
|
make example2
|
||||||
```
|
```
|
||||||
|
|
||||||
## basic2
|
## Waku API
|
||||||
|
|
||||||
TODO
|
Uses the simplified Waku API to create and start a node,
|
||||||
|
you need an RPC endpoint for Linea Sepolia for RLN:
|
||||||
|
|
||||||
|
```console
|
||||||
|
./build/waku_api --ethRpcEndpoint=https://linea-sepolia.infura.io/v3/<your key>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you can't be bothered but still want to see some action,
|
||||||
|
just run the binary and it will use a non-RLN network:
|
||||||
|
|
||||||
|
```console
|
||||||
|
./build/waku_api
|
||||||
|
```
|
||||||
|
|
||||||
## publisher/subscriber
|
## publisher/subscriber
|
||||||
|
|
||||||
|
|||||||
38
examples/waku_example.nim
Normal file
38
examples/waku_example.nim
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import std/options
|
||||||
|
import chronos, results, confutils, confutils/defs
|
||||||
|
import waku
|
||||||
|
|
||||||
|
type CliArgs = object
|
||||||
|
ethRpcEndpoint* {.
|
||||||
|
defaultValue: "", desc: "ETH RPC Endpoint, if passed, RLN is enabled"
|
||||||
|
.}: string
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
let args = CliArgs.load()
|
||||||
|
|
||||||
|
echo "Starting Waku node..."
|
||||||
|
|
||||||
|
let config =
|
||||||
|
if (args.ethRpcEndpoint == ""):
|
||||||
|
# Create a basic configuration for the Waku node
|
||||||
|
# No RLN as we don't have an ETH RPC Endpoint
|
||||||
|
NodeConfig.init(wakuConfig = WakuConfig.init(entryNodes = @[], clusterId = 42))
|
||||||
|
else:
|
||||||
|
# Connect to TWN, use ETH RPC Endpoint for RLN
|
||||||
|
NodeConfig.init(ethRpcEndpoints = @[args.ethRpcEndpoint])
|
||||||
|
|
||||||
|
# Create the node using the library API's createNode function
|
||||||
|
let node = (waitFor createNode(config)).valueOr:
|
||||||
|
echo "Failed to create node: ", error
|
||||||
|
quit(QuitFailure)
|
||||||
|
|
||||||
|
echo("Waku node created successfully!")
|
||||||
|
|
||||||
|
# Start the node
|
||||||
|
(waitFor startWaku(addr node)).isOkOr:
|
||||||
|
echo "Failed to start node: ", error
|
||||||
|
quit(QuitFailure)
|
||||||
|
|
||||||
|
echo "Node started successfully!"
|
||||||
|
|
||||||
|
runForever()
|
||||||
@ -1,6 +1,7 @@
|
|||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import waku/[common/logging, factory/[waku, networks_config, external_config]]
|
import ../../apps/wakunode2/cli_args
|
||||||
|
import waku/[common/logging, factory/[waku, networks_config]]
|
||||||
import
|
import
|
||||||
std/[options, strutils, os, sequtils],
|
std/[options, strutils, os, sequtils],
|
||||||
chronicles,
|
chronicles,
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import chronos, chronicles, results, confutils, confutils/std/net
|
|||||||
|
|
||||||
import
|
import
|
||||||
../../../waku/node/peer_manager/peer_manager,
|
../../../waku/node/peer_manager/peer_manager,
|
||||||
../../../waku/factory/external_config,
|
../../../tools/confutils/cli_args,
|
||||||
../../../waku/factory/waku,
|
../../../waku/factory/waku,
|
||||||
../../../waku/factory/node_factory,
|
../../../waku/factory/node_factory,
|
||||||
../../../waku/factory/networks_config,
|
../../../waku/factory/networks_config,
|
||||||
|
|||||||
@ -2,7 +2,8 @@ import std/[net, sequtils, strutils]
|
|||||||
import chronicles, chronos, stew/byteutils, results
|
import chronicles, chronos, stew/byteutils, results
|
||||||
import
|
import
|
||||||
../../../../waku/waku_core/message/message,
|
../../../../waku/waku_core/message/message,
|
||||||
../../../../waku/factory/[external_config, validator_signed, waku],
|
../../../../waku/factory/[validator_signed, waku],
|
||||||
|
../../../../tools/confutils/cli_args,
|
||||||
../../../../waku/waku_node,
|
../../../../waku/waku_node,
|
||||||
../../../../waku/waku_core/message,
|
../../../../waku/waku_core/message,
|
||||||
../../../../waku/waku_core/time, # Timestamp
|
../../../../waku/waku_core/time, # Timestamp
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
## Waku v2
|
## Waku v2
|
||||||
|
|
||||||
|
import ./test_waku
|
||||||
|
|
||||||
# Waku core test suite
|
# Waku core test suite
|
||||||
import
|
import
|
||||||
./waku_core/test_namespaced_topics,
|
./waku_core/test_namespaced_topics,
|
||||||
@ -96,3 +98,9 @@ import ./waku_rln_relay/test_all
|
|||||||
|
|
||||||
# Node Factory
|
# Node Factory
|
||||||
import ./factory/test_all
|
import ./factory/test_all
|
||||||
|
|
||||||
|
# Waku API tests
|
||||||
|
import ./api/test_all
|
||||||
|
|
||||||
|
# Waku tools tests
|
||||||
|
import ./tools/test_all
|
||||||
|
|||||||
3
tests/api/test_all.nim
Normal file
3
tests/api/test_all.nim
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{.used.}
|
||||||
|
|
||||||
|
import ./test_entry_nodes, ./test_node_conf
|
||||||
264
tests/api/test_entry_nodes.nim
Normal file
264
tests/api/test_entry_nodes.nim
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
{.used.}
|
||||||
|
|
||||||
|
import std/options, results, testutils/unittests
|
||||||
|
|
||||||
|
import waku/api/entry_nodes
|
||||||
|
|
||||||
|
# Since classifyEntryNode is internal, we test it indirectly through processEntryNodes behavior
|
||||||
|
# The enum is exported so we can test against it
|
||||||
|
|
||||||
|
suite "Entry Nodes Classification":
|
||||||
|
test "Process ENRTree - standard format":
|
||||||
|
let result = processEntryNodes(
|
||||||
|
@[
|
||||||
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 1
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 0
|
||||||
|
|
||||||
|
test "Process ENRTree - case insensitive":
|
||||||
|
let result = processEntryNodes(
|
||||||
|
@[
|
||||||
|
"ENRTREE://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 1
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 0
|
||||||
|
|
||||||
|
test "Process ENR - standard format":
|
||||||
|
let result = processEntryNodes(
|
||||||
|
@[
|
||||||
|
"enr:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Vn7gmfkTTnAe8Ys2cgGBN8ufJnvzKQFZqFMBgmlkgnY0iXNlY3AyNTZrMaEDS8-D878DrdbNwcuY-3p1qdDp5MOoCurhdsNPJTXZ3c5g3RjcIJ2X4N1ZHCCd2g"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 0
|
||||||
|
bootstrapEnrs.len == 1
|
||||||
|
staticNodes.len == 0
|
||||||
|
|
||||||
|
test "Process ENR - case insensitive":
|
||||||
|
let result = processEntryNodes(
|
||||||
|
@[
|
||||||
|
"ENR:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Vn7gmfkTTnAe8Ys2cgGBN8ufJnvzKQFZqFMBgmlkgnY0iXNlY3AyNTZrMaEDS8-D878DrdbNwcuY-3p1qdDp5MOoCurhdsNPJTXZ3c5g3RjcIJ2X4N1ZHCCd2g"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 0
|
||||||
|
bootstrapEnrs.len == 1
|
||||||
|
staticNodes.len == 0
|
||||||
|
|
||||||
|
test "Process Multiaddress - IPv4":
|
||||||
|
let result = processEntryNodes(
|
||||||
|
@[
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 0
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 1
|
||||||
|
|
||||||
|
test "Process Multiaddress - IPv6":
|
||||||
|
let result = processEntryNodes(
|
||||||
|
@["/ip6/::1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"]
|
||||||
|
)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 0
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 1
|
||||||
|
|
||||||
|
test "Process Multiaddress - DNS":
|
||||||
|
let result = processEntryNodes(
|
||||||
|
@[
|
||||||
|
"/dns4/example.com/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 0
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 1
|
||||||
|
|
||||||
|
test "Process empty string":
|
||||||
|
let result = processEntryNodes(@[""])
|
||||||
|
check:
|
||||||
|
result.isErr()
|
||||||
|
result.error == "Entry node error: Empty entry node address"
|
||||||
|
|
||||||
|
test "Process invalid format - HTTP URL":
|
||||||
|
let result = processEntryNodes(@["http://example.com"])
|
||||||
|
check:
|
||||||
|
result.isErr()
|
||||||
|
result.error ==
|
||||||
|
"Entry node error: Unrecognized entry node format. Must start with 'enrtree:', 'enr:', or '/'"
|
||||||
|
|
||||||
|
test "Process invalid format - some string":
|
||||||
|
let result = processEntryNodes(@["some-string-here"])
|
||||||
|
check:
|
||||||
|
result.isErr()
|
||||||
|
result.error ==
|
||||||
|
"Entry node error: Unrecognized entry node format. Must start with 'enrtree:', 'enr:', or '/'"
|
||||||
|
|
||||||
|
suite "Entry Nodes Processing":
|
||||||
|
test "Process mixed entry nodes":
|
||||||
|
let entryNodes =
|
||||||
|
@[
|
||||||
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im",
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc",
|
||||||
|
"enr:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Vn7gmfkTTnAe8Ys2cgGBN8ufJnvzKQFZqFMBgmlkgnY0iXNlY3AyNTZrMaEDS8-D878DrdbNwcuY-3p1qdDp5MOoCurhdsNPJTXZ3c5g3RjcIJ2X4N1ZHCCd2g",
|
||||||
|
]
|
||||||
|
|
||||||
|
let result = processEntryNodes(entryNodes)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 1 # enrtree
|
||||||
|
bootstrapEnrs.len == 1 # enr
|
||||||
|
staticNodes.len >= 1 # at least the multiaddr
|
||||||
|
enrTreeUrls[0] == entryNodes[0] # enrtree unchanged
|
||||||
|
bootstrapEnrs[0] == entryNodes[2] # enr unchanged
|
||||||
|
staticNodes[0] == entryNodes[1] # multiaddr added to static
|
||||||
|
|
||||||
|
test "Process only ENRTree nodes":
|
||||||
|
let entryNodes =
|
||||||
|
@[
|
||||||
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im",
|
||||||
|
"enrtree://ANOTHER_TREE@example.com",
|
||||||
|
]
|
||||||
|
|
||||||
|
let result = processEntryNodes(entryNodes)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 2
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 0
|
||||||
|
enrTreeUrls == entryNodes
|
||||||
|
|
||||||
|
test "Process only multiaddresses":
|
||||||
|
let entryNodes =
|
||||||
|
@[
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc",
|
||||||
|
"/ip4/192.168.1.1/tcp/60001/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYd",
|
||||||
|
]
|
||||||
|
|
||||||
|
let result = processEntryNodes(entryNodes)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 0
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 2
|
||||||
|
staticNodes == entryNodes
|
||||||
|
|
||||||
|
test "Process only ENR nodes":
|
||||||
|
let entryNodes =
|
||||||
|
@[
|
||||||
|
"enr:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Vn7gmfkTTnAe8Ys2cgGBN8ufJnvzKQFZqFMBgmlkgnY0iXNlY3AyNTZrMaEDS8-D878DrdbNwcuY-3p1qdDp5MOoCurhdsNPJTXZ3c5g3RjcIJ2X4N1ZHCCd2g",
|
||||||
|
"enr:-QEkuECnZ3IbVAgkOzv-QLnKC4dRKAPRY80m1-R7G8jZ7yfT3ipEfBrhKN7ARcQgQ-vg-h40AQzyvAkPYlHPaFKk6u9MBgmlkgnY0iXNlY3AyNTZrMaEDk49D8JjMSns4p1XVNBvJquOUzT4PENSJknkROspfAFGg3RjcIJ2X4N1ZHCCd2g",
|
||||||
|
]
|
||||||
|
|
||||||
|
let result = processEntryNodes(entryNodes)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 0
|
||||||
|
bootstrapEnrs.len == 2
|
||||||
|
staticNodes.len == 0
|
||||||
|
bootstrapEnrs == entryNodes
|
||||||
|
# Note: staticNodes may or may not be populated depending on ENR parsing
|
||||||
|
|
||||||
|
test "Process empty list":
|
||||||
|
let entryNodes: seq[string] = @[]
|
||||||
|
|
||||||
|
let result = processEntryNodes(entryNodes)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 0
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 0
|
||||||
|
|
||||||
|
test "Process with invalid entry":
|
||||||
|
let entryNodes = @["enrtree://VALID@example.com", "invalid://notvalid"]
|
||||||
|
|
||||||
|
let result = processEntryNodes(entryNodes)
|
||||||
|
check:
|
||||||
|
result.isErr()
|
||||||
|
result.error ==
|
||||||
|
"Entry node error: Unrecognized entry node format. Must start with 'enrtree:', 'enr:', or '/'"
|
||||||
|
|
||||||
|
test "Process different multiaddr formats":
|
||||||
|
let entryNodes =
|
||||||
|
@[
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc",
|
||||||
|
"/ip6/::1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYd",
|
||||||
|
"/dns4/example.com/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYe",
|
||||||
|
"/dns/node.example.org/tcp/443/wss/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYf",
|
||||||
|
]
|
||||||
|
|
||||||
|
let result = processEntryNodes(entryNodes)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
enrTreeUrls.len == 0
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 4
|
||||||
|
staticNodes == entryNodes
|
||||||
|
|
||||||
|
test "Process with duplicate entries":
|
||||||
|
let entryNodes =
|
||||||
|
@[
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc",
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc",
|
||||||
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im",
|
||||||
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im",
|
||||||
|
]
|
||||||
|
|
||||||
|
let result = processEntryNodes(entryNodes)
|
||||||
|
check:
|
||||||
|
result.isOk()
|
||||||
|
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodes) = result.get()
|
||||||
|
check:
|
||||||
|
# Duplicates are not filtered out (by design - let downstream handle it)
|
||||||
|
enrTreeUrls.len == 2
|
||||||
|
bootstrapEnrs.len == 0
|
||||||
|
staticNodes.len == 2
|
||||||
277
tests/api/test_node_conf.nim
Normal file
277
tests/api/test_node_conf.nim
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
{.used.}
|
||||||
|
|
||||||
|
import std/options, results, stint, testutils/unittests
|
||||||
|
import waku/api/api_conf, waku/factory/waku_conf, waku/factory/networks_config
|
||||||
|
|
||||||
|
suite "LibWaku Conf - toWakuConf":
|
||||||
|
test "Minimal configuration":
|
||||||
|
## Given
|
||||||
|
let nodeConfig = NodeConfig.init(ethRpcEndpoints = @["http://someaddress"])
|
||||||
|
|
||||||
|
## When
|
||||||
|
let wakuConfRes = toWakuConf(nodeConfig)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
let wakuConf = wakuConfRes.valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
wakuConf.validate().isOkOr:
|
||||||
|
raiseAssert error
|
||||||
|
check:
|
||||||
|
wakuConf.clusterId == 1
|
||||||
|
wakuConf.shardingConf.numShardsInCluster == 8
|
||||||
|
wakuConf.staticNodes.len == 0
|
||||||
|
|
||||||
|
test "Core mode configuration":
|
||||||
|
## Given
|
||||||
|
let wakuConfig = WakuConfig.init(entryNodes = @[], clusterId = 1)
|
||||||
|
|
||||||
|
let nodeConfig = NodeConfig.init(mode = Core, wakuConfig = wakuConfig)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let wakuConfRes = toWakuConf(nodeConfig)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
require wakuConfRes.isOk()
|
||||||
|
let wakuConf = wakuConfRes.get()
|
||||||
|
require wakuConf.validate().isOk()
|
||||||
|
check:
|
||||||
|
wakuConf.relay == true
|
||||||
|
wakuConf.lightPush == true
|
||||||
|
wakuConf.peerExchangeService == true
|
||||||
|
wakuConf.clusterId == 1
|
||||||
|
|
||||||
|
test "Auto-sharding configuration":
|
||||||
|
## Given
|
||||||
|
let nodeConfig = NodeConfig.init(
|
||||||
|
mode = Core,
|
||||||
|
wakuConfig = WakuConfig.init(
|
||||||
|
entryNodes = @[],
|
||||||
|
staticStoreNodes = @[],
|
||||||
|
clusterId = 42,
|
||||||
|
autoShardingConfig = AutoShardingConfig(numShardsInCluster: 16),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let wakuConfRes = toWakuConf(nodeConfig)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
require wakuConfRes.isOk()
|
||||||
|
let wakuConf = wakuConfRes.get()
|
||||||
|
require wakuConf.validate().isOk()
|
||||||
|
check:
|
||||||
|
wakuConf.clusterId == 42
|
||||||
|
wakuConf.shardingConf.numShardsInCluster == 16
|
||||||
|
|
||||||
|
test "Bootstrap nodes configuration":
|
||||||
|
## Given
|
||||||
|
let entryNodes =
|
||||||
|
@[
|
||||||
|
"enr:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Vn7gmfkTTnAe8Ys2cgGBN8ufJnvzKQFZqFMBgmlkgnY0iXNlY3AyNTZrMaEDS8-D878DrdbNwcuY-3p1qdDp5MOoCurhdsNPJTXZ3c5g3RjcIJ2X4N1ZHCCd2g",
|
||||||
|
"enr:-QEkuECnZ3IbVAgkOzv-QLnKC4dRKAPRY80m1-R7G8jZ7yfT3ipEfBrhKN7ARcQgQ-vg-h40AQzyvAkPYlHPaFKk6u9MBgmlkgnY0iXNlY3AyNTZrMaEDk49D8JjMSns4p1XVNBvJquOUzT4PENSJknkROspfAFGg3RjcIJ2X4N1ZHCCd2g",
|
||||||
|
]
|
||||||
|
let libConf = NodeConfig.init(
|
||||||
|
mode = Core,
|
||||||
|
wakuConfig =
|
||||||
|
WakuConfig.init(entryNodes = entryNodes, staticStoreNodes = @[], clusterId = 1),
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let wakuConfRes = toWakuConf(libConf)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
require wakuConfRes.isOk()
|
||||||
|
let wakuConf = wakuConfRes.get()
|
||||||
|
require wakuConf.validate().isOk()
|
||||||
|
require wakuConf.discv5Conf.isSome()
|
||||||
|
check:
|
||||||
|
wakuConf.discv5Conf.get().bootstrapNodes == entryNodes
|
||||||
|
|
||||||
|
test "Static store nodes configuration":
|
||||||
|
## Given
|
||||||
|
let staticStoreNodes =
|
||||||
|
@[
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc",
|
||||||
|
"/ip4/192.168.1.1/tcp/60001/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYd",
|
||||||
|
]
|
||||||
|
let nodeConf = NodeConfig.init(
|
||||||
|
wakuConfig = WakuConfig.init(
|
||||||
|
entryNodes = @[], staticStoreNodes = staticStoreNodes, clusterId = 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let wakuConfRes = toWakuConf(nodeConf)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
require wakuConfRes.isOk()
|
||||||
|
let wakuConf = wakuConfRes.get()
|
||||||
|
require wakuConf.validate().isOk()
|
||||||
|
check:
|
||||||
|
wakuConf.staticNodes == staticStoreNodes
|
||||||
|
|
||||||
|
test "Message validation with max message size":
|
||||||
|
## Given
|
||||||
|
let nodeConfig = NodeConfig.init(
|
||||||
|
wakuConfig = WakuConfig.init(
|
||||||
|
entryNodes = @[],
|
||||||
|
staticStoreNodes = @[],
|
||||||
|
clusterId = 1,
|
||||||
|
messageValidation =
|
||||||
|
MessageValidation(maxMessageSize: "100KiB", rlnConfig: none(RlnConfig)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let wakuConfRes = toWakuConf(nodeConfig)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
require wakuConfRes.isOk()
|
||||||
|
let wakuConf = wakuConfRes.get()
|
||||||
|
require wakuConf.validate().isOk()
|
||||||
|
check:
|
||||||
|
wakuConf.maxMessageSizeBytes == 100'u64 * 1024'u64
|
||||||
|
|
||||||
|
test "Message validation with RLN config":
|
||||||
|
## Given
|
||||||
|
let nodeConfig = NodeConfig.init(
|
||||||
|
wakuConfig = WakuConfig.init(
|
||||||
|
entryNodes = @[],
|
||||||
|
clusterId = 1,
|
||||||
|
messageValidation = MessageValidation(
|
||||||
|
maxMessageSize: "150 KiB",
|
||||||
|
rlnConfig: some(
|
||||||
|
RlnConfig(
|
||||||
|
contractAddress: "0x1234567890123456789012345678901234567890",
|
||||||
|
chainId: 1'u,
|
||||||
|
epochSizeSec: 600'u64,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ethRpcEndpoints = @["http://127.0.0.1:1111"],
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let wakuConf = toWakuConf(nodeConfig).valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
|
wakuConf.validate().isOkOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
|
check:
|
||||||
|
wakuConf.maxMessageSizeBytes == 150'u64 * 1024'u64
|
||||||
|
|
||||||
|
require wakuConf.rlnRelayConf.isSome()
|
||||||
|
let rlnConf = wakuConf.rlnRelayConf.get()
|
||||||
|
check:
|
||||||
|
rlnConf.dynamic == true
|
||||||
|
rlnConf.ethContractAddress == "0x1234567890123456789012345678901234567890"
|
||||||
|
rlnConf.chainId == 1'u256
|
||||||
|
rlnConf.epochSizeSec == 600'u64
|
||||||
|
|
||||||
|
test "Full Core mode configuration with all fields":
|
||||||
|
## Given
|
||||||
|
let nodeConfig = NodeConfig.init(
|
||||||
|
mode = Core,
|
||||||
|
wakuConfig = WakuConfig.init(
|
||||||
|
entryNodes =
|
||||||
|
@[
|
||||||
|
"enr:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Vn7gmfkTTnAe8Ys2cgGBN8ufJnvzKQFZqFMBgmlkgnY0iXNlY3AyNTZrMaEDS8-D878DrdbNwcuY-3p1qdDp5MOoCurhdsNPJTXZ3c5g3RjcIJ2X4N1ZHCCd2g"
|
||||||
|
],
|
||||||
|
staticStoreNodes =
|
||||||
|
@[
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
||||||
|
],
|
||||||
|
clusterId = 99,
|
||||||
|
autoShardingConfig = AutoShardingConfig(numShardsInCluster: 12),
|
||||||
|
messageValidation = MessageValidation(
|
||||||
|
maxMessageSize: "512KiB",
|
||||||
|
rlnConfig: some(
|
||||||
|
RlnConfig(
|
||||||
|
contractAddress: "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
||||||
|
chainId: 5'u, # Goerli
|
||||||
|
epochSizeSec: 300'u64,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ethRpcEndpoints = @["https://127.0.0.1:8333"],
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let wakuConfRes = toWakuConf(nodeConfig)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
let wakuConf = wakuConfRes.valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
wakuConf.validate().isOkOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
|
# Check basic settings
|
||||||
|
check:
|
||||||
|
wakuConf.relay == true
|
||||||
|
wakuConf.lightPush == true
|
||||||
|
wakuConf.peerExchangeService == true
|
||||||
|
wakuConf.rendezvous == true
|
||||||
|
wakuConf.clusterId == 99
|
||||||
|
|
||||||
|
# Check sharding
|
||||||
|
check:
|
||||||
|
wakuConf.shardingConf.numShardsInCluster == 12
|
||||||
|
|
||||||
|
# Check bootstrap nodes
|
||||||
|
require wakuConf.discv5Conf.isSome()
|
||||||
|
check:
|
||||||
|
wakuConf.discv5Conf.get().bootstrapNodes.len == 1
|
||||||
|
|
||||||
|
# Check static nodes
|
||||||
|
check:
|
||||||
|
wakuConf.staticNodes.len == 1
|
||||||
|
wakuConf.staticNodes[0] ==
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
||||||
|
|
||||||
|
# Check message validation
|
||||||
|
check:
|
||||||
|
wakuConf.maxMessageSizeBytes == 512'u64 * 1024'u64
|
||||||
|
|
||||||
|
# Check RLN config
|
||||||
|
require wakuConf.rlnRelayConf.isSome()
|
||||||
|
let rlnConf = wakuConf.rlnRelayConf.get()
|
||||||
|
check:
|
||||||
|
rlnConf.dynamic == true
|
||||||
|
rlnConf.ethContractAddress == "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||||
|
rlnConf.chainId == 5'u256
|
||||||
|
rlnConf.epochSizeSec == 300'u64
|
||||||
|
|
||||||
|
test "NodeConfig with mixed entry nodes (integration test)":
|
||||||
|
## Given
|
||||||
|
let entryNodes =
|
||||||
|
@[
|
||||||
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im",
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc",
|
||||||
|
]
|
||||||
|
|
||||||
|
let nodeConfig = NodeConfig.init(
|
||||||
|
mode = Core,
|
||||||
|
wakuConfig =
|
||||||
|
WakuConfig.init(entryNodes = entryNodes, staticStoreNodes = @[], clusterId = 1),
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let wakuConfRes = toWakuConf(nodeConfig)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
require wakuConfRes.isOk()
|
||||||
|
let wakuConf = wakuConfRes.get()
|
||||||
|
require wakuConf.validate().isOk()
|
||||||
|
|
||||||
|
# Check that ENRTree went to DNS discovery
|
||||||
|
require wakuConf.dnsDiscoveryConf.isSome()
|
||||||
|
check:
|
||||||
|
wakuConf.dnsDiscoveryConf.get().enrTreeUrl == entryNodes[0]
|
||||||
|
|
||||||
|
# Check that multiaddr went to static nodes
|
||||||
|
check:
|
||||||
|
wakuConf.staticNodes.len == 1
|
||||||
|
wakuConf.staticNodes[0] == entryNodes[1]
|
||||||
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
import
|
import
|
||||||
./test_base64_codec,
|
./test_base64_codec,
|
||||||
./test_confutils_envvar,
|
|
||||||
./test_enr_builder,
|
./test_enr_builder,
|
||||||
./test_envvar_serialization,
|
|
||||||
./test_protobuf_validation,
|
./test_protobuf_validation,
|
||||||
./test_sqlite_migrations,
|
./test_sqlite_migrations,
|
||||||
./test_parse_size,
|
./test_parse_size,
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
import ./test_external_config, ./test_node_factory, ./test_waku_conf
|
import ./test_waku_conf, ./test_node_factory
|
||||||
|
|||||||
@ -4,9 +4,10 @@ import testutils/unittests, chronos, libp2p/protocols/connectivity/relay/relay
|
|||||||
|
|
||||||
import
|
import
|
||||||
../testlib/wakunode,
|
../testlib/wakunode,
|
||||||
waku/factory/node_factory,
|
|
||||||
waku/waku_node,
|
waku/waku_node,
|
||||||
waku/factory/conf_builder/conf_builder
|
waku/factory/node_factory,
|
||||||
|
waku/factory/conf_builder/conf_builder,
|
||||||
|
waku/factory/conf_builder/web_socket_conf_builder
|
||||||
|
|
||||||
suite "Node Factory":
|
suite "Node Factory":
|
||||||
asynctest "Set up a node based on default configurations":
|
asynctest "Set up a node based on default configurations":
|
||||||
@ -48,8 +49,9 @@ asynctest "Set up a node with Filter enabled":
|
|||||||
check:
|
check:
|
||||||
not node.isNil()
|
not node.isNil()
|
||||||
not node.wakuFilter.isNil()
|
not node.wakuFilter.isNil()
|
||||||
|
echo "TEST END"
|
||||||
|
|
||||||
asynctest "Start a node based on default configurations":
|
asynctest "Start a node based on default test configuration":
|
||||||
let conf = defaultTestWakuConf()
|
let conf = defaultTestWakuConf()
|
||||||
|
|
||||||
let node = (await setupNode(conf, relay = Relay.new())).valueOr:
|
let node = (await setupNode(conf, relay = Relay.new())).valueOr:
|
||||||
|
|||||||
91
tests/test_waku.nim
Normal file
91
tests/test_waku.nim
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
{.used.}
|
||||||
|
|
||||||
|
import chronos, testutils/unittests, std/options
|
||||||
|
|
||||||
|
import waku
|
||||||
|
|
||||||
|
suite "Waku API - Create node":
|
||||||
|
asyncTest "Create node with minimal configuration":
|
||||||
|
## Given
|
||||||
|
let nodeConfig =
|
||||||
|
NodeConfig.init(wakuConfig = WakuConfig.init(entryNodes = @[], clusterId = 1))
|
||||||
|
|
||||||
|
# This is the actual minimal config but as the node auto-start, it is not suitable for tests
|
||||||
|
# NodeConfig.init(ethRpcEndpoints = @["http://someaddress"])
|
||||||
|
|
||||||
|
## When
|
||||||
|
let node = (await createNode(nodeConfig)).valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
|
## Then
|
||||||
|
check:
|
||||||
|
not node.isNil()
|
||||||
|
node.conf.clusterId == 1
|
||||||
|
node.conf.relay == true
|
||||||
|
|
||||||
|
asyncTest "Create node with full configuration":
|
||||||
|
## Given
|
||||||
|
let nodeConfig = NodeConfig.init(
|
||||||
|
mode = Core,
|
||||||
|
wakuConfig = WakuConfig.init(
|
||||||
|
entryNodes =
|
||||||
|
@[
|
||||||
|
"enr:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Vn7gmfkTTnAe8Ys2cgGBN8ufJnvzKQFZqFMBgmlkgnY0iXNlY3AyNTZrMaEDS8-D878DrdbNwcuY-3p1qdDp5MOoCurhdsNPJTXZ3c5g3RjcIJ2X4N1ZHCCd2g"
|
||||||
|
],
|
||||||
|
staticStoreNodes =
|
||||||
|
@[
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
||||||
|
],
|
||||||
|
clusterId = 99,
|
||||||
|
autoShardingConfig = AutoShardingConfig(numShardsInCluster: 16),
|
||||||
|
messageValidation =
|
||||||
|
MessageValidation(maxMessageSize: "1024 KiB", rlnConfig: none(RlnConfig)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let node = (await createNode(nodeConfig)).valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
|
## Then
|
||||||
|
check:
|
||||||
|
not node.isNil()
|
||||||
|
node.conf.clusterId == 99
|
||||||
|
node.conf.shardingConf.numShardsInCluster == 16
|
||||||
|
node.conf.maxMessageSizeBytes == 1024'u64 * 1024'u64
|
||||||
|
node.conf.staticNodes.len == 1
|
||||||
|
node.conf.relay == true
|
||||||
|
node.conf.lightPush == true
|
||||||
|
node.conf.peerExchangeService == true
|
||||||
|
node.conf.rendezvous == true
|
||||||
|
|
||||||
|
asyncTest "Create node with mixed entry nodes (enrtree, multiaddr)":
|
||||||
|
## Given
|
||||||
|
let nodeConfig = NodeConfig.init(
|
||||||
|
mode = Core,
|
||||||
|
wakuConfig = WakuConfig.init(
|
||||||
|
entryNodes =
|
||||||
|
@[
|
||||||
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im",
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc",
|
||||||
|
],
|
||||||
|
clusterId = 42,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let node = (await createNode(nodeConfig)).valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
|
## Then
|
||||||
|
check:
|
||||||
|
not node.isNil()
|
||||||
|
node.conf.clusterId == 42
|
||||||
|
# ENRTree should go to DNS discovery
|
||||||
|
node.conf.dnsDiscoveryConf.isSome()
|
||||||
|
node.conf.dnsDiscoveryConf.get().enrTreeUrl ==
|
||||||
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im"
|
||||||
|
# Multiaddr should go to static nodes
|
||||||
|
node.conf.staticNodes.len == 1
|
||||||
|
node.conf.staticNodes[0] ==
|
||||||
|
"/ip4/127.0.0.1/tcp/60000/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
||||||
@ -4,7 +4,10 @@ import chronos, confutils/toml/std/net, libp2p/multiaddress, testutils/unittests
|
|||||||
|
|
||||||
import ./testlib/wakunode, waku/waku_enr/capabilities
|
import ./testlib/wakunode, waku/waku_enr/capabilities
|
||||||
|
|
||||||
include waku/node/net_config
|
include
|
||||||
|
waku/node/net_config,
|
||||||
|
waku/factory/conf_builder/web_socket_conf_builder,
|
||||||
|
waku/factory/conf_builder/conf_builder
|
||||||
|
|
||||||
proc defaultTestWakuFlags(): CapabilitiesBitfield =
|
proc defaultTestWakuFlags(): CapabilitiesBitfield =
|
||||||
CapabilitiesBitfield.init(
|
CapabilitiesBitfield.init(
|
||||||
@ -150,9 +153,15 @@ suite "Waku NetConfig":
|
|||||||
netConfig.announcedAddresses[0] == dns4TcpEndPoint(dns4DomainName, extPort)
|
netConfig.announcedAddresses[0] == dns4TcpEndPoint(dns4DomainName, extPort)
|
||||||
|
|
||||||
asyncTest "AnnouncedAddresses includes WebSocket addresses when enabled":
|
asyncTest "AnnouncedAddresses includes WebSocket addresses when enabled":
|
||||||
var
|
var confBuilder = defaultTestWakuConfBuilder()
|
||||||
conf = defaultTestWakuConf()
|
|
||||||
wssEnabled = false
|
confBuilder.webSocketConf.withEnabled(true)
|
||||||
|
confBuilder.webSocketConf.withWebSocketPort(Port(8000))
|
||||||
|
|
||||||
|
let conf = confBuilder.build().valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
|
var wssEnabled = false
|
||||||
|
|
||||||
var netConfigRes = NetConfig.init(
|
var netConfigRes = NetConfig.init(
|
||||||
bindIp = conf.endpointConf.p2pListenAddress,
|
bindIp = conf.endpointConf.p2pListenAddress,
|
||||||
@ -197,8 +206,14 @@ suite "Waku NetConfig":
|
|||||||
)
|
)
|
||||||
|
|
||||||
asyncTest "Announced WebSocket address contains external IP if provided":
|
asyncTest "Announced WebSocket address contains external IP if provided":
|
||||||
|
var confBuilder = defaultTestWakuConfBuilder()
|
||||||
|
confBuilder.webSocketConf.withEnabled(true)
|
||||||
|
confBuilder.webSocketConf.withWebSocketPort(Port(8000))
|
||||||
|
|
||||||
|
let conf = confBuilder.build().valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
let
|
let
|
||||||
conf = defaultTestWakuConf()
|
|
||||||
extIp = parseIpAddress("1.2.3.4")
|
extIp = parseIpAddress("1.2.3.4")
|
||||||
extPort = Port(1234)
|
extPort = Port(1234)
|
||||||
wssEnabled = false
|
wssEnabled = false
|
||||||
@ -222,8 +237,14 @@ suite "Waku NetConfig":
|
|||||||
(ip4TcpEndPoint(extIp, conf.websocketConf.get().port) & wsFlag(wssEnabled))
|
(ip4TcpEndPoint(extIp, conf.websocketConf.get().port) & wsFlag(wssEnabled))
|
||||||
|
|
||||||
asyncTest "Announced WebSocket address contains dns4DomainName if provided":
|
asyncTest "Announced WebSocket address contains dns4DomainName if provided":
|
||||||
|
var confBuilder = defaultTestWakuConfBuilder()
|
||||||
|
confBuilder.webSocketConf.withEnabled(true)
|
||||||
|
confBuilder.webSocketConf.withWebSocketPort(Port(8000))
|
||||||
|
|
||||||
|
let conf = confBuilder.build().valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
let
|
let
|
||||||
conf = defaultTestWakuConf()
|
|
||||||
dns4DomainName = "example.com"
|
dns4DomainName = "example.com"
|
||||||
extPort = Port(1234)
|
extPort = Port(1234)
|
||||||
wssEnabled = false
|
wssEnabled = false
|
||||||
@ -249,8 +270,14 @@ suite "Waku NetConfig":
|
|||||||
)
|
)
|
||||||
|
|
||||||
asyncTest "Announced WebSocket address contains dns4DomainName if provided alongside extIp":
|
asyncTest "Announced WebSocket address contains dns4DomainName if provided alongside extIp":
|
||||||
|
var confBuilder = defaultTestWakuConfBuilder()
|
||||||
|
confBuilder.webSocketConf.withEnabled(true)
|
||||||
|
confBuilder.webSocketConf.withWebSocketPort(Port(8000))
|
||||||
|
|
||||||
|
let conf = confBuilder.build().valueOr:
|
||||||
|
raiseAssert error
|
||||||
|
|
||||||
let
|
let
|
||||||
conf = defaultTestWakuConf()
|
|
||||||
dns4DomainName = "example.com"
|
dns4DomainName = "example.com"
|
||||||
extIp = parseIpAddress("1.2.3.4")
|
extIp = parseIpAddress("1.2.3.4")
|
||||||
extPort = Port(1234)
|
extPort = Port(1234)
|
||||||
|
|||||||
@ -42,8 +42,6 @@ proc defaultTestWakuConfBuilder*(): WakuConfBuilder =
|
|||||||
builder.withRendezvous(true)
|
builder.withRendezvous(true)
|
||||||
builder.storeServiceConf.withDbMigration(false)
|
builder.storeServiceConf.withDbMigration(false)
|
||||||
builder.storeServiceConf.withSupportV2(false)
|
builder.storeServiceConf.withSupportV2(false)
|
||||||
builder.webSocketConf.withWebSocketPort(Port(8000))
|
|
||||||
builder.webSocketConf.withEnabled(true)
|
|
||||||
return builder
|
return builder
|
||||||
|
|
||||||
proc defaultTestWakuConf*(): WakuConf =
|
proc defaultTestWakuConf*(): WakuConf =
|
||||||
|
|||||||
3
tests/tools/test_all.nim
Normal file
3
tests/tools/test_all.nim
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{.used.}
|
||||||
|
|
||||||
|
import ./test_confutils_envvar, ./test_confutils_envvar_serialization.nim
|
||||||
@ -7,9 +7,7 @@ import
|
|||||||
confutils,
|
confutils,
|
||||||
confutils/defs,
|
confutils/defs,
|
||||||
confutils/std/net
|
confutils/std/net
|
||||||
import
|
import ../../tools/confutils/[envvar as confEnvvarDefs, envvar_net as confEnvvarNet]
|
||||||
waku/common/confutils/envvar/defs as confEnvvarDefs,
|
|
||||||
waku/common/confutils/envvar/std/net as confEnvvarNet
|
|
||||||
|
|
||||||
type ConfResult[T] = Result[T, string]
|
type ConfResult[T] = Result[T, string]
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
import testutils/unittests
|
import testutils/unittests
|
||||||
import waku/common/envvar_serialization/utils
|
import ../../tools/confutils/envvar_serialization/utils
|
||||||
|
|
||||||
suite "nim-envvar-serialization - utils":
|
suite "nim-envvar-serialization - utils":
|
||||||
test "construct env var key":
|
test "construct env var key":
|
||||||
@ -439,7 +439,6 @@ suite "Waku Discovery v5":
|
|||||||
confBuilder.discv5Conf.withEnabled(true)
|
confBuilder.discv5Conf.withEnabled(true)
|
||||||
confBuilder.discv5Conf.withUdpPort(9001.Port)
|
confBuilder.discv5Conf.withUdpPort(9001.Port)
|
||||||
confBuilder.withP2pTcpPort(60001.Port)
|
confBuilder.withP2pTcpPort(60001.Port)
|
||||||
confBuilder.websocketConf.withEnabled(false)
|
|
||||||
|
|
||||||
let conf1 = confBuilder.build().valueOr:
|
let conf1 = confBuilder.build().valueOr:
|
||||||
raiseAssert error
|
raiseAssert error
|
||||||
@ -456,7 +455,6 @@ suite "Waku Discovery v5":
|
|||||||
confBuilder.withP2pTcpPort(60003.Port)
|
confBuilder.withP2pTcpPort(60003.Port)
|
||||||
confBuilder.discv5Conf.withUdpPort(9003.Port)
|
confBuilder.discv5Conf.withUdpPort(9003.Port)
|
||||||
confBuilder.withNodeKey(crypto.PrivateKey.random(Secp256k1, myRng[])[])
|
confBuilder.withNodeKey(crypto.PrivateKey.random(Secp256k1, myRng[])[])
|
||||||
confBuilder.websocketConf.withEnabled(false)
|
|
||||||
|
|
||||||
let conf2 = confBuilder.build().valueOr:
|
let conf2 = confBuilder.build().valueOr:
|
||||||
raiseAssert error
|
raiseAssert error
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
import ./test_app, ./test_validators
|
import ./test_app, ./test_validators, ./test_cli_args
|
||||||
|
|||||||
@ -10,12 +10,15 @@ import
|
|||||||
secp256k1,
|
secp256k1,
|
||||||
confutils,
|
confutils,
|
||||||
stint
|
stint
|
||||||
|
|
||||||
|
import tools/confutils/cli_args
|
||||||
|
|
||||||
import
|
import
|
||||||
../../waku/factory/external_config,
|
|
||||||
../../waku/factory/networks_config,
|
../../waku/factory/networks_config,
|
||||||
../../waku/factory/waku_conf,
|
../../waku/factory/waku_conf,
|
||||||
../../waku/common/logging,
|
../../waku/common/logging,
|
||||||
../../waku/common/utils/parse_size_units
|
../../waku/common/utils/parse_size_units,
|
||||||
|
../../waku/waku_core/message/default_values
|
||||||
|
|
||||||
suite "Waku external config - default values":
|
suite "Waku external config - default values":
|
||||||
test "Default sharding value":
|
test "Default sharding value":
|
||||||
@ -12,14 +12,8 @@ import
|
|||||||
libp2p/multihash,
|
libp2p/multihash,
|
||||||
secp256k1
|
secp256k1
|
||||||
import
|
import
|
||||||
waku/[
|
waku/[waku_core, node/peer_manager, waku_node, factory/validator_signed],
|
||||||
waku_core,
|
tools/confutils/cli_args,
|
||||||
node/peer_manager,
|
|
||||||
waku_node,
|
|
||||||
waku_relay,
|
|
||||||
factory/external_config,
|
|
||||||
factory/validator_signed,
|
|
||||||
],
|
|
||||||
../testlib/wakucore,
|
../testlib/wakucore,
|
||||||
../testlib/wakunode
|
../testlib/wakunode
|
||||||
|
|
||||||
|
|||||||
@ -19,23 +19,22 @@ import
|
|||||||
json
|
json
|
||||||
|
|
||||||
import
|
import
|
||||||
./waku_conf,
|
waku/factory/[waku_conf, conf_builder/conf_builder, networks_config],
|
||||||
./conf_builder/conf_builder,
|
waku/common/[logging],
|
||||||
./networks_config,
|
waku/[
|
||||||
../common/confutils/envvar/defs as confEnvvarDefs,
|
waku_enr,
|
||||||
../common/confutils/envvar/std/net as confEnvvarNet,
|
node/peer_manager,
|
||||||
../common/logging,
|
waku_core/topics/pubsub_topic,
|
||||||
../waku_enr,
|
waku_core/message/default_values,
|
||||||
../node/peer_manager,
|
],
|
||||||
../waku_core/topics/pubsub_topic,
|
|
||||||
../../tools/rln_keystore_generator/rln_keystore_generator
|
../../tools/rln_keystore_generator/rln_keystore_generator
|
||||||
|
|
||||||
include ../waku_core/message/default_values
|
import ./envvar as confEnvvarDefs, ./envvar_net as confEnvvarNet
|
||||||
|
|
||||||
export confTomlDefs, confTomlNet, confEnvvarDefs, confEnvvarNet, ProtectedShard
|
export confTomlDefs, confTomlNet, confEnvvarDefs, confEnvvarNet, ProtectedShard
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "waku external config"
|
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.} = "n/a"
|
||||||
@ -161,7 +160,7 @@ type WakuNodeConf* = object
|
|||||||
.}: uint16
|
.}: uint16
|
||||||
|
|
||||||
agentString* {.
|
agentString* {.
|
||||||
defaultValue: "nwaku-" & external_config.git_version,
|
defaultValue: "nwaku-" & 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
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import confutils/defs as confutilsDefs
|
import confutils/defs as confutilsDefs
|
||||||
import ../../envvar_serialization
|
import ./envvar_serialization
|
||||||
|
|
||||||
export envvar_serialization, confutilsDefs
|
export envvar_serialization, confutilsDefs
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import std/[strutils, net]
|
import std/[strutils, net]
|
||||||
import ../../../envvar_serialization
|
import ./envvar_serialization
|
||||||
|
|
||||||
export net, envvar_serialization
|
export net, envvar_serialization
|
||||||
|
|
||||||
10
waku.nim
Normal file
10
waku.nim
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
## Main module for using nwaku as a Nimble library
|
||||||
|
##
|
||||||
|
## This module re-exports the public API for creating and managing Waku nodes
|
||||||
|
## when using nwaku as a library dependency.
|
||||||
|
|
||||||
|
import waku/api/[api, api_conf]
|
||||||
|
export api, api_conf
|
||||||
|
|
||||||
|
import waku/factory/waku
|
||||||
|
export waku
|
||||||
@ -140,6 +140,7 @@ task testwakunode2, "Build & run wakunode2 app tests":
|
|||||||
test "all_tests_wakunode2"
|
test "all_tests_wakunode2"
|
||||||
|
|
||||||
task example2, "Build Waku examples":
|
task example2, "Build Waku examples":
|
||||||
|
buildBinary "waku_example", "examples/"
|
||||||
buildBinary "publisher", "examples/"
|
buildBinary "publisher", "examples/"
|
||||||
buildBinary "subscriber", "examples/"
|
buildBinary "subscriber", "examples/"
|
||||||
buildBinary "filter_subscriber", "examples/"
|
buildBinary "filter_subscriber", "examples/"
|
||||||
|
|||||||
17
waku/api/api.nim
Normal file
17
waku/api/api.nim
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import chronicles, chronos, results
|
||||||
|
|
||||||
|
import waku/factory/waku
|
||||||
|
|
||||||
|
import ./api_conf
|
||||||
|
|
||||||
|
# TODO: Specs says it should return a `WakuNode`. As `send` and other APIs are defined, we can align.
|
||||||
|
proc createNode*(config: NodeConfig): Future[Result[Waku, string]] {.async.} =
|
||||||
|
let wakuConf = toWakuConf(config).valueOr:
|
||||||
|
return err("Failed to handle the configuration: " & error)
|
||||||
|
|
||||||
|
## We are not defining app callbacks at node creation
|
||||||
|
let wakuRes = (await Waku.new(wakuConf)).valueOr:
|
||||||
|
error "waku initialization failed", error = error
|
||||||
|
return err("Failed setting up Waku: " & $error)
|
||||||
|
|
||||||
|
return ok(wakuRes)
|
||||||
203
waku/api/api_conf.nim
Normal file
203
waku/api/api_conf.nim
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
import std/[net, options]
|
||||||
|
|
||||||
|
import results
|
||||||
|
|
||||||
|
import
|
||||||
|
waku/common/utils/parse_size_units,
|
||||||
|
waku/factory/waku_conf,
|
||||||
|
waku/factory/conf_builder/conf_builder,
|
||||||
|
waku/factory/networks_config,
|
||||||
|
./entry_nodes
|
||||||
|
|
||||||
|
type AutoShardingConfig* {.requiresInit.} = object
|
||||||
|
numShardsInCluster*: uint16
|
||||||
|
|
||||||
|
type RlnConfig* {.requiresInit.} = object
|
||||||
|
contractAddress*: string
|
||||||
|
chainId*: uint
|
||||||
|
epochSizeSec*: uint64
|
||||||
|
|
||||||
|
type NetworkingConfig* {.requiresInit.} = object
|
||||||
|
listenIpv4*: string
|
||||||
|
p2pTcpPort*: uint16
|
||||||
|
discv5UdpPort*: uint16
|
||||||
|
|
||||||
|
type MessageValidation* {.requiresInit.} = object
|
||||||
|
maxMessageSize*: string # Accepts formats like "150 KiB", "1500 B"
|
||||||
|
rlnConfig*: Option[RlnConfig]
|
||||||
|
|
||||||
|
type WakuConfig* {.requiresInit.} = object
|
||||||
|
entryNodes: seq[string]
|
||||||
|
staticStoreNodes: seq[string]
|
||||||
|
clusterId: uint16
|
||||||
|
autoShardingConfig: AutoShardingConfig
|
||||||
|
messageValidation: MessageValidation
|
||||||
|
|
||||||
|
const DefaultNetworkingConfig* =
|
||||||
|
NetworkingConfig(listenIpv4: "0.0.0.0", p2pTcpPort: 60000, discv5UdpPort: 9000)
|
||||||
|
|
||||||
|
const DefaultAutoShardingConfig* = AutoShardingConfig(numShardsInCluster: 1)
|
||||||
|
|
||||||
|
const DefaultMessageValidation* =
|
||||||
|
MessageValidation(maxMessageSize: "150 KiB", rlnConfig: none(RlnConfig))
|
||||||
|
|
||||||
|
proc init*(
|
||||||
|
T: typedesc[WakuConfig],
|
||||||
|
entryNodes: seq[string],
|
||||||
|
staticStoreNodes: seq[string] = @[],
|
||||||
|
clusterId: uint16,
|
||||||
|
autoShardingConfig: AutoShardingConfig = DefaultAutoShardingConfig,
|
||||||
|
messageValidation: MessageValidation = DefaultMessageValidation,
|
||||||
|
): T =
|
||||||
|
return T(
|
||||||
|
entryNodes: entryNodes,
|
||||||
|
staticStoreNodes: staticStoreNodes,
|
||||||
|
clusterId: clusterId,
|
||||||
|
autoShardingConfig: autoShardingConfig,
|
||||||
|
messageValidation: messageValidation,
|
||||||
|
)
|
||||||
|
|
||||||
|
const TheWakuNetworkPreset* = WakuConfig(
|
||||||
|
entryNodes:
|
||||||
|
@[
|
||||||
|
"enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im"
|
||||||
|
],
|
||||||
|
staticStoreNodes: @[],
|
||||||
|
clusterId: 1,
|
||||||
|
autoShardingConfig: AutoShardingConfig(numShardsInCluster: 8),
|
||||||
|
messageValidation: MessageValidation(
|
||||||
|
maxMessageSize: "150 KiB",
|
||||||
|
rlnConfig: some(
|
||||||
|
RlnConfig(
|
||||||
|
contractAddress: "0xB9cd878C90E49F797B4431fBF4fb333108CB90e6",
|
||||||
|
chainId: 59141,
|
||||||
|
epochSizeSec: 600, # 10 minutes
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
type WakuMode* {.pure.} = enum
|
||||||
|
Edge
|
||||||
|
Core
|
||||||
|
|
||||||
|
type NodeConfig* {.requiresInit.} = object
|
||||||
|
mode: WakuMode
|
||||||
|
wakuConfig: WakuConfig
|
||||||
|
networkingConfig: NetworkingConfig
|
||||||
|
ethRpcEndpoints: seq[string]
|
||||||
|
|
||||||
|
proc init*(
|
||||||
|
T: typedesc[NodeConfig],
|
||||||
|
mode: WakuMode = WakuMode.Core,
|
||||||
|
wakuConfig: WakuConfig = TheWakuNetworkPreset,
|
||||||
|
networkingConfig: NetworkingConfig = DefaultNetworkingConfig,
|
||||||
|
ethRpcEndpoints: seq[string] = @[],
|
||||||
|
): T =
|
||||||
|
return T(
|
||||||
|
mode: mode,
|
||||||
|
wakuConfig: wakuConfig,
|
||||||
|
networkingConfig: networkingConfig,
|
||||||
|
ethRpcEndpoints: ethRpcEndpoints,
|
||||||
|
)
|
||||||
|
|
||||||
|
proc toWakuConf*(nodeConfig: NodeConfig): Result[WakuConf, string] =
|
||||||
|
var b = WakuConfBuilder.init()
|
||||||
|
|
||||||
|
# Apply networking configuration
|
||||||
|
let networkingConfig = nodeConfig.networkingConfig
|
||||||
|
let ip = parseIpAddress(networkingConfig.listenIpv4)
|
||||||
|
|
||||||
|
b.withP2pListenAddress(ip)
|
||||||
|
b.withP2pTcpPort(networkingConfig.p2pTcpPort)
|
||||||
|
b.discv5Conf.withUdpPort(networkingConfig.discv5UdpPort)
|
||||||
|
|
||||||
|
case nodeConfig.mode
|
||||||
|
of Core:
|
||||||
|
b.withRelay(true)
|
||||||
|
|
||||||
|
# Metadata is always mounted
|
||||||
|
|
||||||
|
b.filterServiceConf.withEnabled(true)
|
||||||
|
b.filterServiceConf.withMaxPeersToServe(20)
|
||||||
|
|
||||||
|
b.withLightPush(true)
|
||||||
|
|
||||||
|
b.discv5Conf.withEnabled(true)
|
||||||
|
b.withPeerExchange(true)
|
||||||
|
b.withRendezvous(true)
|
||||||
|
|
||||||
|
# TODO: fix store as client usage
|
||||||
|
|
||||||
|
b.rateLimitConf.withRateLimits(@["filter:100/1s", "lightpush:5/1s", "px:5/1s"])
|
||||||
|
of Edge:
|
||||||
|
return err("Edge mode is not implemented")
|
||||||
|
|
||||||
|
## Network Conf
|
||||||
|
let wakuConfig = nodeConfig.wakuConfig
|
||||||
|
|
||||||
|
# Set cluster ID
|
||||||
|
b.withClusterId(wakuConfig.clusterId)
|
||||||
|
|
||||||
|
# Set sharding configuration
|
||||||
|
b.withShardingConf(ShardingConfKind.AutoSharding)
|
||||||
|
let autoShardingConfig = wakuConfig.autoShardingConfig
|
||||||
|
b.withNumShardsInCluster(autoShardingConfig.numShardsInCluster)
|
||||||
|
|
||||||
|
# Process entry nodes - supports enrtree:, enr:, and multiaddress formats
|
||||||
|
if wakuConfig.entryNodes.len > 0:
|
||||||
|
let (enrTreeUrls, bootstrapEnrs, staticNodesFromEntry) = processEntryNodes(
|
||||||
|
wakuConfig.entryNodes
|
||||||
|
).valueOr:
|
||||||
|
return err("Failed to process entry nodes: " & error)
|
||||||
|
|
||||||
|
# Set ENRTree URLs for DNS discovery
|
||||||
|
if enrTreeUrls.len > 0:
|
||||||
|
for url in enrTreeUrls:
|
||||||
|
b.dnsDiscoveryConf.withEnrTreeUrl(url)
|
||||||
|
b.dnsDiscoveryconf.withNameServers(
|
||||||
|
@[parseIpAddress("1.1.1.1"), parseIpAddress("1.0.0.1")]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set ENR records as bootstrap nodes for discv5
|
||||||
|
if bootstrapEnrs.len > 0:
|
||||||
|
b.discv5Conf.withBootstrapNodes(bootstrapEnrs)
|
||||||
|
|
||||||
|
# Add static nodes (multiaddrs and those extracted from ENR entries)
|
||||||
|
if staticNodesFromEntry.len > 0:
|
||||||
|
b.withStaticNodes(staticNodesFromEntry)
|
||||||
|
|
||||||
|
# TODO: verify behaviour
|
||||||
|
# Set static store nodes
|
||||||
|
if wakuConfig.staticStoreNodes.len > 0:
|
||||||
|
b.withStaticNodes(wakuConfig.staticStoreNodes)
|
||||||
|
|
||||||
|
# Set message validation
|
||||||
|
let msgValidation = wakuConfig.messageValidation
|
||||||
|
let maxSizeBytes = parseMsgSize(msgValidation.maxMessageSize).valueOr:
|
||||||
|
return err("Failed to parse max message size: " & error)
|
||||||
|
b.withMaxMessageSize(maxSizeBytes)
|
||||||
|
|
||||||
|
# Set RLN config if provided
|
||||||
|
if msgValidation.rlnConfig.isSome():
|
||||||
|
let rlnConfig = msgValidation.rlnConfig.get()
|
||||||
|
b.rlnRelayConf.withEnabled(true)
|
||||||
|
b.rlnRelayConf.withEthContractAddress(rlnConfig.contractAddress)
|
||||||
|
b.rlnRelayConf.withChainId(rlnConfig.chainId)
|
||||||
|
b.rlnRelayConf.withEpochSizeSec(rlnConfig.epochSizeSec)
|
||||||
|
b.rlnRelayConf.withDynamic(true)
|
||||||
|
b.rlnRelayConf.withEthClientUrls(nodeConfig.ethRpcEndpoints)
|
||||||
|
|
||||||
|
# TODO: we should get rid of those two
|
||||||
|
b.rlnRelayconf.withUserMessageLimit(100)
|
||||||
|
|
||||||
|
## Various configurations
|
||||||
|
b.withNatStrategy("any")
|
||||||
|
|
||||||
|
let wakuConf = b.build().valueOr:
|
||||||
|
return err("Failed to build configuration: " & error)
|
||||||
|
|
||||||
|
wakuConf.validate().isOkOr:
|
||||||
|
return err("Failed to validate configuration: " & error)
|
||||||
|
|
||||||
|
return ok(wakuConf)
|
||||||
77
waku/api/entry_nodes.nim
Normal file
77
waku/api/entry_nodes.nim
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import std/strutils
|
||||||
|
|
||||||
|
import results, eth/p2p/discoveryv5/enr
|
||||||
|
|
||||||
|
import waku/waku_core/peers
|
||||||
|
|
||||||
|
type EntryNodeType {.pure.} = enum
|
||||||
|
EnrTree
|
||||||
|
Enr
|
||||||
|
Multiaddr
|
||||||
|
|
||||||
|
proc classifyEntryNode(address: string): Result[EntryNodeType, string] =
|
||||||
|
## Classifies an entry node address by its type
|
||||||
|
## Returns the type as EntryNodeType enum
|
||||||
|
if address.len == 0:
|
||||||
|
return err("Empty entry node address")
|
||||||
|
|
||||||
|
let lowerAddress = address.toLowerAscii()
|
||||||
|
if lowerAddress.startsWith("enrtree:"):
|
||||||
|
return ok(EnrTree)
|
||||||
|
elif lowerAddress.startsWith("enr:"):
|
||||||
|
return ok(Enr)
|
||||||
|
elif address[0] == '/':
|
||||||
|
return ok(Multiaddr)
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
err("Unrecognized entry node format. Must start with 'enrtree:', 'enr:', or '/'")
|
||||||
|
|
||||||
|
proc parseEnrToMultiaddrs(enrStr: string): Result[seq[string], string] =
|
||||||
|
## Parses an ENR string and extracts multiaddresses from it
|
||||||
|
let enrRec = enr.Record.fromURI(enrStr).valueOr:
|
||||||
|
return err("Invalid ENR record")
|
||||||
|
|
||||||
|
let remotePeerInfo = toRemotePeerInfo(enrRec).valueOr:
|
||||||
|
return err("Failed to convert ENR to peer info: " & $error)
|
||||||
|
|
||||||
|
# Convert RemotePeerInfo addresses to multiaddr strings
|
||||||
|
var multiaddrs: seq[string]
|
||||||
|
for addr in remotePeerInfo.addrs:
|
||||||
|
multiaddrs.add($addr & "/p2p/" & $remotePeerInfo.peerId)
|
||||||
|
|
||||||
|
if multiaddrs.len == 0:
|
||||||
|
return err("No valid addresses found in ENR")
|
||||||
|
|
||||||
|
return ok(multiaddrs)
|
||||||
|
|
||||||
|
proc processEntryNodes*(
|
||||||
|
entryNodes: seq[string]
|
||||||
|
): Result[(seq[string], seq[string], seq[string]), string] =
|
||||||
|
## Processes entry nodes and returns (enrTreeUrls, bootstrapEnrs, staticNodes)
|
||||||
|
## ENRTree URLs for DNS discovery, ENR records for bootstrap, multiaddrs for static nodes
|
||||||
|
var enrTreeUrls: seq[string]
|
||||||
|
var bootstrapEnrs: seq[string]
|
||||||
|
var staticNodes: seq[string]
|
||||||
|
|
||||||
|
for node in entryNodes:
|
||||||
|
let nodeType = classifyEntryNode(node).valueOr:
|
||||||
|
return err("Entry node error: " & error)
|
||||||
|
|
||||||
|
case nodeType
|
||||||
|
of EnrTree:
|
||||||
|
# ENRTree URLs go to DNS discovery configuration
|
||||||
|
enrTreeUrls.add(node)
|
||||||
|
of Enr:
|
||||||
|
# ENR records go to bootstrap nodes for discv5
|
||||||
|
bootstrapEnrs.add(node)
|
||||||
|
# Additionally, extract multiaddrs for static connections
|
||||||
|
let multiaddrsRes = parseEnrToMultiaddrs(node)
|
||||||
|
if multiaddrsRes.isOk():
|
||||||
|
for maddr in multiaddrsRes.get():
|
||||||
|
staticNodes.add(maddr)
|
||||||
|
# If we can't extract multiaddrs, just use it as bootstrap (already added above)
|
||||||
|
of Multiaddr:
|
||||||
|
# Multiaddresses go to static nodes
|
||||||
|
staticNodes.add(node)
|
||||||
|
|
||||||
|
return ok((enrTreeUrls, bootstrapEnrs, staticNodes))
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import
|
import
|
||||||
libp2p/crypto/crypto,
|
libp2p/crypto/crypto,
|
||||||
libp2p/multiaddress,
|
libp2p/multiaddress,
|
||||||
std/[net, options, sequtils, strutils],
|
std/[net, options, sequtils],
|
||||||
stint,
|
stint,
|
||||||
chronicles,
|
chronicles,
|
||||||
chronos,
|
chronos,
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import
|
|||||||
libp2p/crypto/curve25519,
|
libp2p/crypto/curve25519,
|
||||||
libp2p/multiaddress,
|
libp2p/multiaddress,
|
||||||
libp2p/nameresolving/dnsresolver,
|
libp2p/nameresolving/dnsresolver,
|
||||||
std/[options, sequtils, net, strutils],
|
std/[options, sequtils, net],
|
||||||
results
|
results
|
||||||
|
|
||||||
import ../common/utils/nat, ../node/net_config, ../waku_enr, ../waku_core, ./waku_conf
|
import ../common/utils/nat, ../node/net_config, ../waku_enr, ../waku_core, ./waku_conf
|
||||||
|
|||||||
@ -42,7 +42,6 @@ import
|
|||||||
../waku_filter_v2,
|
../waku_filter_v2,
|
||||||
../factory/node_factory,
|
../factory/node_factory,
|
||||||
../factory/internal_config,
|
../factory/internal_config,
|
||||||
../factory/external_config,
|
|
||||||
../factory/app_callbacks,
|
../factory/app_callbacks,
|
||||||
../waku_enr/multiaddr,
|
../waku_enr/multiaddr,
|
||||||
./waku_conf
|
./waku_conf
|
||||||
|
|||||||
@ -57,7 +57,6 @@ import
|
|||||||
../common/rate_limit/setting,
|
../common/rate_limit/setting,
|
||||||
../common/callbacks,
|
../common/callbacks,
|
||||||
../common/nimchronos,
|
../common/nimchronos,
|
||||||
../waku_enr/mix,
|
|
||||||
../waku_mix
|
../waku_mix
|
||||||
|
|
||||||
declarePublicCounter waku_node_messages, "number of messages received", ["type"]
|
declarePublicCounter waku_node_messages, "number of messages received", ["type"]
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[options, sequtils, sets, strutils, tables],
|
std/[options, sequtils, sets, tables],
|
||||||
stew/byteutils,
|
stew/byteutils,
|
||||||
chronicles,
|
chronicles,
|
||||||
chronos,
|
chronos,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user