@waku/core 0.0.36-a7f52e4.0 → 0.0.36-a8ca168.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/index.js +138 -19
- package/bundle/lib/message/version_0.js +1 -1
- package/bundle/{version_0-CiYGrPc2.js → version_0-CyeTW0Vr.js} +17 -5
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/filter/filter.d.ts +4 -2
- package/dist/lib/filter/filter.js +21 -3
- package/dist/lib/filter/filter.js.map +1 -1
- package/dist/lib/message/version_0.d.ts +2 -3
- package/dist/lib/message/version_0.js +1 -4
- package/dist/lib/message/version_0.js.map +1 -1
- package/dist/lib/message_hash/index.d.ts +1 -0
- package/dist/lib/message_hash/index.js +2 -0
- package/dist/lib/message_hash/index.js.map +1 -0
- package/dist/lib/message_hash/message_hash.d.ts +52 -0
- package/dist/lib/message_hash/message_hash.js +84 -0
- package/dist/lib/message_hash/message_hash.js.map +1 -0
- package/dist/lib/store/rpc.js +16 -10
- package/dist/lib/store/rpc.js.map +1 -1
- package/dist/lib/store/store.js +12 -2
- package/dist/lib/store/store.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/lib/filter/filter.ts +33 -6
- package/src/lib/message/version_0.ts +3 -7
- package/src/lib/message_hash/index.ts +1 -0
- package/src/lib/message_hash/message_hash.ts +106 -0
- package/src/lib/store/rpc.ts +23 -19
- package/src/lib/store/store.ts +13 -1
@@ -0,0 +1,52 @@
|
|
1
|
+
import type { IDecodedMessage, IProtoMessage } from "@waku/interfaces";
|
2
|
+
/**
|
3
|
+
* Deterministic Message Hashing as defined in
|
4
|
+
* [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/#deterministic-message-hashing)
|
5
|
+
*
|
6
|
+
* Computes a SHA-256 hash of the concatenation of pubsub topic, payload, content topic, meta, and timestamp.
|
7
|
+
*
|
8
|
+
* @param pubsubTopic - The pubsub topic string
|
9
|
+
* @param message - The message to be hashed
|
10
|
+
* @returns A Uint8Array containing the SHA-256 hash
|
11
|
+
*
|
12
|
+
* @example
|
13
|
+
* ```typescript
|
14
|
+
* import { messageHash } from "@waku/core";
|
15
|
+
*
|
16
|
+
* const pubsubTopic = "/waku/2/default-waku/proto";
|
17
|
+
* const message = {
|
18
|
+
* payload: new Uint8Array([1, 2, 3, 4]),
|
19
|
+
* contentTopic: "/waku/2/default-content/proto",
|
20
|
+
* meta: new Uint8Array([5, 6, 7, 8]),
|
21
|
+
* timestamp: new Date()
|
22
|
+
* };
|
23
|
+
*
|
24
|
+
* const hash = messageHash(pubsubTopic, message);
|
25
|
+
* ```
|
26
|
+
*/
|
27
|
+
export declare function messageHash(pubsubTopic: string, message: IProtoMessage | IDecodedMessage): Uint8Array;
|
28
|
+
/**
|
29
|
+
* Computes a deterministic message hash and returns it as a hexadecimal string.
|
30
|
+
* This is a convenience wrapper around messageHash that converts the result to a hex string.
|
31
|
+
*
|
32
|
+
* @param pubsubTopic - The pubsub topic string
|
33
|
+
* @param message - The message to be hashed
|
34
|
+
* @returns A string containing the hex representation of the SHA-256 hash
|
35
|
+
*
|
36
|
+
* @example
|
37
|
+
* ```typescript
|
38
|
+
* import { messageHashStr } from "@waku/core";
|
39
|
+
*
|
40
|
+
* const pubsubTopic = "/waku/2/default-waku/proto";
|
41
|
+
* const message = {
|
42
|
+
* payload: new Uint8Array([1, 2, 3, 4]),
|
43
|
+
* contentTopic: "/waku/2/default-content/proto",
|
44
|
+
* meta: new Uint8Array([5, 6, 7, 8]),
|
45
|
+
* timestamp: new Date()
|
46
|
+
* };
|
47
|
+
*
|
48
|
+
* const hashString = messageHashStr(pubsubTopic, message);
|
49
|
+
* console.log(hashString); // e.g. "a1b2c3d4..."
|
50
|
+
* ```
|
51
|
+
*/
|
52
|
+
export declare function messageHashStr(pubsubTopic: string, message: IProtoMessage | IDecodedMessage): string;
|
@@ -0,0 +1,84 @@
|
|
1
|
+
import { sha256 } from "@noble/hashes/sha256";
|
2
|
+
import { isDefined } from "@waku/utils";
|
3
|
+
import { bytesToHex, concat, numberToBytes, utf8ToBytes } from "@waku/utils/bytes";
|
4
|
+
/**
|
5
|
+
* Deterministic Message Hashing as defined in
|
6
|
+
* [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/#deterministic-message-hashing)
|
7
|
+
*
|
8
|
+
* Computes a SHA-256 hash of the concatenation of pubsub topic, payload, content topic, meta, and timestamp.
|
9
|
+
*
|
10
|
+
* @param pubsubTopic - The pubsub topic string
|
11
|
+
* @param message - The message to be hashed
|
12
|
+
* @returns A Uint8Array containing the SHA-256 hash
|
13
|
+
*
|
14
|
+
* @example
|
15
|
+
* ```typescript
|
16
|
+
* import { messageHash } from "@waku/core";
|
17
|
+
*
|
18
|
+
* const pubsubTopic = "/waku/2/default-waku/proto";
|
19
|
+
* const message = {
|
20
|
+
* payload: new Uint8Array([1, 2, 3, 4]),
|
21
|
+
* contentTopic: "/waku/2/default-content/proto",
|
22
|
+
* meta: new Uint8Array([5, 6, 7, 8]),
|
23
|
+
* timestamp: new Date()
|
24
|
+
* };
|
25
|
+
*
|
26
|
+
* const hash = messageHash(pubsubTopic, message);
|
27
|
+
* ```
|
28
|
+
*/
|
29
|
+
export function messageHash(pubsubTopic, message) {
|
30
|
+
const pubsubTopicBytes = utf8ToBytes(pubsubTopic);
|
31
|
+
const contentTopicBytes = utf8ToBytes(message.contentTopic);
|
32
|
+
const timestampBytes = tryConvertTimestampToBytes(message.timestamp);
|
33
|
+
const bytes = concat([
|
34
|
+
pubsubTopicBytes,
|
35
|
+
message.payload,
|
36
|
+
contentTopicBytes,
|
37
|
+
message.meta,
|
38
|
+
timestampBytes
|
39
|
+
].filter(isDefined));
|
40
|
+
return sha256(bytes);
|
41
|
+
}
|
42
|
+
function tryConvertTimestampToBytes(timestamp) {
|
43
|
+
if (!timestamp) {
|
44
|
+
return;
|
45
|
+
}
|
46
|
+
let bigIntTimestamp;
|
47
|
+
if (typeof timestamp === "bigint") {
|
48
|
+
bigIntTimestamp = timestamp;
|
49
|
+
}
|
50
|
+
else {
|
51
|
+
bigIntTimestamp = BigInt(timestamp.valueOf()) * 1000000n;
|
52
|
+
}
|
53
|
+
return numberToBytes(bigIntTimestamp);
|
54
|
+
}
|
55
|
+
/**
|
56
|
+
* Computes a deterministic message hash and returns it as a hexadecimal string.
|
57
|
+
* This is a convenience wrapper around messageHash that converts the result to a hex string.
|
58
|
+
*
|
59
|
+
* @param pubsubTopic - The pubsub topic string
|
60
|
+
* @param message - The message to be hashed
|
61
|
+
* @returns A string containing the hex representation of the SHA-256 hash
|
62
|
+
*
|
63
|
+
* @example
|
64
|
+
* ```typescript
|
65
|
+
* import { messageHashStr } from "@waku/core";
|
66
|
+
*
|
67
|
+
* const pubsubTopic = "/waku/2/default-waku/proto";
|
68
|
+
* const message = {
|
69
|
+
* payload: new Uint8Array([1, 2, 3, 4]),
|
70
|
+
* contentTopic: "/waku/2/default-content/proto",
|
71
|
+
* meta: new Uint8Array([5, 6, 7, 8]),
|
72
|
+
* timestamp: new Date()
|
73
|
+
* };
|
74
|
+
*
|
75
|
+
* const hashString = messageHashStr(pubsubTopic, message);
|
76
|
+
* console.log(hashString); // e.g. "a1b2c3d4..."
|
77
|
+
* ```
|
78
|
+
*/
|
79
|
+
export function messageHashStr(pubsubTopic, message) {
|
80
|
+
const hash = messageHash(pubsubTopic, message);
|
81
|
+
const hashStr = bytesToHex(hash);
|
82
|
+
return hashStr;
|
83
|
+
}
|
84
|
+
//# sourceMappingURL=message_hash.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"message_hash.js","sourceRoot":"","sources":["../../../src/lib/message_hash/message_hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,UAAU,EACV,MAAM,EACN,aAAa,EACb,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,WAAW,CACzB,WAAmB,EACnB,OAAwC;IAExC,MAAM,gBAAgB,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAClD,MAAM,iBAAiB,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5D,MAAM,cAAc,GAAG,0BAA0B,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAErE,MAAM,KAAK,GAAG,MAAM,CAClB;QACE,gBAAgB;QAChB,OAAO,CAAC,OAAO;QACf,iBAAiB;QACjB,OAAO,CAAC,IAAI;QACZ,cAAc;KACf,CAAC,MAAM,CAAC,SAAS,CAAC,CACpB,CAAC;IAEF,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,0BAA0B,CACjC,SAA6C;IAE7C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,IAAI,eAAuB,CAAC;IAE5B,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,eAAe,GAAG,SAAS,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC;IAC3D,CAAC;IAED,OAAO,aAAa,CAAC,eAAe,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,cAAc,CAC5B,WAAmB,EACnB,OAAwC;IAExC,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/lib/store/rpc.js
CHANGED
@@ -12,6 +12,7 @@ export class StoreQueryRequest {
|
|
12
12
|
static create(params) {
|
13
13
|
const request = new StoreQueryRequest({
|
14
14
|
...params,
|
15
|
+
contentTopics: params.contentTopics || [],
|
15
16
|
requestId: uuid(),
|
16
17
|
timeStart: params.timeStart
|
17
18
|
? BigInt(params.timeStart.getTime() * ONE_MILLION)
|
@@ -24,17 +25,22 @@ export class StoreQueryRequest {
|
|
24
25
|
? BigInt(params.paginationLimit)
|
25
26
|
: undefined
|
26
27
|
});
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
const isHashQuery = params.messageHashes && params.messageHashes.length > 0;
|
29
|
+
const hasContentTopics = params.contentTopics && params.contentTopics.length > 0;
|
30
|
+
const hasTimeFilter = params.timeStart || params.timeEnd;
|
31
|
+
if (isHashQuery) {
|
32
|
+
if (hasContentTopics || hasTimeFilter) {
|
33
|
+
throw new Error("Message hash lookup queries cannot include content filter criteria (contentTopics, timeStart, or timeEnd)");
|
34
|
+
}
|
31
35
|
}
|
32
|
-
|
33
|
-
(params.pubsubTopic
|
34
|
-
params.contentTopics ||
|
35
|
-
params.
|
36
|
-
|
37
|
-
|
36
|
+
else {
|
37
|
+
if ((params.pubsubTopic &&
|
38
|
+
(!params.contentTopics || params.contentTopics.length === 0)) ||
|
39
|
+
(!params.pubsubTopic &&
|
40
|
+
params.contentTopics &&
|
41
|
+
params.contentTopics.length > 0)) {
|
42
|
+
throw new Error("Both pubsubTopic and contentTopics must be set together for content-filtered queries");
|
43
|
+
}
|
38
44
|
}
|
39
45
|
return request;
|
40
46
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../../src/lib/store/rpc.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,IAAI,KAAK,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAElC,iHAAiH;AACjH,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AACjC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAE7B,MAAM,OAAO,iBAAiB;IACF;IAA1B,YAA0B,KAA8B;QAA9B,UAAK,GAAL,KAAK,CAAyB;IAAG,CAAC;IAErD,MAAM,CAAC,MAAM,CAAC,MAA0B;QAC7C,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,GAAG,MAAM;YACT,SAAS,EAAE,IAAI,EAAE;YACjB,SAAS,EAAE,MAAM,CAAC,SAAS;gBACzB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC;gBAClD,CAAC,CAAC,SAAS;YACb,OAAO,EAAE,MAAM,CAAC,OAAO;gBACrB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC;gBAChD,CAAC,CAAC,SAAS;YACb,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;YACzC,eAAe,EAAE,MAAM,CAAC,eAAe;gBACrC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;gBAChC,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;QAEH,
|
1
|
+
{"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../../src/lib/store/rpc.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/store/store.js
CHANGED
@@ -15,8 +15,12 @@ export class StoreCore extends BaseProtocol {
|
|
15
15
|
this.pubsubTopics = pubsubTopics;
|
16
16
|
}
|
17
17
|
async *queryPerPage(queryOpts, decoders, peerId) {
|
18
|
-
|
19
|
-
|
18
|
+
// Only validate decoder content topics for content-filtered queries
|
19
|
+
const isHashQuery = queryOpts.messageHashes && queryOpts.messageHashes.length > 0;
|
20
|
+
if (!isHashQuery &&
|
21
|
+
queryOpts.contentTopics &&
|
22
|
+
queryOpts.contentTopics.toString() !==
|
23
|
+
Array.from(decoders.keys()).toString()) {
|
20
24
|
throw new Error("Internal error, the decoders should match the query's content topics");
|
21
25
|
}
|
22
26
|
let currentCursor = queryOpts.paginationCursor;
|
@@ -25,6 +29,12 @@ export class StoreCore extends BaseProtocol {
|
|
25
29
|
...queryOpts,
|
26
30
|
paginationCursor: currentCursor
|
27
31
|
});
|
32
|
+
log.info("Sending store query request:", {
|
33
|
+
hasMessageHashes: !!queryOpts.messageHashes?.length,
|
34
|
+
messageHashCount: queryOpts.messageHashes?.length,
|
35
|
+
pubsubTopic: queryOpts.pubsubTopic,
|
36
|
+
contentTopics: queryOpts.contentTopics
|
37
|
+
});
|
28
38
|
let stream;
|
29
39
|
try {
|
30
40
|
stream = await this.getStream(peerId);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/lib/store/store.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,GAAG,MAAM,QAAQ,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAElB,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC;AAEhC,MAAM,CAAC,MAAM,UAAU,GAAG,6BAA6B,CAAC;AAExD,MAAM,OAAO,SAAU,SAAQ,YAAY;IAEvB;IADlB,YACkB,YAA2B,EAC3C,MAAc;QAEd,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QAHnC,iBAAY,GAAZ,YAAY,CAAe;IAI7C,CAAC;IAEM,KAAK,CAAC,CAAC,YAAY,CACxB,SAA6B,EAC7B,QAAkC,EAClC,MAAc;QAEd,IACE,SAAS,CAAC,aAAa,CAAC,QAAQ,EAAE;
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/lib/store/store.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"name":"@waku/core","version":"0.0.36-
|
1
|
+
{"name":"@waku/core","version":"0.0.36-a8ca168.0","description":"TypeScript implementation of the Waku v2 protocol","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./lib/message/version_0":{"types":"./dist/lib/message/version_0.d.ts","import":"./dist/lib/message/version_0.js"},"./lib/base_protocol":{"types":"./dist/lib/base_protocol.d.ts","import":"./dist/lib/base_protocol.js"}},"typesVersions":{"*":{"lib/*":["dist/lib/*"],"constants/*":["dist/constants/*"]}},"type":"module","homepage":"https://github.com/waku-org/js-waku/tree/master/packages/core#readme","repository":{"type":"git","url":"https://github.com/waku-org/js-waku.git"},"bugs":{"url":"https://github.com/waku-org/js-waku/issues"},"license":"MIT OR Apache-2.0","keywords":["waku","decentralised","communication","web3","ethereum","dapps"],"scripts":{"build":"run-s build:**","build:esm":"tsc","build:bundle":"rollup --config rollup.config.js","fix":"run-s fix:*","fix:lint":"eslint src *.js --fix","check":"run-s check:*","check:tsc":"tsc -p tsconfig.dev.json","check:lint":"eslint src *.js","check:spelling":"cspell \"{README.md,src/**/*.ts}\"","test":"NODE_ENV=test run-s test:*","test:node":"NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha","test:browser":"NODE_ENV=test karma start karma.conf.cjs","watch:build":"tsc -p tsconfig.json -w","watch:test":"mocha --watch","prepublish":"npm run build","reset-hard":"git clean -dfx -e .idea && git reset --hard && npm i && npm run build"},"engines":{"node":">=20"},"dependencies":{"@waku/enr":"0.0.30-a8ca168.0","@waku/interfaces":"0.0.31-a8ca168.0","@libp2p/ping":"2.0.1","@waku/proto":"0.0.11-a8ca168.0","@waku/utils":"0.0.24-a8ca168.0","debug":"^4.3.4","@noble/hashes":"^1.3.2","it-all":"^3.0.4","it-length-prefixed":"^9.0.4","it-pipe":"^3.0.1","uint8arraylist":"^2.4.3","uuid":"^9.0.0"},"devDependencies":{"@libp2p/peer-id":"^5.0.1","@libp2p/interface":"^2.1.3","@multiformats/multiaddr":"^12.0.0","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.0.0","@rollup/plugin-node-resolve":"^15.2.3","@types/chai":"^4.3.11","@types/debug":"^4.1.12","@types/mocha":"^10.0.6","@types/uuid":"^9.0.8","@waku/build-utils":"*","chai":"^4.3.10","sinon":"^18.0.0","cspell":"^8.6.1","fast-check":"^3.19.0","ignore-loader":"^0.1.2","isomorphic-fetch":"^3.0.0","mocha":"^10.3.0","npm-run-all":"^4.1.5","process":"^0.11.10","rollup":"^4.12.0"},"peerDependencies":{"@multiformats/multiaddr":"^12.0.0","libp2p":"2.1.8"},"peerDependenciesMeta":{"@multiformats/multiaddr":{"optional":true},"libp2p":{"optional":true}},"files":["dist","bundle","src/**/*.ts","!**/*.spec.*","!**/*.json","CHANGELOG.md","LICENSE","README.md"]}
|
package/src/index.ts
CHANGED
@@ -20,3 +20,5 @@ export { ConnectionManager } from "./lib/connection_manager/index.js";
|
|
20
20
|
export { StreamManager } from "./lib/stream_manager/index.js";
|
21
21
|
|
22
22
|
export { MetadataCodec, wakuMetadata } from "./lib/metadata/index.js";
|
23
|
+
|
24
|
+
export { messageHash, messageHashStr } from "./lib/message_hash/index.js";
|
package/src/lib/filter/filter.ts
CHANGED
@@ -30,18 +30,45 @@ export const FilterCodecs = {
|
|
30
30
|
PUSH: "/vac/waku/filter-push/2.0.0-beta1"
|
31
31
|
};
|
32
32
|
|
33
|
+
type IncomingMessageHandler = (
|
34
|
+
pubsubTopic: PubsubTopic,
|
35
|
+
wakuMessage: WakuMessage,
|
36
|
+
peerIdStr: string
|
37
|
+
) => Promise<void>;
|
38
|
+
|
33
39
|
export class FilterCore extends BaseProtocol implements IBaseProtocolCore {
|
40
|
+
private static handleIncomingMessage?: IncomingMessageHandler;
|
41
|
+
|
34
42
|
public constructor(
|
35
|
-
|
36
|
-
pubsubTopic: PubsubTopic,
|
37
|
-
wakuMessage: WakuMessage,
|
38
|
-
peerIdStr: string
|
39
|
-
) => Promise<void>,
|
43
|
+
handleIncomingMessage: IncomingMessageHandler,
|
40
44
|
public readonly pubsubTopics: PubsubTopic[],
|
41
45
|
libp2p: Libp2p
|
42
46
|
) {
|
43
47
|
super(FilterCodecs.SUBSCRIBE, libp2p.components, pubsubTopics);
|
44
48
|
|
49
|
+
// TODO(weboko): remove when @waku/sdk 0.0.33 is released
|
50
|
+
const prevHandler = FilterCore.handleIncomingMessage;
|
51
|
+
FilterCore.handleIncomingMessage = !prevHandler
|
52
|
+
? handleIncomingMessage
|
53
|
+
: async (pubsubTopic, message, peerIdStr): Promise<void> => {
|
54
|
+
try {
|
55
|
+
await prevHandler(pubsubTopic, message, peerIdStr);
|
56
|
+
} catch (e) {
|
57
|
+
log.error(
|
58
|
+
"Previous FilterCore incoming message handler failed ",
|
59
|
+
e
|
60
|
+
);
|
61
|
+
}
|
62
|
+
|
63
|
+
try {
|
64
|
+
await handleIncomingMessage(pubsubTopic, message, peerIdStr);
|
65
|
+
} catch (e) {
|
66
|
+
log.error("Present FilterCore incoming message handler failed ", e);
|
67
|
+
}
|
68
|
+
|
69
|
+
return;
|
70
|
+
};
|
71
|
+
|
45
72
|
libp2p
|
46
73
|
.handle(FilterCodecs.PUSH, this.onRequest.bind(this), {
|
47
74
|
maxInboundStreams: 100
|
@@ -291,7 +318,7 @@ export class FilterCore extends BaseProtocol implements IBaseProtocolCore {
|
|
291
318
|
return;
|
292
319
|
}
|
293
320
|
|
294
|
-
await
|
321
|
+
await FilterCore.handleIncomingMessage?.(
|
295
322
|
pubsubTopic,
|
296
323
|
wakuMessage,
|
297
324
|
connection.remotePeer.toString()
|
@@ -22,7 +22,7 @@ export { proto };
|
|
22
22
|
export class DecodedMessage implements IDecodedMessage {
|
23
23
|
public constructor(
|
24
24
|
public pubsubTopic: string,
|
25
|
-
|
25
|
+
private proto: proto.WakuMessage
|
26
26
|
) {}
|
27
27
|
|
28
28
|
public get ephemeral(): boolean {
|
@@ -37,10 +37,6 @@ export class DecodedMessage implements IDecodedMessage {
|
|
37
37
|
return this.proto.contentTopic;
|
38
38
|
}
|
39
39
|
|
40
|
-
public get _rawTimestamp(): bigint | undefined {
|
41
|
-
return this.proto.timestamp;
|
42
|
-
}
|
43
|
-
|
44
40
|
public get timestamp(): Date | undefined {
|
45
41
|
// In the case we receive a value that is bigger than JS's max number,
|
46
42
|
// we catch the error and return undefined.
|
@@ -63,7 +59,7 @@ export class DecodedMessage implements IDecodedMessage {
|
|
63
59
|
public get version(): number {
|
64
60
|
// https://rfc.vac.dev/spec/14/
|
65
61
|
// > If omitted, the value SHOULD be interpreted as version 0.
|
66
|
-
return this.proto.version ??
|
62
|
+
return this.proto.version ?? Version;
|
67
63
|
}
|
68
64
|
|
69
65
|
public get rateLimitProof(): IRateLimitProof | undefined {
|
@@ -160,7 +156,7 @@ export class Decoder implements IDecoder<IDecodedMessage> {
|
|
160
156
|
public async fromProtoObj(
|
161
157
|
pubsubTopic: string,
|
162
158
|
proto: IProtoMessage
|
163
|
-
): Promise<
|
159
|
+
): Promise<IDecodedMessage | undefined> {
|
164
160
|
// https://rfc.vac.dev/spec/14/
|
165
161
|
// > If omitted, the value SHOULD be interpreted as version 0.
|
166
162
|
if (proto.version ?? 0 !== Version) {
|
@@ -0,0 +1 @@
|
|
1
|
+
export { messageHash, messageHashStr } from "./message_hash.js";
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import { sha256 } from "@noble/hashes/sha256";
|
2
|
+
import type { IDecodedMessage, IProtoMessage } from "@waku/interfaces";
|
3
|
+
import { isDefined } from "@waku/utils";
|
4
|
+
import {
|
5
|
+
bytesToHex,
|
6
|
+
concat,
|
7
|
+
numberToBytes,
|
8
|
+
utf8ToBytes
|
9
|
+
} from "@waku/utils/bytes";
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Deterministic Message Hashing as defined in
|
13
|
+
* [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/#deterministic-message-hashing)
|
14
|
+
*
|
15
|
+
* Computes a SHA-256 hash of the concatenation of pubsub topic, payload, content topic, meta, and timestamp.
|
16
|
+
*
|
17
|
+
* @param pubsubTopic - The pubsub topic string
|
18
|
+
* @param message - The message to be hashed
|
19
|
+
* @returns A Uint8Array containing the SHA-256 hash
|
20
|
+
*
|
21
|
+
* @example
|
22
|
+
* ```typescript
|
23
|
+
* import { messageHash } from "@waku/core";
|
24
|
+
*
|
25
|
+
* const pubsubTopic = "/waku/2/default-waku/proto";
|
26
|
+
* const message = {
|
27
|
+
* payload: new Uint8Array([1, 2, 3, 4]),
|
28
|
+
* contentTopic: "/waku/2/default-content/proto",
|
29
|
+
* meta: new Uint8Array([5, 6, 7, 8]),
|
30
|
+
* timestamp: new Date()
|
31
|
+
* };
|
32
|
+
*
|
33
|
+
* const hash = messageHash(pubsubTopic, message);
|
34
|
+
* ```
|
35
|
+
*/
|
36
|
+
export function messageHash(
|
37
|
+
pubsubTopic: string,
|
38
|
+
message: IProtoMessage | IDecodedMessage
|
39
|
+
): Uint8Array {
|
40
|
+
const pubsubTopicBytes = utf8ToBytes(pubsubTopic);
|
41
|
+
const contentTopicBytes = utf8ToBytes(message.contentTopic);
|
42
|
+
const timestampBytes = tryConvertTimestampToBytes(message.timestamp);
|
43
|
+
|
44
|
+
const bytes = concat(
|
45
|
+
[
|
46
|
+
pubsubTopicBytes,
|
47
|
+
message.payload,
|
48
|
+
contentTopicBytes,
|
49
|
+
message.meta,
|
50
|
+
timestampBytes
|
51
|
+
].filter(isDefined)
|
52
|
+
);
|
53
|
+
|
54
|
+
return sha256(bytes);
|
55
|
+
}
|
56
|
+
|
57
|
+
function tryConvertTimestampToBytes(
|
58
|
+
timestamp: Date | number | bigint | undefined
|
59
|
+
): undefined | Uint8Array {
|
60
|
+
if (!timestamp) {
|
61
|
+
return;
|
62
|
+
}
|
63
|
+
|
64
|
+
let bigIntTimestamp: bigint;
|
65
|
+
|
66
|
+
if (typeof timestamp === "bigint") {
|
67
|
+
bigIntTimestamp = timestamp;
|
68
|
+
} else {
|
69
|
+
bigIntTimestamp = BigInt(timestamp.valueOf()) * 1000000n;
|
70
|
+
}
|
71
|
+
|
72
|
+
return numberToBytes(bigIntTimestamp);
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* Computes a deterministic message hash and returns it as a hexadecimal string.
|
77
|
+
* This is a convenience wrapper around messageHash that converts the result to a hex string.
|
78
|
+
*
|
79
|
+
* @param pubsubTopic - The pubsub topic string
|
80
|
+
* @param message - The message to be hashed
|
81
|
+
* @returns A string containing the hex representation of the SHA-256 hash
|
82
|
+
*
|
83
|
+
* @example
|
84
|
+
* ```typescript
|
85
|
+
* import { messageHashStr } from "@waku/core";
|
86
|
+
*
|
87
|
+
* const pubsubTopic = "/waku/2/default-waku/proto";
|
88
|
+
* const message = {
|
89
|
+
* payload: new Uint8Array([1, 2, 3, 4]),
|
90
|
+
* contentTopic: "/waku/2/default-content/proto",
|
91
|
+
* meta: new Uint8Array([5, 6, 7, 8]),
|
92
|
+
* timestamp: new Date()
|
93
|
+
* };
|
94
|
+
*
|
95
|
+
* const hashString = messageHashStr(pubsubTopic, message);
|
96
|
+
* console.log(hashString); // e.g. "a1b2c3d4..."
|
97
|
+
* ```
|
98
|
+
*/
|
99
|
+
export function messageHashStr(
|
100
|
+
pubsubTopic: string,
|
101
|
+
message: IProtoMessage | IDecodedMessage
|
102
|
+
): string {
|
103
|
+
const hash = messageHash(pubsubTopic, message);
|
104
|
+
const hashStr = bytesToHex(hash);
|
105
|
+
return hashStr;
|
106
|
+
}
|
package/src/lib/store/rpc.ts
CHANGED
@@ -14,6 +14,7 @@ export class StoreQueryRequest {
|
|
14
14
|
public static create(params: QueryRequestParams): StoreQueryRequest {
|
15
15
|
const request = new StoreQueryRequest({
|
16
16
|
...params,
|
17
|
+
contentTopics: params.contentTopics || [],
|
17
18
|
requestId: uuid(),
|
18
19
|
timeStart: params.timeStart
|
19
20
|
? BigInt(params.timeStart.getTime() * ONE_MILLION)
|
@@ -27,26 +28,29 @@ export class StoreQueryRequest {
|
|
27
28
|
: undefined
|
28
29
|
});
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
) {
|
35
|
-
throw new Error(
|
36
|
-
"Both pubsubTopic and contentTopics must be set or unset"
|
37
|
-
);
|
38
|
-
}
|
31
|
+
const isHashQuery = params.messageHashes && params.messageHashes.length > 0;
|
32
|
+
const hasContentTopics =
|
33
|
+
params.contentTopics && params.contentTopics.length > 0;
|
34
|
+
const hasTimeFilter = params.timeStart || params.timeEnd;
|
39
35
|
|
40
|
-
if (
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
36
|
+
if (isHashQuery) {
|
37
|
+
if (hasContentTopics || hasTimeFilter) {
|
38
|
+
throw new Error(
|
39
|
+
"Message hash lookup queries cannot include content filter criteria (contentTopics, timeStart, or timeEnd)"
|
40
|
+
);
|
41
|
+
}
|
42
|
+
} else {
|
43
|
+
if (
|
44
|
+
(params.pubsubTopic &&
|
45
|
+
(!params.contentTopics || params.contentTopics.length === 0)) ||
|
46
|
+
(!params.pubsubTopic &&
|
47
|
+
params.contentTopics &&
|
48
|
+
params.contentTopics.length > 0)
|
49
|
+
) {
|
50
|
+
throw new Error(
|
51
|
+
"Both pubsubTopic and contentTopics must be set together for content-filtered queries"
|
52
|
+
);
|
53
|
+
}
|
50
54
|
}
|
51
55
|
|
52
56
|
return request;
|
package/src/lib/store/store.ts
CHANGED
@@ -40,9 +40,14 @@ export class StoreCore extends BaseProtocol implements IStoreCore {
|
|
40
40
|
decoders: Map<string, IDecoder<T>>,
|
41
41
|
peerId: PeerId
|
42
42
|
): AsyncGenerator<Promise<T | undefined>[]> {
|
43
|
+
// Only validate decoder content topics for content-filtered queries
|
44
|
+
const isHashQuery =
|
45
|
+
queryOpts.messageHashes && queryOpts.messageHashes.length > 0;
|
43
46
|
if (
|
47
|
+
!isHashQuery &&
|
48
|
+
queryOpts.contentTopics &&
|
44
49
|
queryOpts.contentTopics.toString() !==
|
45
|
-
|
50
|
+
Array.from(decoders.keys()).toString()
|
46
51
|
) {
|
47
52
|
throw new Error(
|
48
53
|
"Internal error, the decoders should match the query's content topics"
|
@@ -56,6 +61,13 @@ export class StoreCore extends BaseProtocol implements IStoreCore {
|
|
56
61
|
paginationCursor: currentCursor
|
57
62
|
});
|
58
63
|
|
64
|
+
log.info("Sending store query request:", {
|
65
|
+
hasMessageHashes: !!queryOpts.messageHashes?.length,
|
66
|
+
messageHashCount: queryOpts.messageHashes?.length,
|
67
|
+
pubsubTopic: queryOpts.pubsubTopic,
|
68
|
+
contentTopics: queryOpts.contentTopics
|
69
|
+
});
|
70
|
+
|
59
71
|
let stream;
|
60
72
|
try {
|
61
73
|
stream = await this.getStream(peerId);
|