@dignetwork/dig-sdk 0.0.1-alpha.8 → 0.0.1-alpha.81
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/dist/DataIntegrityTree/DataIntegrityTree.d.ts +5 -2
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -1
- package/dist/DataIntegrityTree/DataIntegrityTree.js +93 -34
- package/dist/DigNetwork/ContentServer.d.ts +9 -4
- package/dist/DigNetwork/ContentServer.d.ts.map +1 -1
- package/dist/DigNetwork/ContentServer.js +55 -19
- package/dist/DigNetwork/DigNetwork.d.ts +3 -9
- package/dist/DigNetwork/DigNetwork.d.ts.map +1 -1
- package/dist/DigNetwork/DigNetwork.js +98 -189
- package/dist/DigNetwork/DigPeer.d.ts +8 -3
- package/dist/DigNetwork/DigPeer.d.ts.map +1 -1
- package/dist/DigNetwork/DigPeer.js +65 -114
- package/dist/DigNetwork/PropagationServer.d.ts +67 -33
- package/dist/DigNetwork/PropagationServer.d.ts.map +1 -1
- package/dist/DigNetwork/PropagationServer.js +480 -365
- package/dist/blockchain/DataStore.d.ts +17 -6
- package/dist/blockchain/DataStore.d.ts.map +1 -1
- package/dist/blockchain/DataStore.js +74 -97
- package/dist/blockchain/DataStoreSerializer.d.ts +1 -1
- package/dist/blockchain/DataStoreSerializer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.d.ts +9 -1
- package/dist/blockchain/FullNodePeer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.js +38 -10
- package/dist/blockchain/ServerCoin.d.ts +11 -3
- package/dist/blockchain/ServerCoin.d.ts.map +1 -1
- package/dist/blockchain/ServerCoin.js +51 -17
- package/dist/blockchain/Wallet.d.ts +2 -2
- package/dist/blockchain/Wallet.d.ts.map +1 -1
- package/dist/blockchain/Wallet.js +2 -2
- package/dist/blockchain/coins.d.ts +1 -1
- package/dist/blockchain/coins.d.ts.map +1 -1
- package/dist/blockchain/coins.js +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/ContentScanner.d.ts +63 -0
- package/dist/utils/ContentScanner.d.ts.map +1 -0
- package/dist/utils/ContentScanner.js +175 -0
- package/dist/utils/FileTransfer.d.ts +47 -0
- package/dist/utils/FileTransfer.d.ts.map +1 -0
- package/dist/utils/FileTransfer.js +209 -0
- package/dist/utils/StoreArchiveManager.d.ts +45 -0
- package/dist/utils/StoreArchiveManager.d.ts.map +1 -0
- package/dist/utils/StoreArchiveManager.js +153 -0
- package/dist/utils/asyncPool.d.ts +9 -0
- package/dist/utils/asyncPool.d.ts.map +1 -0
- package/dist/utils/asyncPool.js +23 -0
- package/dist/utils/config.d.ts +1 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +2 -3
- package/dist/utils/directoryUtils.d.ts +0 -6
- package/dist/utils/directoryUtils.d.ts.map +1 -1
- package/dist/utils/directoryUtils.js +30 -11
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/merkle.d.ts +2 -0
- package/dist/utils/merkle.d.ts.map +1 -0
- package/dist/utils/merkle.js +28 -0
- package/dist/utils/network.d.ts.map +1 -1
- package/dist/utils/network.js +0 -1
- package/package.json +13 -3
- package/dist/utils/deltaUtils.d.ts +0 -2
- package/dist/utils/deltaUtils.d.ts.map +0 -1
- package/dist/utils/deltaUtils.js +0 -83
|
@@ -78,6 +78,9 @@ declare class DataIntegrityTree {
|
|
|
78
78
|
* @returns The serialized Merkle tree.
|
|
79
79
|
*/
|
|
80
80
|
serialize(rootHash?: string | null): object;
|
|
81
|
+
static getRootOfForeignTree(treeData: {
|
|
82
|
+
leaves: string[];
|
|
83
|
+
}): string;
|
|
81
84
|
/**
|
|
82
85
|
* Deserialize a JSON object to a Merkle tree.
|
|
83
86
|
* @param rootHash - The root hash of the tree.
|
|
@@ -106,7 +109,7 @@ declare class DataIntegrityTree {
|
|
|
106
109
|
* @param rootHash - The root hash of the tree. Defaults to the latest root hash.
|
|
107
110
|
* @returns The readable stream for the file.
|
|
108
111
|
*/
|
|
109
|
-
getValueStream(hexKey: string, rootHash?: string | null): Readable;
|
|
112
|
+
getValueStream(hexKey: string, rootHash?: string | null, byteOffset?: number | null, length?: number | null): Readable;
|
|
110
113
|
/**
|
|
111
114
|
* Delete all leaves from the Merkle tree.
|
|
112
115
|
*/
|
|
@@ -154,7 +157,7 @@ declare class DataIntegrityTree {
|
|
|
154
157
|
* @param expectedRootHash - The expected root hash of the Merkle tree.
|
|
155
158
|
* @returns A boolean indicating if the SHA-256 is present in the foreign tree and the root hash matches.
|
|
156
159
|
*/
|
|
157
|
-
static validateKeyIntegrityWithForeignTree(
|
|
160
|
+
static validateKeyIntegrityWithForeignTree(hexkey: string, sha256: string, serializedTree: object, expectedRootHash: string, dataDir: string): Promise<boolean>;
|
|
158
161
|
}
|
|
159
162
|
export { DataIntegrityTree };
|
|
160
163
|
//# sourceMappingURL=DataIntegrityTree.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataIntegrityTree.d.ts","sourceRoot":"","sources":["../../src/DataIntegrityTree/DataIntegrityTree.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAuClC,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,cAAM,iBAAiB;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAa;gBAEb,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,wBAA6B;
|
|
1
|
+
{"version":3,"file":"DataIntegrityTree.d.ts","sourceRoot":"","sources":["../../src/DataIntegrityTree/DataIntegrityTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -94,8 +94,7 @@ class DataIntegrityTree {
|
|
|
94
94
|
}
|
|
95
95
|
this.files = new Map();
|
|
96
96
|
if (options.rootHash) {
|
|
97
|
-
|
|
98
|
-
if (manifest.includes(options.rootHash)) {
|
|
97
|
+
if (fs.existsSync(path.join(this.storeDir, `${options.rootHash}.dat`))) {
|
|
99
98
|
this.tree = this.deserializeTree(options.rootHash);
|
|
100
99
|
}
|
|
101
100
|
else {
|
|
@@ -111,7 +110,10 @@ class DataIntegrityTree {
|
|
|
111
110
|
}
|
|
112
111
|
}
|
|
113
112
|
static from(storeId, options) {
|
|
114
|
-
return new DataIntegrityTree(storeId, {
|
|
113
|
+
return new DataIntegrityTree(storeId, {
|
|
114
|
+
...options,
|
|
115
|
+
disableInitialize: true,
|
|
116
|
+
});
|
|
115
117
|
}
|
|
116
118
|
/**
|
|
117
119
|
* Load the manifest file.
|
|
@@ -132,7 +134,10 @@ class DataIntegrityTree {
|
|
|
132
134
|
const manifest = this._loadManifest();
|
|
133
135
|
if (manifest.length > 0) {
|
|
134
136
|
const latestRootHash = manifest[manifest.length - 1];
|
|
135
|
-
|
|
137
|
+
if (latestRootHash && isHexString(latestRootHash)) {
|
|
138
|
+
return this.deserializeTree(latestRootHash);
|
|
139
|
+
}
|
|
140
|
+
return new merkletreejs_1.MerkleTree([], crypto_js_1.SHA256, { sortPairs: true });
|
|
136
141
|
}
|
|
137
142
|
else {
|
|
138
143
|
return new merkletreejs_1.MerkleTree([], crypto_js_1.SHA256, { sortPairs: true });
|
|
@@ -220,14 +225,19 @@ class DataIntegrityTree {
|
|
|
220
225
|
hash: combinedHash,
|
|
221
226
|
sha256: sha256,
|
|
222
227
|
});
|
|
228
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
223
229
|
this._rebuildTree();
|
|
230
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
224
231
|
resolve();
|
|
225
232
|
}
|
|
226
233
|
catch (err) {
|
|
227
234
|
reject(err);
|
|
228
235
|
}
|
|
236
|
+
tempWriteStream.end();
|
|
237
|
+
finalWriteStream.end();
|
|
229
238
|
});
|
|
230
239
|
tempWriteStream.on("error", (err) => {
|
|
240
|
+
tempWriteStream.end();
|
|
231
241
|
reject(err);
|
|
232
242
|
});
|
|
233
243
|
readStream.on("error", (err) => {
|
|
@@ -305,6 +315,11 @@ class DataIntegrityTree {
|
|
|
305
315
|
files: Object.fromEntries(this.files),
|
|
306
316
|
};
|
|
307
317
|
}
|
|
318
|
+
static getRootOfForeignTree(treeData) {
|
|
319
|
+
const leaves = treeData.leaves.map((leaf) => Buffer.from(leaf, "hex"));
|
|
320
|
+
const tree = new merkletreejs_1.MerkleTree(leaves, crypto_js_1.SHA256, { sortPairs: true });
|
|
321
|
+
return tree.getRoot().toString("hex");
|
|
322
|
+
}
|
|
308
323
|
/**
|
|
309
324
|
* Deserialize a JSON object to a Merkle tree.
|
|
310
325
|
* @param rootHash - The root hash of the tree.
|
|
@@ -337,7 +352,9 @@ class DataIntegrityTree {
|
|
|
337
352
|
? fs.readFileSync(manifestPath, "utf-8").trim().split("\n")
|
|
338
353
|
: [];
|
|
339
354
|
// Check if the last entry is the same as the rootHash to avoid duplicates
|
|
340
|
-
const latestRootHash = manifestContent.length > 0
|
|
355
|
+
const latestRootHash = manifestContent.length > 0
|
|
356
|
+
? manifestContent[manifestContent.length - 1]
|
|
357
|
+
: null;
|
|
341
358
|
if (latestRootHash !== rootHash) {
|
|
342
359
|
// Append the new rootHash if it is not the same as the last one
|
|
343
360
|
fs.appendFileSync(manifestPath, `${rootHash}\n`);
|
|
@@ -413,7 +430,7 @@ class DataIntegrityTree {
|
|
|
413
430
|
* @param rootHash - The root hash of the tree. Defaults to the latest root hash.
|
|
414
431
|
* @returns The readable stream for the file.
|
|
415
432
|
*/
|
|
416
|
-
getValueStream(hexKey, rootHash = null) {
|
|
433
|
+
getValueStream(hexKey, rootHash = null, byteOffset = null, length = null) {
|
|
417
434
|
if (!isHexString(hexKey)) {
|
|
418
435
|
throw new Error("key must be a valid hex string");
|
|
419
436
|
}
|
|
@@ -436,8 +453,22 @@ class DataIntegrityTree {
|
|
|
436
453
|
if (!fs.existsSync(filePath)) {
|
|
437
454
|
throw new Error(`File at path ${filePath} does not exist`);
|
|
438
455
|
}
|
|
439
|
-
|
|
440
|
-
|
|
456
|
+
const fileSize = fs.statSync(filePath).size;
|
|
457
|
+
// Validate offset and length
|
|
458
|
+
if (byteOffset !== null && length !== null) {
|
|
459
|
+
if (byteOffset + length > fileSize) {
|
|
460
|
+
throw new Error(`Offset (${byteOffset}) and length (${length}) exceed the file size (${fileSize}).`);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
// Create the read stream with optional byte range
|
|
464
|
+
const options = {};
|
|
465
|
+
if (byteOffset !== null) {
|
|
466
|
+
options.start = byteOffset;
|
|
467
|
+
}
|
|
468
|
+
if (length !== null && byteOffset !== null) {
|
|
469
|
+
options.end = byteOffset + length - 1; // `end` is inclusive, hence `byteOffset + length - 1`
|
|
470
|
+
}
|
|
471
|
+
const readStream = fs.createReadStream(filePath, options);
|
|
441
472
|
const decompressStream = zlib.createGunzip();
|
|
442
473
|
// Return the combined stream as a generic Readable stream
|
|
443
474
|
return readStream.pipe(decompressStream);
|
|
@@ -579,14 +610,13 @@ class DataIntegrityTree {
|
|
|
579
610
|
decompressStream.on("end", () => {
|
|
580
611
|
const uncompressedSha256 = hash.digest("hex");
|
|
581
612
|
const isValid = uncompressedSha256 === sha256;
|
|
582
|
-
console.log(`SHA-256 of uncompressed file: ${uncompressedSha256}`);
|
|
583
613
|
if (!isValid) {
|
|
584
614
|
return resolve(false);
|
|
585
615
|
}
|
|
586
616
|
const tree = this.deserializeTree(rootHash);
|
|
587
617
|
const combinedHash = crypto
|
|
588
618
|
.createHash("sha256")
|
|
589
|
-
.update(
|
|
619
|
+
.update(sha256)
|
|
590
620
|
.digest("hex");
|
|
591
621
|
const leaf = Buffer.from(combinedHash, "hex");
|
|
592
622
|
const isInTree = tree.getLeafIndex(leaf) !== -1;
|
|
@@ -610,8 +640,8 @@ class DataIntegrityTree {
|
|
|
610
640
|
* @param expectedRootHash - The expected root hash of the Merkle tree.
|
|
611
641
|
* @returns A boolean indicating if the SHA-256 is present in the foreign tree and the root hash matches.
|
|
612
642
|
*/
|
|
613
|
-
static validateKeyIntegrityWithForeignTree(
|
|
614
|
-
if (!isHexString(
|
|
643
|
+
static async validateKeyIntegrityWithForeignTree(hexkey, sha256, serializedTree, expectedRootHash, dataDir) {
|
|
644
|
+
if (!isHexString(hexkey)) {
|
|
615
645
|
throw new Error("key must be a valid hex string");
|
|
616
646
|
}
|
|
617
647
|
if (!isHexString(sha256)) {
|
|
@@ -620,29 +650,58 @@ class DataIntegrityTree {
|
|
|
620
650
|
if (!isHexString(expectedRootHash)) {
|
|
621
651
|
throw new Error("expectedRootHash must be a valid hex string");
|
|
622
652
|
}
|
|
623
|
-
//
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
if (treeRootHash !== expectedRootHash) {
|
|
629
|
-
console.warn(`Expected root hash ${expectedRootHash}, but got ${treeRootHash}`);
|
|
630
|
-
return false;
|
|
653
|
+
// File path based on sha256
|
|
654
|
+
const filePath = path.join(dataDir, sha256.match(/.{1,2}/g).join("/"));
|
|
655
|
+
// Check if the file exists
|
|
656
|
+
if (!fs.existsSync(filePath)) {
|
|
657
|
+
throw new Error(`File at path ${filePath} does not exist`);
|
|
631
658
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
.
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
659
|
+
const compressedReadStream = fs.createReadStream(filePath);
|
|
660
|
+
const decompressStream = zlib.createGunzip();
|
|
661
|
+
const hash = crypto.createHash("sha256");
|
|
662
|
+
// Process file decompression and hash comparison
|
|
663
|
+
return new Promise((resolve, reject) => {
|
|
664
|
+
compressedReadStream.pipe(decompressStream);
|
|
665
|
+
decompressStream.on("data", (chunk) => {
|
|
666
|
+
hash.update(chunk);
|
|
667
|
+
});
|
|
668
|
+
decompressStream.on("end", () => {
|
|
669
|
+
const uncompressedSha256 = hash.digest("hex");
|
|
670
|
+
if (uncompressedSha256 !== sha256) {
|
|
671
|
+
console.warn(`File hash mismatch. Expected: ${sha256}, got: ${uncompressedSha256}`);
|
|
672
|
+
return resolve(false);
|
|
673
|
+
}
|
|
674
|
+
// Deserialize the foreign tree
|
|
675
|
+
const leaves = serializedTree.leaves.map((leaf) => Buffer.from(leaf, "hex"));
|
|
676
|
+
const tree = new merkletreejs_1.MerkleTree(leaves, crypto_js_1.SHA256, { sortPairs: true });
|
|
677
|
+
// Verify that the deserialized tree's root matches the expected root hash
|
|
678
|
+
const treeRootHash = tree.getRoot().toString("hex");
|
|
679
|
+
if (treeRootHash !== expectedRootHash) {
|
|
680
|
+
console.warn(`Expected root hash ${expectedRootHash}, but got ${treeRootHash}`);
|
|
681
|
+
return resolve(false);
|
|
682
|
+
}
|
|
683
|
+
// Rebuild the files map from the serialized tree
|
|
684
|
+
// @ts-ignore
|
|
685
|
+
tree.files = new Map(Object.entries(serializedTree.files).map(([key, value]) => [
|
|
686
|
+
key,
|
|
687
|
+
{ hash: value.hash, sha256: value.sha256 },
|
|
688
|
+
]));
|
|
689
|
+
// Check if the SHA-256 exists in the foreign tree's files
|
|
690
|
+
const combinedHash = crypto
|
|
691
|
+
.createHash("sha256")
|
|
692
|
+
.update(`${hexkey}/${sha256}`)
|
|
693
|
+
.digest("hex");
|
|
694
|
+
const leaf = Buffer.from(combinedHash, "hex");
|
|
695
|
+
const isInTree = tree.getLeafIndex(leaf) !== -1;
|
|
696
|
+
resolve(isInTree);
|
|
697
|
+
});
|
|
698
|
+
decompressStream.on("error", (err) => {
|
|
699
|
+
reject(err);
|
|
700
|
+
});
|
|
701
|
+
compressedReadStream.on("error", (err) => {
|
|
702
|
+
reject(err);
|
|
703
|
+
});
|
|
704
|
+
});
|
|
646
705
|
}
|
|
647
706
|
}
|
|
648
707
|
exports.DataIntegrityTree = DataIntegrityTree;
|
|
@@ -3,6 +3,8 @@ import { Readable } from "stream";
|
|
|
3
3
|
export declare class ContentServer {
|
|
4
4
|
private ipAddress;
|
|
5
5
|
private storeId;
|
|
6
|
+
private static certPath;
|
|
7
|
+
private static keyPath;
|
|
6
8
|
private static readonly port;
|
|
7
9
|
constructor(ipAddress: string, storeId: string);
|
|
8
10
|
getKey(key: string, rootHash: string, challengeHex?: string): Promise<string>;
|
|
@@ -10,16 +12,19 @@ export declare class ContentServer {
|
|
|
10
12
|
getWellKnown(): Promise<any>;
|
|
11
13
|
getKnownStores(): Promise<any>;
|
|
12
14
|
getStoresIndex(): Promise<any>;
|
|
13
|
-
getKeysIndex(): Promise<any>;
|
|
14
|
-
headKey(key: string): Promise<{
|
|
15
|
+
getKeysIndex(rootHash?: string): Promise<any>;
|
|
16
|
+
headKey(key: string, rootHash?: string): Promise<{
|
|
15
17
|
success: boolean;
|
|
16
18
|
headers?: http.IncomingHttpHeaders;
|
|
17
19
|
}>;
|
|
18
|
-
headStore(
|
|
20
|
+
headStore(options?: {
|
|
21
|
+
hasRootHash: string;
|
|
22
|
+
}): Promise<{
|
|
19
23
|
success: boolean;
|
|
20
24
|
headers?: http.IncomingHttpHeaders;
|
|
21
25
|
}>;
|
|
22
|
-
|
|
26
|
+
hasRootHash(rootHash: string): Promise<boolean>;
|
|
27
|
+
streamKey(key: string, rootHash?: string): Promise<Readable>;
|
|
23
28
|
private head;
|
|
24
29
|
private fetchJson;
|
|
25
30
|
private fetchWithRetries;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/ContentServer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ContentServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/ContentServer.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAChC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAS;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAQ;gBAExB,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAYjC,MAAM,CACjB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC;IAaL,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAepC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC;IAM5B,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAM9B,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAM9B,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAY7C,OAAO,CAClB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAA;KAAE,CAAC;IAYvD,SAAS,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QACjE,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC;KACpC,CAAC;IAUW,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUrD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;YAgDrD,IAAI;YA0EJ,SAAS;YAMT,gBAAgB;YAiChB,KAAK;CA0DpB"}
|
|
@@ -4,17 +4,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ContentServer = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
8
|
const http_1 = __importDefault(require("http"));
|
|
8
9
|
const url_1 = require("url");
|
|
10
|
+
const ssl_1 = require("../utils/ssl");
|
|
9
11
|
class ContentServer {
|
|
10
12
|
constructor(ipAddress, storeId) {
|
|
11
13
|
this.ipAddress = ipAddress;
|
|
12
14
|
this.storeId = storeId;
|
|
15
|
+
if (!ContentServer.certPath || !ContentServer.keyPath) {
|
|
16
|
+
const { certPath, keyPath } = (0, ssl_1.getOrCreateSSLCerts)();
|
|
17
|
+
ContentServer.certPath = certPath;
|
|
18
|
+
ContentServer.keyPath = keyPath;
|
|
19
|
+
}
|
|
13
20
|
}
|
|
14
21
|
// Method to get the content of a specified key from the peer, with optional challenge query
|
|
15
22
|
async getKey(key, rootHash, challengeHex) {
|
|
16
23
|
// Construct the base URL
|
|
17
|
-
let url = `
|
|
24
|
+
let url = `https://${this.ipAddress}:${ContentServer.port}/chia.${this.storeId}.${rootHash}/${key}`;
|
|
18
25
|
// If a challenge is provided, append it as a query parameter
|
|
19
26
|
if (challengeHex) {
|
|
20
27
|
url += `?challenge=${challengeHex}`;
|
|
@@ -35,38 +42,61 @@ class ContentServer {
|
|
|
35
42
|
}
|
|
36
43
|
// Method to get the .well-known information
|
|
37
44
|
async getWellKnown() {
|
|
38
|
-
const url = `
|
|
45
|
+
const url = `https://${this.ipAddress}:${ContentServer.port}/.well-known`;
|
|
39
46
|
return this.fetchJson(url);
|
|
40
47
|
}
|
|
41
48
|
// Method to get the list of known stores
|
|
42
49
|
async getKnownStores() {
|
|
43
|
-
const url = `
|
|
50
|
+
const url = `https://${this.ipAddress}:${ContentServer.port}/.well-known/stores`;
|
|
44
51
|
return this.fetchJson(url);
|
|
45
52
|
}
|
|
46
53
|
// Method to get the index of all stores
|
|
47
54
|
async getStoresIndex() {
|
|
48
|
-
const url = `
|
|
55
|
+
const url = `https://${this.ipAddress}:${ContentServer.port}/`;
|
|
49
56
|
return this.fetchJson(url);
|
|
50
57
|
}
|
|
51
58
|
// Method to get the index of keys in a store
|
|
52
|
-
async getKeysIndex() {
|
|
53
|
-
|
|
59
|
+
async getKeysIndex(rootHash) {
|
|
60
|
+
let udi = `chia.${this.storeId}`;
|
|
61
|
+
if (rootHash) {
|
|
62
|
+
udi += `.${rootHash}`;
|
|
63
|
+
}
|
|
64
|
+
const url = `https://${this.ipAddress}:${ContentServer.port}/${udi}`;
|
|
54
65
|
return this.fetchJson(url);
|
|
55
66
|
}
|
|
56
67
|
// Method to check if a specific key exists (HEAD request)
|
|
57
|
-
async headKey(key) {
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
async headKey(key, rootHash) {
|
|
69
|
+
let udi = `chia.${this.storeId}`;
|
|
70
|
+
if (rootHash) {
|
|
71
|
+
udi += `.${rootHash}`;
|
|
72
|
+
}
|
|
73
|
+
const url = `https://${this.ipAddress}:${ContentServer.port}/${udi}/${key}`;
|
|
74
|
+
return this.head(url);
|
|
60
75
|
}
|
|
61
76
|
// Method to check if a specific store exists (HEAD request)
|
|
62
|
-
async headStore() {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
async headStore(options) {
|
|
78
|
+
let url = `https://${this.ipAddress}:${ContentServer.port}/chia.${this.storeId}`;
|
|
79
|
+
if (options?.hasRootHash) {
|
|
80
|
+
url += `?hasRootHash=${options.hasRootHash}`;
|
|
81
|
+
}
|
|
82
|
+
return this.head(url);
|
|
66
83
|
}
|
|
67
|
-
|
|
84
|
+
async hasRootHash(rootHash) {
|
|
85
|
+
const { success, headers } = await this.headStore({
|
|
86
|
+
hasRootHash: rootHash,
|
|
87
|
+
});
|
|
88
|
+
if (success) {
|
|
89
|
+
return headers?.["x-has-root-hash"] === "true";
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
streamKey(key, rootHash) {
|
|
94
|
+
let udi = `chia.${this.storeId}`;
|
|
95
|
+
if (rootHash) {
|
|
96
|
+
udi += `.${rootHash}`;
|
|
97
|
+
}
|
|
68
98
|
return new Promise((resolve, reject) => {
|
|
69
|
-
const url = `
|
|
99
|
+
const url = `https://${this.ipAddress}:${ContentServer.port}/${udi}/${key}`;
|
|
70
100
|
const urlObj = new url_1.URL(url);
|
|
71
101
|
const requestOptions = {
|
|
72
102
|
hostname: urlObj.hostname,
|
|
@@ -93,7 +123,7 @@ class ContentServer {
|
|
|
93
123
|
}
|
|
94
124
|
});
|
|
95
125
|
request.on("error", (error) => {
|
|
96
|
-
console.error(`Request error for ${url}:`, error);
|
|
126
|
+
console.error(`GET Request error for ${url}:`, error);
|
|
97
127
|
reject(error);
|
|
98
128
|
});
|
|
99
129
|
request.end();
|
|
@@ -111,6 +141,9 @@ class ContentServer {
|
|
|
111
141
|
(urlObj.protocol === "http:" ? 80 : ContentServer.port),
|
|
112
142
|
path: urlObj.pathname + urlObj.search,
|
|
113
143
|
method: "HEAD",
|
|
144
|
+
key: fs_1.default.readFileSync(ContentServer.keyPath),
|
|
145
|
+
cert: fs_1.default.readFileSync(ContentServer.certPath),
|
|
146
|
+
rejectUnauthorized: false,
|
|
114
147
|
};
|
|
115
148
|
const request = http_1.default.request(requestOptions, (response) => {
|
|
116
149
|
const { statusCode, headers } = response;
|
|
@@ -149,7 +182,7 @@ class ContentServer {
|
|
|
149
182
|
}
|
|
150
183
|
});
|
|
151
184
|
request.on("error", (error) => {
|
|
152
|
-
console.error(`
|
|
185
|
+
console.error(`HEAD ${url}:`, error.message);
|
|
153
186
|
reject({ success: false });
|
|
154
187
|
});
|
|
155
188
|
request.end();
|
|
@@ -201,6 +234,9 @@ class ContentServer {
|
|
|
201
234
|
port: urlObj.port || ContentServer.port,
|
|
202
235
|
path: urlObj.pathname + urlObj.search, // Include query params
|
|
203
236
|
method: "GET",
|
|
237
|
+
key: fs_1.default.readFileSync(ContentServer.keyPath),
|
|
238
|
+
cert: fs_1.default.readFileSync(ContentServer.certPath),
|
|
239
|
+
rejectUnauthorized: false,
|
|
204
240
|
};
|
|
205
241
|
const request = http_1.default.request(requestOptions, (response) => {
|
|
206
242
|
let data = "";
|
|
@@ -232,7 +268,7 @@ class ContentServer {
|
|
|
232
268
|
}
|
|
233
269
|
});
|
|
234
270
|
request.on("error", (error) => {
|
|
235
|
-
console.error(`
|
|
271
|
+
console.error(`GET ${url}:`, error.message);
|
|
236
272
|
reject(error);
|
|
237
273
|
});
|
|
238
274
|
request.end();
|
|
@@ -240,4 +276,4 @@ class ContentServer {
|
|
|
240
276
|
}
|
|
241
277
|
}
|
|
242
278
|
exports.ContentServer = ContentServer;
|
|
243
|
-
ContentServer.port =
|
|
279
|
+
ContentServer.port = 4161;
|
|
@@ -5,16 +5,10 @@ export declare class DigNetwork {
|
|
|
5
5
|
private storeDir;
|
|
6
6
|
private peerBlacklist;
|
|
7
7
|
constructor(storeId: string);
|
|
8
|
-
private uploadPreflight;
|
|
9
|
-
uploadStoreHead(digPeer: DigPeer): Promise<void>;
|
|
10
|
-
uploadStore(digPeer: DigPeer): Promise<void>;
|
|
11
8
|
static subscribeToStore(storeId: string): Promise<void>;
|
|
9
|
+
static findPeerWithStoreKey(storeId: string, rootHash: string, key?: string, intialBlackList?: string[]): Promise<DigPeer | null>;
|
|
12
10
|
static unsubscribeFromStore(storeId: string): void;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
private downloadHeightFile;
|
|
16
|
-
private downloadManifestFile;
|
|
17
|
-
private downloadFileFromPeers;
|
|
18
|
-
private runProgressBar;
|
|
11
|
+
syncStoreFromPeers(maxRootsToProcess?: number): Promise<void>;
|
|
12
|
+
fetchAvailablePeers(): Promise<DigPeer[]>;
|
|
19
13
|
}
|
|
20
14
|
//# sourceMappingURL=DigNetwork.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DigNetwork.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigNetwork.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DigNetwork.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigNetwork.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA2B;gBAEpC,OAAO,EAAE,MAAM;WAOP,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAQhD,oBAAoB,CACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,MAAM,EACZ,eAAe,GAAE,MAAM,EAAO,GAC7B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;WA2DZ,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO5C,kBAAkB,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiG7D,mBAAmB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;CAUvD"}
|