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
This commit is contained in:
Oskar Thorén 2020-10-06 11:33:28 +08:00 committed by GitHub
parent 065016393a
commit a6e94bf171
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 93 additions and 34 deletions

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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] =

View File

@ -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