feat!: re-work messaging parts and sharding (#2399)

* remove message-hash package, move it to core

* add js-doc to message hash

* up

* address type changes

* fix lint
This commit is contained in:
Sasha 2025-06-03 11:08:02 +02:00 committed by GitHub
parent 16328a3f11
commit 1905558753
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 255 additions and 567 deletions

View File

@ -2,7 +2,6 @@
"packages/utils": "0.0.23",
"packages/proto": "0.0.10",
"packages/interfaces": "0.0.30",
"packages/message-hash": "0.1.19",
"packages/enr": "0.0.29",
"packages/core": "0.0.35",
"packages/message-encryption": "0.0.33",

View File

@ -59,7 +59,7 @@ module.exports = [
},
{
name: "Deterministic Message Hashing",
path: "packages/message-hash/bundle/index.js",
path: ["packages/core/bundle/index.js"],
import: "{ messageHash }",
},
];

13
package-lock.json generated
View File

@ -9,7 +9,6 @@
"packages/proto",
"packages/interfaces",
"packages/utils",
"packages/message-hash",
"packages/enr",
"packages/core",
"packages/discovery",
@ -11728,10 +11727,6 @@
"resolved": "packages/message-encryption",
"link": true
},
"node_modules/@waku/message-hash": {
"resolved": "packages/message-hash",
"link": true
},
"node_modules/@waku/proto": {
"resolved": "packages/proto",
"link": true
@ -43435,6 +43430,7 @@
"license": "MIT OR Apache-2.0",
"dependencies": {
"@libp2p/ping": "2.0.1",
"@noble/hashes": "^1.3.2",
"@waku/enr": "^0.0.29",
"@waku/interfaces": "0.0.30",
"@waku/proto": "0.0.10",
@ -43599,6 +43595,7 @@
"license": "MIT"
},
"packages/headless-tests": {
"name": "@waku/headless-tests",
"version": "0.1.0",
"dependencies": {
"@waku/sdk": "^0.0.30"
@ -43996,9 +43993,6 @@
"name": "@waku/interfaces",
"version": "0.0.30",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@waku/proto": "^0.0.10"
},
"devDependencies": {
"@chainsafe/libp2p-gossipsub": "^14.1.0",
"@multiformats/multiaddr": "^12.0.0",
@ -44052,6 +44046,7 @@
"packages/message-hash": {
"name": "@waku/message-hash",
"version": "0.1.19",
"extraneous": true,
"license": "MIT OR Apache-2.0",
"dependencies": {
"@noble/hashes": "^1.3.2",
@ -44341,7 +44336,6 @@
"@waku/core": "0.0.35",
"@waku/discovery": "0.0.8",
"@waku/interfaces": "0.0.30",
"@waku/message-hash": "0.1.19",
"@waku/proto": "^0.0.10",
"@waku/utils": "0.0.23",
"libp2p": "2.1.8"
@ -44477,7 +44471,6 @@
"dependencies": {
"@libp2p/interface": "2.7.0",
"@noble/hashes": "^1.7.1",
"@waku/message-hash": "^0.1.19",
"@waku/proto": "^0.0.10",
"@waku/utils": "^0.0.23",
"chai": "^5.1.2"

View File

@ -6,7 +6,6 @@
"packages/proto",
"packages/interfaces",
"packages/utils",
"packages/message-hash",
"packages/enr",
"packages/core",
"packages/discovery",

View File

@ -74,6 +74,7 @@
"@waku/proto": "0.0.10",
"@waku/utils": "0.0.23",
"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",

View File

@ -20,3 +20,5 @@ export { ConnectionManager } from "./lib/connection_manager/index.js";
export { StreamManager } from "./lib/stream_manager/index.js";
export { MetadataCodec, wakuMetadata } from "./lib/metadata/index.js";
export { messageHash, messageHashStr } from "./lib/message_hash/index.js";

View File

@ -22,7 +22,7 @@ export { proto };
export class DecodedMessage implements IDecodedMessage {
public constructor(
public pubsubTopic: string,
protected proto: proto.WakuMessage
private proto: proto.WakuMessage
) {}
public get ephemeral(): boolean {
@ -37,10 +37,6 @@ export class DecodedMessage implements IDecodedMessage {
return this.proto.contentTopic;
}
public get _rawTimestamp(): bigint | undefined {
return this.proto.timestamp;
}
public get timestamp(): Date | undefined {
// In the case we receive a value that is bigger than JS's max number,
// we catch the error and return undefined.
@ -63,7 +59,7 @@ export class DecodedMessage implements IDecodedMessage {
public get version(): number {
// https://rfc.vac.dev/spec/14/
// > If omitted, the value SHOULD be interpreted as version 0.
return this.proto.version ?? 0;
return this.proto.version ?? Version;
}
public get rateLimitProof(): IRateLimitProof | undefined {
@ -160,7 +156,7 @@ export class Decoder implements IDecoder<IDecodedMessage> {
public async fromProtoObj(
pubsubTopic: string,
proto: IProtoMessage
): Promise<DecodedMessage | undefined> {
): Promise<IDecodedMessage | undefined> {
// https://rfc.vac.dev/spec/14/
// > If omitted, the value SHOULD be interpreted as version 0.
if (proto.version ?? 0 !== Version) {

View File

@ -0,0 +1 @@
export { messageHash, messageHashStr } from "./message_hash.js";

View File

@ -2,10 +2,10 @@ import type { IDecodedMessage, IProtoMessage } from "@waku/interfaces";
import { bytesToHex, hexToBytes } from "@waku/utils/bytes";
import { expect } from "chai";
import { messageHash } from "./index.js";
import { messageHash, messageHashStr } from "./index.js";
// https://rfc.vac.dev/spec/14/#test-vectors
describe("RFC Test Vectors", () => {
describe("Message Hash: RFC Test Vectors", () => {
it("Waku message hash computation (meta size of 12 bytes)", () => {
const expectedHash =
"64cce733fed134e83da02b02c6f689814872b1a0ac97ea56b76095c3c72bfe05";
@ -98,6 +98,7 @@ describe("RFC Test Vectors", () => {
"3f11bc950dce0e3ffdcf205ae6414c01130bb5d9f20644869bff80407fa52c8f";
const pubsubTopic = "/waku/2/default-waku/proto";
const message: IDecodedMessage = {
version: 0,
payload: new Uint8Array(),
pubsubTopic,
contentTopic: "/waku/2/default-content/proto",
@ -110,3 +111,71 @@ describe("RFC Test Vectors", () => {
expect(bytesToHex(hash)).to.equal(expectedHash);
});
});
describe("messageHash and messageHashStr", () => {
const pubsubTopic = "/waku/2/default-waku/proto";
const testMessage: IProtoMessage = {
payload: hexToBytes("0x010203045445535405060708"),
contentTopic: "/waku/2/default-content/proto",
meta: hexToBytes("0x73757065722d736563726574"),
timestamp: BigInt("0x175789bfa23f8400"),
ephemeral: undefined,
rateLimitProof: undefined,
version: undefined
};
it("messageHash returns a Uint8Array", () => {
const hash = messageHash(pubsubTopic, testMessage);
expect(hash).to.be.instanceOf(Uint8Array);
expect(hash.length).to.equal(32); // SHA-256 hash is 32 bytes
});
it("messageHashStr returns a hex string", () => {
const hashStr = messageHashStr(pubsubTopic, testMessage);
expect(typeof hashStr).to.equal("string");
expect(hashStr.length).to.equal(64); // SHA-256 hash is 32 bytes = 64 hex chars
expect(hashStr).to.match(/^[0-9a-f]+$/); // Should be a valid hex string
});
it("messageHashStr returns the same value as bytesToHex(messageHash)", () => {
const hash = messageHash(pubsubTopic, testMessage);
const hashStrFromBytes = bytesToHex(hash);
const hashStr = messageHashStr(pubsubTopic, testMessage);
expect(hashStr).to.equal(hashStrFromBytes);
});
it("messageHashStr works with IDecodedMessage", () => {
const decodedMessage: IDecodedMessage = {
version: 0,
payload: new Uint8Array([1, 2, 3, 4]),
pubsubTopic,
contentTopic: "/waku/2/default-content/proto",
meta: new Uint8Array([5, 6, 7, 8]),
timestamp: new Date("2024-04-30T10:54:14.978Z"),
ephemeral: undefined,
rateLimitProof: undefined
};
const hashStr = messageHashStr(pubsubTopic, decodedMessage);
expect(typeof hashStr).to.equal("string");
expect(hashStr.length).to.equal(64);
});
it("messageHashStr produces consistent results for the same input", () => {
const hashStr1 = messageHashStr(pubsubTopic, testMessage);
const hashStr2 = messageHashStr(pubsubTopic, testMessage);
expect(hashStr1).to.equal(hashStr2);
});
it("messageHashStr produces different results for different inputs", () => {
const hashStr1 = messageHashStr(pubsubTopic, testMessage);
const differentMessage = {
...testMessage,
payload: hexToBytes("0x0102030454455354050607080A") // Different payload
};
const hashStr2 = messageHashStr(pubsubTopic, differentMessage);
expect(hashStr1).to.not.equal(hashStr2);
});
});

View File

@ -11,6 +11,27 @@ import {
/**
* Deterministic Message Hashing as defined in
* [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/#deterministic-message-hashing)
*
* Computes a SHA-256 hash of the concatenation of pubsub topic, payload, content topic, meta, and timestamp.
*
* @param pubsubTopic - The pubsub topic string
* @param message - The message to be hashed
* @returns A Uint8Array containing the SHA-256 hash
*
* @example
* ```typescript
* import { messageHash } from "@waku/core";
*
* const pubsubTopic = "/waku/2/default-waku/proto";
* const message = {
* payload: new Uint8Array([1, 2, 3, 4]),
* contentTopic: "/waku/2/default-content/proto",
* meta: new Uint8Array([5, 6, 7, 8]),
* timestamp: new Date()
* };
*
* const hash = messageHash(pubsubTopic, message);
* ```
*/
export function messageHash(
pubsubTopic: string,
@ -51,6 +72,30 @@ function tryConvertTimestampToBytes(
return numberToBytes(bigIntTimestamp);
}
/**
* Computes a deterministic message hash and returns it as a hexadecimal string.
* This is a convenience wrapper around messageHash that converts the result to a hex string.
*
* @param pubsubTopic - The pubsub topic string
* @param message - The message to be hashed
* @returns A string containing the hex representation of the SHA-256 hash
*
* @example
* ```typescript
* import { messageHashStr } from "@waku/core";
*
* const pubsubTopic = "/waku/2/default-waku/proto";
* const message = {
* payload: new Uint8Array([1, 2, 3, 4]),
* contentTopic: "/waku/2/default-content/proto",
* meta: new Uint8Array([5, 6, 7, 8]),
* timestamp: new Date()
* };
*
* const hashString = messageHashStr(pubsubTopic, message);
* console.log(hashString); // e.g. "a1b2c3d4..."
* ```
*/
export function messageHashStr(
pubsubTopic: string,
message: IProtoMessage | IDecodedMessage

View File

@ -62,8 +62,5 @@
"CHANGELOG.md",
"LICENSE",
"README.md"
],
"dependencies": {
"@waku/proto": "^0.0.10"
}
]
}

View File

@ -1,4 +1,4 @@
import type { PubsubTopic } from "./misc.js";
import type { ContentTopic, PubsubTopic } from "./misc.js";
export interface SingleShardInfo {
clusterId: number;
@ -18,6 +18,39 @@ export interface IRateLimitProof {
rlnIdentifier: Uint8Array;
}
export interface IDecodedMessage {
version: number;
payload: Uint8Array;
contentTopic: ContentTopic;
pubsubTopic: PubsubTopic;
timestamp: Date | undefined;
rateLimitProof: IRateLimitProof | undefined;
ephemeral: boolean | undefined;
meta: Uint8Array | undefined;
}
export interface IRlnMessage extends IDecodedMessage {
epoch: number | undefined;
verify(roots: Uint8Array[]): boolean | undefined;
verifyNoRoot(): boolean | undefined;
}
export interface IEncryptedMessage extends IDecodedMessage {
signature?: Uint8Array;
signaturePublicKey?: Uint8Array;
verifySignature(publicKey: Uint8Array): boolean;
}
export interface ITopicOnlyMessage extends IDecodedMessage {
payload: Uint8Array;
contentTopic: ContentTopic;
pubsubTopic: PubsubTopic;
timestamp: undefined;
rateLimitProof: undefined;
ephemeral: undefined;
meta: undefined;
}
/**
* Interface matching the protobuf library.
* Field types matches the protobuf type over the wire
@ -74,16 +107,6 @@ export interface IEncoder {
toProtoObj: (message: IMessage) => Promise<IProtoMessage | undefined>;
}
export interface IDecodedMessage {
payload: Uint8Array;
contentTopic: string;
pubsubTopic: PubsubTopic;
timestamp: Date | undefined;
rateLimitProof: IRateLimitProof | undefined;
ephemeral: boolean | undefined;
meta: Uint8Array | undefined;
}
export interface IDecoder<T extends IDecodedMessage> {
pubsubTopic: PubsubTopic;
contentTopic: string;

View File

@ -2,12 +2,12 @@ import {
DecodedMessage as DecodedMessageV0,
proto
} from "@waku/core/lib/message/version_0";
import type { IDecodedMessage } from "@waku/interfaces";
import type { IEncryptedMessage } from "@waku/interfaces";
import { equals } from "uint8arrays/equals";
export class DecodedMessage
extends DecodedMessageV0
implements IDecodedMessage
implements IEncryptedMessage
{
private readonly _decodedPayload: Uint8Array;

View File

@ -3,6 +3,7 @@ import {
type EncoderOptions as BaseEncoderOptions,
type IDecoder,
type IEncoder,
type IEncryptedMessage,
type IMessage,
type IMetaSetter,
type IProtoMessage,
@ -122,7 +123,7 @@ export function createEncoder({
);
}
class Decoder extends DecoderV0 implements IDecoder<DecodedMessage> {
class Decoder extends DecoderV0 implements IDecoder<IEncryptedMessage> {
public constructor(
pubsubTopic: PubsubTopic,
contentTopic: string,
@ -134,7 +135,7 @@ class Decoder extends DecoderV0 implements IDecoder<DecodedMessage> {
public async fromProtoObj(
pubsubTopic: string,
protoMessage: IProtoMessage
): Promise<DecodedMessage | undefined> {
): Promise<IEncryptedMessage | undefined> {
const cipherPayload = protoMessage.payload;
if (protoMessage.version !== Version) {

View File

@ -1,13 +1,14 @@
import { Decoder as DecoderV0 } from "@waku/core/lib/message/version_0";
import {
type EncoderOptions as BaseEncoderOptions,
type IDecoder,
type IEncoder,
type IMessage,
type IMetaSetter,
type IProtoMessage,
type PubsubTopic,
type SingleShardInfo
import type {
EncoderOptions as BaseEncoderOptions,
IDecoder,
IEncoder,
IEncryptedMessage,
IMessage,
IMetaSetter,
IProtoMessage,
PubsubTopic,
SingleShardInfo
} from "@waku/interfaces";
import { WakuMessage } from "@waku/proto";
import { determinePubsubTopic, Logger } from "@waku/utils";
@ -118,7 +119,7 @@ export function createEncoder({
);
}
class Decoder extends DecoderV0 implements IDecoder<DecodedMessage> {
class Decoder extends DecoderV0 implements IDecoder<IEncryptedMessage> {
public constructor(
pubsubTopic: PubsubTopic,
contentTopic: string,
@ -130,7 +131,7 @@ class Decoder extends DecoderV0 implements IDecoder<DecodedMessage> {
public async fromProtoObj(
pubsubTopic: string,
protoMessage: IProtoMessage
): Promise<DecodedMessage | undefined> {
): Promise<IEncryptedMessage | undefined> {
const cipherPayload = protoMessage.payload;
if (protoMessage.version !== Version) {

View File

@ -1,6 +0,0 @@
module.exports = {
parserOptions: {
tsconfigRootDir: __dirname,
project: "./tsconfig.dev.json"
}
};

View File

@ -1,6 +0,0 @@
{
"reporterEnabled": "spec, allure-mocha",
"allureMochaReporter": {
"outputDir": "allure-results"
}
}

View File

@ -1,26 +0,0 @@
const config = {
extension: ['ts'],
spec: 'src/**/*.spec.ts',
require: ['ts-node/register', 'isomorphic-fetch'],
loader: 'ts-node/esm',
'node-option': [
'experimental-specifier-resolution=node',
'loader=ts-node/esm'
],
exit: true,
retries: 4
};
if (process.env.CI) {
console.log("Running tests in parallel");
config.parallel = true;
config.jobs = 6;
console.log("Activating allure reporting");
config.reporter = 'mocha-multi-reporters';
config.reporterOptions = {
configFile: '.mocha.reporters.json'
};
} else {
console.log("Running tests serially. To enable parallel execution update mocha config");
}
module.exports = config;

View File

@ -1,5 +0,0 @@
build
bundle
dist
node_modules
CHANGELOG.md

View File

@ -1,245 +0,0 @@
# Changelog
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.6 to 0.0.7
* devDependencies
* @waku/interfaces bumped from 0.0.13 to 0.0.14
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.7 to 0.0.8
* devDependencies
* @waku/interfaces bumped from 0.0.14 to 0.0.15
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.8 to 0.0.9
* devDependencies
* @waku/interfaces bumped from 0.0.15 to 0.0.16
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.9 to 0.0.10
* devDependencies
* @waku/interfaces bumped from 0.0.16 to 0.0.17
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.12 to 0.0.13
* devDependencies
* @waku/interfaces bumped from 0.0.19 to 0.0.20
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.13 to 0.0.14
* devDependencies
* @waku/interfaces bumped from 0.0.20 to 0.0.21
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.17 to 0.0.18
* devDependencies
* @waku/interfaces bumped from 0.0.24 to 0.0.25
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.18 to 0.0.19
* devDependencies
* @waku/interfaces bumped from 0.0.25 to 0.0.26
## [0.1.19](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.18...message-hash-v0.1.19) (2025-04-23)
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.22 to 0.0.23
* devDependencies
* @waku/interfaces bumped from 0.0.29 to 0.0.30
## [0.1.18](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.17...message-hash-v0.1.18) (2025-03-24)
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.21 to 0.0.22
* devDependencies
* @waku/interfaces bumped from 0.0.28 to 0.0.29
## [0.1.17](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.16...message-hash-v0.1.17) (2024-10-16)
### Bug Fixes
* Attempt to fix some of the Filter issues ([#2183](https://github.com/waku-org/js-waku/issues/2183)) ([ded994f](https://github.com/waku-org/js-waku/commit/ded994f8ecd4ebec05cb9760f7eb3da273e5e02b))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.20 to 0.0.21
* devDependencies
* @waku/interfaces bumped from 0.0.27 to 0.0.28
## [0.1.16](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.15...message-hash-v0.1.16) (2024-09-05)
### Bug Fixes
* Temporarily remove peer cross dependencies ([#2123](https://github.com/waku-org/js-waku/issues/2123)) ([f4b6bb0](https://github.com/waku-org/js-waku/commit/f4b6bb04b38842745c946b427bb3518680df09dc))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.19 to 0.0.20
* devDependencies
* @waku/interfaces bumped from 0.0.26 to 0.0.27
## [0.1.13](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.12...message-hash-v0.1.13) (2024-04-30)
### Features
* Make message hash compatible with decoded message ([#1993](https://github.com/waku-org/js-waku/issues/1993)) ([e529335](https://github.com/waku-org/js-waku/commit/e5293356d86231f413810f97e41d02430732f15c))
### Bug Fixes
* **message-hash:** Account for `timestamp` ([#1986](https://github.com/waku-org/js-waku/issues/1986)) ([73d4f19](https://github.com/waku-org/js-waku/commit/73d4f197467fe3e58fc49e3264f73e00a79004f9))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.16 to 0.0.17
* devDependencies
* @waku/interfaces bumped from 0.0.23 to 0.0.24
## [0.1.12](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.11...message-hash-v0.1.12) (2024-04-09)
### Features
* Add cross peer dependency for [@waku](https://github.com/waku) packages ([#1889](https://github.com/waku-org/js-waku/issues/1889)) ([8f86740](https://github.com/waku-org/js-waku/commit/8f867404e3e950b6e491c8831068962c6968ed4e))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.15 to 0.0.16
* devDependencies
* @waku/interfaces bumped from 0.0.22 to 0.0.23
## [0.1.11](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.10...message-hash-v0.1.11) (2024-03-04)
### Features
* Lightpush & filter send requests to multiple peers ([#1779](https://github.com/waku-org/js-waku/issues/1779)) ([7affbe2](https://github.com/waku-org/js-waku/commit/7affbe222dd30ccb6619839f4bc5eb86433a80f7))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.14 to 0.0.15
* devDependencies
* @waku/interfaces bumped from 0.0.21 to 0.0.22
## [0.1.8](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.7...message-hash-v0.1.8) (2023-10-16)
### Features
* Add Firefox and Webkit to karma ([#1598](https://github.com/waku-org/js-waku/issues/1598)) ([d9e4bcb](https://github.com/waku-org/js-waku/commit/d9e4bcbe3f7bcc092f20621bd362d76426701dab))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.11 to 0.0.12
* devDependencies
* @waku/interfaces bumped from 0.0.18 to 0.0.19
## [0.1.7](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.6...message-hash-v0.1.7) (2023-09-11)
### ⚠ BREAKING CHANGES
* @waku/relay ([#1316](https://github.com/waku-org/js-waku/issues/1316))
### Features
* @waku/relay ([#1316](https://github.com/waku-org/js-waku/issues/1316)) ([50c2c25](https://github.com/waku-org/js-waku/commit/50c2c2540f3c5ff78d93f3fea646da0eee246e17))
* Implement deterministic message hash logic ([fe57461](https://github.com/waku-org/js-waku/commit/fe574613290875d1c142aa51c18641346208401d))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from 0.0.10 to 0.0.11
* devDependencies
* @waku/interfaces bumped from 0.0.17 to 0.0.18
## [0.1.2](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.1...message-hash-v0.1.2) (2023-05-18)
### ⚠ BREAKING CHANGES
* @waku/relay ([#1316](https://github.com/waku-org/js-waku/issues/1316))
### Features
* @waku/relay ([#1316](https://github.com/waku-org/js-waku/issues/1316)) ([50c2c25](https://github.com/waku-org/js-waku/commit/50c2c2540f3c5ff78d93f3fea646da0eee246e17))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from * to 0.0.6
* devDependencies
* @waku/interfaces bumped from * to 0.0.13
## [0.1.1](https://github.com/waku-org/js-waku/compare/message-hash-v0.1.0...message-hash-v0.1.1) (2023-05-09)
### Features
* Implement deterministic message hash logic ([fe57461](https://github.com/waku-org/js-waku/commit/fe574613290875d1c142aa51c18641346208401d))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* @waku/utils bumped from * to 0.0.5
* devDependencies
* @waku/interfaces bumped from * to 0.0.12

View File

@ -1,26 +0,0 @@
[![NPM](https://nodei.co/npm/@waku/message-hash.png)](https://npmjs.org/package/@waku/message-hash)
![GitHub Action](https://img.shields.io/github/workflow/status/waku-org/js-waku/CI)
[![Discord chat](https://img.shields.io/discord/864066763682218004.svg?logo=discord&colorB=7289DA)](https://discord.gg/Nrac59MfSX)
# @waku/message-hash
TypeScript implementation of the _Deterministic Message Hashing_ as specified in [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/).
See [JS-Waku README](https://github.com/waku-org/js-waku) for more information.
## Contributing
See [CONTRIBUTING.md](https://github.com/waku-org/js-waku/blob/master/CONTRIBUTING.md).
## License
Licensed and distributed under either of
- MIT license: [LICENSE-MIT](https://github.com/waku-org/js-waku/blob/master/LICENSE-MIT) or http://opensource.org/licenses/MIT
or
- Apache License, Version 2.0, ([LICENSE-APACHE-v2](https://github.com/waku-org/js-waku/blob/master/LICENSE-APACHE-v2) or http://www.apache.org/licenses/LICENSE-2.0)
at your option. These files may not be copied, modified, or distributed except according to those terms.

View File

@ -1,3 +0,0 @@
const config = require("../../karma.conf.cjs");
module.exports = config;

View File

@ -1,86 +0,0 @@
{
"name": "@waku/message-hash",
"version": "0.1.19",
"description": "TypeScript implementation of the Deterministic Message Hashing as specified in 14/WAKU2-MESSAGE",
"types": "./dist/index.d.ts",
"module": "./dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"type": "module",
"homepage": "https://github.com/waku-org/js-waku/tree/master/packages/message-hash#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": {
"@noble/hashes": "^1.3.2",
"@waku/utils": "0.0.23"
},
"devDependencies": {
"@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",
"@waku/build-utils": "*",
"@waku/interfaces": "0.0.30",
"chai": "^4.3.10",
"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"
},
"files": [
"dist",
"bundle",
"src/*.ts",
"src/lib/**/*.ts",
"!**/*.spec.*",
"!**/*.json",
"CHANGELOG.md",
"LICENSE",
"README.md"
]
}

View File

@ -1,24 +0,0 @@
import commonjs from "@rollup/plugin-commonjs";
import json from "@rollup/plugin-json";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import { extractExports } from "@waku/build-utils";
import * as packageJson from "./package.json" assert { type: "json" };
const input = extractExports(packageJson);
export default {
input,
output: {
dir: "bundle",
format: "esm"
},
plugins: [
commonjs(),
json(),
nodeResolve({
browser: true,
preferBuiltins: false
})
]
};

View File

@ -1,3 +0,0 @@
{
"extends": "../../tsconfig.dev"
}

View File

@ -1,10 +0,0 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "dist/",
"rootDir": "src",
"tsBuildInfoFile": "dist/.tsbuildinfo"
},
"include": ["src"],
"exclude": ["src/**/*.spec.ts", "src/test_utils"]
}

View File

@ -1,4 +0,0 @@
{
"extends": ["../../typedoc.base.json"],
"entryPoints": ["src/index.ts"]
}

View File

@ -1,12 +1,14 @@
import { message } from "@waku/core";
import type {
IDecodedMessage,
IDecoder,
IProtoMessage,
ITopicOnlyMessage,
PubsubTopic
} from "@waku/interfaces";
import { TopicOnlyMessage as ProtoTopicOnlyMessage } from "@waku/proto";
export class TopicOnlyMessage implements IDecodedMessage {
export class TopicOnlyMessage implements ITopicOnlyMessage {
public version = message.version_0.Version;
public payload: Uint8Array = new Uint8Array();
public rateLimitProof: undefined;
public timestamp: undefined;
@ -24,7 +26,7 @@ export class TopicOnlyMessage implements IDecodedMessage {
}
// This decoder is used only for reading `contentTopic` from the WakuMessage
export class TopicOnlyDecoder implements IDecoder<TopicOnlyMessage> {
export class TopicOnlyDecoder implements IDecoder<ITopicOnlyMessage> {
public contentTopic = "";
// pubsubTopic is ignored
@ -48,7 +50,7 @@ export class TopicOnlyDecoder implements IDecoder<TopicOnlyMessage> {
public async fromProtoObj(
pubsubTopic: string,
proto: IProtoMessage
): Promise<TopicOnlyMessage | undefined> {
): Promise<ITopicOnlyMessage | undefined> {
return new TopicOnlyMessage(pubsubTopic, proto);
}
}

View File

@ -54,6 +54,7 @@
"@rollup/plugin-node-resolve": "^15.2.3",
"@types/chai": "^5.0.1",
"@types/chai-spies": "^1.0.6",
"@waku/interfaces": "0.0.30",
"@types/deep-equal-in-any-order": "^1.0.4",
"@types/lodash": "^4.17.15",
"@types/sinon": "^17.0.3",

View File

@ -1,8 +1,5 @@
import {
createDecoder,
createEncoder,
DecodedMessage
} from "@waku/core/lib/message/version_0";
import { createDecoder, createEncoder } from "@waku/core/lib/message/version_0";
import { IDecodedMessage } from "@waku/interfaces";
import {
generatePrivateKey,
generateSymmetricKey,
@ -84,7 +81,7 @@ describe("RLN codec with version 0", () => {
const msg = (await rlnDecoder.fromProtoObj(
TEST_CONSTANTS.emptyPubsubTopic,
proto!
)) as RlnMessage<DecodedMessage>;
)) as RlnMessage<IDecodedMessage>;
verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 0, rlnInstance);
});
@ -145,10 +142,10 @@ describe("RLN codec with version 1", () => {
const proto = await rlnEncoder.toProtoObj({ payload });
expect(proto).to.not.be.undefined;
const msg = (await rlnDecoder.fromProtoObj(
const msg = await rlnDecoder.fromProtoObj(
TEST_CONSTANTS.emptyPubsubTopic,
proto!
)) as RlnMessage<DecodedMessage>;
);
verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 1, rlnInstance);
});
@ -209,10 +206,10 @@ describe("RLN codec with version 1", () => {
const proto = await rlnEncoder.toProtoObj({ payload });
expect(proto).to.not.be.undefined;
const msg = (await rlnDecoder.fromProtoObj(
const msg = await rlnDecoder.fromProtoObj(
TEST_CONSTANTS.emptyPubsubTopic,
proto!
)) as RlnMessage<DecodedMessage>;
);
verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 1, rlnInstance);
});
@ -240,7 +237,7 @@ describe("RLN Codec - epoch", () => {
const msg = (await rlnDecoder.fromProtoObj(
TEST_CONSTANTS.emptyPubsubTopic,
proto!
)) as RlnMessage<DecodedMessage>;
)) as RlnMessage<IDecodedMessage>;
const epochBytes = proto!.rateLimitProof!.epoch;
const epoch = epochBytesToInt(epochBytes);
@ -313,7 +310,7 @@ describe("RLN codec with version 0 and meta setter", () => {
const msg = (await rlnDecoder.fromProtoObj(
TEST_CONSTANTS.emptyPubsubTopic,
proto!
)) as RlnMessage<DecodedMessage>;
)) as RlnMessage<IDecodedMessage>;
const expectedMeta = metaSetter({
...EMPTY_PROTO_MESSAGE,

View File

@ -1,7 +1,9 @@
import { message } from "@waku/core";
import type {
IDecodedMessage,
IMessage,
IRateLimitProof
IRateLimitProof,
IRlnMessage
} from "@waku/interfaces";
import * as utils from "@waku/utils/bytes";
@ -13,12 +15,13 @@ export function toRLNSignal(contentTopic: string, msg: IMessage): Uint8Array {
return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]);
}
export class RlnMessage<T extends IDecodedMessage> implements IDecodedMessage {
export class RlnMessage<T extends IDecodedMessage> implements IRlnMessage {
public pubsubTopic = "";
public version = message.version_0.Version;
public constructor(
public rlnInstance: RLNInstance,
public msg: T,
private rlnInstance: RLNInstance,
private msg: T,
public rateLimitProof: IRateLimitProof | undefined
) {}

View File

@ -72,7 +72,6 @@
"@waku/interfaces": "0.0.30",
"@waku/proto": "^0.0.10",
"@waku/utils": "0.0.23",
"@waku/message-hash": "0.1.19",
"libp2p": "2.1.8"
},
"devDependencies": {

View File

@ -1,5 +1,5 @@
import type { EventHandler, PeerId } from "@libp2p/interface";
import { FilterCore } from "@waku/core";
import { FilterCore, messageHashStr } from "@waku/core";
import type {
FilterProtocolOptions,
IConnectionManager,
@ -8,7 +8,6 @@ import type {
Libp2p
} from "@waku/interfaces";
import { EConnectionStateEvents } from "@waku/interfaces";
import { messageHashStr } from "@waku/message-hash";
import { PeerManager } from "../peer_manager/index.js";

View File

@ -3,7 +3,7 @@ import {
type PeerId,
TypedEventEmitter
} from "@libp2p/interface";
import { FilterCore } from "@waku/core";
import { FilterCore, messageHashStr } from "@waku/core";
import type {
Callback,
NextFilterOptions as FilterOptions,
@ -12,7 +12,6 @@ import type {
IProtoMessage,
Libp2p
} from "@waku/interfaces";
import { messageHashStr } from "@waku/message-hash";
import { WakuMessage } from "@waku/proto";
import { Logger } from "@waku/utils";

View File

@ -1,5 +1,5 @@
import type { PeerId } from "@libp2p/interface";
import { ConnectionManager, StoreCore } from "@waku/core";
import { ConnectionManager, messageHash, StoreCore } from "@waku/core";
import {
IDecodedMessage,
IDecoder,
@ -9,7 +9,6 @@ import {
StoreCursor,
StoreProtocolOptions
} from "@waku/interfaces";
import { messageHash } from "@waku/message-hash";
import { ensurePubsubTopicIsConfigured, isDefined, Logger } from "@waku/utils";
import { PeerManager } from "../peer_manager/index.js";

View File

@ -61,7 +61,6 @@
"dependencies": {
"@libp2p/interface": "2.7.0",
"@noble/hashes": "^1.7.1",
"@waku/message-hash": "^0.1.19",
"@waku/proto": "^0.0.10",
"@waku/utils": "^0.0.23",
"chai": "^5.1.2"

View File

@ -1,5 +1,9 @@
import { DecodedMessage } from "@waku/core";
import { AutoSharding, NetworkConfig, StaticSharding } from "@waku/interfaces";
import {
AutoSharding,
IDecodedMessage,
NetworkConfig,
StaticSharding
} from "@waku/interfaces";
import { contentTopicToShardIndex, Logger } from "@waku/utils";
import { expect } from "chai";
@ -122,14 +126,14 @@ export class ServiceNodesFleet {
}
class MultipleNodesMessageCollector {
public callback: (msg: DecodedMessage) => void = () => {};
protected messageList: Array<DecodedMessage> = [];
public callback: (msg: IDecodedMessage) => void = () => {};
protected messageList: Array<IDecodedMessage> = [];
public constructor(
private messageCollectors: MessageCollector[],
private relayNodes?: ServiceNode[],
private strictChecking: boolean = false
) {
this.callback = (msg: DecodedMessage): void => {
this.callback = (msg: IDecodedMessage): void => {
log.info("Got a message");
this.messageList.push(msg);
};
@ -151,7 +155,7 @@ class MultipleNodesMessageCollector {
}
}
public getMessage(index: number): MessageRpcResponse | DecodedMessage {
public getMessage(index: number): MessageRpcResponse | IDecodedMessage {
return this.messageList[index];
}

View File

@ -1,4 +1,4 @@
import { DecodedMessage } from "@waku/core";
import type { IDecodedMessage } from "@waku/interfaces";
import { Logger } from "@waku/utils";
import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes";
import { AssertionError, expect } from "chai";
@ -19,12 +19,12 @@ const log = new Logger("test:message-collector");
* and offers a way to wait for incoming messages.
*/
export class MessageCollector {
public list: Array<MessageRpcResponse | DecodedMessage> = [];
public callback: (msg: DecodedMessage) => void = () => {};
public list: Array<MessageRpcResponse | IDecodedMessage> = [];
public callback: (msg: IDecodedMessage) => void = () => {};
public constructor(private nwaku?: ServiceNode) {
if (!this.nwaku) {
this.callback = (msg: DecodedMessage): void => {
this.callback = (msg: IDecodedMessage): void => {
log.info("Got a message");
this.list.push(msg);
};
@ -35,7 +35,7 @@ export class MessageCollector {
return this.list.length;
}
public getMessage(index: number): MessageRpcResponse | DecodedMessage {
public getMessage(index: number): MessageRpcResponse | IDecodedMessage {
return this.list[index];
}
@ -56,7 +56,7 @@ export class MessageCollector {
// Type guard to determine if a message is of type MessageRpcResponse
public isMessageRpcResponse(
message: MessageRpcResponse | DecodedMessage
message: MessageRpcResponse | IDecodedMessage
): message is MessageRpcResponse {
return (
("payload" in message && typeof message.payload === "string") ||

View File

@ -1,6 +1,6 @@
import { createDecoder, createEncoder, DecodedMessage } from "@waku/core";
import { createDecoder, createEncoder } from "@waku/core";
import { Protocols } from "@waku/interfaces";
import type { LightNode } from "@waku/interfaces";
import type { IDecodedMessage, LightNode } from "@waku/interfaces";
import {
generatePrivateKey,
generateSymmetricKey,
@ -173,7 +173,7 @@ describe("Waku Message Ephemeral field", function () {
await waku2.waitForPeers([Protocols.Store]);
const messages: DecodedMessage[] = [];
const messages: IDecodedMessage[] = [];
log.info("Retrieving messages from store");
for await (const msgPromises of waku2.store.queryGenerator([
@ -203,8 +203,8 @@ describe("Waku Message Ephemeral field", function () {
pubsubTopic: PubsubTopic
});
const messages: DecodedMessage[] = [];
const callback = (msg: DecodedMessage): void => {
const messages: IDecodedMessage[] = [];
const callback = (msg: IDecodedMessage): void => {
messages.push(msg);
};
await waku.filter.subscribe([TestDecoder], callback);
@ -250,8 +250,8 @@ describe("Waku Message Ephemeral field", function () {
});
const decoder = createSymDecoder(SymContentTopic, symKey, PubsubTopic);
const messages: DecodedMessage[] = [];
const callback = (msg: DecodedMessage): void => {
const messages: IDecodedMessage[] = [];
const callback = (msg: IDecodedMessage): void => {
messages.push(msg);
};
await waku.filter.subscribe([decoder], callback);
@ -301,8 +301,8 @@ describe("Waku Message Ephemeral field", function () {
PubsubTopic
);
const messages: DecodedMessage[] = [];
const callback = (msg: DecodedMessage): void => {
const messages: IDecodedMessage[] = [];
const callback = (msg: IDecodedMessage): void => {
messages.push(msg);
};
await waku.filter.subscribe([decoder], callback);

View File

@ -1,5 +1,5 @@
import { createDecoder, createEncoder, DecodedMessage } from "@waku/core";
import { IDecoder, LightNode } from "@waku/interfaces";
import { createDecoder, createEncoder } from "@waku/core";
import { IDecodedMessage, IDecoder, LightNode } from "@waku/interfaces";
import {
ecies,
generatePrivateKey,
@ -473,7 +473,7 @@ const runTests = (strictCheckNodes: boolean): void => {
});
await waku.nextFilter.subscribe(
newDecoder as IDecoder<DecodedMessage>,
newDecoder as IDecoder<IDecodedMessage>,
serviceNodes.messageCollector.callback
);
await waku.lightPush.send(newEncoder, messagePayload);

View File

@ -1,5 +1,5 @@
import { createDecoder, createEncoder, DecodedMessage } from "@waku/core";
import { RelayNode } from "@waku/interfaces";
import { createDecoder, createEncoder } from "@waku/core";
import { IDecodedMessage, RelayNode } from "@waku/interfaces";
import {
generatePrivateKey,
generateSymmetricKey,
@ -66,7 +66,7 @@ describe("Waku Relay", function () {
);
const symDecoder = createSymDecoder(symTopic, symKey, TestPubsubTopic);
const msgs: DecodedMessage[] = [];
const msgs: IDecodedMessage[] = [];
void waku2.relay.subscribeWithUnsubscribe([eciesDecoder], (wakuMsg) => {
msgs.push(wakuMsg);
});
@ -95,7 +95,7 @@ describe("Waku Relay", function () {
const contentTopic = "/test/1/observer/proto";
// The promise **fails** if we receive a message on this observer.
const receivedMsgPromise: Promise<DecodedMessage> = new Promise(
const receivedMsgPromise: Promise<IDecodedMessage> = new Promise(
(resolve, reject) => {
const deleteObserver = waku2.relay.subscribeWithUnsubscribe(
[createDecoder(contentTopic)],

View File

@ -1,6 +1,5 @@
import type { PeerId } from "@libp2p/interface";
import { DecodedMessage } from "@waku/core";
import { Protocols, RelayNode } from "@waku/interfaces";
import { IDecodedMessage, Protocols, RelayNode } from "@waku/interfaces";
import { createRelayNode } from "@waku/relay";
import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes";
import { expect } from "chai";
@ -74,9 +73,9 @@ describe("Waku Relay, Interop", function () {
const messageText = "Here is another message.";
const receivedMsgPromise: Promise<DecodedMessage> = new Promise(
const receivedMsgPromise: Promise<IDecodedMessage> = new Promise(
(resolve) => {
void waku.relay.subscribeWithUnsubscribe<DecodedMessage>(
void waku.relay.subscribeWithUnsubscribe<IDecodedMessage>(
TestDecoder,
(msg) => resolve(msg)
);
@ -118,7 +117,7 @@ describe("Waku Relay, Interop", function () {
const msgStr = "Hello there!";
const message = { payload: utf8ToBytes(msgStr) };
const waku2ReceivedMsgPromise: Promise<DecodedMessage> = new Promise(
const waku2ReceivedMsgPromise: Promise<IDecodedMessage> = new Promise(
(resolve) => {
void waku2.relay.subscribeWithUnsubscribe(TestDecoder, resolve);
}

View File

@ -1,11 +1,12 @@
import { createDecoder, createEncoder, DecodedMessage } from "@waku/core";
import { createDecoder, createEncoder } from "@waku/core";
import {
ContentTopicInfo,
IDecodedMessage,
Protocols,
RelayNode,
ShardInfo,
SingleShardInfo
} from "@waku/interfaces";
import { Protocols } from "@waku/interfaces";
import { createRelayNode } from "@waku/relay";
import {
contentTopicToPubsubTopic,
@ -295,7 +296,7 @@ describe("Waku Relay, multiple pubsub topics", function () {
const messageText = "Communicating using a custom pubsub topic";
const waku2ReceivedMsgPromise: Promise<DecodedMessage> = new Promise(
const waku2ReceivedMsgPromise: Promise<IDecodedMessage> = new Promise(
(resolve) => {
void waku2.relay.subscribeWithUnsubscribe([customDecoder1], resolve);
}
@ -303,7 +304,7 @@ describe("Waku Relay, multiple pubsub topics", function () {
// The promise **fails** if we receive a message on the default
// pubsub topic.
const waku3NoMsgPromise: Promise<DecodedMessage> = new Promise(
const waku3NoMsgPromise: Promise<IDecodedMessage> = new Promise(
(resolve, reject) => {
void waku3.relay.subscribeWithUnsubscribe([TestDecoder], reject);
setTimeout(resolve, 1000);
@ -636,7 +637,7 @@ describe("Waku Relay (Autosharding), multiple pubsub topics", function () {
const messageText = "Communicating using a custom pubsub topic";
const waku2ReceivedMsgPromise: Promise<DecodedMessage> = new Promise(
const waku2ReceivedMsgPromise: Promise<IDecodedMessage> = new Promise(
(resolve) => {
void waku2.relay.subscribeWithUnsubscribe([customDecoder1], resolve);
}
@ -644,7 +645,7 @@ describe("Waku Relay (Autosharding), multiple pubsub topics", function () {
// The promise **fails** if we receive a message on the default
// pubsub topic.
const waku3NoMsgPromise: Promise<DecodedMessage> = new Promise(
const waku3NoMsgPromise: Promise<IDecodedMessage> = new Promise(
(resolve, reject) => {
void waku3.relay.subscribeWithUnsubscribe([TestDecoder], reject);
setTimeout(resolve, 1000);

View File

@ -1,7 +1,11 @@
import { bootstrap } from "@libp2p/bootstrap";
import type { PeerId } from "@libp2p/interface";
import { DecodedMessage } from "@waku/core";
import type { IWaku, LightNode, RelayNode } from "@waku/interfaces";
import type {
IDecodedMessage,
IWaku,
LightNode,
RelayNode
} from "@waku/interfaces";
import { Protocols } from "@waku/interfaces";
import { generateSymmetricKey } from "@waku/message-encryption";
import {
@ -220,7 +224,7 @@ describe("Decryption Keys", function () {
timestamp: messageTimestamp
};
const receivedMsgPromise: Promise<DecodedMessage> = new Promise(
const receivedMsgPromise: Promise<IDecodedMessage> = new Promise(
(resolve) => {
void waku2.relay.subscribeWithUnsubscribe([decoder], resolve);
}

View File

@ -16,7 +16,6 @@
"packages/utils": {},
"packages/proto": {},
"packages/interfaces": {},
"packages/message-hash": {},
"packages/enr": {},
"packages/core": {},
"packages/message-encryption": {},