2022-09-09 13:54:16 +00:00
|
|
|
{.used.}
|
|
|
|
|
|
|
|
import
|
2022-11-23 09:08:00 +00:00
|
|
|
stew/shims/net as stewNet,
|
2022-09-09 13:54:16 +00:00
|
|
|
testutils/unittests,
|
2022-11-23 09:08:00 +00:00
|
|
|
chronicles,
|
|
|
|
chronos,
|
2022-09-09 13:54:16 +00:00
|
|
|
libp2p/crypto/crypto,
|
|
|
|
libp2p/peerid,
|
|
|
|
libp2p/multiaddress,
|
|
|
|
libp2p/switch,
|
|
|
|
libp2p/protocols/pubsub/rpc/messages,
|
|
|
|
libp2p/protocols/pubsub/pubsub,
|
2022-09-20 09:39:52 +00:00
|
|
|
libp2p/protocols/pubsub/gossipsub
|
2022-09-09 13:54:16 +00:00
|
|
|
import
|
2023-06-22 09:27:40 +00:00
|
|
|
../../../waku/common/databases/db_sqlite,
|
2023-08-09 17:11:50 +00:00
|
|
|
../../../waku/waku_core,
|
2023-11-22 16:32:56 +00:00
|
|
|
../../../waku/waku_core/message/digest,
|
2023-08-09 17:11:50 +00:00
|
|
|
../../../waku/node/peer_manager,
|
|
|
|
../../../waku/waku_archive,
|
|
|
|
../../../waku/waku_archive/driver/sqlite_driver,
|
|
|
|
../../../waku/waku_store,
|
|
|
|
../../../waku/waku_filter,
|
|
|
|
../../../waku/waku_node,
|
2023-02-13 10:43:49 +00:00
|
|
|
../testlib/common,
|
2023-04-05 14:01:51 +00:00
|
|
|
../testlib/wakucore,
|
|
|
|
../testlib/wakunode
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2022-11-23 09:08:00 +00:00
|
|
|
proc newTestArchiveDriver(): ArchiveDriver =
|
2022-10-27 22:05:02 +00:00
|
|
|
let database = SqliteDatabase.new(":memory:").tryGet()
|
2022-11-23 09:08:00 +00:00
|
|
|
SqliteDriver.new(database).tryGet()
|
|
|
|
|
2023-01-30 14:21:51 +00:00
|
|
|
proc computeTestCursor(pubsubTopic: PubsubTopic, message: WakuMessage): HistoryCursor =
|
|
|
|
HistoryCursor(
|
|
|
|
pubsubTopic: pubsubTopic,
|
|
|
|
senderTime: message.timestamp,
|
|
|
|
storeTime: message.timestamp,
|
2023-11-08 00:41:23 +00:00
|
|
|
digest: waku_archive.computeDigest(message)
|
2023-01-30 14:21:51 +00:00
|
|
|
)
|
2022-09-09 13:54:16 +00:00
|
|
|
|
|
|
|
procSuite "WakuNode - Store":
|
2023-01-30 14:21:51 +00:00
|
|
|
## Fixtures
|
|
|
|
let timeOrigin = now()
|
|
|
|
let msgListA = @[
|
|
|
|
fakeWakuMessage(@[byte 00], ts=ts(00, timeOrigin)),
|
|
|
|
fakeWakuMessage(@[byte 01], ts=ts(10, timeOrigin)),
|
|
|
|
fakeWakuMessage(@[byte 02], ts=ts(20, timeOrigin)),
|
|
|
|
fakeWakuMessage(@[byte 03], ts=ts(30, timeOrigin)),
|
|
|
|
fakeWakuMessage(@[byte 04], ts=ts(40, timeOrigin)),
|
|
|
|
fakeWakuMessage(@[byte 05], ts=ts(50, timeOrigin)),
|
|
|
|
fakeWakuMessage(@[byte 06], ts=ts(60, timeOrigin)),
|
|
|
|
fakeWakuMessage(@[byte 07], ts=ts(70, timeOrigin)),
|
|
|
|
fakeWakuMessage(@[byte 08], ts=ts(80, timeOrigin)),
|
|
|
|
fakeWakuMessage(@[byte 09], ts=ts(90, timeOrigin))
|
|
|
|
]
|
|
|
|
|
|
|
|
let archiveA = block:
|
2023-05-25 15:34:34 +00:00
|
|
|
let driver = newTestArchiveDriver()
|
2023-01-30 14:21:51 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
for msg in msgListA:
|
2023-11-08 00:41:23 +00:00
|
|
|
let msg_digest = waku_archive.computeDigest(msg)
|
2023-11-22 16:32:56 +00:00
|
|
|
let msg_hash = computeMessageHash(DefaultPubsubTopic, msg)
|
|
|
|
require (waitFor driver.put(DefaultPubsubTopic, msg, msg_digest, msg_hash, msg.timestamp)).isOk()
|
2023-01-30 14:21:51 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
driver
|
2023-01-30 14:21:51 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
test "Store protocol returns expected messages":
|
2022-09-21 16:27:40 +00:00
|
|
|
## Setup
|
2022-09-09 13:54:16 +00:00
|
|
|
let
|
2023-02-13 10:43:49 +00:00
|
|
|
serverKey = generateSecp256k1Key()
|
2023-04-05 14:01:51 +00:00
|
|
|
server = newTestWakuNode(serverKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
2023-02-13 10:43:49 +00:00
|
|
|
clientKey = generateSecp256k1Key()
|
2023-04-05 14:01:51 +00:00
|
|
|
client = newTestWakuNode(clientKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor allFutures(client.start(), server.start())
|
2022-11-23 09:08:00 +00:00
|
|
|
|
2023-06-27 11:24:31 +00:00
|
|
|
let mountArchiveRes = server.mountArchive(archiveA)
|
|
|
|
assert mountArchiveRes.isOk(), mountArchiveRes.error
|
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor server.mountStore()
|
2022-11-23 09:08:00 +00:00
|
|
|
|
2022-10-28 18:11:28 +00:00
|
|
|
client.mountStoreClient()
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
## Given
|
2023-01-30 14:21:51 +00:00
|
|
|
let req = HistoryQuery(contentTopics: @[DefaultContentTopic])
|
2022-10-28 18:11:28 +00:00
|
|
|
let serverPeer = server.peerInfo.toRemotePeerInfo()
|
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
## When
|
2023-05-25 15:34:34 +00:00
|
|
|
let queryRes = waitFor client.query(req, peer=serverPeer)
|
2022-11-23 09:08:00 +00:00
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
## Then
|
|
|
|
check queryRes.isOk()
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
let response = queryRes.get()
|
2022-09-09 13:54:16 +00:00
|
|
|
check:
|
2023-01-30 14:21:51 +00:00
|
|
|
response.messages == msgListA
|
|
|
|
|
|
|
|
# Cleanup
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor allFutures(client.stop(), server.stop())
|
2023-01-30 14:21:51 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
test "Store node history response - forward pagination":
|
2023-01-30 14:21:51 +00:00
|
|
|
## Setup
|
|
|
|
let
|
2023-02-13 10:43:49 +00:00
|
|
|
serverKey = generateSecp256k1Key()
|
2023-04-05 14:01:51 +00:00
|
|
|
server = newTestWakuNode(serverKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
2023-02-13 10:43:49 +00:00
|
|
|
clientKey = generateSecp256k1Key()
|
2023-04-05 14:01:51 +00:00
|
|
|
client = newTestWakuNode(clientKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
2023-01-30 14:21:51 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor allFutures(client.start(), server.start())
|
2023-01-30 14:21:51 +00:00
|
|
|
|
2023-06-27 11:24:31 +00:00
|
|
|
let mountArchiveRes = server.mountArchive(archiveA)
|
|
|
|
assert mountArchiveRes.isOk(), mountArchiveRes.error
|
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor server.mountStore()
|
2023-01-30 14:21:51 +00:00
|
|
|
|
|
|
|
client.mountStoreClient()
|
|
|
|
|
|
|
|
## Given
|
|
|
|
let req = HistoryQuery(contentTopics: @[DefaultContentTopic], pageSize: 7, ascending: true)
|
|
|
|
let serverPeer = server.peerInfo.toRemotePeerInfo()
|
|
|
|
|
|
|
|
## When
|
|
|
|
var nextReq = req # copy
|
|
|
|
|
|
|
|
var pages = newSeq[seq[WakuMessage]](2)
|
|
|
|
var cursors = newSeq[Option[HistoryCursor]](2)
|
|
|
|
|
|
|
|
for i in 0..<2:
|
2023-05-25 15:34:34 +00:00
|
|
|
let res = waitFor client.query(nextReq, peer=serverPeer)
|
2023-01-30 14:21:51 +00:00
|
|
|
require res.isOk()
|
|
|
|
|
|
|
|
# Keep query response content
|
|
|
|
let response = res.get()
|
|
|
|
pages[i] = response.messages
|
|
|
|
cursors[i] = response.cursor
|
|
|
|
|
|
|
|
# Set/update the request cursor
|
|
|
|
nextReq.cursor = cursors[i]
|
|
|
|
|
|
|
|
## Then
|
|
|
|
check:
|
|
|
|
cursors[0] == some(computeTestCursor(DefaultPubsubTopic, msgListA[6]))
|
|
|
|
cursors[1] == none(HistoryCursor)
|
|
|
|
|
|
|
|
check:
|
|
|
|
pages[0] == msgListA[0..6]
|
|
|
|
pages[1] == msgListA[7..9]
|
|
|
|
|
|
|
|
# Cleanup
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor allFutures(client.stop(), server.stop())
|
2023-01-30 14:21:51 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
test "Store node history response - backward pagination":
|
2023-01-30 14:21:51 +00:00
|
|
|
## Setup
|
|
|
|
let
|
2023-02-13 10:43:49 +00:00
|
|
|
serverKey = generateSecp256k1Key()
|
2023-04-05 14:01:51 +00:00
|
|
|
server = newTestWakuNode(serverKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
2023-02-13 10:43:49 +00:00
|
|
|
clientKey = generateSecp256k1Key()
|
2023-04-05 14:01:51 +00:00
|
|
|
client = newTestWakuNode(clientKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
2023-01-30 14:21:51 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor allFutures(client.start(), server.start())
|
2023-01-30 14:21:51 +00:00
|
|
|
|
2023-06-27 11:24:31 +00:00
|
|
|
let mountArchiveRes = server.mountArchive(archiveA)
|
|
|
|
assert mountArchiveRes.isOk(), mountArchiveRes.error
|
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor server.mountStore()
|
2023-01-30 14:21:51 +00:00
|
|
|
|
|
|
|
client.mountStoreClient()
|
|
|
|
|
|
|
|
## Given
|
|
|
|
let req = HistoryQuery(contentTopics: @[DefaultContentTopic], pageSize: 7, ascending: false)
|
|
|
|
let serverPeer = server.peerInfo.toRemotePeerInfo()
|
|
|
|
|
|
|
|
## When
|
|
|
|
var nextReq = req # copy
|
|
|
|
|
|
|
|
var pages = newSeq[seq[WakuMessage]](2)
|
|
|
|
var cursors = newSeq[Option[HistoryCursor]](2)
|
|
|
|
|
|
|
|
for i in 0..<2:
|
2023-05-25 15:34:34 +00:00
|
|
|
let res = waitFor client.query(nextReq, peer=serverPeer)
|
2023-01-30 14:21:51 +00:00
|
|
|
require res.isOk()
|
|
|
|
|
|
|
|
# Keep query response content
|
|
|
|
let response = res.get()
|
|
|
|
pages[i] = response.messages
|
|
|
|
cursors[i] = response.cursor
|
|
|
|
|
|
|
|
# Set/update the request cursor
|
|
|
|
nextReq.cursor = cursors[i]
|
|
|
|
|
|
|
|
## Then
|
|
|
|
check:
|
|
|
|
cursors[0] == some(computeTestCursor(DefaultPubsubTopic, msgListA[3]))
|
|
|
|
cursors[1] == none(HistoryCursor)
|
|
|
|
|
|
|
|
check:
|
|
|
|
pages[0] == msgListA[3..9]
|
|
|
|
pages[1] == msgListA[0..2]
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
# Cleanup
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor allFutures(client.stop(), server.stop())
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
test "Store protocol returns expected message when relay is disabled and filter enabled":
|
2022-09-21 16:27:40 +00:00
|
|
|
## See nwaku issue #937: 'Store: ability to decouple store from relay'
|
|
|
|
## Setup
|
2022-09-09 13:54:16 +00:00
|
|
|
let
|
2023-02-13 10:43:49 +00:00
|
|
|
filterSourceKey = generateSecp256k1Key()
|
2023-04-05 14:01:51 +00:00
|
|
|
filterSource = newTestWakuNode(filterSourceKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
2023-02-13 10:43:49 +00:00
|
|
|
serverKey = generateSecp256k1Key()
|
2023-04-05 14:01:51 +00:00
|
|
|
server = newTestWakuNode(serverKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
2023-02-13 10:43:49 +00:00
|
|
|
clientKey = generateSecp256k1Key()
|
2023-04-05 14:01:51 +00:00
|
|
|
client = newTestWakuNode(clientKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor allFutures(client.start(), server.start(), filterSource.start())
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor filterSource.mountFilter()
|
2022-11-23 09:08:00 +00:00
|
|
|
let driver = newTestArchiveDriver()
|
2023-06-27 11:24:31 +00:00
|
|
|
|
|
|
|
let mountArchiveRes = server.mountArchive(driver)
|
|
|
|
assert mountArchiveRes.isOk(), mountArchiveRes.error
|
2023-09-14 19:28:57 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor server.mountStore()
|
|
|
|
waitFor server.mountFilterClient()
|
2022-10-28 18:11:28 +00:00
|
|
|
client.mountStoreClient()
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
## Given
|
|
|
|
let message = fakeWakuMessage()
|
2022-11-23 09:08:00 +00:00
|
|
|
let
|
2022-11-02 10:59:58 +00:00
|
|
|
serverPeer = server.peerInfo.toRemotePeerInfo()
|
|
|
|
filterSourcePeer = filterSource.peerInfo.toRemotePeerInfo()
|
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
## Then
|
2022-11-02 10:59:58 +00:00
|
|
|
let filterFut = newFuture[(PubsubTopic, WakuMessage)]()
|
2023-05-25 15:34:34 +00:00
|
|
|
proc filterHandler(pubsubTopic: PubsubTopic, msg: WakuMessage) {.async, gcsafe, closure.} =
|
2022-11-02 10:59:58 +00:00
|
|
|
filterFut.complete((pubsubTopic, msg))
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2023-09-14 19:28:57 +00:00
|
|
|
waitFor server.legacyFilterSubscribe(some(DefaultPubsubTopic), DefaultContentTopic, filterHandler, peer=filterSourcePeer)
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor sleepAsync(100.millis)
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
# Send filter push message to server from source node
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor filterSource.wakuFilterLegacy.handleMessage(DefaultPubsubTopic, message)
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
# Wait for the server filter to receive the push message
|
2023-05-25 15:34:34 +00:00
|
|
|
require waitFor filterFut.withTimeout(5.seconds)
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
let res = waitFor client.query(HistoryQuery(contentTopics: @[DefaultContentTopic]), peer=serverPeer)
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
## Then
|
|
|
|
check res.isOk()
|
2022-09-09 13:54:16 +00:00
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
let response = res.get()
|
2022-09-09 13:54:16 +00:00
|
|
|
check:
|
2022-09-21 16:27:40 +00:00
|
|
|
response.messages.len == 1
|
|
|
|
response.messages[0] == message
|
|
|
|
|
2022-11-02 10:59:58 +00:00
|
|
|
let (handledPubsubTopic, handledMsg) = filterFut.read()
|
|
|
|
check:
|
|
|
|
handledPubsubTopic == DefaultPubsubTopic
|
|
|
|
handledMsg == message
|
|
|
|
|
2022-09-21 16:27:40 +00:00
|
|
|
## Cleanup
|
2023-05-25 15:34:34 +00:00
|
|
|
waitFor allFutures(client.stop(), server.stop(), filterSource.stop())
|
2023-11-22 08:32:39 +00:00
|
|
|
|
|
|
|
test "history query should return INVALID_CURSOR if the cursor has empty data in the request":
|
|
|
|
## Setup
|
|
|
|
let
|
|
|
|
serverKey = generateSecp256k1Key()
|
|
|
|
server = newTestWakuNode(serverKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
|
|
|
clientKey = generateSecp256k1Key()
|
|
|
|
client = newTestWakuNode(clientKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
|
|
|
|
|
|
|
waitFor allFutures(client.start(), server.start())
|
|
|
|
|
|
|
|
let mountArchiveRes = server.mountArchive(archiveA)
|
|
|
|
assert mountArchiveRes.isOk(), mountArchiveRes.error
|
|
|
|
|
|
|
|
waitFor server.mountStore()
|
|
|
|
|
|
|
|
client.mountStoreClient()
|
|
|
|
|
|
|
|
## Forcing a bad cursor with empty digest data
|
|
|
|
var data: array[32, byte] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
|
|
let cursor = HistoryCursor(
|
|
|
|
pubsubTopic: "pubsubTopic",
|
|
|
|
senderTime: now(),
|
|
|
|
storeTime: now(),
|
|
|
|
digest: waku_archive.MessageDigest(data: data)
|
|
|
|
)
|
|
|
|
|
|
|
|
## Given
|
|
|
|
let req = HistoryQuery(contentTopics: @[DefaultContentTopic], cursor: some(cursor))
|
|
|
|
let serverPeer = server.peerInfo.toRemotePeerInfo()
|
|
|
|
|
|
|
|
## When
|
|
|
|
let queryRes = waitFor client.query(req, peer=serverPeer)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
check not queryRes.isOk()
|
|
|
|
|
|
|
|
check queryRes.error == "BAD_REQUEST: invalid cursor"
|
|
|
|
|
|
|
|
# Cleanup
|
|
|
|
waitFor allFutures(client.stop(), server.stop())
|