2020-11-24 04:34:32 +00:00
|
|
|
## Waku Store protocol for historical messaging support.
|
|
|
|
## See spec for more details:
|
|
|
|
## https://github.com/vacp2p/specs/blob/master/specs/waku/v2/waku-store.md
|
2022-11-04 09:52:27 +00:00
|
|
|
when (NimMajor, NimMinor) < (1, 4):
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
else:
|
|
|
|
{.push raises: [].}
|
2021-06-09 14:37:08 +00:00
|
|
|
|
2020-08-31 03:32:41 +00:00
|
|
|
import
|
2022-11-24 18:42:19 +00:00
|
|
|
std/options,
|
2022-08-01 16:21:11 +00:00
|
|
|
stew/results,
|
2021-07-16 22:28:35 +00:00
|
|
|
chronicles,
|
2022-11-21 08:36:41 +00:00
|
|
|
chronos,
|
2022-09-07 15:31:27 +00:00
|
|
|
bearssl/rand,
|
2020-09-28 21:44:14 +00:00
|
|
|
libp2p/crypto/crypto,
|
2020-08-31 03:32:41 +00:00
|
|
|
libp2p/protocols/protocol,
|
|
|
|
libp2p/protobuf/minprotobuf,
|
|
|
|
libp2p/stream/connection,
|
2022-07-25 11:01:37 +00:00
|
|
|
metrics
|
|
|
|
import
|
2023-04-19 14:39:52 +00:00
|
|
|
../waku_core,
|
2023-04-18 13:22:10 +00:00
|
|
|
../node/peer_manager,
|
2022-11-09 17:50:18 +00:00
|
|
|
./common,
|
2022-07-25 11:01:37 +00:00
|
|
|
./rpc,
|
2022-09-28 11:36:05 +00:00
|
|
|
./rpc_codec,
|
2022-10-20 16:09:40 +00:00
|
|
|
./protocol_metrics
|
2020-11-24 04:34:32 +00:00
|
|
|
|
2020-08-27 02:44:09 +00:00
|
|
|
|
2020-09-16 04:23:10 +00:00
|
|
|
logScope:
|
2022-11-03 15:36:24 +00:00
|
|
|
topics = "waku store"
|
2020-09-16 04:23:10 +00:00
|
|
|
|
2022-09-22 09:17:38 +00:00
|
|
|
|
2022-11-21 08:36:41 +00:00
|
|
|
const
|
2022-10-06 15:07:12 +00:00
|
|
|
MaxMessageTimestampVariance* = getNanoSecondTime(20) # 20 seconds maximum allowable sender timestamp "drift"
|
2022-07-25 11:01:37 +00:00
|
|
|
|
2020-08-27 02:44:09 +00:00
|
|
|
|
2023-05-25 15:34:34 +00:00
|
|
|
type HistoryQueryHandler* = proc(req: HistoryQuery): Future[HistoryResult] {.async, gcsafe.}
|
2022-11-21 10:16:57 +00:00
|
|
|
|
2022-06-13 17:59:53 +00:00
|
|
|
type
|
|
|
|
WakuStore* = ref object of LPProtocol
|
2022-11-21 10:16:57 +00:00
|
|
|
peerManager: PeerManager
|
|
|
|
rng: ref rand.HmacDrbgContext
|
|
|
|
queryHandler: HistoryQueryHandler
|
2022-11-09 17:50:18 +00:00
|
|
|
|
|
|
|
## Protocol
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2022-11-21 08:36:41 +00:00
|
|
|
proc initProtocolHandler(ws: WakuStore) =
|
|
|
|
|
2021-06-09 14:37:08 +00:00
|
|
|
proc handler(conn: Connection, proto: string) {.async.} =
|
2022-09-02 08:14:58 +00:00
|
|
|
let buf = await conn.readLp(MaxRpcSize.int)
|
|
|
|
|
2022-11-09 17:50:18 +00:00
|
|
|
let decodeRes = HistoryRPC.decode(buf)
|
|
|
|
if decodeRes.isErr():
|
2022-12-07 11:30:32 +00:00
|
|
|
error "failed to decode rpc", peerId= $conn.peerId
|
2021-02-09 08:31:38 +00:00
|
|
|
waku_store_errors.inc(labelValues = [decodeRpcFailure])
|
2022-11-09 17:50:18 +00:00
|
|
|
# TODO: Return (BAD_REQUEST, cause: "decode rpc failed")
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
let reqRpc = decodeRes.value
|
|
|
|
|
2022-11-17 19:40:08 +00:00
|
|
|
if reqRpc.query.isNone():
|
2022-12-07 11:30:32 +00:00
|
|
|
error "empty query rpc", peerId= $conn.peerId, requestId=reqRpc.requestId
|
2022-11-09 17:50:18 +00:00
|
|
|
waku_store_errors.inc(labelValues = [emptyRpcQueryFailure])
|
|
|
|
# TODO: Return (BAD_REQUEST, cause: "empty query")
|
2020-08-27 02:44:09 +00:00
|
|
|
return
|
|
|
|
|
2022-11-21 10:16:57 +00:00
|
|
|
let
|
|
|
|
requestId = reqRpc.requestId
|
|
|
|
request = reqRpc.query.get().toAPI()
|
2022-09-02 08:14:58 +00:00
|
|
|
|
2022-11-21 10:16:57 +00:00
|
|
|
info "received history query", peerId=conn.peerId, requestId=requestId, query=request
|
2022-01-06 11:23:25 +00:00
|
|
|
waku_store_queries.inc()
|
2020-08-27 02:44:09 +00:00
|
|
|
|
2023-04-11 11:12:45 +00:00
|
|
|
var responseRes: HistoryResult
|
|
|
|
try:
|
2023-05-25 15:34:34 +00:00
|
|
|
responseRes = await ws.queryHandler(request)
|
2023-04-11 11:12:45 +00:00
|
|
|
except Exception:
|
|
|
|
error "history query failed", peerId= $conn.peerId, requestId=requestId, error=getCurrentExceptionMsg()
|
|
|
|
|
|
|
|
let error = HistoryError(kind: HistoryErrorKind.UNKNOWN).toRPC()
|
|
|
|
let response = HistoryResponseRPC(error: error)
|
|
|
|
let rpc = HistoryRPC(requestId: requestId, response: some(response))
|
|
|
|
await conn.writeLp(rpc.encode().buffer)
|
|
|
|
return
|
2022-11-09 17:50:18 +00:00
|
|
|
|
2022-11-21 10:16:57 +00:00
|
|
|
if responseRes.isErr():
|
2022-12-07 11:30:32 +00:00
|
|
|
error "history query failed", peerId= $conn.peerId, requestId=requestId, error=responseRes.error
|
2022-11-09 17:50:18 +00:00
|
|
|
|
2022-11-21 10:16:57 +00:00
|
|
|
let response = responseRes.toRPC()
|
|
|
|
let rpc = HistoryRPC(requestId: requestId, response: some(response))
|
2022-11-09 17:50:18 +00:00
|
|
|
await conn.writeLp(rpc.encode().buffer)
|
|
|
|
return
|
|
|
|
|
|
|
|
|
2022-11-21 10:16:57 +00:00
|
|
|
let response = responseRes.toRPC()
|
2020-11-24 04:53:42 +00:00
|
|
|
|
2022-11-21 10:16:57 +00:00
|
|
|
info "sending history response", peerId=conn.peerId, requestId=requestId, messages=response.messages.len
|
2022-11-09 17:50:18 +00:00
|
|
|
|
2022-11-21 10:16:57 +00:00
|
|
|
let rpc = HistoryRPC(requestId: requestId, response: some(response))
|
2022-09-02 08:14:58 +00:00
|
|
|
await conn.writeLp(rpc.encode().buffer)
|
2020-08-27 02:44:09 +00:00
|
|
|
|
2021-06-09 14:37:08 +00:00
|
|
|
ws.handler = handler
|
2020-08-27 02:44:09 +00:00
|
|
|
ws.codec = WakuStoreCodec
|
2020-11-16 08:38:52 +00:00
|
|
|
|
2022-11-21 10:16:57 +00:00
|
|
|
|
|
|
|
proc new*(T: type WakuStore,
|
|
|
|
peerManager: PeerManager,
|
|
|
|
rng: ref rand.HmacDrbgContext,
|
|
|
|
queryHandler: HistoryQueryHandler): T =
|
|
|
|
|
|
|
|
# Raise a defect if history query handler is nil
|
|
|
|
if queryHandler.isNil():
|
|
|
|
raise newException(NilAccessDefect, "history query handler is nil")
|
|
|
|
|
|
|
|
let ws = WakuStore(
|
|
|
|
rng: rng,
|
|
|
|
peerManager: peerManager,
|
|
|
|
queryHandler: queryHandler
|
|
|
|
)
|
2022-09-20 09:39:52 +00:00
|
|
|
ws.initProtocolHandler()
|
2022-11-09 17:50:18 +00:00
|
|
|
ws
|