diff --git a/CHANGELOG.md b/CHANGELOG.md index a83888322..7e2b2829d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - PubSub topic `subscribe` and `unsubscribe` no longer returns a future (removed `async` designation) - Added a peer manager for `relay`, `filter`, `store` and `swap` peers. - `relay`, `filter`, `store` and `swap` peers are now stored in a common, shared peer store and no longer in separate sets. +- Admin API now provides a `post` method to connect to peers on an ad-hoc basis ## 2021-01-05 v0.2 diff --git a/tests/v2/test_jsonrpc_waku.nim b/tests/v2/test_jsonrpc_waku.nim index 915a4e291..15bd9a4e8 100644 --- a/tests/v2/test_jsonrpc_waku.nim +++ b/tests/v2/test_jsonrpc_waku.nim @@ -367,6 +367,62 @@ procSuite "Waku v2 JSON-RPC API": server.close() waitfor node.stop() + asyncTest "Admin API: connect to ad-hoc peers": + # Create a couple of nodes + let + nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[] + node1 = WakuNode.init(nodeKey1, ValidIpAddress.init("0.0.0.0"), + Port(60000)) + nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[] + node2 = WakuNode.init(nodeKey2, ValidIpAddress.init("0.0.0.0"), + Port(60002)) + peerInfo2 = node2.peerInfo + nodeKey3 = crypto.PrivateKey.random(Secp256k1, rng[])[] + node3 = WakuNode.init(nodeKey3, ValidIpAddress.init("0.0.0.0"), + Port(60004)) + peerInfo3 = node3.peerInfo + + await allFutures([node1.start(), node2.start(), node3.start()]) + + node1.mountRelay() + node2.mountRelay() + node3.mountRelay() + + # RPC server setup + let + rpcPort = Port(8545) + ta = initTAddress(bindIp, rpcPort) + server = newRpcHttpServer([ta]) + + installAdminApiHandlers(node1, server) + server.start() + + let client = newRpcHttpClient() + await client.connect("127.0.0.1", rpcPort) + + # Connect to nodes 2 and 3 using the Admin API + let postRes = await client.post_waku_v2_admin_v1_peers(@[constructMultiaddrStr(peerInfo2), + constructMultiaddrStr(peerInfo3)]) + + check: + postRes + + # Verify that newly connected peers are being managed + let getRes = await client.get_waku_v2_admin_v1_peers() + + check: + getRes.len == 2 + # Check peer 2 + getRes.anyIt(it.protocol == WakuRelayCodec and + it.multiaddr == constructMultiaddrStr(peerInfo2)) + # Check peer 3 + getRes.anyIt(it.protocol == WakuRelayCodec and + it.multiaddr == constructMultiaddrStr(peerInfo3)) + + server.stop() + server.close() + await allFutures([node1.stop(), node2.stop(), node3.stop()]) + asyncTest "Admin API: get managed peer information": # Create a couple of nodes let diff --git a/waku/v2/node/jsonrpc/admin_api.nim b/waku/v2/node/jsonrpc/admin_api.nim index 819b02e19..d228592e2 100644 --- a/waku/v2/node/jsonrpc/admin_api.nim +++ b/waku/v2/node/jsonrpc/admin_api.nim @@ -14,6 +14,8 @@ import export jsonrpc_types +const futTimeout* = 30.seconds # Max time to wait for futures + proc constructMultiaddrStr*(wireaddr: MultiAddress, peerId: PeerId): string = # Constructs a multiaddress with both wire address and p2p identity $wireaddr & "/p2p/" & $peerId @@ -25,6 +27,17 @@ proc constructMultiaddrStr*(peerInfo: PeerInfo): string = proc installAdminApiHandlers*(node: WakuNode, rpcsrv: RpcServer) = ## Admin API version 1 definitions + + rpcsrv.rpc("post_waku_v2_admin_v1_peers") do(peers: seq[string]) -> bool: + ## Connect to a list of peers + debug "post_waku_v2_admin_v1_peers" + + if (await node.connectToNodes(peers).withTimeout(futTimeout)): + # Successfully connected to peers + return true + else: + # Failed to connect to peers + raise newException(ValueError, "Failed to connect to peers: " & $peers) rpcsrv.rpc("get_waku_v2_admin_v1_peers") do() -> seq[WakuPeer]: ## Returns history for a list of content topics with optional paging diff --git a/waku/v2/node/jsonrpc/jsonrpc_callsigs.nim b/waku/v2/node/jsonrpc/jsonrpc_callsigs.nim index 98b36b158..e49bb8d74 100644 --- a/waku/v2/node/jsonrpc/jsonrpc_callsigs.nim +++ b/waku/v2/node/jsonrpc/jsonrpc_callsigs.nim @@ -1,6 +1,7 @@ # Admin API proc get_waku_v2_admin_v1_peers(): seq[WakuPeer] +proc post_waku_v2_admin_v1_peers(peers: seq[string]): bool # Debug API