mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-01-02 14:03:06 +00:00
* fix: admin API peer shards field from metadata protocol Store and return peer shard info from metadata protocol exchange instead of only checking ENR records. * peer_manager set shard info and extend rest test to validate it Co-authored-by: MorganaFuture <andrewmochalskyi@gmail.com>
336 lines
10 KiB
Nim
336 lines
10 KiB
Nim
{.used.}
|
|
|
|
import
|
|
std/[sequtils, net],
|
|
testutils/unittests,
|
|
presto,
|
|
presto/client as presto_client,
|
|
presto /../ tests/helpers,
|
|
libp2p/crypto/crypto
|
|
|
|
import
|
|
waku/[
|
|
waku_core,
|
|
waku_node,
|
|
waku_filter_v2/client,
|
|
node/peer_manager,
|
|
rest_api/endpoint/server,
|
|
rest_api/endpoint/client,
|
|
rest_api/endpoint/responses,
|
|
rest_api/endpoint/admin/types,
|
|
rest_api/endpoint/admin/handlers as admin_rest_interface,
|
|
rest_api/endpoint/admin/client as admin_rest_client,
|
|
waku_relay,
|
|
waku_peer_exchange,
|
|
],
|
|
../testlib/wakucore,
|
|
../testlib/wakunode,
|
|
../testlib/testasync
|
|
|
|
suite "Waku v2 Rest API - Admin":
|
|
var node1 {.threadvar.}: WakuNode
|
|
var node2 {.threadvar.}: WakuNode
|
|
var node3 {.threadvar.}: WakuNode
|
|
var peerInfo1 {.threadvar.}: RemotePeerInfo
|
|
var peerInfo2 {.threadvar.}: RemotePeerInfo
|
|
var peerInfo3 {.threadvar.}: RemotePeerInfo
|
|
var restServer {.threadvar.}: WakuRestServerRef
|
|
var client {.threadvar.}: RestClientRef
|
|
|
|
asyncSetup:
|
|
node1 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(60600))
|
|
node2 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(60602))
|
|
node3 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(60604))
|
|
|
|
let clusterId = 1.uint16
|
|
let shards: seq[uint16] = @[0]
|
|
node1.mountMetadata(clusterId, shards).isOkOr:
|
|
assert false, "Failed to mount metadata: " & $error
|
|
node2.mountMetadata(clusterId, shards).isOkOr:
|
|
assert false, "Failed to mount metadata: " & $error
|
|
node3.mountMetadata(clusterId, shards).isOkOr:
|
|
assert false, "Failed to mount metadata: " & $error
|
|
|
|
await allFutures(node1.start(), node2.start(), node3.start())
|
|
await allFutures(
|
|
node1.mountRelay(),
|
|
node2.mountRelay(),
|
|
node3.mountRelay(),
|
|
node3.mountPeerExchange(),
|
|
)
|
|
|
|
# The three nodes should be subscribed to the same shard
|
|
proc simpleHandler(
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
): Future[void] {.async, gcsafe.} =
|
|
await sleepAsync(0.milliseconds)
|
|
|
|
let shard = RelayShard(clusterId: clusterId, shardId: 5)
|
|
node1.subscribe((kind: PubsubSub, topic: $shard), simpleHandler).isOkOr:
|
|
assert false, "Failed to subscribe to topic: " & $error
|
|
node2.subscribe((kind: PubsubSub, topic: $shard), simpleHandler).isOkOr:
|
|
assert false, "Failed to subscribe to topic: " & $error
|
|
node3.subscribe((kind: PubsubSub, topic: $shard), simpleHandler).isOkOr:
|
|
assert false, "Failed to subscribe to topic: " & $error
|
|
|
|
peerInfo1 = node1.switch.peerInfo
|
|
peerInfo2 = node2.switch.peerInfo
|
|
peerInfo3 = node3.switch.peerInfo
|
|
|
|
var restPort = Port(0)
|
|
let restAddress = parseIpAddress("127.0.0.1")
|
|
restServer = WakuRestServerRef.init(restAddress, restPort).tryGet()
|
|
restPort = restServer.httpServer.address.port # update with bound port for client use
|
|
|
|
installAdminApiHandlers(restServer.router, node1)
|
|
|
|
restServer.start()
|
|
|
|
client = newRestHttpClient(initTAddress(restAddress, restPort))
|
|
|
|
asyncTearDown:
|
|
await restServer.stop()
|
|
await restServer.closeWait()
|
|
await allFutures(node1.stop(), node2.stop(), node3.stop())
|
|
|
|
asyncTest "Set and get remote peers":
|
|
# Connect to nodes 2 and 3 using the Admin API
|
|
let postRes = await client.postPeers(
|
|
@[constructMultiaddrStr(peerInfo2), constructMultiaddrStr(peerInfo3)]
|
|
)
|
|
|
|
check:
|
|
postRes.status == 200
|
|
|
|
# Verify that newly connected peers are being managed
|
|
let getRes = await client.getPeers()
|
|
|
|
check:
|
|
getRes.status == 200
|
|
$getRes.contentType == $MIMETYPE_JSON
|
|
getRes.data.len() == 2
|
|
# Check peer 2
|
|
getRes.data.anyIt(
|
|
it.protocols.find(WakuRelayCodec) >= 0 and
|
|
it.multiaddr == constructMultiaddrStr(peerInfo2)
|
|
)
|
|
# Check peer 3
|
|
getRes.data.anyIt(
|
|
it.protocols.find(WakuRelayCodec) >= 0 and
|
|
it.multiaddr == constructMultiaddrStr(peerInfo3)
|
|
)
|
|
|
|
# Check peer 3
|
|
getRes.data.anyIt(
|
|
it.protocols.find(WakuPeerExchangeCodec) >= 0 and
|
|
it.multiaddr == constructMultiaddrStr(peerInfo3)
|
|
)
|
|
|
|
asyncTest "Set wrong peer":
|
|
let nonExistentPeer =
|
|
"/ip4/0.0.0.0/tcp/10000/p2p/16Uiu2HAm6HZZr7aToTvEBPpiys4UxajCTU97zj5v7RNR2gbniy1D"
|
|
let postRes = await client.postPeers(@[nonExistentPeer])
|
|
|
|
check:
|
|
postRes.status == 400
|
|
$postRes.contentType == $MIMETYPE_TEXT
|
|
postRes.data == "Failed to connect to peer at index: 0 - " & nonExistentPeer
|
|
|
|
# Verify that newly connected peers are being managed
|
|
let getRes = await client.getPeers()
|
|
|
|
check:
|
|
getRes.status == 200
|
|
$getRes.contentType == $MIMETYPE_JSON
|
|
getRes.data.len() == 1
|
|
getRes.data[0].multiaddr == nonExistentPeer
|
|
getRes.data[0].connected == CannotConnect
|
|
|
|
asyncTest "Get filter data":
|
|
await allFutures(
|
|
node1.mountFilter(), node2.mountFilterClient(), node3.mountFilterClient()
|
|
)
|
|
|
|
let
|
|
contentFiltersNode2 = @[DefaultContentTopic, ContentTopic("2"), ContentTopic("3")]
|
|
contentFiltersNode3 = @[ContentTopic("3"), ContentTopic("4")]
|
|
pubsubTopicNode2 = DefaultPubsubTopic
|
|
pubsubTopicNode3 = PubsubTopic("/waku/2/custom-waku/proto")
|
|
|
|
let
|
|
subscribeResponse2 = await node2.wakuFilterClient.subscribe(
|
|
peerInfo1, pubsubTopicNode2, contentFiltersNode2
|
|
)
|
|
subscribeResponse3 = await node3.wakuFilterClient.subscribe(
|
|
peerInfo1, pubsubTopicNode3, contentFiltersNode3
|
|
)
|
|
|
|
assert subscribeResponse2.isOk(), $subscribeResponse2.error
|
|
assert subscribeResponse3.isOk(), $subscribeResponse3.error
|
|
|
|
let getRes = await client.getFilterSubscriptions()
|
|
|
|
check:
|
|
getRes.status == 200
|
|
$getRes.contentType == $MIMETYPE_JSON
|
|
getRes.data.len() == 2
|
|
|
|
let
|
|
peers = @[getRes.data[0].peerId, getRes.data[1].peerId]
|
|
numCriteria =
|
|
@[getRes.data[0].filterCriteria.len, getRes.data[1].filterCriteria.len]
|
|
|
|
check:
|
|
$peerInfo2 in peers
|
|
$peerInfo3 in peers
|
|
2 in numCriteria
|
|
3 in numCriteria
|
|
|
|
asyncTest "Get filter data - no filter subscribers":
|
|
await node1.mountFilter()
|
|
|
|
let getRes = await client.getFilterSubscriptions()
|
|
|
|
check:
|
|
getRes.status == 200
|
|
$getRes.contentType == $MIMETYPE_JSON
|
|
getRes.data.len() == 0
|
|
|
|
asyncTest "Get filter data - filter not mounted":
|
|
let getRes = await client.getFilterSubscriptionsFilterNotMounted()
|
|
|
|
check:
|
|
getRes.status == 400
|
|
getRes.data == "Error: Filter Protocol is not mounted to the node"
|
|
|
|
asyncTest "Get peer origin":
|
|
# Adding peers to the Peer Store
|
|
node1.peerManager.addPeer(peerInfo2, Discv5)
|
|
node1.peerManager.addPeer(peerInfo3, PeerExchange)
|
|
|
|
# Connecting to both peers
|
|
let conn2 = await node1.peerManager.connectPeer(peerInfo2)
|
|
let conn3 = await node1.peerManager.connectPeer(peerInfo3)
|
|
|
|
var count = 0
|
|
while count < 20:
|
|
## Wait ~1s at most for the peer store to update shard info
|
|
let getRes = await client.getPeers()
|
|
if getRes.data.allIt(it.shards == @[5.uint16]):
|
|
break
|
|
|
|
count.inc()
|
|
await sleepAsync(50.milliseconds)
|
|
|
|
assert count < 20, "Timeout waiting for shards to be updated in peer store"
|
|
|
|
# Check successful connections
|
|
check:
|
|
conn2 == true
|
|
conn3 == true
|
|
|
|
# Query peers REST endpoint
|
|
let getRes = await client.getPeers()
|
|
|
|
check:
|
|
getRes.status == 200
|
|
$getRes.contentType == $MIMETYPE_JSON
|
|
getRes.data.len() == 2
|
|
# Check peer 2
|
|
getRes.data.anyIt(it.origin == Discv5)
|
|
# Check peer 3
|
|
getRes.data.anyIt(it.origin == PeerExchange)
|
|
|
|
asyncTest "get peers by id":
|
|
# Connect to nodes 2 and 3 using the Admin API
|
|
let postRes = await client.postPeers(
|
|
@[constructMultiaddrStr(peerInfo2), constructMultiaddrStr(peerInfo3)]
|
|
)
|
|
|
|
check:
|
|
postRes.status == 200
|
|
|
|
let getRes = await client.getPeerById($peerInfo2.peerId)
|
|
|
|
check:
|
|
getRes.status == 200
|
|
$getRes.contentType == $MIMETYPE_JSON
|
|
getRes.data.protocols.find(WakuRelayCodec) >= 0
|
|
getRes.data.multiaddr == constructMultiaddrStr(peerInfo2)
|
|
|
|
## nim-presto library's RestClient does not support text error case decode if
|
|
## the RestResponse expects a JSON with complex type
|
|
# let getRes2 = await client.getPeerById("bad peer id")
|
|
let getRes2 = await httpClient(
|
|
restServer.httpServer.address, MethodGet, "/admin/v1/peer/bad+peer+id", ""
|
|
)
|
|
check:
|
|
getRes2.status == 400
|
|
getRes2.data == "Invalid argument:peerid: incorrect PeerId string"
|
|
|
|
asyncTest "get connected peers":
|
|
# Connect to nodes 2 and 3 using the Admin API
|
|
let postRes = await client.postPeers(
|
|
@[constructMultiaddrStr(peerInfo2), constructMultiaddrStr(peerInfo3)]
|
|
)
|
|
|
|
check:
|
|
postRes.status == 200
|
|
|
|
let getRes = await client.getConnectedPeers()
|
|
|
|
check:
|
|
getRes.status == 200
|
|
$getRes.contentType == $MIMETYPE_JSON
|
|
getRes.data.len() == 2
|
|
# Check peer 2
|
|
getRes.data.anyIt(it.multiaddr == constructMultiaddrStr(peerInfo2))
|
|
# Check peer 3
|
|
getRes.data.anyIt(it.multiaddr == constructMultiaddrStr(peerInfo3))
|
|
|
|
# Seems shard info is not available in the peer manager
|
|
# let getRes2 = await client.getConnectedPeersByShard(0)
|
|
# check:
|
|
# getRes2.status == 200
|
|
# $getRes2.contentType == $MIMETYPE_JSON
|
|
# getRes2.data.len() == 2
|
|
|
|
let getRes3 = await client.getConnectedPeersByShard(99)
|
|
check:
|
|
getRes3.status == 200
|
|
$getRes3.contentType == $MIMETYPE_JSON
|
|
getRes3.data.len() == 0
|
|
|
|
asyncTest "get relay peers":
|
|
# Connect to nodes 2 and 3 using the Admin API
|
|
let postRes = await client.postPeers(
|
|
@[constructMultiaddrStr(peerInfo2), constructMultiaddrStr(peerInfo3)]
|
|
)
|
|
|
|
check:
|
|
postRes.status == 200
|
|
|
|
let getRes = await client.getRelayPeers()
|
|
|
|
check:
|
|
getRes.status == 200
|
|
$getRes.contentType == $MIMETYPE_JSON
|
|
require getRes.data.len() == 1 # Check peer 2
|
|
check getRes.data[0].peers.anyIt(it.multiaddr == constructMultiaddrStr(peerInfo2))
|
|
# Check peer 2
|
|
check getRes.data[0].peers.anyIt(it.multiaddr == constructMultiaddrStr(peerInfo3))
|
|
# Check peer 3
|
|
|
|
# Todo: investigate why the test setup missing remote peer's shard info
|
|
# let getRes2 = await client.getRelayPeersByShard(0)
|
|
# check:
|
|
# getRes2.status == 200
|
|
# $getRes2.contentType == $MIMETYPE_JSON
|
|
# getRes2.data.peers.len() == 2
|
|
|
|
let getRes3 = await client.getRelayPeersByShard(99)
|
|
check:
|
|
getRes3.status == 200
|
|
$getRes3.contentType == $MIMETYPE_JSON
|
|
getRes3.data.peers.len() == 0
|