@waku/enr 0.0.17 → 0.0.19-a42b7be.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/CHANGELOG.md +17 -0
- package/bundle/index.js +11353 -13478
- package/dist/.tsbuildinfo +1 -1
- package/dist/decoder.js +3 -2
- package/dist/decoder.js.map +1 -1
- package/dist/enr.d.ts +2 -1
- package/dist/enr.js +10 -5
- package/dist/enr.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/raw_enr.d.ts +3 -1
- package/dist/raw_enr.js +13 -0
- package/dist/raw_enr.js.map +1 -1
- package/dist/relay_shard_codec.d.ts +3 -0
- package/dist/relay_shard_codec.js +54 -0
- package/dist/relay_shard_codec.js.map +1 -0
- package/package.json +1 -100
- package/src/decoder.ts +4 -2
- package/src/enr.ts +12 -4
- package/src/index.ts +1 -0
- package/src/raw_enr.ts +20 -1
- package/src/relay_shard_codec.ts +60 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
export const decodeRelayShard = (bytes) => {
|
2
|
+
// explicitly converting to Uint8Array to avoid Buffer
|
3
|
+
// https://github.com/libp2p/js-libp2p/issues/2146
|
4
|
+
bytes = new Uint8Array(bytes);
|
5
|
+
if (bytes.length < 3)
|
6
|
+
throw new Error("Insufficient data");
|
7
|
+
const view = new DataView(bytes.buffer);
|
8
|
+
const cluster = view.getUint16(0);
|
9
|
+
const indexList = [];
|
10
|
+
if (bytes.length === 130) {
|
11
|
+
// rsv format (Bit Vector)
|
12
|
+
for (let i = 0; i < 1024; i++) {
|
13
|
+
const byteIndex = Math.floor(i / 8) + 2; // Adjusted for the 2-byte cluster field
|
14
|
+
const bitIndex = 7 - (i % 8);
|
15
|
+
if (view.getUint8(byteIndex) & (1 << bitIndex)) {
|
16
|
+
indexList.push(i);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
else {
|
21
|
+
// rs format (Index List)
|
22
|
+
const numIndices = view.getUint8(2);
|
23
|
+
for (let i = 0, offset = 3; i < numIndices; i++, offset += 2) {
|
24
|
+
if (offset + 1 >= bytes.length)
|
25
|
+
throw new Error("Unexpected end of data");
|
26
|
+
indexList.push(view.getUint16(offset));
|
27
|
+
}
|
28
|
+
}
|
29
|
+
return { cluster, indexList };
|
30
|
+
};
|
31
|
+
export const encodeRelayShard = (shardInfo) => {
|
32
|
+
const { cluster, indexList } = shardInfo;
|
33
|
+
const totalLength = indexList.length >= 64 ? 130 : 3 + 2 * indexList.length;
|
34
|
+
const buffer = new ArrayBuffer(totalLength);
|
35
|
+
const view = new DataView(buffer);
|
36
|
+
view.setUint16(0, cluster);
|
37
|
+
if (indexList.length >= 64) {
|
38
|
+
// rsv format (Bit Vector)
|
39
|
+
for (const index of indexList) {
|
40
|
+
const byteIndex = Math.floor(index / 8) + 2; // Adjusted for the 2-byte cluster field
|
41
|
+
const bitIndex = 7 - (index % 8);
|
42
|
+
view.setUint8(byteIndex, view.getUint8(byteIndex) | (1 << bitIndex));
|
43
|
+
}
|
44
|
+
}
|
45
|
+
else {
|
46
|
+
// rs format (Index List)
|
47
|
+
view.setUint8(2, indexList.length);
|
48
|
+
for (let i = 0, offset = 3; i < indexList.length; i++, offset += 2) {
|
49
|
+
view.setUint16(offset, indexList[i]);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
return new Uint8Array(buffer);
|
53
|
+
};
|
54
|
+
//# sourceMappingURL=relay_shard_codec.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"relay_shard_codec.js","sourceRoot":"","sources":["../src/relay_shard_codec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,100 +1 @@
|
|
1
|
-
{
|
2
|
-
"name": "@waku/enr",
|
3
|
-
"version": "0.0.17",
|
4
|
-
"description": "ENR (EIP-778) for Waku",
|
5
|
-
"types": "./dist/index.d.ts",
|
6
|
-
"module": "./dist/index.js",
|
7
|
-
"exports": {
|
8
|
-
".": {
|
9
|
-
"types": "./dist/index.d.ts",
|
10
|
-
"import": "./dist/index.js"
|
11
|
-
}
|
12
|
-
},
|
13
|
-
"type": "module",
|
14
|
-
"author": "Waku Team",
|
15
|
-
"homepage": "https://github.com/waku-org/js-waku/tree/master/packages/enr#readme",
|
16
|
-
"repository": {
|
17
|
-
"type": "git",
|
18
|
-
"url": "https://github.com/waku-org/js-waku.git"
|
19
|
-
},
|
20
|
-
"bugs": {
|
21
|
-
"url": "https://github.com/waku-org/js-waku/issues"
|
22
|
-
},
|
23
|
-
"license": "MIT OR Apache-2.0",
|
24
|
-
"keywords": [
|
25
|
-
"waku",
|
26
|
-
"decentralized",
|
27
|
-
"secure",
|
28
|
-
"communication",
|
29
|
-
"web3",
|
30
|
-
"ethereum",
|
31
|
-
"dapps",
|
32
|
-
"privacy"
|
33
|
-
],
|
34
|
-
"scripts": {
|
35
|
-
"build": "run-s build:**",
|
36
|
-
"build:esm": "tsc",
|
37
|
-
"build:bundle": "rollup --config rollup.config.js",
|
38
|
-
"fix": "run-s fix:*",
|
39
|
-
"fix:lint": "eslint src *.js --fix",
|
40
|
-
"check": "run-s check:*",
|
41
|
-
"check:lint": "eslint src --ext .ts",
|
42
|
-
"check:spelling": "cspell \"{README.md,src/**/*.ts}\"",
|
43
|
-
"check:tsc": "tsc -p tsconfig.dev.json",
|
44
|
-
"test": "run-s test:*",
|
45
|
-
"test:node": "TS_NODE_PROJECT=./tsconfig.dev.json mocha",
|
46
|
-
"test:browser": "karma start karma.conf.cjs",
|
47
|
-
"prepublish": "npm run build",
|
48
|
-
"reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build"
|
49
|
-
},
|
50
|
-
"engines": {
|
51
|
-
"node": ">=16"
|
52
|
-
},
|
53
|
-
"dependencies": {
|
54
|
-
"@ethersproject/rlp": "^5.7.0",
|
55
|
-
"@libp2p/crypto": "^1.0.17",
|
56
|
-
"@libp2p/peer-id": "^3.0.2",
|
57
|
-
"@multiformats/multiaddr": "^12.0.0",
|
58
|
-
"@noble/secp256k1": "^1.7.1",
|
59
|
-
"@waku/utils": "0.0.11",
|
60
|
-
"debug": "^4.3.4",
|
61
|
-
"js-sha3": "^0.8.0"
|
62
|
-
},
|
63
|
-
"devDependencies": {
|
64
|
-
"@libp2p/peer-id-factory": "^3.0.3",
|
65
|
-
"@rollup/plugin-commonjs": "^25.0.4",
|
66
|
-
"@rollup/plugin-json": "^6.0.0",
|
67
|
-
"@rollup/plugin-node-resolve": "^15.1.0",
|
68
|
-
"@types/chai": "^4.3.5",
|
69
|
-
"@types/mocha": "^10.0.1",
|
70
|
-
"@waku/build-utils": "*",
|
71
|
-
"@waku/interfaces": "0.0.18",
|
72
|
-
"chai": "^4.3.7",
|
73
|
-
"cspell": "^7.3.2",
|
74
|
-
"karma": "^6.4.1",
|
75
|
-
"karma-chrome-launcher": "^3.2.0",
|
76
|
-
"karma-mocha": "^2.0.1",
|
77
|
-
"karma-webpack": "^5.0.0",
|
78
|
-
"mocha": "^10.2.0",
|
79
|
-
"npm-run-all": "^4.1.5",
|
80
|
-
"process": "^0.11.10",
|
81
|
-
"puppeteer": "^21.1.1",
|
82
|
-
"rollup": "^3.29.0",
|
83
|
-
"ts-loader": "^9.4.2",
|
84
|
-
"typescript": "^5.0.4",
|
85
|
-
"uint8arrays": "^4.0.4"
|
86
|
-
},
|
87
|
-
"typedoc": {
|
88
|
-
"entryPoint": "./src/index.ts"
|
89
|
-
},
|
90
|
-
"files": [
|
91
|
-
"dist",
|
92
|
-
"bundle",
|
93
|
-
"src/**/*.ts",
|
94
|
-
"!**/*.spec.*",
|
95
|
-
"!**/*.json",
|
96
|
-
"CHANGELOG.md",
|
97
|
-
"LICENSE",
|
98
|
-
"README.md"
|
99
|
-
]
|
100
|
-
}
|
1
|
+
{"name":"@waku/enr","version":"0.0.19-a42b7be.0","description":"ENR (EIP-778) for Waku","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"type":"module","author":"Waku Team","homepage":"https://github.com/waku-org/js-waku/tree/master/packages/enr#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","decentralized","secure","communication","web3","ethereum","dapps","privacy"],"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:lint":"eslint src --ext .ts","check:spelling":"cspell \"{README.md,src/**/*.ts}\"","check:tsc":"tsc -p tsconfig.dev.json","test":"run-s test:*","test:node":"TS_NODE_PROJECT=./tsconfig.dev.json mocha","test:browser":"karma start karma.conf.cjs","prepublish":"npm run build","reset-hard":"git clean -dfx -e .idea && git reset --hard && npm i && npm run build"},"engines":{"node":">=18"},"dependencies":{"@ethersproject/rlp":"^5.7.0","@libp2p/crypto":"^1.0.17","@libp2p/peer-id":"^3.0.3","@multiformats/multiaddr":"^12.0.0","@noble/secp256k1":"^1.7.1","@waku/utils":"0.0.13-a42b7be.0","debug":"^4.3.4","js-sha3":"^0.9.2"},"devDependencies":{"@libp2p/peer-id-factory":"^3.0.3","@rollup/plugin-commonjs":"^25.0.4","@rollup/plugin-json":"^6.0.0","@rollup/plugin-node-resolve":"^15.2.3","@types/chai":"^4.3.5","@types/mocha":"^10.0.1","@waku/build-utils":"*","@waku/interfaces":"0.0.20-a42b7be.0","chai":"^4.3.7","cspell":"^7.3.2","fast-check":"^3.13.1","mocha":"^10.2.0","npm-run-all":"^4.1.5","process":"^0.11.10","rollup":"^3.29.2","uint8arrays":"^4.0.4"},"files":["dist","bundle","src/**/*.ts","!**/*.spec.*","!**/*.json","CHANGELOG.md","LICENSE","README.md"]}
|
package/src/decoder.ts
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
import * as RLP from "@ethersproject/rlp";
|
2
2
|
import type { ENRKey, ENRValue } from "@waku/interfaces";
|
3
|
+
import { Logger } from "@waku/utils";
|
3
4
|
import { bytesToHex, bytesToUtf8, hexToBytes } from "@waku/utils/bytes";
|
4
|
-
import { log } from "debug";
|
5
5
|
import { fromString } from "uint8arrays/from-string";
|
6
6
|
|
7
7
|
import { ENR } from "./enr.js";
|
8
8
|
|
9
|
+
const log = new Logger("enr:decoder");
|
10
|
+
|
9
11
|
export class EnrDecoder {
|
10
12
|
static fromString(encoded: string): Promise<ENR> {
|
11
13
|
if (!encoded.startsWith(ENR.RECORD_PREFIX)) {
|
@@ -30,7 +32,7 @@ async function fromValues(values: Uint8Array[]): Promise<ENR> {
|
|
30
32
|
try {
|
31
33
|
obj[bytesToUtf8(kvs[i])] = kvs[i + 1];
|
32
34
|
} catch (e) {
|
33
|
-
log("Failed to decode ENR key to UTF-8, skipping it", kvs[i], e);
|
35
|
+
log.error("Failed to decode ENR key to UTF-8, skipping it", kvs[i], e);
|
34
36
|
}
|
35
37
|
}
|
36
38
|
const _seq = decodeSeq(seq);
|
package/src/enr.ts
CHANGED
@@ -6,9 +6,10 @@ import type {
|
|
6
6
|
ENRValue,
|
7
7
|
IEnr,
|
8
8
|
NodeId,
|
9
|
-
SequenceNumber
|
9
|
+
SequenceNumber,
|
10
|
+
ShardInfo
|
10
11
|
} from "@waku/interfaces";
|
11
|
-
import
|
12
|
+
import { Logger } from "@waku/utils";
|
12
13
|
|
13
14
|
import { ERR_INVALID_ID } from "./constants.js";
|
14
15
|
import { keccak256, verifySignature } from "./crypto.js";
|
@@ -17,7 +18,7 @@ import { createPeerIdFromPublicKey } from "./peer_id.js";
|
|
17
18
|
import { RawEnr } from "./raw_enr.js";
|
18
19
|
import * as v4 from "./v4.js";
|
19
20
|
|
20
|
-
const log =
|
21
|
+
const log = new Logger("enr");
|
21
22
|
|
22
23
|
export enum TransportProtocol {
|
23
24
|
TCP = "tcp",
|
@@ -46,7 +47,7 @@ export class ENR extends RawEnr implements IEnr {
|
|
46
47
|
enr.peerId = await createPeerIdFromPublicKey(publicKey);
|
47
48
|
}
|
48
49
|
} catch (e) {
|
49
|
-
log("Could not calculate peer id for ENR", e);
|
50
|
+
log.error("Could not calculate peer id for ENR", e);
|
50
51
|
}
|
51
52
|
|
52
53
|
return enr;
|
@@ -64,6 +65,13 @@ export class ENR extends RawEnr implements IEnr {
|
|
64
65
|
protocol: TransportProtocol | TransportProtocolPerIpVersion
|
65
66
|
) => Multiaddr | undefined = locationMultiaddrFromEnrFields.bind({}, this);
|
66
67
|
|
68
|
+
get shardInfo(): ShardInfo | undefined {
|
69
|
+
if (this.rs && this.rsv) {
|
70
|
+
log.warn("ENR contains both `rs` and `rsv` fields.");
|
71
|
+
}
|
72
|
+
return this.rs || this.rsv;
|
73
|
+
}
|
74
|
+
|
67
75
|
setLocationMultiaddr(multiaddr: Multiaddr): void {
|
68
76
|
const protoNames = multiaddr.protoNames();
|
69
77
|
if (
|
package/src/index.ts
CHANGED
package/src/raw_enr.ts
CHANGED
@@ -3,11 +3,18 @@ import {
|
|
3
3
|
convertToBytes,
|
4
4
|
convertToString
|
5
5
|
} from "@multiformats/multiaddr/convert";
|
6
|
-
import type {
|
6
|
+
import type {
|
7
|
+
ENRKey,
|
8
|
+
ENRValue,
|
9
|
+
SequenceNumber,
|
10
|
+
ShardInfo,
|
11
|
+
Waku2
|
12
|
+
} from "@waku/interfaces";
|
7
13
|
import { bytesToUtf8 } from "@waku/utils/bytes";
|
8
14
|
|
9
15
|
import { ERR_INVALID_ID } from "./constants.js";
|
10
16
|
import { decodeMultiaddrs, encodeMultiaddrs } from "./multiaddrs_codec.js";
|
17
|
+
import { decodeRelayShard } from "./relay_shard_codec.js";
|
11
18
|
import { decodeWaku2, encodeWaku2 } from "./waku2_codec.js";
|
12
19
|
|
13
20
|
export class RawEnr extends Map<ENRKey, ENRValue> {
|
@@ -45,6 +52,18 @@ export class RawEnr extends Map<ENRKey, ENRValue> {
|
|
45
52
|
}
|
46
53
|
}
|
47
54
|
|
55
|
+
get rs(): ShardInfo | undefined {
|
56
|
+
const rs = this.get("rs");
|
57
|
+
if (!rs) return undefined;
|
58
|
+
return decodeRelayShard(rs);
|
59
|
+
}
|
60
|
+
|
61
|
+
get rsv(): ShardInfo | undefined {
|
62
|
+
const rsv = this.get("rsv");
|
63
|
+
if (!rsv) return undefined;
|
64
|
+
return decodeRelayShard(rsv);
|
65
|
+
}
|
66
|
+
|
48
67
|
get ip(): string | undefined {
|
49
68
|
return getStringValue(this, "ip", "ip4");
|
50
69
|
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import type { ShardInfo } from "@waku/interfaces";
|
2
|
+
|
3
|
+
export const decodeRelayShard = (bytes: Uint8Array): ShardInfo => {
|
4
|
+
// explicitly converting to Uint8Array to avoid Buffer
|
5
|
+
// https://github.com/libp2p/js-libp2p/issues/2146
|
6
|
+
bytes = new Uint8Array(bytes);
|
7
|
+
|
8
|
+
if (bytes.length < 3) throw new Error("Insufficient data");
|
9
|
+
|
10
|
+
const view = new DataView(bytes.buffer);
|
11
|
+
const cluster = view.getUint16(0);
|
12
|
+
|
13
|
+
const indexList = [];
|
14
|
+
|
15
|
+
if (bytes.length === 130) {
|
16
|
+
// rsv format (Bit Vector)
|
17
|
+
for (let i = 0; i < 1024; i++) {
|
18
|
+
const byteIndex = Math.floor(i / 8) + 2; // Adjusted for the 2-byte cluster field
|
19
|
+
const bitIndex = 7 - (i % 8);
|
20
|
+
if (view.getUint8(byteIndex) & (1 << bitIndex)) {
|
21
|
+
indexList.push(i);
|
22
|
+
}
|
23
|
+
}
|
24
|
+
} else {
|
25
|
+
// rs format (Index List)
|
26
|
+
const numIndices = view.getUint8(2);
|
27
|
+
for (let i = 0, offset = 3; i < numIndices; i++, offset += 2) {
|
28
|
+
if (offset + 1 >= bytes.length) throw new Error("Unexpected end of data");
|
29
|
+
indexList.push(view.getUint16(offset));
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
return { cluster, indexList };
|
34
|
+
};
|
35
|
+
|
36
|
+
export const encodeRelayShard = (shardInfo: ShardInfo): Uint8Array => {
|
37
|
+
const { cluster, indexList } = shardInfo;
|
38
|
+
const totalLength = indexList.length >= 64 ? 130 : 3 + 2 * indexList.length;
|
39
|
+
const buffer = new ArrayBuffer(totalLength);
|
40
|
+
const view = new DataView(buffer);
|
41
|
+
|
42
|
+
view.setUint16(0, cluster);
|
43
|
+
|
44
|
+
if (indexList.length >= 64) {
|
45
|
+
// rsv format (Bit Vector)
|
46
|
+
for (const index of indexList) {
|
47
|
+
const byteIndex = Math.floor(index / 8) + 2; // Adjusted for the 2-byte cluster field
|
48
|
+
const bitIndex = 7 - (index % 8);
|
49
|
+
view.setUint8(byteIndex, view.getUint8(byteIndex) | (1 << bitIndex));
|
50
|
+
}
|
51
|
+
} else {
|
52
|
+
// rs format (Index List)
|
53
|
+
view.setUint8(2, indexList.length);
|
54
|
+
for (let i = 0, offset = 3; i < indexList.length; i++, offset += 2) {
|
55
|
+
view.setUint16(offset, indexList[i]);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
return new Uint8Array(buffer);
|
60
|
+
};
|