chore(wakucanary): add canary tool (#1205)

* chore(wakucanary): create folder structure

* chore(wakucanary): spawn waku node

* chore(wakucanary): get supported protocols from lp2p

* chore(wakucanary): add timeout + refactor

* chore(wakucanary): fix comments v1

* chore(wakucanary): update readme

* chore(wakucanary): static->relay, abbr, logLevel, filter issue, colon

* chore(wakucanary): fix typos
This commit is contained in:
Alvaro Revuelta 2022-10-11 05:58:44 +02:00 committed by GitHub
parent f282621a1c
commit a36de4036b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 185 additions and 0 deletions

View File

@ -158,6 +158,11 @@ example2: | build deps
echo -e $(BUILD_MSG) "build/$@" && \
$(ENV_SCRIPT) nim example2 $(NIM_PARAMS) waku.nims
# Waku tooling targets
wakucanary: | build deps
echo -e $(BUILD_MSG) "build/$@" && \
$(ENV_SCRIPT) nim wakucanary $(NIM_PARAMS) waku.nims
installganache:
ifeq ($(ONCHAIN_RLN), true)

View File

@ -55,6 +55,10 @@ make test
Examples can be found in the examples folder. For Waku v2, there is a fully
featured chat example.
### Tools
Different tools and their corresponding how-to guides can be found in the `tools` folder.
### Bugs, Questions & Features
For an inquiry, or if you would like to propose new features, feel free to [open a general issue](https://github.com/status-im/nim-waku/issues/new/).

39
tools/README.md Normal file
View File

@ -0,0 +1,39 @@
## waku canary tool
Attempts to dial a peer and asserts it supports a given set of protocols.
```console
Usage:
wakucanary [OPTIONS]...
The following options are available:
-a, --address Multiaddress of the peer node to attempt to dial.
-t, --timeout Timeout to consider that the connection failed [=chronos.seconds(10)].
-p, --protocol Protocol required to be supported: store,relay,lightpush,filter (can be used
multiple times).
-l, --log-level Sets the log level [=LogLevel.DEBUG].
```
The tool can be built as:
```console
$ make wakucanary
```
And used as follows. A reachable node that supports both `store` and `filter` protocols.
```console
$ ./build/wakucanary --address=/ip4/8.210.222.231/tcp/30303/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD --protocol=store --protocol=filter
$ echo $?
0
```
A node that can't be reached.
```console
$ ./build/wakucanary --address=/ip4/8.210.222.231/tcp/1000/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD --protocol=store --protocol=filter
$ echo $?
1
```

View File

@ -0,0 +1,133 @@
import
std/[strutils, sequtils, tables],
confutils,
chronos,
stew/shims/net,
chronicles/topics_registry
import
libp2p/protocols/ping,
libp2p/crypto/[crypto, secp]
import
../../waku/v2/node/peer_manager/peer_manager,
../../waku/v2/utils/peers,
../../waku/v2/node/wakunode2,
../../waku/v2/node/waku_payload,
../../waku/v2/utils/peers
# protocols and their tag
const ProtocolsTable = {
"store": "/vac/waku/store/",
"relay": "/vac/waku/relay/",
"lightpush": "/vac/waku/lightpush/",
"filter": "/vac/waku/filter/",
}.toTable
# cli flags
type
WakuCanaryConf* = object
address* {.
desc: "Multiaddress of the peer node to attempt to dial",
defaultValue: "",
name: "address",
abbr: "a" }: string
timeout* {.
desc: "Timeout to consider that the connection failed",
defaultValue: chronos.seconds(10),
name: "timeout",
abbr: "t" }: chronos.Duration
protocols* {.
desc: "Protocol required to be supported: store,relay,lightpush,filter (can be used multiple times)",
name: "protocol",
abbr: "p" }: seq[string]
logLevel* {.
desc: "Sets the log level",
defaultValue: LogLevel.DEBUG,
name: "log-level",
abbr: "l" .}: LogLevel
proc parseCmdArg*(T: type chronos.Duration, p: TaintedString): T =
try:
result = chronos.seconds(parseInt(p))
except CatchableError as e:
raise newException(ConfigurationError, "Invalid timeout value")
proc completeCmdArg*(T: type chronos.Duration, val: TaintedString): seq[string] =
return @[]
# checks if rawProtocols (skipping version) are supported in nodeProtocols
proc areProtocolsSupported(
rawProtocols: seq[string],
nodeProtocols: seq[string]): bool =
var numOfSupportedProt: int = 0
for nodeProtocol in nodeProtocols:
for rawProtocol in rawProtocols:
let protocolTag = ProtocolsTable[rawProtocol]
if nodeProtocol.startsWith(protocolTag):
info "Supported protocol ok", expected=protocolTag, supported=nodeProtocol
numOfSupportedProt += 1
break
if numOfSupportedProt == rawProtocols.len:
return true
return false
proc main(): Future[int] {.async.} =
let conf: WakuCanaryConf = WakuCanaryConf.load()
if conf.logLevel != LogLevel.NONE:
setLogLevel(conf.logLevel)
# ensure input protocols are valid
for p in conf.protocols:
if p notin ProtocolsTable:
error "invalid protocol", protocol=p, valid=ProtocolsTable
raise newException(ConfigurationError, "Invalid cli flag values" & p)
info "Cli flags",
address=conf.address,
timeout=conf.timeout,
protocols=conf.protocols,
logLevel=conf.logLevel
let
peer: RemotePeerInfo = parseRemotePeerInfo(conf.address)
rng = crypto.newRng()
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
node = WakuNode.new(
nodeKey,
ValidIpAddress.init("0.0.0.0"),
Port(60000))
await node.start()
let timedOut = not await node.connectToNodes(@[peer]).withTimeout(conf.timeout)
if timedOut:
error "Timedout after", timeout=conf.timeout
let lp2pPeerStore = node.switch.peerStore
let conStatus = node.peerManager.peerStore.connectionBook[peer.peerId]
if conStatus in [Connected, CanConnect]:
let nodeProtocols = lp2pPeerStore[ProtoBook][peer.peerId]
if not areProtocolsSupported(conf.protocols, nodeProtocols):
error "Not all protocols are supported", expected=conf.protocols, supported=nodeProtocols
return 1
elif conStatus == CannotConnect:
error "Could not connect", peerId = peer.peerId
return 1
return 0
when isMainModule:
let status = waitFor main()
if status == 0:
info "The node is reachable and supports all specified protocols"
else:
error "The node has some problems (see logs)"
quit status

View File

@ -99,3 +99,7 @@ task chat2bridge, "Build chat2-matterbridge":
buildBinary name, "examples/v2/matterbridge/", "-d:chronicles_log_level=DEBUG"
### Waku Tooling
task wakucanary, "Build waku-canary tool":
let name = "wakucanary"
buildBinary name, "tools/wakucanary/", "-d:chronicles_log_level=DEBUG -d:chronicles_runtime_filtering:on"