2021-03-22 09:44:45 +00:00
|
|
|
{.used.}
|
|
|
|
|
|
|
|
import
|
2022-06-27 12:16:15 +00:00
|
|
|
std/[sequtils, strutils, tables],
|
2022-11-28 20:07:21 +00:00
|
|
|
stew/byteutils,
|
|
|
|
stew/shims/net as stewNet,
|
2021-03-26 09:52:04 +00:00
|
|
|
testutils/unittests,
|
2022-11-28 20:07:21 +00:00
|
|
|
chronos,
|
2021-03-22 09:44:45 +00:00
|
|
|
libp2p/crypto/crypto,
|
|
|
|
libp2p/crypto/secp,
|
|
|
|
libp2p/peerid,
|
|
|
|
libp2p/multiaddress,
|
|
|
|
libp2p/switch,
|
|
|
|
libp2p/protocols/pubsub/rpc/messages,
|
|
|
|
libp2p/protocols/pubsub/pubsub,
|
|
|
|
eth/p2p,
|
2022-10-12 19:41:25 +00:00
|
|
|
eth/keys
|
|
|
|
import
|
2021-03-22 09:44:45 +00:00
|
|
|
../../waku/v1/protocol/waku_protocol,
|
2021-03-23 08:04:51 +00:00
|
|
|
../../waku/v2/protocol/waku_message,
|
2023-02-07 09:45:25 +00:00
|
|
|
../../waku/v2/node/waku_node,
|
|
|
|
../../waku/v2/utils/compat,
|
2021-10-06 12:29:08 +00:00
|
|
|
../../waku/v2/utils/peers,
|
2021-03-22 09:44:45 +00:00
|
|
|
../test_helpers
|
|
|
|
|
2023-02-10 08:54:47 +00:00
|
|
|
import
|
|
|
|
../../apps/wakubridge/wakubridge
|
|
|
|
|
|
|
|
|
2021-03-22 09:44:45 +00:00
|
|
|
procSuite "WakuBridge":
|
2021-05-20 16:03:56 +00:00
|
|
|
###############
|
|
|
|
# Suite setup #
|
|
|
|
###############
|
|
|
|
|
2021-06-17 10:59:28 +00:00
|
|
|
const DefaultBridgeTopic = "/waku/2/default-bridge/proto"
|
|
|
|
|
2021-05-20 16:03:56 +00:00
|
|
|
let
|
|
|
|
rng = keys.newRng()
|
2022-09-07 15:31:27 +00:00
|
|
|
cryptoRng = crypto.newRng()
|
2021-05-20 16:03:56 +00:00
|
|
|
|
|
|
|
# Bridge
|
|
|
|
nodev1Key = keys.KeyPair.random(rng[])
|
2022-09-07 15:31:27 +00:00
|
|
|
nodev2Key = crypto.PrivateKey.random(Secp256k1, cryptoRng[])[]
|
2021-05-20 16:03:56 +00:00
|
|
|
bridge = WakuBridge.new(
|
|
|
|
nodev1Key= nodev1Key,
|
2023-02-10 08:54:47 +00:00
|
|
|
nodev1Address = localAddress(62200),
|
2021-05-20 16:03:56 +00:00
|
|
|
powRequirement = 0.002,
|
|
|
|
rng = rng,
|
|
|
|
nodev2Key = nodev2Key,
|
2023-02-10 08:54:47 +00:00
|
|
|
nodev2BindIp = ValidIpAddress.init("0.0.0.0"), nodev2BindPort= Port(62201),
|
2021-06-17 10:59:28 +00:00
|
|
|
nodev2PubsubTopic = DefaultBridgeTopic)
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2021-05-20 16:03:56 +00:00
|
|
|
# Waku v1 node
|
|
|
|
v1Node = setupTestNode(rng, Waku)
|
|
|
|
|
|
|
|
# Waku v2 node
|
2022-09-07 15:31:27 +00:00
|
|
|
v2NodeKey = crypto.PrivateKey.random(Secp256k1, cryptoRng[])[]
|
2023-02-10 08:54:47 +00:00
|
|
|
v2Node = WakuNode.new(v2NodeKey, ValidIpAddress.init("0.0.0.0"), Port(62203))
|
2021-05-20 16:03:56 +00:00
|
|
|
|
2021-08-26 12:24:00 +00:00
|
|
|
contentTopic = ContentTopic("/waku/1/0x1a2b3c4d/rfc26")
|
2021-06-18 10:30:24 +00:00
|
|
|
topic = [byte 0x1a, byte 0x2b, byte 0x3c, byte 0x4d]
|
2021-05-20 16:03:56 +00:00
|
|
|
payloadV1 = "hello from V1".toBytes()
|
|
|
|
payloadV2 = "hello from V2".toBytes()
|
2021-08-26 12:24:00 +00:00
|
|
|
encodedPayloadV2 = Payload(payload: payloadV2, dst: some(nodev1Key.pubKey))
|
|
|
|
message = WakuMessage(payload: encodedPayloadV2.encode(1, rng[]).get(), contentTopic: contentTopic, version: 1)
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2021-05-20 16:03:56 +00:00
|
|
|
########################
|
|
|
|
# Tests setup/teardown #
|
|
|
|
########################
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2021-06-18 10:30:24 +00:00
|
|
|
# setup:
|
|
|
|
# # Runs before each test
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2021-06-18 10:30:24 +00:00
|
|
|
# teardown:
|
|
|
|
# # Runs after each test
|
|
|
|
|
|
|
|
###############
|
|
|
|
# Suite tests #
|
|
|
|
###############
|
|
|
|
|
|
|
|
asyncTest "Messages are bridged between Waku v1 and Waku v2":
|
|
|
|
# Setup test
|
|
|
|
|
2021-05-20 16:03:56 +00:00
|
|
|
waitFor bridge.start()
|
|
|
|
|
|
|
|
waitFor v2Node.start()
|
2022-09-07 15:31:27 +00:00
|
|
|
await v2Node.mountRelay(@[DefaultBridgeTopic], triggerSelf = false)
|
2021-05-20 16:03:56 +00:00
|
|
|
|
|
|
|
discard waitFor v1Node.rlpxConnect(newNode(bridge.nodev1.toENode()))
|
2022-01-10 15:07:35 +00:00
|
|
|
waitFor v2Node.connectToNodes(@[bridge.nodev2.switch.peerInfo.toRemotePeerInfo()])
|
2021-03-22 09:44:45 +00:00
|
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
2021-05-20 16:03:56 +00:00
|
|
|
|
2022-11-28 20:07:21 +00:00
|
|
|
proc relayHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
2022-11-07 15:24:16 +00:00
|
|
|
let msg = WakuMessage.decode(data)
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2021-03-22 09:44:45 +00:00
|
|
|
if msg.isOk() and msg.value().version == 1:
|
2021-03-23 08:04:51 +00:00
|
|
|
check:
|
|
|
|
# Message fields are as expected
|
|
|
|
msg.value().contentTopic == contentTopic # Topic translation worked
|
|
|
|
string.fromBytes(msg.value().payload).contains("from V1")
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2021-03-22 09:44:45 +00:00
|
|
|
completionFut.complete(true)
|
|
|
|
|
2021-05-20 16:03:56 +00:00
|
|
|
v2Node.subscribe(DefaultBridgeTopic, relayHandler)
|
2021-03-22 09:44:45 +00:00
|
|
|
|
|
|
|
# Test bridging from V2 to V1
|
2021-05-20 16:03:56 +00:00
|
|
|
await v2Node.publish(DefaultBridgeTopic, message)
|
2021-03-22 09:44:45 +00:00
|
|
|
|
2022-11-28 20:07:21 +00:00
|
|
|
await sleepAsync(1.seconds)
|
2021-03-22 09:44:45 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
# v1Node received message published by v2Node
|
|
|
|
v1Node.protocolState(Waku).queue.items.len == 1
|
2021-03-23 08:04:51 +00:00
|
|
|
|
2021-08-26 12:24:00 +00:00
|
|
|
let
|
|
|
|
msg = v1Node.protocolState(Waku).queue.items[0]
|
|
|
|
decodedPayload = msg.env.data.decode(some(nodev1Key.seckey), none[SymKey]()).get()
|
2021-03-23 08:04:51 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
# Message fields are as expected
|
|
|
|
msg.env.topic == topic # Topic translation worked
|
2021-08-26 12:24:00 +00:00
|
|
|
string.fromBytes(decodedPayload.payload).contains("from V2")
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2021-03-22 09:44:45 +00:00
|
|
|
# Test bridging from V1 to V2
|
|
|
|
check:
|
|
|
|
v1Node.postMessage(ttl = 5,
|
|
|
|
topic = topic,
|
|
|
|
payload = payloadV1) == true
|
|
|
|
|
|
|
|
# v2Node received payload published by v1Node
|
|
|
|
await completionFut.withTimeout(5.seconds)
|
|
|
|
|
2021-05-20 16:03:56 +00:00
|
|
|
# Test filtering of WakuMessage duplicates
|
|
|
|
v1Node.resetMessageQueue()
|
|
|
|
|
|
|
|
await v2Node.publish(DefaultBridgeTopic, message)
|
|
|
|
|
2022-11-28 20:07:21 +00:00
|
|
|
await sleepAsync(1.seconds)
|
2021-05-20 16:03:56 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
# v1Node did not receive duplicate of previous message
|
|
|
|
v1Node.protocolState(Waku).queue.items.len == 0
|
2021-06-18 10:30:24 +00:00
|
|
|
|
|
|
|
# Teardown test
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2021-06-18 10:30:24 +00:00
|
|
|
bridge.nodeV1.resetMessageQueue()
|
|
|
|
v1Node.resetMessageQueue()
|
|
|
|
waitFor allFutures([bridge.stop(), v2Node.stop()])
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2022-06-27 12:16:15 +00:00
|
|
|
asyncTest "Bridge manages its v1 connections":
|
|
|
|
# Given
|
|
|
|
let
|
|
|
|
# Waku v1 node
|
|
|
|
v1NodePool = @[setupTestNode(rng, Waku),
|
|
|
|
setupTestNode(rng, Waku),
|
|
|
|
setupTestNode(rng, Waku)]
|
|
|
|
targetV1Peers = v1NodePool.len() - 1
|
|
|
|
|
|
|
|
# Bridge
|
|
|
|
v1Bridge = WakuBridge.new(
|
|
|
|
nodev1Key= nodev1Key,
|
2023-02-10 08:54:47 +00:00
|
|
|
nodev1Address = localAddress(62210),
|
2022-06-27 12:16:15 +00:00
|
|
|
powRequirement = 0.002,
|
|
|
|
rng = rng,
|
|
|
|
nodev2Key = nodev2Key,
|
2023-02-10 08:54:47 +00:00
|
|
|
nodev2BindIp = ValidIpAddress.init("0.0.0.0"), nodev2BindPort= Port(62211),
|
2022-06-27 12:16:15 +00:00
|
|
|
nodev2PubsubTopic = DefaultBridgeTopic,
|
|
|
|
v1Pool = v1NodePool.mapIt(newNode(it.toEnode())),
|
|
|
|
targetV1Peers = targetV1Peers)
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2022-06-27 12:16:15 +00:00
|
|
|
for node in v1NodePool:
|
|
|
|
node.startListening()
|
2022-11-28 20:07:21 +00:00
|
|
|
|
2022-06-27 12:16:15 +00:00
|
|
|
# When
|
|
|
|
waitFor v1Bridge.start()
|
2022-10-12 19:41:25 +00:00
|
|
|
await sleepAsync(250.millis) # Give peers some time to connect
|
2022-06-27 12:16:15 +00:00
|
|
|
|
|
|
|
# Then
|
|
|
|
check:
|
|
|
|
v1Bridge.nodev1.peerPool.connectedNodes.len() == targetV1Peers
|
|
|
|
|
|
|
|
# When
|
|
|
|
let connected = v1Bridge.nodev1.peerPool.connectedNodes
|
|
|
|
for peer in connected.values():
|
|
|
|
waitFor peer.disconnect(SubprotocolReason)
|
|
|
|
|
|
|
|
# Then
|
|
|
|
check:
|
|
|
|
v1Bridge.nodev1.peerPool.connectedNodes.len() == 0
|
|
|
|
|
|
|
|
# When
|
|
|
|
discard v1Bridge.maintenanceLoop() # Forces one more run of the maintenance loop
|
2022-10-12 19:41:25 +00:00
|
|
|
await sleepAsync(250.millis) # Give peers some time to connect
|
2022-06-27 12:16:15 +00:00
|
|
|
|
|
|
|
# Then
|
|
|
|
check:
|
|
|
|
v1Bridge.nodev1.peerPool.connectedNodes.len() == targetV1Peers
|
|
|
|
|
|
|
|
# Cleanup
|
|
|
|
v1Bridge.nodev1.resetMessageQueue()
|
|
|
|
|
|
|
|
for node in v1NodePool:
|
|
|
|
node.resetMessageQueue()
|
|
|
|
|
|
|
|
waitFor v1Bridge.stop()
|