@dignetwork/dig-sdk 0.0.1-alpha.15 → 0.0.1-alpha.150
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 +11 -2
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -1
- package/dist/DataIntegrityTree/DataIntegrityTree.js +117 -58
- package/dist/DigNetwork/ContentServer.d.ts +12 -5
- package/dist/DigNetwork/ContentServer.d.ts.map +1 -1
- package/dist/DigNetwork/ContentServer.js +172 -24
- package/dist/DigNetwork/DigNetwork.d.ts +15 -9
- package/dist/DigNetwork/DigNetwork.d.ts.map +1 -1
- package/dist/DigNetwork/DigNetwork.js +146 -189
- package/dist/DigNetwork/DigPeer.d.ts +8 -3
- package/dist/DigNetwork/DigPeer.d.ts.map +1 -1
- package/dist/DigNetwork/DigPeer.js +68 -115
- package/dist/DigNetwork/IncentiveServer.d.ts.map +1 -1
- package/dist/DigNetwork/IncentiveServer.js +6 -5
- package/dist/DigNetwork/PropagationServer.d.ts +83 -33
- package/dist/DigNetwork/PropagationServer.d.ts.map +1 -1
- package/dist/DigNetwork/PropagationServer.js +605 -356
- package/dist/blockchain/DataStore.d.ts +25 -7
- package/dist/blockchain/DataStore.d.ts.map +1 -1
- package/dist/blockchain/DataStore.js +114 -159
- package/dist/blockchain/DataStoreSerializer.d.ts +1 -1
- package/dist/blockchain/DataStoreSerializer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.d.ts +94 -10
- package/dist/blockchain/FullNodePeer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.js +325 -100
- package/dist/blockchain/ServerCoin.d.ts +13 -5
- package/dist/blockchain/ServerCoin.d.ts.map +1 -1
- package/dist/blockchain/ServerCoin.js +90 -28
- package/dist/blockchain/StoreMonitorRegistry.d.ts +85 -0
- package/dist/blockchain/StoreMonitorRegistry.d.ts.map +1 -0
- package/dist/blockchain/StoreMonitorRegistry.js +241 -0
- package/dist/blockchain/Wallet.d.ts +2 -2
- package/dist/blockchain/Wallet.d.ts.map +1 -1
- package/dist/blockchain/Wallet.js +50 -18
- package/dist/blockchain/coins.d.ts +1 -2
- package/dist/blockchain/coins.d.ts.map +1 -1
- package/dist/blockchain/coins.js +1 -55
- package/dist/blockchain/index.d.ts +1 -0
- package/dist/blockchain/index.d.ts.map +1 -1
- package/dist/blockchain/index.js +1 -0
- package/dist/types.d.ts +2 -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/Environment.d.ts +21 -0
- package/dist/utils/Environment.d.ts.map +1 -0
- package/dist/utils/Environment.js +92 -0
- package/dist/utils/FileCache.d.ts +1 -1
- package/dist/utils/FileCache.d.ts.map +1 -1
- package/dist/utils/FileCache.js +2 -2
- 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/NconfManager.js +2 -1
- package/dist/utils/PeerRanker.d.ts +53 -0
- package/dist/utils/PeerRanker.d.ts.map +1 -0
- package/dist/utils/PeerRanker.js +171 -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/config.d.ts +4 -3
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +12 -7
- package/dist/utils/directoryUtils.d.ts.map +1 -1
- package/dist/utils/directoryUtils.js +9 -12
- package/dist/utils/index.d.ts +3 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -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 +1 -0
- package/dist/utils/network.d.ts.map +1 -1
- package/dist/utils/network.js +38 -11
- package/dist/utils/promiseUtils.d.ts +19 -0
- package/dist/utils/promiseUtils.d.ts.map +1 -0
- package/dist/utils/promiseUtils.js +43 -0
- package/dist/utils/ssl.js +2 -2
- package/package.json +17 -5
- package/dist/utils/deltaUtils.d.ts +0 -2
- package/dist/utils/deltaUtils.d.ts.map +0 -1
- package/dist/utils/deltaUtils.js +0 -83
|
@@ -17,6 +17,7 @@ declare class DataIntegrityTree {
|
|
|
17
17
|
files: Map<string, {
|
|
18
18
|
hash: string;
|
|
19
19
|
sha256: string;
|
|
20
|
+
bytes: string;
|
|
20
21
|
}>;
|
|
21
22
|
private tree;
|
|
22
23
|
constructor(storeId: string, options?: DataIntegrityTreeOptions);
|
|
@@ -78,6 +79,9 @@ declare class DataIntegrityTree {
|
|
|
78
79
|
* @returns The serialized Merkle tree.
|
|
79
80
|
*/
|
|
80
81
|
serialize(rootHash?: string | null): object;
|
|
82
|
+
static getRootOfForeignTree(treeData: {
|
|
83
|
+
leaves: string[];
|
|
84
|
+
}): string;
|
|
81
85
|
/**
|
|
82
86
|
* Deserialize a JSON object to a Merkle tree.
|
|
83
87
|
* @param rootHash - The root hash of the tree.
|
|
@@ -106,7 +110,7 @@ declare class DataIntegrityTree {
|
|
|
106
110
|
* @param rootHash - The root hash of the tree. Defaults to the latest root hash.
|
|
107
111
|
* @returns The readable stream for the file.
|
|
108
112
|
*/
|
|
109
|
-
getValueStream(hexKey: string, rootHash?: string | null): Readable;
|
|
113
|
+
getValueStream(hexKey: string, rootHash?: string | null, byteOffset?: number | null, length?: number | null): Readable;
|
|
110
114
|
/**
|
|
111
115
|
* Delete all leaves from the Merkle tree.
|
|
112
116
|
*/
|
|
@@ -152,9 +156,14 @@ declare class DataIntegrityTree {
|
|
|
152
156
|
* @param sha256 - The SHA-256 hash of the file.
|
|
153
157
|
* @param serializedTree - The foreign serialized Merkle tree.
|
|
154
158
|
* @param expectedRootHash - The expected root hash of the Merkle tree.
|
|
159
|
+
* @param dataDir - The directory where the data is stored.
|
|
160
|
+
* @param verifiedSha256 - A boolean indicating if the SHA-256 hash has already been verified.
|
|
155
161
|
* @returns A boolean indicating if the SHA-256 is present in the foreign tree and the root hash matches.
|
|
156
162
|
*/
|
|
157
|
-
static validateKeyIntegrityWithForeignTree(
|
|
163
|
+
static validateKeyIntegrityWithForeignTree(hexkey: string, sha256: string, serializedTree: object, expectedRootHash: string, dataDir: string, verifiedSha256?: boolean): Promise<boolean>;
|
|
164
|
+
private static verifyFileHash;
|
|
165
|
+
private static deserializeAndVerifyTree;
|
|
166
|
+
private static checkHashInTree;
|
|
158
167
|
}
|
|
159
168
|
export { DataIntegrityTree };
|
|
160
169
|
//# 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;
|
|
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 });
|
|
@@ -186,83 +191,62 @@ class DataIntegrityTree {
|
|
|
186
191
|
fs.mkdirSync(tempDir, { recursive: true });
|
|
187
192
|
}
|
|
188
193
|
const tempFilePath = path.join(tempDir, `${crypto.randomUUID()}.gz`);
|
|
194
|
+
let totalBytes = 0;
|
|
189
195
|
return new Promise((resolve, reject) => {
|
|
190
196
|
const tempWriteStream = fs.createWriteStream(tempFilePath);
|
|
191
|
-
// Update the hash with the original data
|
|
192
197
|
readStream.on("data", (chunk) => {
|
|
193
198
|
uncompressedHash.update(chunk);
|
|
194
199
|
});
|
|
195
|
-
//
|
|
200
|
+
// Now listen to the gzip stream for compressed data size
|
|
201
|
+
gzip.on("data", (chunk) => {
|
|
202
|
+
totalBytes += chunk.length; // This counts compressed bytes
|
|
203
|
+
});
|
|
196
204
|
readStream.pipe(gzip).pipe(tempWriteStream);
|
|
197
205
|
tempWriteStream.on("finish", async () => {
|
|
198
|
-
|
|
206
|
+
sha256 = uncompressedHash.digest("hex");
|
|
207
|
+
const finalWriteStream = this._createWriteStream(sha256);
|
|
208
|
+
const finalPath = finalWriteStream.path;
|
|
209
|
+
// Ensure the directory exists before copying the file
|
|
210
|
+
const finalDir = path.dirname(finalPath);
|
|
211
|
+
if (!fs.existsSync(finalDir)) {
|
|
212
|
+
fs.mkdirSync(finalDir, { recursive: true });
|
|
213
|
+
}
|
|
199
214
|
try {
|
|
200
|
-
sha256 = uncompressedHash.digest("hex");
|
|
201
|
-
finalWriteStream = this._createWriteStream(sha256);
|
|
202
|
-
const finalPath = finalWriteStream.path;
|
|
203
|
-
// Ensure the directory exists
|
|
204
|
-
const finalDir = path.dirname(finalPath);
|
|
205
|
-
if (!fs.existsSync(finalDir)) {
|
|
206
|
-
fs.mkdirSync(finalDir, { recursive: true });
|
|
207
|
-
}
|
|
208
|
-
// Copy the temporary gzipped file to the final destination
|
|
209
215
|
await this._streamFile(tempFilePath, finalPath);
|
|
210
|
-
await unlink(tempFilePath);
|
|
216
|
+
await unlink(tempFilePath);
|
|
211
217
|
const combinedHash = crypto
|
|
212
218
|
.createHash("sha256")
|
|
213
219
|
.update(`${key}/${sha256}`)
|
|
214
220
|
.digest("hex");
|
|
215
|
-
// Check if the key already exists with the same hash
|
|
216
221
|
if (Array.from(this.files.values()).some((file) => file.hash === combinedHash)) {
|
|
217
222
|
console.log(`No changes detected for key: ${key}`);
|
|
218
223
|
return resolve();
|
|
219
224
|
}
|
|
220
|
-
// Delete existing key if present
|
|
221
225
|
if (this.files.has(key)) {
|
|
222
226
|
this.deleteKey(key);
|
|
223
227
|
}
|
|
224
|
-
// Insert the new key with the hash
|
|
225
228
|
console.log(`Inserted key: ${key}`);
|
|
226
229
|
this.files.set(key, {
|
|
227
230
|
hash: combinedHash,
|
|
228
231
|
sha256: sha256,
|
|
232
|
+
bytes: totalBytes.toString(),
|
|
229
233
|
});
|
|
234
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
230
235
|
this._rebuildTree();
|
|
236
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
231
237
|
resolve();
|
|
232
238
|
}
|
|
233
239
|
catch (err) {
|
|
234
|
-
// On error, cleanup the temporary file and reject
|
|
235
|
-
await unlink(tempFilePath).catch(() => { });
|
|
236
240
|
reject(err);
|
|
237
241
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (finalWriteStream) {
|
|
241
|
-
finalWriteStream.end();
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
tempWriteStream.on("error", async (err) => {
|
|
246
|
-
// Close streams and clean up in case of error
|
|
247
|
-
tempWriteStream.destroy();
|
|
248
|
-
gzip.destroy();
|
|
249
|
-
readStream.destroy();
|
|
250
|
-
await unlink(tempFilePath).catch(() => { }); // Clean up the temp file
|
|
251
|
-
reject(err);
|
|
242
|
+
tempWriteStream.end();
|
|
243
|
+
finalWriteStream.end();
|
|
252
244
|
});
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
tempWriteStream.destroy();
|
|
256
|
-
gzip.destroy();
|
|
257
|
-
readStream.destroy();
|
|
258
|
-
await unlink(tempFilePath).catch(() => { }); // Clean up the temp file
|
|
245
|
+
tempWriteStream.on("error", (err) => {
|
|
246
|
+
tempWriteStream.end();
|
|
259
247
|
reject(err);
|
|
260
248
|
});
|
|
261
|
-
|
|
262
|
-
// Handle errors in the gzip stream
|
|
263
|
-
tempWriteStream.destroy();
|
|
264
|
-
gzip.destroy();
|
|
265
|
-
readStream.destroy();
|
|
249
|
+
readStream.on("error", (err) => {
|
|
266
250
|
reject(err);
|
|
267
251
|
});
|
|
268
252
|
});
|
|
@@ -337,6 +321,11 @@ class DataIntegrityTree {
|
|
|
337
321
|
files: Object.fromEntries(this.files),
|
|
338
322
|
};
|
|
339
323
|
}
|
|
324
|
+
static getRootOfForeignTree(treeData) {
|
|
325
|
+
const leaves = treeData.leaves.map((leaf) => Buffer.from(leaf, "hex"));
|
|
326
|
+
const tree = new merkletreejs_1.MerkleTree(leaves, crypto_js_1.SHA256, { sortPairs: true });
|
|
327
|
+
return tree.getRoot().toString("hex");
|
|
328
|
+
}
|
|
340
329
|
/**
|
|
341
330
|
* Deserialize a JSON object to a Merkle tree.
|
|
342
331
|
* @param rootHash - The root hash of the tree.
|
|
@@ -369,7 +358,9 @@ class DataIntegrityTree {
|
|
|
369
358
|
? fs.readFileSync(manifestPath, "utf-8").trim().split("\n")
|
|
370
359
|
: [];
|
|
371
360
|
// Check if the last entry is the same as the rootHash to avoid duplicates
|
|
372
|
-
const latestRootHash = manifestContent.length > 0
|
|
361
|
+
const latestRootHash = manifestContent.length > 0
|
|
362
|
+
? manifestContent[manifestContent.length - 1]
|
|
363
|
+
: null;
|
|
373
364
|
if (latestRootHash !== rootHash) {
|
|
374
365
|
// Append the new rootHash if it is not the same as the last one
|
|
375
366
|
fs.appendFileSync(manifestPath, `${rootHash}\n`);
|
|
@@ -445,7 +436,7 @@ class DataIntegrityTree {
|
|
|
445
436
|
* @param rootHash - The root hash of the tree. Defaults to the latest root hash.
|
|
446
437
|
* @returns The readable stream for the file.
|
|
447
438
|
*/
|
|
448
|
-
getValueStream(hexKey, rootHash = null) {
|
|
439
|
+
getValueStream(hexKey, rootHash = null, byteOffset = null, length = null) {
|
|
449
440
|
if (!isHexString(hexKey)) {
|
|
450
441
|
throw new Error("key must be a valid hex string");
|
|
451
442
|
}
|
|
@@ -468,8 +459,22 @@ class DataIntegrityTree {
|
|
|
468
459
|
if (!fs.existsSync(filePath)) {
|
|
469
460
|
throw new Error(`File at path ${filePath} does not exist`);
|
|
470
461
|
}
|
|
471
|
-
|
|
472
|
-
|
|
462
|
+
const fileSize = fs.statSync(filePath).size;
|
|
463
|
+
// Validate offset and length
|
|
464
|
+
if (byteOffset !== null && length !== null) {
|
|
465
|
+
if (byteOffset + length > fileSize) {
|
|
466
|
+
throw new Error(`Offset (${byteOffset}) and length (${length}) exceed the file size (${fileSize}).`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
// Create the read stream with optional byte range
|
|
470
|
+
const options = {};
|
|
471
|
+
if (byteOffset !== null) {
|
|
472
|
+
options.start = byteOffset;
|
|
473
|
+
}
|
|
474
|
+
if (length !== null && byteOffset !== null) {
|
|
475
|
+
options.end = byteOffset + length - 1; // `end` is inclusive, hence `byteOffset + length - 1`
|
|
476
|
+
}
|
|
477
|
+
const readStream = fs.createReadStream(filePath, options);
|
|
473
478
|
const decompressStream = zlib.createGunzip();
|
|
474
479
|
// Return the combined stream as a generic Readable stream
|
|
475
480
|
return readStream.pipe(decompressStream);
|
|
@@ -611,14 +616,13 @@ class DataIntegrityTree {
|
|
|
611
616
|
decompressStream.on("end", () => {
|
|
612
617
|
const uncompressedSha256 = hash.digest("hex");
|
|
613
618
|
const isValid = uncompressedSha256 === sha256;
|
|
614
|
-
console.log(`SHA-256 of uncompressed file: ${uncompressedSha256}`);
|
|
615
619
|
if (!isValid) {
|
|
616
620
|
return resolve(false);
|
|
617
621
|
}
|
|
618
622
|
const tree = this.deserializeTree(rootHash);
|
|
619
623
|
const combinedHash = crypto
|
|
620
624
|
.createHash("sha256")
|
|
621
|
-
.update(
|
|
625
|
+
.update(sha256)
|
|
622
626
|
.digest("hex");
|
|
623
627
|
const leaf = Buffer.from(combinedHash, "hex");
|
|
624
628
|
const isInTree = tree.getLeafIndex(leaf) !== -1;
|
|
@@ -640,10 +644,12 @@ class DataIntegrityTree {
|
|
|
640
644
|
* @param sha256 - The SHA-256 hash of the file.
|
|
641
645
|
* @param serializedTree - The foreign serialized Merkle tree.
|
|
642
646
|
* @param expectedRootHash - The expected root hash of the Merkle tree.
|
|
647
|
+
* @param dataDir - The directory where the data is stored.
|
|
648
|
+
* @param verifiedSha256 - A boolean indicating if the SHA-256 hash has already been verified.
|
|
643
649
|
* @returns A boolean indicating if the SHA-256 is present in the foreign tree and the root hash matches.
|
|
644
650
|
*/
|
|
645
|
-
static validateKeyIntegrityWithForeignTree(
|
|
646
|
-
if (!isHexString(
|
|
651
|
+
static async validateKeyIntegrityWithForeignTree(hexkey, sha256, serializedTree, expectedRootHash, dataDir, verifiedSha256 = false) {
|
|
652
|
+
if (!isHexString(hexkey)) {
|
|
647
653
|
throw new Error("key must be a valid hex string");
|
|
648
654
|
}
|
|
649
655
|
if (!isHexString(sha256)) {
|
|
@@ -652,6 +658,56 @@ class DataIntegrityTree {
|
|
|
652
658
|
if (!isHexString(expectedRootHash)) {
|
|
653
659
|
throw new Error("expectedRootHash must be a valid hex string");
|
|
654
660
|
}
|
|
661
|
+
if (!verifiedSha256) {
|
|
662
|
+
// Verify the file's SHA-256 hash
|
|
663
|
+
const isFileValid = await this.verifyFileHash(sha256, dataDir);
|
|
664
|
+
if (!isFileValid) {
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
// Deserialize and verify the tree
|
|
669
|
+
const tree = this.deserializeAndVerifyTree(serializedTree, expectedRootHash);
|
|
670
|
+
if (!tree) {
|
|
671
|
+
return false;
|
|
672
|
+
}
|
|
673
|
+
// Check if the combined hash exists in the foreign tree's leaves
|
|
674
|
+
const isInTree = this.checkHashInTree(tree, hexkey, sha256);
|
|
675
|
+
return isInTree;
|
|
676
|
+
}
|
|
677
|
+
// Function to verify the file's SHA-256 hash
|
|
678
|
+
static async verifyFileHash(sha256, dataDir) {
|
|
679
|
+
const filePath = path.join(dataDir, sha256.match(/.{1,2}/g).join("/"));
|
|
680
|
+
// Check if the file exists
|
|
681
|
+
if (!fs.existsSync(filePath)) {
|
|
682
|
+
throw new Error(`File at path ${filePath} does not exist`);
|
|
683
|
+
}
|
|
684
|
+
const compressedReadStream = fs.createReadStream(filePath);
|
|
685
|
+
const decompressStream = zlib.createGunzip();
|
|
686
|
+
const hash = crypto.createHash("sha256");
|
|
687
|
+
// Process file decompression and hash comparison
|
|
688
|
+
return new Promise((resolve, reject) => {
|
|
689
|
+
compressedReadStream.pipe(decompressStream);
|
|
690
|
+
decompressStream.on("data", (chunk) => {
|
|
691
|
+
hash.update(chunk);
|
|
692
|
+
});
|
|
693
|
+
decompressStream.on("end", () => {
|
|
694
|
+
const uncompressedSha256 = hash.digest("hex");
|
|
695
|
+
if (uncompressedSha256 !== sha256) {
|
|
696
|
+
console.warn(`File hash mismatch. Expected: ${sha256}, got: ${uncompressedSha256}`);
|
|
697
|
+
return resolve(false);
|
|
698
|
+
}
|
|
699
|
+
resolve(true);
|
|
700
|
+
});
|
|
701
|
+
decompressStream.on("error", (err) => {
|
|
702
|
+
reject(err);
|
|
703
|
+
});
|
|
704
|
+
compressedReadStream.on("error", (err) => {
|
|
705
|
+
reject(err);
|
|
706
|
+
});
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
// Function to deserialize and verify the tree
|
|
710
|
+
static deserializeAndVerifyTree(serializedTree, expectedRootHash) {
|
|
655
711
|
// Deserialize the foreign tree
|
|
656
712
|
const leaves = serializedTree.leaves.map((leaf) => Buffer.from(leaf, "hex"));
|
|
657
713
|
const tree = new merkletreejs_1.MerkleTree(leaves, crypto_js_1.SHA256, { sortPairs: true });
|
|
@@ -659,7 +715,7 @@ class DataIntegrityTree {
|
|
|
659
715
|
const treeRootHash = tree.getRoot().toString("hex");
|
|
660
716
|
if (treeRootHash !== expectedRootHash) {
|
|
661
717
|
console.warn(`Expected root hash ${expectedRootHash}, but got ${treeRootHash}`);
|
|
662
|
-
return
|
|
718
|
+
return null;
|
|
663
719
|
}
|
|
664
720
|
// Rebuild the files map from the serialized tree
|
|
665
721
|
// @ts-ignore
|
|
@@ -667,10 +723,13 @@ class DataIntegrityTree {
|
|
|
667
723
|
key,
|
|
668
724
|
{ hash: value.hash, sha256: value.sha256 },
|
|
669
725
|
]));
|
|
670
|
-
|
|
726
|
+
return tree;
|
|
727
|
+
}
|
|
728
|
+
// Function to check if the combined hash exists in the tree
|
|
729
|
+
static checkHashInTree(tree, hexkey, sha256) {
|
|
671
730
|
const combinedHash = crypto
|
|
672
731
|
.createHash("sha256")
|
|
673
|
-
.update(`${
|
|
732
|
+
.update(`${hexkey}/${sha256}`)
|
|
674
733
|
.digest("hex");
|
|
675
734
|
const leaf = Buffer.from(combinedHash, "hex");
|
|
676
735
|
const isInTree = tree.getLeafIndex(leaf) !== -1;
|
|
@@ -3,26 +3,33 @@ 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>;
|
|
9
|
-
|
|
11
|
+
getKeyChunk(key: string, rootHash: string): Promise<Buffer>;
|
|
12
|
+
getPaymentAddress(): Promise<string | null>;
|
|
10
13
|
getWellKnown(): Promise<any>;
|
|
11
14
|
getKnownStores(): Promise<any>;
|
|
12
15
|
getStoresIndex(): Promise<any>;
|
|
13
|
-
getKeysIndex(): Promise<any>;
|
|
14
|
-
headKey(key: string): Promise<{
|
|
16
|
+
getKeysIndex(rootHash?: string): Promise<any>;
|
|
17
|
+
headKey(key: string, rootHash?: string): Promise<{
|
|
15
18
|
success: boolean;
|
|
16
19
|
headers?: http.IncomingHttpHeaders;
|
|
17
20
|
}>;
|
|
18
|
-
headStore(
|
|
21
|
+
headStore(options?: {
|
|
22
|
+
hasRootHash: string;
|
|
23
|
+
}): Promise<{
|
|
19
24
|
success: boolean;
|
|
20
25
|
headers?: http.IncomingHttpHeaders;
|
|
21
26
|
}>;
|
|
22
|
-
|
|
27
|
+
hasRootHash(rootHash: string): Promise<boolean>;
|
|
28
|
+
streamKey(key: string, rootHash?: string): Promise<Readable>;
|
|
23
29
|
private head;
|
|
24
30
|
private fetchJson;
|
|
25
31
|
private fetchWithRetries;
|
|
26
32
|
private fetch;
|
|
33
|
+
private fetchFirstChunk;
|
|
27
34
|
}
|
|
28
35
|
//# sourceMappingURL=ContentServer.d.ts.map
|
|
@@ -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;AAIlC,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;IAaJ,WAAW,CACvB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC;IAOL,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAe3C,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;YA+GL,eAAe;CA2G9B"}
|