From a6e94bf171a9c22d57a4e2fe000473a5271881c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Thor=C3=A9n?= Date: Tue, 6 Oct 2020 11:33:28 +0800 Subject: [PATCH] Node Info API call. (#202) RPC node info fix Makefile error fix rpc query error add rpc_node_info to scripts target hm node info -> info consistent query node ref Add info to node api update node api docs update node api doc for consistency and accuracy minor --- Makefile | 4 --- docs/api/v2/node.md | 49 ++++++++++++++++++++----------- waku.nimble | 1 + waku/node/v2/rpc/rpc_info.nim | 19 ++++++++++++ waku/node/v2/rpc/rpc_query.nim | 2 +- waku/node/v2/rpc/wakucallsigs.nim | 3 ++ waku/node/v2/rpc/wakurpc.nim | 18 ++++++------ waku/node/v2/waku_types.nim | 5 ++++ waku/node/v2/wakunode2.nim | 26 ++++++++++++++-- 9 files changed, 93 insertions(+), 34 deletions(-) create mode 100644 waku/node/v2/rpc/rpc_info.nim diff --git a/Makefile b/Makefile index 21e69565c..c62778426 100644 --- a/Makefile +++ b/Makefile @@ -105,10 +105,6 @@ test2: echo -e $(BUILD_MSG) "build/$@" && \ $(ENV_SCRIPT) nim test2 $(NIM_PARAMS) waku.nims -example2: - echo -e $(BUILD_MSG) "build/$@" && \ - $(ENV_SCRIPT) nim example2 $(NIM_PARAMS) waku.nims - chat2: echo -e $(BUILD_MSG) "build/$@" && \ $(ENV_SCRIPT) nim chat2 $(NIM_PARAMS) waku.nims diff --git a/docs/api/v2/node.md b/docs/api/v2/node.md index 628967d01..17d3d2b58 100644 --- a/docs/api/v2/node.md +++ b/docs/api/v2/node.md @@ -2,61 +2,76 @@ ## Nim API -The Nim Waku API consist of five methods. Some of them have different arity -depending on what privacy/bandwidth trade-off the consumer wants to make. These -five method are: +The Nim Waku API consist of a set of methods opearting on the Waku Node object. +Some of them have different arity depending on what privacy/bandwidth trade-off +the consumer wants to make. These methods are: -1. **Init** - create and start a node. -2. **Subscribe** - to a topic or a specific content filter. -3. **Unsubscribe** - to a topic or a specific content filter. -4. **Publish** - to a topic, or a topic and a specific content filter. -5. **Query** - for historical messages. +1. **Init** - create a node. +2. **Start** - start a created node. +3. **Subscribe** - to a topic or a specific content filter. +4. **Unsubscribe** - to a topic or a specific content filter. +5. **Publish** - to a topic, or a topic and a specific content filter. +6. **Query** - for historical messages. +7. **Info** - to get information about the node. ```Nim -proc init*(T: type WakuNode, conf: WakuNodeConf): Future[T] - ## Creates and starts a Waku node. +proc init*(T: type WakuNode, nodeKey: crypto.PrivateKey, + bindIp: ValidIpAddress, bindPort: Port, + extIp = none[ValidIpAddress](), extPort = none[Port](), topics = newSeq[string]()): T = + ## Creates a Waku Node. ## ## Status: Implemented. -method subscribe*(w: WakuNode, topic: Topic, handler: TopicHandler) +proc start*(node: WakuNode) {.async.} = + ## Starts a created Waku Node. + ## + ## Status: Implemented. + +proc subscribe*(node: WakuNode, topic: Topic, handler: TopicHandler) {.async.} = ## Subscribes to a PubSub topic. Triggers handler when receiving messages on ## this topic. TopicHandler is a method that takes a topic and some data. ## ## NOTE The data field SHOULD be decoded as a WakuMessage. ## Status: Implemented. -method subscribe*(w: WakuNode, filter: FilterRequest, handler: ContentFilterHandler) +proc subscribe*(node: WakuNode, request: FilterRequest, handler: ContentFilterHandler) {.async, gcsafe.} = ## Registers for messages that match a specific filter. Triggers the handler whenever a message is received. ## FilterHandler is a method that takes a MessagePush. ## ## Status: Implemented. -method unsubscribe*(w: WakuNode, topic: Topic) +proc unsubscribe*(w: WakuNode, topic: Topic) = ## Unsubscribe from a topic. ## ## Status: Not yet implemented. ## TODO Implement. -method unsubscribe*(w: WakuNode, contentFilter: ContentFilter) +proc unsubscribe*(w: WakuNode, contentFilter: ContentFilter) = ## Unsubscribe from a content filter. ## ## Status: Not yet implemented. ## TODO Implement. -method publish*(w: WakuNode, topic: Topic, message: WakuMessage) +proc publish*(node: WakuNode, topic: Topic, message: WakuMessage) = ## Publish a `WakuMessage` to a PubSub topic. `WakuMessage` should contain a ## `contentTopic` field for light node functionality. This field may be also ## be omitted. ## ## Status: Implemented. -method query*(w: WakuNode, query: HistoryQuery, handler: QueryHandlerFunc) {.async, gcsafe.} = +proc query*(w: WakuNode, query: HistoryQuery, handler: QueryHandlerFunc) {.async, gcsafe.} = ## Queries known nodes for historical messages. Triggers the handler whenever a response is received. ## QueryHandlerFunc is a method that takes a HistoryResponse. ## ## Status: Implemented. + +proc info*(node: WakuNode): WakuInfo = + ## Returns information about the Node, such as what multiaddress it can be reached at. + ## + ## Status: Implemented. + ## ``` ## JSON RPC -### TODO To specify +TODO To specify diff --git a/waku.nimble b/waku.nimble index 1cd8808f0..ac70cf7de 100644 --- a/waku.nimble +++ b/waku.nimble @@ -72,6 +72,7 @@ task scripts2, "Build Waku v2 scripts": buildBinary "rpc_publish", "waku/node/v2/rpc/", "-d:chronicles_log_level=DEBUG" buildBinary "rpc_subscribe", "waku/node/v2/rpc/", "-d:chronicles_log_level=DEBUG" buildBinary "rpc_query", "waku/node/v2/rpc/", "-d:chronicles_log_level=DEBUG" + buildBinary "rpc_info", "waku/node/v2/rpc/", "-d:chronicles_log_level=DEBUG" task example2, "Build example Waku usage": let name = "basic2" diff --git a/waku/node/v2/rpc/rpc_info.nim b/waku/node/v2/rpc/rpc_info.nim new file mode 100644 index 000000000..2e50440ad --- /dev/null +++ b/waku/node/v2/rpc/rpc_info.nim @@ -0,0 +1,19 @@ +import + os, strutils, strformat, chronicles, json_rpc/[rpcclient, rpcserver], nimcrypto/sysrand, + libp2p/protobuf/minprotobuf, + libp2p/[peerinfo, multiaddress], + eth/common as eth_common, eth/keys, + system, + options + +from strutils import rsplit +template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0] + +const sigWakuPath = sourceDir / "wakucallsigs.nim" +createRpcSigs(RpcHttpClient, sigWakuPath) + +var node = newRpcHttpClient() +waitfor node.connect("localhost", Port(8545)) + +var res = waitfor node.wakuInfo() +echo "Waku info res: ", res diff --git a/waku/node/v2/rpc/rpc_query.nim b/waku/node/v2/rpc/rpc_query.nim index 780537e80..eb6c91e83 100644 --- a/waku/node/v2/rpc/rpc_query.nim +++ b/waku/node/v2/rpc/rpc_query.nim @@ -26,5 +26,5 @@ echo "Input is:", input var node = newRpcHttpClient() waitfor node.connect("localhost", rpcPort) -var res = waitfor node.wakuQuery("foo", @[input]) +var res = waitfor node.wakuQuery(@[input]) echo "Waku query response: ", res diff --git a/waku/node/v2/rpc/wakucallsigs.nim b/waku/node/v2/rpc/wakucallsigs.nim index 112b2af3f..34b75286a 100644 --- a/waku/node/v2/rpc/wakucallsigs.nim +++ b/waku/node/v2/rpc/wakucallsigs.nim @@ -8,6 +8,9 @@ proc waku_subscribe(topic: string): bool proc waku_query(topics: seq[string]): bool proc waku_subscribe_filter(topic: string, contentFilters: seq[seq[string]]): bool #proc waku_subscribe(topic: string, handler: Topichandler): bool +# +# TODO turn into WakuInfo object +proc waku_info(): string # NYI #proc waku_info(): WakuInfo diff --git a/waku/node/v2/rpc/wakurpc.nim b/waku/node/v2/rpc/wakurpc.nim index 8f5f1838f..1ee8b205f 100644 --- a/waku/node/v2/rpc/wakurpc.nim +++ b/waku/node/v2/rpc/wakurpc.nim @@ -6,17 +6,8 @@ import ../../../protocol/v2/waku_relay, ../waku_types, ../wakunode2 -# Instead of using rlpx waku_protocol here, lets do mock waku2_protocol -# This should wrap GossipSub, not use EthereumNode here - -# In Waku0/1 we use node.protocolState(Waku) a lot to get information -# Also keys to get priate key, etc -# Where is the equivalent in Waku/2? -# TODO: Extend to get access to protocol state and keys -#proc setupWakuRPC*(node: EthereumNode, keys: KeyStorage, rpcsrv: RpcServer) = proc setupWakuRPC*(node: WakuNode, rpcsrv: RpcServer) = - # Seems easy enough, lets try to get this first rpcsrv.rpc("waku_version") do() -> string: ## Returns string of the current Waku protocol version. result = WakuRelayCodec @@ -89,3 +80,12 @@ proc setupWakuRPC*(node: WakuNode, rpcsrv: RpcServer) = await node.subscribe(FilterRequest(topic: topic, contentFilters: filters), handler) return true + + rpcsrv.rpc("waku_info") do() -> string: + debug "waku_node_info" + + let wakuInfo = node.info() + let listenStr = wakuInfo.listenStr + info "Listening on", full = listenStr + + return listenStr diff --git a/waku/node/v2/waku_types.nim b/waku/node/v2/waku_types.nim index e4f77216b..a60190437 100644 --- a/waku/node/v2/waku_types.nim +++ b/waku/node/v2/waku_types.nim @@ -110,6 +110,11 @@ type WakuRelay* = ref object of GossipSub gossipEnabled*: bool + WakuInfo* = object + # NOTE One for simplicity, can extend later as needed + listenStr*: string + #multiaddrStrings*: seq[string] + # Encoding and decoding ------------------------------------------------------- proc init*(T: type WakuMessage, buffer: seq[byte]): ProtoResult[T] = diff --git a/waku/node/v2/wakunode2.nim b/waku/node/v2/wakunode2.nim index 73cee2624..83e67e0c2 100644 --- a/waku/node/v2/wakunode2.nim +++ b/waku/node/v2/wakunode2.nim @@ -54,7 +54,10 @@ template tcpEndPoint(address, port): auto = proc init*(T: type WakuNode, nodeKey: crypto.PrivateKey, bindIp: ValidIpAddress, bindPort: Port, extIp = none[ValidIpAddress](), extPort = none[Port](), topics = newSeq[string]()): T = - ## Creates and starts a Waku node. + ## Creates a Waku Node. + ## + ## Status: Implemented. + ## let hostAddress = tcpEndPoint(bindIp, bindPort) announcedAddresses = if extIp.isNone() or extPort.isNone(): @[] @@ -101,6 +104,10 @@ proc init*(T: type WakuNode, nodeKey: crypto.PrivateKey, discard result.subscribe(topic, handler) proc start*(node: WakuNode) {.async.} = + ## Starts a created Waku Node. + ## + ## Status: Implemented. + ## node.libp2pTransportLoops = await node.switch.start() # NOTE WakuRelay is being instantiated as part of initing node @@ -191,12 +198,25 @@ proc publish*(node: WakuNode, topic: Topic, message: WakuMessage) = # XXX Consider awaiting here discard wakuRelay.publish(topic, data) -proc query*(w: WakuNode, query: HistoryQuery, handler: QueryHandlerFunc) {.async, gcsafe.} = +proc query*(node: WakuNode, query: HistoryQuery, handler: QueryHandlerFunc) {.async, gcsafe.} = ## Queries known nodes for historical messages. Triggers the handler whenever a response is received. ## QueryHandlerFunc is a method that takes a HistoryResponse. ## ## Status: Implemented. - await w.wakuStore.query(query, handler) + await node.wakuStore.query(query, handler) + +# TODO Extend with more relevant info: topics, peers, memory usage, online time, etc +proc info*(node: WakuNode): WakuInfo = + ## Returns information about the Node, such as what multiaddress it can be reached at. + ## + ## Status: Implemented. + ## + + # TODO Generalize this for other type of multiaddresses + let peerInfo = node.peerInfo + let listenStr = $peerInfo.addrs[0] & "/p2p/" & $peerInfo.peerId + let wakuInfo = WakuInfo(listenStr: listenStr) + return wakuInfo when isMainModule: import