Add basic example usage for Waku v2 (#52)

* Make Waku node async and gcsafe, hacky

...but the nimbus people are doing it!

* Add skeleton example usage

* Rename example to basic2 and add to Makefile

* Sketch out basic example and qualify imports etc

Loading config to start with.

Quite messy with imports/ambiguous identifiers/qualified names. Probably a
better way with exports (hide implementation details) and fully qualified names
by default?

* Example usage run, public run function

* Sketch out API usage

* Example basic RPC client usage

* waitFor run to compile

* Remove run and gsync markers; adjust example
This commit is contained in:
Oskar Thorén 2020-07-20 12:40:35 +08:00 committed by GitHub
parent 95438b9389
commit e493c84b2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 12 deletions

View File

@ -92,6 +92,10 @@ wakutest2:
echo -e $(BUILD_MSG) "build/$@" && \
$(ENV_SCRIPT) nim wakutest2 $(NIM_PARAMS) waku.nims
wakuexample2:
echo -e $(BUILD_MSG) "build/$@" && \
$(ENV_SCRIPT) nim wakuexample2 $(NIM_PARAMS) waku.nims
# symlink
waku.nims:
ln -s waku.nimble $@

51
examples/v2/basic2.nim Normal file
View File

@ -0,0 +1,51 @@
# Here's an example of how you would start a Waku node, subscribe to topics, and
# publish to them
import confutils, chronicles, chronos, os
import libp2p/crypto/crypto
import libp2p/crypto/secp
import eth/keys
import json_rpc/[rpcclient, rpcserver]
import ../../waku/node/v2/config
import ../../waku/node/v2/wakunode2
# Loads the config in `waku/node/v2/config.nim`
let conf = WakuNodeConf.load()
# Start the node
# Running this should give you output like this:
# INF Listening on tid=5719 full=/ip4/127.0.0.1/tcp/60000/p2p/16Uiu2HAmNiAqr1cwhyntotP9fiSDyBvfKtB4ZiaDsrkipSCoKCB4
# TODO Run this in background
# See https://github.com/status-im/nim-waku/pull/59
proc runBackground(conf: WakuNodeConf) {.async.} =
run(conf)
runForever()
discard runBackground(conf)
# To do more operations on this node, we can do this in two ways:
# - We can use the Nim Node API, which is currently not exposed
# - We can use JSON RPC
# TODO Subscribe and publish to topic via Node API
# Requires https://github.com/status-im/nim-waku/issues/53
# Here's how to do it with JSON RPC
# Get RPC call signatures in Nim
from strutils import rsplit
template sourceDir: string = currentSourcePath.parentDir().parentDir().rsplit(DirSep, 1)[0]
const sigWakuPath = sourceDir / "waku" / "node" / "v2" / "rpc" / "wakucallsigs.nim"
createRpcSigs(RpcHttpClient, sigWakuPath)
# Create RPC Client and connect to it
var node = newRpcHttpClient()
waitfor node.connect("localhost", Port(8547))
# TODO Do something with res
var res = waitFor node.wakuSubscribe("apptopic")
# TODO Use publish as well

View File

@ -64,3 +64,8 @@ task wakunode2, "Build Experimental Waku cli":
task wakusim2, "Build Experimental Waku simulation tools":
buildBinary "quicksim2", "waku/node/v2/", "-d:chronicles_log_level=DEBUG"
buildBinary "start_network2", "waku/node/v2/", "-d:chronicles_log_level=TRACE"
task wakuexample2, "Build example Waku usage":
let name = "basic2"
buildBinary name, "examples/v2/", "-d:chronicles_log_level=DEBUG"
exec "build/" & name

View File

@ -2,7 +2,8 @@ import
confutils/defs, chronicles, chronos,
libp2p/crypto/crypto,
libp2p/crypto/secp,
nimcrypto/utils
nimcrypto/utils,
eth/keys
type
Fleet* = enum
@ -88,8 +89,8 @@ type
# NOTE: Signature is different here, we return PrivateKey and not KeyPair
nodekey* {.
desc: "P2P node private key as hex.",
defaultValue: PrivateKey.random(Secp256k1, keys.newRng()[]).tryGet()
name: "nodekey" }: PrivateKey
defaultValue: crypto.PrivateKey.random(Secp256k1, keys.newRng()[]).tryGet()
name: "nodekey" }: crypto.PrivateKey
# TODO: Add nodekey file option
bootnodeOnly* {.
@ -137,15 +138,15 @@ type
# - mailserver functionality
# NOTE: Keys are different in nim-libp2p
proc parseCmdArg*(T: type PrivateKey, p: TaintedString): T =
proc parseCmdArg*(T: type crypto.PrivateKey, p: TaintedString): T =
try:
let key = SkPrivateKey.init(utils.fromHex(p)).tryGet()
# XXX: Here at the moment
result = PrivateKey(scheme: Secp256k1, skkey: key)
result = crypto.PrivateKey(scheme: Secp256k1, skkey: key)
except CatchableError as e:
raise newException(ConfigurationError, "Invalid private key")
proc completeCmdArg*(T: type PrivateKey, val: TaintedString): seq[string] =
proc completeCmdArg*(T: type crypto.PrivateKey, val: TaintedString): seq[string] =
return @[]
proc parseCmdArg*(T: type IpAddress, p: TaintedString): T =

View File

@ -63,7 +63,7 @@ proc connectToNodes(p: WakuProto, nodes: openArray[string]) =
# NOTE: Looks almost identical to beacon_chain/eth2_network.nim
proc setupNat(conf: WakuNodeConf): tuple[ip: IpAddress,
tcpPort: Port,
udpPort: Port] =
udpPort: Port] {.gcsafe.} =
# defaults
result.ip = globalListeningAddr
result.tcpPort = Port(conf.tcpPort + conf.portsShift)
@ -92,9 +92,11 @@ proc setupNat(conf: WakuNodeConf): tuple[ip: IpAddress,
let extIP = getExternalIP(nat)
if extIP.isSome:
result.ip = extIP.get()
let extPorts = redirectPorts(tcpPort = result.tcpPort,
udpPort = result.udpPort,
description = clientId)
# XXX: GC safety danger zone! See NBC eth2_network.nim
let extPorts = ({.gcsafe.}:
redirectPorts(tcpPort = result.tcpPort,
udpPort = result.udpPort,
description = clientId))
if extPorts.isSome:
(result.tcpPort, result.udpPort) = extPorts.get()
@ -109,13 +111,14 @@ proc newWakuProto(switch: Switch): WakuProto =
wakuproto.handler = handle
return wakuproto
proc run(config: WakuNodeConf) =
proc run*(config: WakuNodeConf) =
info "libp2p support WIP"
if config.logLevel != LogLevel.NONE:
setLogLevel(config.logLevel)
# TODO Clean up host and announced IP a la eth2_network.nim
let
# External TCP and UDP ports
(ip, tcpPort, udpPort) = setupNat(config)
@ -131,7 +134,7 @@ proc run(config: WakuNodeConf) =
nodekey = config.nodekey
seckey = nodekey
pubkey = seckey.getKey.get()
keys = KeyPair(seckey: seckey, pubkey: pubkey)
keys = crypto.KeyPair(seckey: seckey, pubkey: pubkey)
peerInfo = PeerInfo.init(nodekey)