2020-08-31 03:32:41 +00:00
|
|
|
{.used.}
|
|
|
|
|
|
|
|
import
|
2021-03-26 09:52:04 +00:00
|
|
|
testutils/unittests,
|
2020-09-01 02:09:54 +00:00
|
|
|
chronicles, chronos, stew/shims/net as stewNet, stew/byteutils,
|
2020-08-31 03:32:41 +00:00
|
|
|
libp2p/crypto/crypto,
|
|
|
|
libp2p/crypto/secp,
|
2021-01-25 11:03:52 +00:00
|
|
|
libp2p/peerid,
|
|
|
|
libp2p/multiaddress,
|
2020-09-02 03:15:25 +00:00
|
|
|
libp2p/switch,
|
2021-03-11 23:42:26 +00:00
|
|
|
libp2p/protocols/pubsub/rpc/messages,
|
|
|
|
libp2p/protocols/pubsub/pubsub,
|
2021-04-01 09:37:14 +00:00
|
|
|
libp2p/protocols/pubsub/gossipsub,
|
2020-08-31 03:32:41 +00:00
|
|
|
eth/keys,
|
2021-06-22 03:30:12 +00:00
|
|
|
../../waku/v2/node/storage/sqlite,
|
|
|
|
../../waku/v2/node/storage/message/waku_message_store,
|
2021-07-13 07:18:51 +00:00
|
|
|
../../waku/v2/protocol/[waku_relay, waku_message],
|
2020-11-24 04:34:32 +00:00
|
|
|
../../waku/v2/protocol/waku_store/waku_store,
|
2021-01-05 04:52:10 +00:00
|
|
|
../../waku/v2/protocol/waku_filter/waku_filter,
|
2021-04-24 04:56:37 +00:00
|
|
|
../../waku/v2/protocol/waku_lightpush/waku_lightpush,
|
|
|
|
../../waku/v2/node/peer_manager/peer_manager,
|
2021-01-25 11:03:52 +00:00
|
|
|
../../waku/v2/utils/peers,
|
2020-11-17 09:34:53 +00:00
|
|
|
../../waku/v2/node/wakunode2,
|
2021-01-06 09:35:05 +00:00
|
|
|
../test_helpers
|
2020-07-29 13:24:01 +00:00
|
|
|
|
|
|
|
procSuite "WakuNode":
|
2020-09-02 03:15:25 +00:00
|
|
|
let rng = keys.newRng()
|
2020-07-29 13:24:01 +00:00
|
|
|
asyncTest "Message published with content filter is retrievable":
|
2020-09-01 02:09:54 +00:00
|
|
|
let
|
|
|
|
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node = WakuNode.new(nodeKey, ValidIpAddress.init("0.0.0.0"),
|
2020-09-01 02:09:54 +00:00
|
|
|
Port(60000))
|
2020-09-02 03:15:25 +00:00
|
|
|
pubSubTopic = "chat"
|
2021-04-08 09:55:19 +00:00
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
2021-05-05 08:34:40 +00:00
|
|
|
filterRequest = FilterRequest(pubSubTopic: pubSubTopic, contentFilters: @[ContentFilter(contentTopic: contentTopic)], subscribe: true)
|
2020-09-02 03:15:25 +00:00
|
|
|
message = WakuMessage(payload: "hello world".toBytes(),
|
|
|
|
contentTopic: contentTopic)
|
|
|
|
|
|
|
|
# This could/should become a more fixed handler (at least default) that
|
|
|
|
# would be enforced on WakuNode level.
|
|
|
|
proc relayHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
|
|
|
let msg = WakuMessage.init(data)
|
|
|
|
if msg.isOk():
|
|
|
|
check:
|
|
|
|
topic == "chat"
|
2020-10-02 12:48:56 +00:00
|
|
|
node.filters.notify(msg.value(), topic)
|
2020-09-02 03:15:25 +00:00
|
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
|
|
|
|
|
|
|
# This would be the actual application handler
|
2020-10-02 12:48:56 +00:00
|
|
|
proc contentHandler(msg: WakuMessage) {.gcsafe, closure.} =
|
|
|
|
let message = string.fromBytes(msg.payload)
|
2020-09-02 03:15:25 +00:00
|
|
|
check:
|
2020-10-02 12:48:56 +00:00
|
|
|
message == "hello world"
|
2020-09-02 03:15:25 +00:00
|
|
|
completionFut.complete(true)
|
2020-07-29 13:24:01 +00:00
|
|
|
|
2020-09-01 02:09:54 +00:00
|
|
|
await node.start()
|
2020-07-29 13:24:01 +00:00
|
|
|
|
2021-02-02 11:33:59 +00:00
|
|
|
node.mountRelay()
|
2020-10-20 02:36:27 +00:00
|
|
|
|
2020-09-02 03:15:25 +00:00
|
|
|
# Subscribe our node to the pubSubTopic where all chat data go onto.
|
2021-02-02 11:33:59 +00:00
|
|
|
node.subscribe(pubSubTopic, relayHandler)
|
2020-10-02 12:48:56 +00:00
|
|
|
|
2020-09-02 03:15:25 +00:00
|
|
|
# Subscribe a contentFilter to trigger a specific application handler when
|
|
|
|
# WakuMessages with that content are received
|
2020-10-02 12:48:56 +00:00
|
|
|
await node.subscribe(filterRequest, contentHandler)
|
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
2020-09-02 03:15:25 +00:00
|
|
|
|
2020-12-02 08:40:53 +00:00
|
|
|
await node.publish(pubSubTopic, message)
|
2020-09-02 03:15:25 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
(await completionFut.withTimeout(5.seconds)) == true
|
|
|
|
|
|
|
|
await node.stop()
|
|
|
|
|
|
|
|
asyncTest "Content filtered publishing over network":
|
2020-09-01 02:09:54 +00:00
|
|
|
let
|
2020-09-02 03:15:25 +00:00
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
2020-09-02 03:15:25 +00:00
|
|
|
Port(60000))
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
2020-09-02 03:15:25 +00:00
|
|
|
Port(60002))
|
|
|
|
pubSubTopic = "chat"
|
2021-04-08 09:55:19 +00:00
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
2021-05-05 08:34:40 +00:00
|
|
|
filterRequest = FilterRequest(pubSubTopic: pubSubTopic, contentFilters: @[ContentFilter(contentTopic: contentTopic)], subscribe: true)
|
2020-09-02 03:15:25 +00:00
|
|
|
message = WakuMessage(payload: "hello world".toBytes(),
|
2020-09-01 15:20:38 +00:00
|
|
|
contentTopic: contentTopic)
|
2020-07-29 13:24:01 +00:00
|
|
|
|
2020-09-02 03:15:25 +00:00
|
|
|
var completionFut = newFuture[bool]()
|
|
|
|
|
|
|
|
# This could/should become a more fixed handler (at least default) that
|
|
|
|
# would be enforced on WakuNode level.
|
|
|
|
proc relayHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
|
|
|
let msg = WakuMessage.init(data)
|
|
|
|
if msg.isOk():
|
|
|
|
check:
|
|
|
|
topic == "chat"
|
2020-10-02 12:48:56 +00:00
|
|
|
node1.filters.notify(msg.value(), topic)
|
2020-09-02 03:15:25 +00:00
|
|
|
|
|
|
|
# This would be the actual application handler
|
2020-10-02 12:48:56 +00:00
|
|
|
proc contentHandler(msg: WakuMessage) {.gcsafe, closure.} =
|
|
|
|
let message = string.fromBytes(msg.payload)
|
2020-09-02 03:15:25 +00:00
|
|
|
check:
|
2020-10-02 12:48:56 +00:00
|
|
|
message == "hello world"
|
2020-09-02 03:15:25 +00:00
|
|
|
completionFut.complete(true)
|
|
|
|
|
|
|
|
await allFutures([node1.start(), node2.start()])
|
|
|
|
|
2021-02-02 11:33:59 +00:00
|
|
|
node1.mountRelay()
|
|
|
|
node2.mountRelay()
|
2020-10-20 02:36:27 +00:00
|
|
|
|
|
|
|
node1.mountFilter()
|
|
|
|
node2.mountFilter()
|
|
|
|
|
2020-09-02 03:15:25 +00:00
|
|
|
# Subscribe our node to the pubSubTopic where all chat data go onto.
|
2021-02-02 11:33:59 +00:00
|
|
|
node1.subscribe(pubSubTopic, relayHandler)
|
2020-09-02 03:15:25 +00:00
|
|
|
# Subscribe a contentFilter to trigger a specific application handler when
|
|
|
|
# WakuMessages with that content are received
|
2021-10-06 12:29:08 +00:00
|
|
|
node1.wakuFilter.setPeer(node2.peerInfo.toRemotePeerInfo())
|
2020-10-02 12:48:56 +00:00
|
|
|
await node1.subscribe(filterRequest, contentHandler)
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
2020-09-02 03:15:25 +00:00
|
|
|
# Connect peers by dialing from node2 to node1
|
2020-11-20 13:59:29 +00:00
|
|
|
let conn = await node2.switch.dial(node1.peerInfo.peerId, node1.peerInfo.addrs, WakuRelayCodec)
|
2020-10-02 12:48:56 +00:00
|
|
|
|
2020-09-16 04:23:10 +00:00
|
|
|
# We need to sleep to allow the subscription to go through
|
|
|
|
info "Going to sleep to allow subscribe to go through"
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
info "Waking up and publishing"
|
2020-12-02 08:40:53 +00:00
|
|
|
await node2.publish(pubSubTopic, message)
|
2020-09-02 03:15:25 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
(await completionFut.withTimeout(5.seconds)) == true
|
2020-09-24 02:16:25 +00:00
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
2021-04-13 05:56:49 +00:00
|
|
|
|
|
|
|
asyncTest "Can receive filtered messages published on both default and other topics":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), Port(60000))
|
2021-04-13 05:56:49 +00:00
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"), Port(60002))
|
2021-04-13 05:56:49 +00:00
|
|
|
defaultTopic = "/waku/2/default-waku/proto"
|
|
|
|
otherTopic = "/non/waku/formatted"
|
|
|
|
defaultContentTopic = "defaultCT"
|
|
|
|
otherContentTopic = "otherCT"
|
|
|
|
defaultPayload = @[byte 1]
|
|
|
|
otherPayload = @[byte 9]
|
|
|
|
defaultMessage = WakuMessage(payload: defaultPayload, contentTopic: defaultContentTopic)
|
|
|
|
otherMessage = WakuMessage(payload: otherPayload, contentTopic: otherContentTopic)
|
2021-05-05 08:34:40 +00:00
|
|
|
defaultFR = FilterRequest(contentFilters: @[ContentFilter(contentTopic: defaultContentTopic)], subscribe: true)
|
|
|
|
otherFR = FilterRequest(contentFilters: @[ContentFilter(contentTopic: otherContentTopic)], subscribe: true)
|
2021-04-13 05:56:49 +00:00
|
|
|
|
|
|
|
await node1.start()
|
|
|
|
node1.mountRelay()
|
|
|
|
node1.mountFilter()
|
|
|
|
|
|
|
|
await node2.start()
|
|
|
|
node2.mountRelay()
|
|
|
|
node2.mountFilter()
|
2021-10-06 12:29:08 +00:00
|
|
|
node2.wakuFilter.setPeer(node1.peerInfo.toRemotePeerInfo())
|
2021-04-13 05:56:49 +00:00
|
|
|
|
|
|
|
var defaultComplete = newFuture[bool]()
|
|
|
|
var otherComplete = newFuture[bool]()
|
|
|
|
|
|
|
|
# Subscribe nodes 1 and 2 to otherTopic
|
|
|
|
proc emptyHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
|
|
|
# Do not notify filters or subscriptions here. This should be default behaviour for all topics
|
|
|
|
discard
|
|
|
|
|
|
|
|
node1.subscribe(otherTopic, emptyHandler)
|
|
|
|
node2.subscribe(otherTopic, emptyHandler)
|
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
proc defaultHandler(msg: WakuMessage) {.gcsafe, closure.} =
|
|
|
|
check:
|
|
|
|
msg.payload == defaultPayload
|
|
|
|
msg.contentTopic == defaultContentTopic
|
|
|
|
defaultComplete.complete(true)
|
|
|
|
|
|
|
|
proc otherHandler(msg: WakuMessage) {.gcsafe, closure.} =
|
|
|
|
check:
|
|
|
|
msg.payload == otherPayload
|
|
|
|
msg.contentTopic == otherContentTopic
|
|
|
|
otherComplete.complete(true)
|
|
|
|
|
|
|
|
# Subscribe a contentFilter to trigger a specific application handler when
|
|
|
|
# WakuMessages with that content are received
|
|
|
|
await node2.subscribe(defaultFR, defaultHandler)
|
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
# Let's check that content filtering works on the default topic
|
|
|
|
await node1.publish(defaultTopic, defaultMessage)
|
|
|
|
|
|
|
|
check:
|
|
|
|
(await defaultComplete.withTimeout(5.seconds)) == true
|
|
|
|
|
|
|
|
# Now check that content filtering works on other topics
|
|
|
|
await node2.subscribe(otherFR, otherHandler)
|
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
await node1.publish(otherTopic,otherMessage)
|
|
|
|
|
|
|
|
check:
|
|
|
|
(await otherComplete.withTimeout(5.seconds)) == true
|
|
|
|
|
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
2021-05-04 12:11:41 +00:00
|
|
|
|
|
|
|
asyncTest "Filter protocol works on node without relay capability":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), Port(60000))
|
2021-05-04 12:11:41 +00:00
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"), Port(60002))
|
2021-05-04 12:11:41 +00:00
|
|
|
defaultTopic = "/waku/2/default-waku/proto"
|
|
|
|
contentTopic = "defaultCT"
|
|
|
|
payload = @[byte 1]
|
|
|
|
message = WakuMessage(payload: payload, contentTopic: contentTopic)
|
2021-05-05 08:34:40 +00:00
|
|
|
filterRequest = FilterRequest(contentFilters: @[ContentFilter(contentTopic: contentTopic)], subscribe: true)
|
2021-05-04 12:11:41 +00:00
|
|
|
|
|
|
|
await node1.start()
|
|
|
|
node1.mountRelay()
|
|
|
|
node1.mountFilter()
|
|
|
|
|
|
|
|
await node2.start()
|
|
|
|
node2.mountRelay(relayMessages=false) # Do not start WakuRelay or subscribe to any topics
|
|
|
|
node2.mountFilter()
|
2021-10-06 12:29:08 +00:00
|
|
|
node2.wakuFilter.setPeer(node1.peerInfo.toRemotePeerInfo())
|
2021-05-04 12:11:41 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
node1.wakuRelay.isNil == false # Node1 is a full node
|
|
|
|
node2.wakuRelay.isNil == true # Node 2 is a light node
|
|
|
|
|
|
|
|
var completeFut = newFuture[bool]()
|
|
|
|
|
|
|
|
proc filterHandler(msg: WakuMessage) {.gcsafe, closure.} =
|
|
|
|
check:
|
|
|
|
msg.payload == payload
|
|
|
|
msg.contentTopic == contentTopic
|
|
|
|
completeFut.complete(true)
|
|
|
|
|
|
|
|
# Subscribe a contentFilter to trigger a specific application handler when
|
|
|
|
# WakuMessages with that content are received
|
|
|
|
await node2.subscribe(filterRequest, filterHandler)
|
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
# Let's check that content filtering works on the default topic
|
|
|
|
await node1.publish(defaultTopic, message)
|
|
|
|
|
|
|
|
check:
|
|
|
|
(await completeFut.withTimeout(5.seconds)) == true
|
|
|
|
|
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
2020-09-24 02:16:25 +00:00
|
|
|
|
|
|
|
asyncTest "Store protocol returns expected message":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
2020-09-24 02:16:25 +00:00
|
|
|
Port(60000))
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
2020-09-24 02:16:25 +00:00
|
|
|
Port(60002))
|
2021-04-08 09:55:19 +00:00
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
2020-09-24 02:16:25 +00:00
|
|
|
message = WakuMessage(payload: "hello world".toBytes(), contentTopic: contentTopic)
|
|
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
|
|
|
|
|
|
|
await node1.start()
|
2021-05-03 21:30:52 +00:00
|
|
|
node1.mountStore(persistMessages = true)
|
2020-09-24 02:16:25 +00:00
|
|
|
await node2.start()
|
2021-05-03 21:30:52 +00:00
|
|
|
node2.mountStore(persistMessages = true)
|
2020-09-24 02:16:25 +00:00
|
|
|
|
2021-07-13 07:18:51 +00:00
|
|
|
await node2.wakuStore.handleMessage("/waku/2/default-waku/proto", message)
|
2020-09-24 02:16:25 +00:00
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
2021-10-06 12:29:08 +00:00
|
|
|
node1.wakuStore.setPeer(node2.peerInfo.toRemotePeerInfo())
|
2020-09-24 02:16:25 +00:00
|
|
|
|
|
|
|
proc storeHandler(response: HistoryResponse) {.gcsafe, closure.} =
|
|
|
|
check:
|
|
|
|
response.messages[0] == message
|
|
|
|
completionFut.complete(true)
|
|
|
|
|
2021-04-19 17:38:30 +00:00
|
|
|
await node1.query(HistoryQuery(contentFilters: @[HistoryContentFilter(contentTopic: contentTopic)]), storeHandler)
|
|
|
|
|
2020-09-24 02:16:25 +00:00
|
|
|
check:
|
|
|
|
(await completionFut.withTimeout(5.seconds)) == true
|
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
2020-10-02 12:48:56 +00:00
|
|
|
|
|
|
|
asyncTest "Filter protocol returns expected message":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
2020-10-02 12:48:56 +00:00
|
|
|
Port(60000))
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
2020-10-02 12:48:56 +00:00
|
|
|
Port(60002))
|
2021-04-08 09:55:19 +00:00
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
2020-10-02 12:48:56 +00:00
|
|
|
message = WakuMessage(payload: "hello world".toBytes(), contentTopic: contentTopic)
|
|
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
|
|
|
|
|
|
|
await node1.start()
|
2020-10-20 02:36:27 +00:00
|
|
|
node1.mountFilter()
|
2020-10-02 12:48:56 +00:00
|
|
|
await node2.start()
|
2020-10-20 02:36:27 +00:00
|
|
|
node2.mountFilter()
|
2020-10-02 12:48:56 +00:00
|
|
|
|
2021-10-06 12:29:08 +00:00
|
|
|
node1.wakuFilter.setPeer(node2.peerInfo.toRemotePeerInfo())
|
2020-10-02 12:48:56 +00:00
|
|
|
|
|
|
|
proc handler(msg: WakuMessage) {.gcsafe, closure.} =
|
|
|
|
check:
|
|
|
|
msg == message
|
|
|
|
completionFut.complete(true)
|
|
|
|
|
2021-05-05 08:34:40 +00:00
|
|
|
await node1.subscribe(FilterRequest(pubSubTopic: "/waku/2/default-waku/proto", contentFilters: @[ContentFilter(contentTopic: contentTopic)], subscribe: true), handler)
|
2020-10-02 12:48:56 +00:00
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
2021-07-13 07:18:51 +00:00
|
|
|
await node2.wakuFilter.handleMessage("/waku/2/default-waku/proto", message)
|
2020-10-02 12:48:56 +00:00
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
check:
|
|
|
|
(await completionFut.withTimeout(5.seconds)) == true
|
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
2020-10-22 11:12:00 +00:00
|
|
|
|
|
|
|
asyncTest "Messages are correctly relayed":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
2020-10-22 11:12:00 +00:00
|
|
|
Port(60000))
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
2020-10-22 11:12:00 +00:00
|
|
|
Port(60002))
|
|
|
|
nodeKey3 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node3 = WakuNode.new(nodeKey3, ValidIpAddress.init("0.0.0.0"),
|
2020-10-22 11:12:00 +00:00
|
|
|
Port(60003))
|
|
|
|
pubSubTopic = "test"
|
2021-04-08 09:55:19 +00:00
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
2020-10-22 11:12:00 +00:00
|
|
|
payload = "hello world".toBytes()
|
|
|
|
message = WakuMessage(payload: payload, contentTopic: contentTopic)
|
|
|
|
|
|
|
|
await node1.start()
|
2021-02-02 11:33:59 +00:00
|
|
|
node1.mountRelay(@[pubSubTopic])
|
2020-10-22 11:12:00 +00:00
|
|
|
|
|
|
|
await node2.start()
|
2021-02-02 11:33:59 +00:00
|
|
|
node2.mountRelay(@[pubSubTopic])
|
2020-10-22 11:12:00 +00:00
|
|
|
|
|
|
|
await node3.start()
|
2021-02-02 11:33:59 +00:00
|
|
|
node3.mountRelay(@[pubSubTopic])
|
2020-10-22 11:12:00 +00:00
|
|
|
|
2021-10-06 12:29:08 +00:00
|
|
|
await node1.connectToNodes(@[node2.peerInfo.toRemotePeerInfo()])
|
|
|
|
await node3.connectToNodes(@[node2.peerInfo.toRemotePeerInfo()])
|
2020-10-22 11:12:00 +00:00
|
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
|
|
|
proc relayHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
|
|
|
let msg = WakuMessage.init(data)
|
|
|
|
if msg.isOk():
|
|
|
|
let val = msg.value()
|
|
|
|
check:
|
|
|
|
topic == pubSubTopic
|
|
|
|
val.contentTopic == contentTopic
|
|
|
|
val.payload == payload
|
|
|
|
completionFut.complete(true)
|
|
|
|
|
2021-02-02 11:33:59 +00:00
|
|
|
node3.subscribe(pubSubTopic, relayHandler)
|
2020-10-22 11:12:00 +00:00
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
2020-12-02 08:40:53 +00:00
|
|
|
await node1.publish(pubSubTopic, message)
|
2020-10-22 11:12:00 +00:00
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
check:
|
|
|
|
(await completionFut.withTimeout(5.seconds)) == true
|
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
|
|
|
await node3.stop()
|
2021-06-29 14:29:04 +00:00
|
|
|
|
|
|
|
asyncTest "Protocol matcher works as expected":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
2021-06-29 14:29:04 +00:00
|
|
|
Port(60000))
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
2021-06-29 14:29:04 +00:00
|
|
|
Port(60002))
|
|
|
|
pubSubTopic = "/waku/2/default-waku/proto"
|
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
|
|
|
payload = "hello world".toBytes()
|
|
|
|
message = WakuMessage(payload: payload, contentTopic: contentTopic)
|
|
|
|
|
|
|
|
# Setup node 1 with stable codec "/vac/waku/relay/2.0.0"
|
|
|
|
|
|
|
|
await node1.start()
|
|
|
|
node1.mountRelay(@[pubSubTopic])
|
|
|
|
node1.wakuRelay.codec = "/vac/waku/relay/2.0.0"
|
|
|
|
|
|
|
|
# Setup node 2 with beta codec "/vac/waku/relay/2.0.0-beta2"
|
|
|
|
|
|
|
|
await node2.start()
|
|
|
|
node2.mountRelay(@[pubSubTopic])
|
|
|
|
node2.wakuRelay.codec = "/vac/waku/relay/2.0.0-beta2"
|
|
|
|
|
|
|
|
check:
|
|
|
|
# Check that mounted codecs are actually different
|
|
|
|
node1.wakuRelay.codec == "/vac/waku/relay/2.0.0"
|
|
|
|
node2.wakuRelay.codec == "/vac/waku/relay/2.0.0-beta2"
|
|
|
|
|
|
|
|
# Now verify that protocol matcher returns `true` and relay works
|
|
|
|
|
2021-10-06 12:29:08 +00:00
|
|
|
await node1.connectToNodes(@[node2.peerInfo.toRemotePeerInfo()])
|
2021-06-29 14:29:04 +00:00
|
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
|
|
|
proc relayHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
|
|
|
let msg = WakuMessage.init(data)
|
|
|
|
if msg.isOk():
|
|
|
|
let val = msg.value()
|
|
|
|
check:
|
|
|
|
topic == pubSubTopic
|
|
|
|
val.contentTopic == contentTopic
|
|
|
|
val.payload == payload
|
|
|
|
completionFut.complete(true)
|
|
|
|
|
|
|
|
node2.subscribe(pubSubTopic, relayHandler)
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
await node1.publish(pubSubTopic, message)
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
check:
|
|
|
|
(await completionFut.withTimeout(5.seconds)) == true
|
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
2021-01-25 11:03:52 +00:00
|
|
|
|
|
|
|
asyncTest "Peer info parses correctly":
|
|
|
|
## This is such an important utility function for wakunode2
|
|
|
|
## that it deserves its own test :)
|
|
|
|
|
|
|
|
# First test the `happy path` expected case
|
|
|
|
let
|
|
|
|
addrStr = "/ip4/127.0.0.1/tcp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
2021-10-06 12:29:08 +00:00
|
|
|
remotePeerInfo = parseRemotePeerInfo(addrStr)
|
2021-01-25 11:03:52 +00:00
|
|
|
|
|
|
|
check:
|
2021-10-06 12:29:08 +00:00
|
|
|
$(remotePeerInfo.peerId) == "16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc"
|
|
|
|
$(remotePeerInfo.addrs[0][0].tryGet()) == "/ip4/127.0.0.1"
|
|
|
|
$(remotePeerInfo.addrs[0][1].tryGet()) == "/tcp/60002"
|
2021-01-25 11:03:52 +00:00
|
|
|
|
|
|
|
# Now test some common corner cases
|
2021-06-09 14:37:08 +00:00
|
|
|
expect LPError:
|
2021-01-25 11:03:52 +00:00
|
|
|
# gibberish
|
2021-10-06 12:29:08 +00:00
|
|
|
discard parseRemotePeerInfo("/p2p/$UCH GIBBER!SH")
|
2021-01-25 11:03:52 +00:00
|
|
|
|
2021-06-09 14:37:08 +00:00
|
|
|
expect LPError:
|
2021-01-25 11:03:52 +00:00
|
|
|
# leading whitespace
|
2021-10-06 12:29:08 +00:00
|
|
|
discard parseRemotePeerInfo(" /ip4/127.0.0.1/tcp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc")
|
2021-01-25 11:03:52 +00:00
|
|
|
|
2021-06-09 14:37:08 +00:00
|
|
|
expect LPError:
|
2021-01-25 11:03:52 +00:00
|
|
|
# trailing whitespace
|
2021-10-06 12:29:08 +00:00
|
|
|
discard parseRemotePeerInfo("/ip4/127.0.0.1/tcp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc ")
|
2021-01-25 11:03:52 +00:00
|
|
|
|
2021-06-09 14:37:08 +00:00
|
|
|
expect LPError:
|
2021-01-25 11:03:52 +00:00
|
|
|
# invalid IP address
|
2021-10-06 12:29:08 +00:00
|
|
|
discard parseRemotePeerInfo("/ip4/127.0.0.0.1/tcp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc")
|
2021-01-25 11:03:52 +00:00
|
|
|
|
|
|
|
expect ValueError:
|
|
|
|
# no PeerID
|
2021-10-06 12:29:08 +00:00
|
|
|
discard parseRemotePeerInfo("/ip4/127.0.0.1/tcp/60002")
|
2021-01-25 11:03:52 +00:00
|
|
|
|
|
|
|
expect ValueError:
|
|
|
|
# unsupported transport
|
2021-10-06 12:29:08 +00:00
|
|
|
discard parseRemotePeerInfo("/ip4/127.0.0.1/udp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc")
|
2021-03-11 23:42:26 +00:00
|
|
|
|
|
|
|
asyncTest "filtering relayed messages using topic validators":
|
|
|
|
## test scenario:
|
|
|
|
## node1 and node3 set node2 as their relay node
|
|
|
|
## node3 publishes two messages with two different contentTopics but on the same pubsub topic
|
|
|
|
## node1 is also subscribed to the same pubsub topic
|
|
|
|
## node2 sets a validator for the same pubsub topic
|
|
|
|
## only one of the messages gets delivered to node1 because the validator only validates one of the content topics
|
|
|
|
|
|
|
|
let
|
|
|
|
# publisher node
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), Port(60000))
|
2021-03-11 23:42:26 +00:00
|
|
|
# Relay node
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"), Port(60002))
|
2021-03-11 23:42:26 +00:00
|
|
|
# Subscriber
|
|
|
|
nodeKey3 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node3 = WakuNode.new(nodeKey3, ValidIpAddress.init("0.0.0.0"), Port(60003))
|
2021-03-11 23:42:26 +00:00
|
|
|
|
|
|
|
pubSubTopic = "test"
|
2021-04-08 09:55:19 +00:00
|
|
|
contentTopic1 = ContentTopic("/waku/2/default-content/proto")
|
2021-03-11 23:42:26 +00:00
|
|
|
payload = "hello world".toBytes()
|
|
|
|
message1 = WakuMessage(payload: payload, contentTopic: contentTopic1)
|
|
|
|
|
|
|
|
payload2 = "you should not see this message!".toBytes()
|
2021-04-08 09:55:19 +00:00
|
|
|
contentTopic2 = ContentTopic("2")
|
2021-03-11 23:42:26 +00:00
|
|
|
message2 = WakuMessage(payload: payload2, contentTopic: contentTopic2)
|
|
|
|
|
|
|
|
# start all the nodes
|
|
|
|
await node1.start()
|
|
|
|
node1.mountRelay(@[pubSubTopic])
|
|
|
|
|
|
|
|
await node2.start()
|
|
|
|
node2.mountRelay(@[pubSubTopic])
|
|
|
|
|
|
|
|
await node3.start()
|
|
|
|
node3.mountRelay(@[pubSubTopic])
|
|
|
|
|
2021-10-06 12:29:08 +00:00
|
|
|
await node1.connectToNodes(@[node2.peerInfo.toRemotePeerInfo()])
|
|
|
|
await node3.connectToNodes(@[node2.peerInfo.toRemotePeerInfo()])
|
2021-03-11 23:42:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
var completionFutValidatorAcc = newFuture[bool]()
|
|
|
|
var completionFutValidatorRej = newFuture[bool]()
|
|
|
|
|
|
|
|
proc validator(topic: string, message: messages.Message): Future[ValidationResult] {.async.} =
|
|
|
|
## the validator that only allows messages with contentTopic1 to be relayed
|
|
|
|
check:
|
|
|
|
topic == pubSubTopic
|
|
|
|
let msg = WakuMessage.init(message.data)
|
|
|
|
if msg.isOk():
|
|
|
|
# only relay messages with contentTopic1
|
|
|
|
if msg.value().contentTopic == contentTopic1:
|
|
|
|
result = ValidationResult.Accept
|
|
|
|
completionFutValidatorAcc.complete(true)
|
|
|
|
else:
|
|
|
|
result = ValidationResult.Reject
|
|
|
|
completionFutValidatorRej.complete(true)
|
|
|
|
|
|
|
|
# set a topic validator for pubSubTopic
|
|
|
|
let pb = PubSub(node2.wakuRelay)
|
|
|
|
pb.addValidator(pubSubTopic, validator)
|
|
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
|
|
|
proc relayHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
|
|
|
debug "relayed pubsub topic:", topic
|
|
|
|
let msg = WakuMessage.init(data)
|
|
|
|
if msg.isOk():
|
|
|
|
let val = msg.value()
|
|
|
|
check:
|
|
|
|
topic == pubSubTopic
|
|
|
|
# check that only messages with contentTopic1 is relayed (but not contentTopic2)
|
|
|
|
val.contentTopic == contentTopic1
|
|
|
|
# relay handler is called
|
|
|
|
completionFut.complete(true)
|
|
|
|
|
|
|
|
|
|
|
|
node3.subscribe(pubSubTopic, relayHandler)
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
await node1.publish(pubSubTopic, message1)
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
# message2 never gets relayed because of the validator
|
|
|
|
await node1.publish(pubSubTopic, message2)
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
check:
|
|
|
|
(await completionFut.withTimeout(10.seconds)) == true
|
|
|
|
# check that validator is called for message1
|
|
|
|
(await completionFutValidatorAcc.withTimeout(10.seconds)) == true
|
|
|
|
# check that validator is called for message2
|
|
|
|
(await completionFutValidatorRej.withTimeout(10.seconds)) == true
|
|
|
|
|
|
|
|
|
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
|
|
|
await node3.stop()
|
2021-04-01 09:37:14 +00:00
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
when defined(rln):
|
|
|
|
asyncTest "testing rln-relay with mocked zkp":
|
2021-03-16 18:18:40 +00:00
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
let
|
|
|
|
# publisher node
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), Port(60000))
|
2021-06-08 18:56:32 +00:00
|
|
|
# Relay node
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"), Port(60002))
|
2021-06-08 18:56:32 +00:00
|
|
|
# Subscriber
|
|
|
|
nodeKey3 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node3 = WakuNode.new(nodeKey3, ValidIpAddress.init("0.0.0.0"), Port(60003))
|
2021-03-16 18:18:40 +00:00
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
pubSubTopic = "defaultTopic"
|
|
|
|
contentTopic1 = ContentTopic("/waku/2/default-content/proto")
|
|
|
|
payload = "hello world".toBytes()
|
|
|
|
message1 = WakuMessage(payload: payload, contentTopic: contentTopic1)
|
2021-03-16 18:18:40 +00:00
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
# start all the nodes
|
|
|
|
await node1.start()
|
|
|
|
node1.mountRelay(@[pubSubTopic])
|
2021-03-16 18:18:40 +00:00
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
await node2.start()
|
|
|
|
node2.mountRelay(@[pubSubTopic])
|
|
|
|
node2.addRLNRelayValidator(pubSubTopic)
|
2021-03-11 23:42:26 +00:00
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
await node3.start()
|
|
|
|
node3.mountRelay(@[pubSubTopic])
|
2021-03-16 18:18:40 +00:00
|
|
|
|
2021-10-06 12:29:08 +00:00
|
|
|
await node1.connectToNodes(@[node2.peerInfo.toRemotePeerInfo()])
|
|
|
|
await node3.connectToNodes(@[node2.peerInfo.toRemotePeerInfo()])
|
2021-03-16 18:18:40 +00:00
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
var completionFut = newFuture[bool]()
|
|
|
|
proc relayHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
|
|
|
let msg = WakuMessage.init(data)
|
|
|
|
if msg.isOk():
|
|
|
|
let val = msg.value()
|
|
|
|
debug "The received topic:", topic
|
|
|
|
if topic == pubSubTopic:
|
|
|
|
completionFut.complete(true)
|
2021-03-16 18:18:40 +00:00
|
|
|
|
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
node3.subscribe(pubSubTopic, relayHandler)
|
|
|
|
await sleepAsync(2000.millis)
|
2021-03-16 18:18:40 +00:00
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
await node1.publish(pubSubTopic, message1, rlnRelayEnabled = true)
|
|
|
|
await sleepAsync(2000.millis)
|
2021-03-16 18:18:40 +00:00
|
|
|
|
|
|
|
|
2021-06-08 18:56:32 +00:00
|
|
|
check:
|
|
|
|
(await completionFut.withTimeout(10.seconds)) == true
|
|
|
|
|
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
|
|
|
await node3.stop()
|
2021-04-01 09:37:14 +00:00
|
|
|
|
|
|
|
asyncTest "Relay protocol is started correctly":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
2021-04-01 09:37:14 +00:00
|
|
|
Port(60000))
|
|
|
|
|
|
|
|
# Relay protocol starts if mounted after node start
|
|
|
|
|
|
|
|
await node1.start()
|
|
|
|
|
|
|
|
node1.mountRelay()
|
|
|
|
|
|
|
|
check:
|
|
|
|
GossipSub(node1.wakuRelay).heartbeatFut.isNil == false
|
|
|
|
|
|
|
|
# Relay protocol starts if mounted before node start
|
|
|
|
|
|
|
|
let
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
2021-04-01 09:37:14 +00:00
|
|
|
Port(60002))
|
|
|
|
|
|
|
|
node2.mountRelay()
|
|
|
|
|
|
|
|
check:
|
|
|
|
# Relay has not yet started as node has not yet started
|
|
|
|
GossipSub(node2.wakuRelay).heartbeatFut.isNil
|
|
|
|
|
|
|
|
await node2.start()
|
|
|
|
|
|
|
|
check:
|
|
|
|
# Relay started on node start
|
|
|
|
GossipSub(node2.wakuRelay).heartbeatFut.isNil == false
|
|
|
|
|
|
|
|
await allFutures([node1.stop(), node2.stop()])
|
|
|
|
|
2021-05-25 08:31:59 +00:00
|
|
|
asyncTest "Lightpush message return success":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
2021-05-25 08:31:59 +00:00
|
|
|
Port(60010))
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
2021-05-25 08:31:59 +00:00
|
|
|
Port(60012))
|
|
|
|
nodeKey3 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node3 = WakuNode.new(nodeKey3, ValidIpAddress.init("0.0.0.0"),
|
2021-05-25 08:31:59 +00:00
|
|
|
Port(60013))
|
|
|
|
pubSubTopic = "test"
|
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
|
|
|
payload = "hello world".toBytes()
|
|
|
|
message = WakuMessage(payload: payload, contentTopic: contentTopic)
|
|
|
|
|
|
|
|
# Light node, only lightpush
|
|
|
|
await node1.start()
|
|
|
|
node1.mountRelay(relayMessages=false) # Mount WakuRelay, but do not start or subscribe to any topics
|
|
|
|
node1.mountLightPush()
|
|
|
|
|
|
|
|
# Intermediate node
|
|
|
|
await node2.start()
|
|
|
|
node2.mountRelay(@[pubSubTopic])
|
|
|
|
node2.mountLightPush()
|
|
|
|
|
|
|
|
# Receiving node
|
|
|
|
await node3.start()
|
|
|
|
node3.mountRelay(@[pubSubTopic])
|
|
|
|
|
2021-10-06 12:29:08 +00:00
|
|
|
discard await node1.peerManager.dialPeer(node2.peerInfo.toRemotePeerInfo(), WakuLightPushCodec)
|
2021-05-25 08:31:59 +00:00
|
|
|
await sleepAsync(5.seconds)
|
2021-10-06 12:29:08 +00:00
|
|
|
await node3.connectToNodes(@[node2.peerInfo.toRemotePeerInfo()])
|
2021-05-25 08:31:59 +00:00
|
|
|
|
|
|
|
var completionFutLightPush = newFuture[bool]()
|
|
|
|
var completionFutRelay = newFuture[bool]()
|
|
|
|
proc relayHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
|
|
|
let msg = WakuMessage.init(data)
|
|
|
|
if msg.isOk():
|
|
|
|
let val = msg.value()
|
|
|
|
check:
|
|
|
|
topic == pubSubTopic
|
|
|
|
val.contentTopic == contentTopic
|
|
|
|
val.payload == payload
|
|
|
|
completionFutRelay.complete(true)
|
|
|
|
|
|
|
|
node3.subscribe(pubSubTopic, relayHandler)
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
proc handler(response: PushResponse) {.gcsafe, closure.} =
|
|
|
|
debug "push response handler, expecting true"
|
|
|
|
check:
|
|
|
|
response.isSuccess == true
|
|
|
|
completionFutLightPush.complete(true)
|
|
|
|
|
|
|
|
# Publishing with lightpush
|
|
|
|
await node1.lightpush(pubSubTopic, message, handler)
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
check:
|
|
|
|
(await completionFutRelay.withTimeout(5.seconds)) == true
|
|
|
|
(await completionFutLightPush.withTimeout(5.seconds)) == true
|
|
|
|
|
|
|
|
await allFutures([node1.stop(), node2.stop(), node3.stop()])
|
2021-05-26 19:33:22 +00:00
|
|
|
|
|
|
|
# check:
|
|
|
|
# (await completionFutRelay.withTimeout(5.seconds)) == true
|
|
|
|
# (await completionFutLightPush.withTimeout(5.seconds)) == true
|
|
|
|
# await node1.stop()
|
|
|
|
# await node2.stop()
|
|
|
|
# await node3.stop()
|
|
|
|
asyncTest "Resume proc fetches the history":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
2021-05-26 19:33:22 +00:00
|
|
|
Port(60000))
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
2021-05-26 19:33:22 +00:00
|
|
|
Port(60002))
|
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
|
|
|
message = WakuMessage(payload: "hello world".toBytes(), contentTopic: contentTopic)
|
|
|
|
|
|
|
|
await node1.start()
|
|
|
|
node1.mountStore(persistMessages = true)
|
|
|
|
await node2.start()
|
|
|
|
node2.mountStore(persistMessages = true)
|
|
|
|
|
2021-07-13 07:18:51 +00:00
|
|
|
await node2.wakuStore.handleMessage("/waku/2/default-waku/proto", message)
|
2021-05-26 19:33:22 +00:00
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
2021-10-06 12:29:08 +00:00
|
|
|
node1.wakuStore.setPeer(node2.peerInfo.toRemotePeerInfo())
|
2021-05-26 19:33:22 +00:00
|
|
|
|
|
|
|
await node1.resume()
|
|
|
|
|
|
|
|
check:
|
|
|
|
# message is correctly stored
|
|
|
|
node1.wakuStore.messages.len == 1
|
|
|
|
|
|
|
|
await node1.stop()
|
|
|
|
await node2.stop()
|
2021-06-22 03:30:12 +00:00
|
|
|
|
|
|
|
asyncTest "Resume proc discards duplicate messages":
|
|
|
|
let
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
2021-06-22 03:30:12 +00:00
|
|
|
Port(60000))
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
2021-07-14 17:58:46 +00:00
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
2021-06-22 03:30:12 +00:00
|
|
|
Port(60002))
|
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
2021-07-07 23:56:20 +00:00
|
|
|
msg1 = WakuMessage(payload: "hello world1".toBytes(), contentTopic: contentTopic, timestamp: 1)
|
|
|
|
msg2 = WakuMessage(payload: "hello world2".toBytes(), contentTopic: contentTopic, timestamp: 2)
|
2021-06-22 03:30:12 +00:00
|
|
|
|
|
|
|
# setup sqlite database for node1
|
|
|
|
let
|
|
|
|
database = SqliteDatabase.init("", inMemory = true)[]
|
|
|
|
store = WakuMessageStore.init(database)[]
|
|
|
|
|
|
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
|
|
|
|
|
|
|
await node1.start()
|
|
|
|
node1.mountStore(persistMessages = true, store = store)
|
|
|
|
await node2.start()
|
|
|
|
node2.mountStore(persistMessages = true)
|
|
|
|
|
2021-07-13 07:18:51 +00:00
|
|
|
await node2.wakuStore.handleMessage(DefaultTopic, msg1)
|
|
|
|
await node2.wakuStore.handleMessage(DefaultTopic, msg2)
|
2021-06-22 03:30:12 +00:00
|
|
|
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
2021-10-06 12:29:08 +00:00
|
|
|
node1.wakuStore.setPeer(node2.peerInfo.toRemotePeerInfo())
|
2021-06-22 03:30:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
# populate db with msg1 to be a duplicate
|
|
|
|
let index1 = computeIndex(msg1)
|
|
|
|
let output1 = store.put(index1, msg1, DefaultTopic)
|
|
|
|
check output1.isOk
|
|
|
|
node1.wakuStore.messages.add(IndexedWakuMessage(msg: msg1, index: index1, pubsubTopic: DefaultTopic))
|
|
|
|
|
|
|
|
# now run the resume proc
|
|
|
|
await node1.resume()
|
|
|
|
|
|
|
|
# count the total number of retrieved messages from the database
|
|
|
|
var responseCount = 0
|
|
|
|
proc data(receiverTimestamp: float64, msg: WakuMessage, psTopic: string) =
|
|
|
|
responseCount += 1
|
|
|
|
# retrieve all the messages in the db
|
|
|
|
let res = store.getAll(data)
|
|
|
|
check:
|
|
|
|
res.isErr == false
|
|
|
|
|
|
|
|
check:
|
|
|
|
# if the duplicates are discarded properly, then the total number of messages after resume should be 2
|
|
|
|
# check no duplicates is in the messages field
|
|
|
|
node1.wakuStore.messages.len == 2
|
|
|
|
# check no duplicates is in the db
|
|
|
|
responseCount == 2
|
|
|
|
|
|
|
|
await node1.stop()
|
2021-10-12 12:48:48 +00:00
|
|
|
await node2.stop()
|
|
|
|
|
|
|
|
asyncTest "Maximum connections can be configured":
|
|
|
|
let
|
|
|
|
maxConnections = 2
|
|
|
|
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
|
|
|
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"),
|
|
|
|
Port(60010), maxConnections = maxConnections)
|
|
|
|
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
|
|
|
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"),
|
|
|
|
Port(60012))
|
|
|
|
nodeKey3 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
|
|
|
node3 = WakuNode.new(nodeKey3, ValidIpAddress.init("0.0.0.0"),
|
|
|
|
Port(60013))
|
|
|
|
|
|
|
|
check:
|
|
|
|
# Sanity check, to verify config was applied
|
|
|
|
node1.switch.connManager.inSema.size == maxConnections
|
|
|
|
|
|
|
|
# Node with connection limit set to 1
|
|
|
|
await node1.start()
|
|
|
|
node1.mountRelay()
|
|
|
|
|
|
|
|
# Remote node 1
|
|
|
|
await node2.start()
|
|
|
|
node2.mountRelay()
|
|
|
|
|
|
|
|
# Remote node 2
|
|
|
|
await node3.start()
|
|
|
|
node3.mountRelay()
|
|
|
|
|
|
|
|
discard await node1.peerManager.dialPeer(node2.peerInfo.toRemotePeerInfo(), WakuRelayCodec)
|
|
|
|
await sleepAsync(3.seconds)
|
|
|
|
discard await node1.peerManager.dialPeer(node3.peerInfo.toRemotePeerInfo(), WakuRelayCodec)
|
|
|
|
|
|
|
|
check:
|
|
|
|
# Verify that only the first connection succeeded
|
|
|
|
node1.switch.isConnected(node2.peerInfo.peerId)
|
|
|
|
node1.switch.isConnected(node3.peerInfo.peerId) == false
|
|
|
|
|
|
|
|
await allFutures([node1.stop(), node2.stop(), node3.stop()])
|