@dignetwork/dig-sdk 0.0.1-alpha.4 → 0.0.1-alpha.41
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 +160 -0
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -0
- package/dist/DataIntegrityTree/DataIntegrityTree.js +672 -0
- package/dist/DataIntegrityTree/DataLayerError.d.ts +6 -0
- package/dist/DataIntegrityTree/DataLayerError.d.ts.map +1 -0
- package/dist/DataIntegrityTree/DataLayerError.js +17 -0
- package/dist/DataIntegrityTree/index.d.ts +2 -0
- package/dist/DataIntegrityTree/index.d.ts.map +1 -0
- package/dist/DataIntegrityTree/index.js +17 -0
- package/dist/DigNetwork/ContentServer.d.ts +5 -1
- package/dist/DigNetwork/ContentServer.d.ts.map +1 -1
- package/dist/DigNetwork/ContentServer.js +28 -13
- package/dist/DigNetwork/DigNetwork.d.ts +1 -0
- package/dist/DigNetwork/DigNetwork.d.ts.map +1 -1
- package/dist/DigNetwork/DigNetwork.js +74 -50
- package/dist/DigNetwork/DigPeer.d.ts +5 -1
- package/dist/DigNetwork/DigPeer.d.ts.map +1 -1
- package/dist/DigNetwork/DigPeer.js +51 -16
- package/dist/DigNetwork/PropagationServer.d.ts +7 -1
- package/dist/DigNetwork/PropagationServer.d.ts.map +1 -1
- package/dist/DigNetwork/PropagationServer.js +100 -68
- package/dist/blockchain/DataStore.d.ts +2 -2
- package/dist/blockchain/DataStore.d.ts.map +1 -1
- package/dist/blockchain/DataStore.js +9 -5
- package/dist/blockchain/DataStoreSerializer.d.ts +1 -1
- package/dist/blockchain/DataStoreSerializer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.d.ts +8 -1
- package/dist/blockchain/FullNodePeer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.js +39 -7
- package/dist/blockchain/ServerCoin.d.ts +11 -3
- package/dist/blockchain/ServerCoin.d.ts.map +1 -1
- package/dist/blockchain/ServerCoin.js +30 -17
- package/dist/blockchain/Wallet.d.ts +1 -1
- package/dist/blockchain/Wallet.d.ts.map +1 -1
- package/dist/blockchain/Wallet.js +1 -1
- 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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +4 -9
- package/dist/utils/directoryUtils.d.ts +1 -7
- package/dist/utils/directoryUtils.d.ts.map +1 -1
- package/dist/utils/directoryUtils.js +30 -11
- package/package.json +3 -3
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class DataLayerError extends Error {
|
|
4
|
+
constructor(code, message) {
|
|
5
|
+
// Call the parent constructor with the message
|
|
6
|
+
super(message);
|
|
7
|
+
// Set the name of the error to the class name
|
|
8
|
+
this.name = this.constructor.name;
|
|
9
|
+
// Assign the custom code
|
|
10
|
+
this.code = code;
|
|
11
|
+
// Capture the stack trace (if available in the environment)
|
|
12
|
+
if (Error.captureStackTrace) {
|
|
13
|
+
Error.captureStackTrace(this, this.constructor);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.default = DataLayerError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/DataIntegrityTree/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./DataIntegrityTree"), exports);
|
|
@@ -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>;
|
|
@@ -15,7 +17,9 @@ export declare class ContentServer {
|
|
|
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
|
}>;
|
|
@@ -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,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAa7E,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,IAAI,OAAO,CAAC,GAAG,CAAC;IAM5B,OAAO,CAClB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAA;KAAE,CAAC;IAMvD,SAAS,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC;QAChE,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC;KACpC,CAAC;IAUK,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;YA0ClC,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}/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,40 @@ 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}/.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}/.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}/`;
|
|
49
56
|
return this.fetchJson(url);
|
|
50
57
|
}
|
|
51
58
|
// Method to get the index of keys in a store
|
|
52
59
|
async getKeysIndex() {
|
|
53
|
-
const url = `
|
|
60
|
+
const url = `https://${this.ipAddress}/${this.storeId}`;
|
|
54
61
|
return this.fetchJson(url);
|
|
55
62
|
}
|
|
56
63
|
// Method to check if a specific key exists (HEAD request)
|
|
57
64
|
async headKey(key) {
|
|
58
|
-
const url = `
|
|
59
|
-
return this.head(url);
|
|
65
|
+
const url = `https://${this.ipAddress}/${this.storeId}/${key}`;
|
|
66
|
+
return this.head(url);
|
|
60
67
|
}
|
|
61
68
|
// Method to check if a specific store exists (HEAD request)
|
|
62
|
-
async headStore() {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
async headStore(options) {
|
|
70
|
+
let url = `https://${this.ipAddress}/${this.storeId}`;
|
|
71
|
+
if (options?.hasRootHash) {
|
|
72
|
+
url += `?hasRootHash=${options.hasRootHash}`;
|
|
73
|
+
}
|
|
74
|
+
return this.head(url);
|
|
66
75
|
}
|
|
67
76
|
streamKey(key) {
|
|
68
77
|
return new Promise((resolve, reject) => {
|
|
69
|
-
const url = `
|
|
78
|
+
const url = `https://${this.ipAddress}/${this.storeId}/${key}`;
|
|
70
79
|
const urlObj = new url_1.URL(url);
|
|
71
80
|
const requestOptions = {
|
|
72
81
|
hostname: urlObj.hostname,
|
|
@@ -111,6 +120,9 @@ class ContentServer {
|
|
|
111
120
|
(urlObj.protocol === "http:" ? 80 : ContentServer.port),
|
|
112
121
|
path: urlObj.pathname + urlObj.search,
|
|
113
122
|
method: "HEAD",
|
|
123
|
+
key: fs_1.default.readFileSync(ContentServer.keyPath),
|
|
124
|
+
cert: fs_1.default.readFileSync(ContentServer.certPath),
|
|
125
|
+
rejectUnauthorized: false,
|
|
114
126
|
};
|
|
115
127
|
const request = http_1.default.request(requestOptions, (response) => {
|
|
116
128
|
const { statusCode, headers } = response;
|
|
@@ -201,6 +213,9 @@ class ContentServer {
|
|
|
201
213
|
port: urlObj.port || ContentServer.port,
|
|
202
214
|
path: urlObj.pathname + urlObj.search, // Include query params
|
|
203
215
|
method: "GET",
|
|
216
|
+
key: fs_1.default.readFileSync(ContentServer.keyPath),
|
|
217
|
+
cert: fs_1.default.readFileSync(ContentServer.certPath),
|
|
218
|
+
rejectUnauthorized: false,
|
|
204
219
|
};
|
|
205
220
|
const request = http_1.default.request(requestOptions, (response) => {
|
|
206
221
|
let data = "";
|
|
@@ -240,4 +255,4 @@ class ContentServer {
|
|
|
240
255
|
}
|
|
241
256
|
}
|
|
242
257
|
exports.ContentServer = ContentServer;
|
|
243
|
-
ContentServer.port =
|
|
258
|
+
ContentServer.port = 4161;
|
|
@@ -9,6 +9,7 @@ export declare class DigNetwork {
|
|
|
9
9
|
uploadStoreHead(digPeer: DigPeer): Promise<void>;
|
|
10
10
|
uploadStore(digPeer: DigPeer): Promise<void>;
|
|
11
11
|
static subscribeToStore(storeId: string): Promise<void>;
|
|
12
|
+
static findPeerWithStoreKey(storeId: string, rootHash: string, key?: string, intialBlackList?: string[]): Promise<string | null>;
|
|
12
13
|
static unsubscribeFromStore(storeId: string): void;
|
|
13
14
|
downloadFiles(forceDownload?: boolean, renderProgressBar?: boolean, skipData?: boolean): Promise<void>;
|
|
14
15
|
private fetchAvailablePeers;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DigNetwork.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigNetwork.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"DigNetwork.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigNetwork.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,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;YAOb,eAAe;IA8ChB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAsDhD,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;WA6BrC,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,MAAM,GAAG,IAAI,CAAC;WAuCX,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ5C,aAAa,CACxB,aAAa,GAAE,OAAe,EAC9B,iBAAiB,GAAE,OAAc,EACjC,QAAQ,GAAE,OAAe,GACxB,OAAO,CAAC,IAAI,CAAC;YAwEF,mBAAmB;YAWnB,kBAAkB;YASlB,oBAAoB;YASpB,qBAAqB;YA2ErB,cAAc;CAoB7B"}
|
|
@@ -32,6 +32,9 @@ const deltaUtils_1 = require("../utils/deltaUtils");
|
|
|
32
32
|
const hashUtils_1 = require("../utils/hashUtils");
|
|
33
33
|
const blockchain_1 = require("../blockchain");
|
|
34
34
|
const config_1 = require("../utils/config");
|
|
35
|
+
const util_1 = require("util");
|
|
36
|
+
const rename = (0, util_1.promisify)(fs.rename);
|
|
37
|
+
const unlink = (0, util_1.promisify)(fs.unlink);
|
|
35
38
|
class DigNetwork {
|
|
36
39
|
constructor(storeId) {
|
|
37
40
|
this.dataStore = blockchain_1.DataStore.from(storeId);
|
|
@@ -101,7 +104,6 @@ class DigNetwork {
|
|
|
101
104
|
async uploadStore(digPeer) {
|
|
102
105
|
const { generationIndex } = await this.uploadPreflight(digPeer);
|
|
103
106
|
const filesToUpload = await (0, deltaUtils_1.getDeltaFiles)(this.dataStore.StoreId, generationIndex, path.resolve(config_1.DIG_FOLDER_PATH, "stores"));
|
|
104
|
-
console.log(filesToUpload);
|
|
105
107
|
if (!filesToUpload.length) {
|
|
106
108
|
console.log("No files to upload.");
|
|
107
109
|
return;
|
|
@@ -123,6 +125,36 @@ class DigNetwork {
|
|
|
123
125
|
const digNetwork = new DigNetwork(storeId);
|
|
124
126
|
await digNetwork.downloadFiles(true);
|
|
125
127
|
}
|
|
128
|
+
static async findPeerWithStoreKey(storeId, rootHash, key, intialBlackList = []) {
|
|
129
|
+
const peerBlackList = intialBlackList;
|
|
130
|
+
const serverCoin = new blockchain_1.ServerCoin(storeId);
|
|
131
|
+
while (true) {
|
|
132
|
+
try {
|
|
133
|
+
const digPeers = await serverCoin.sampleCurrentEpoch(1, peerBlackList);
|
|
134
|
+
if (digPeers.length === 0)
|
|
135
|
+
break;
|
|
136
|
+
const peerIp = digPeers[0];
|
|
137
|
+
const digPeer = new DigPeer_1.DigPeer(peerIp, storeId);
|
|
138
|
+
const storeResponse = await digPeer.propagationServer.headStore({
|
|
139
|
+
hasRootHash: rootHash,
|
|
140
|
+
});
|
|
141
|
+
console.log(peerIp, storeResponse.headers);
|
|
142
|
+
if (storeResponse.headers?.["x-has-roothash"] === "true") {
|
|
143
|
+
console.log(`Found Peer at ${peerIp} for storeId: ${storeId}, root hash ${rootHash}`);
|
|
144
|
+
if (!key) {
|
|
145
|
+
return peerIp;
|
|
146
|
+
}
|
|
147
|
+
const keyResponse = await digPeer.contentServer.headKey(key);
|
|
148
|
+
if (keyResponse.headers?.["x-key-exists"] === "true") {
|
|
149
|
+
return peerIp;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
peerBlackList.push(peerIp);
|
|
153
|
+
}
|
|
154
|
+
catch { }
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
126
158
|
static unsubscribeFromStore(storeId) {
|
|
127
159
|
fs.rmdirSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId), {
|
|
128
160
|
recursive: true,
|
|
@@ -133,47 +165,35 @@ class DigNetwork {
|
|
|
133
165
|
async downloadFiles(forceDownload = false, renderProgressBar = true, skipData = false) {
|
|
134
166
|
try {
|
|
135
167
|
const rootHistory = await this.dataStore.getRootHistory();
|
|
136
|
-
if (!rootHistory.length)
|
|
168
|
+
if (!rootHistory.length) {
|
|
137
169
|
throw new Error("No roots found in rootHistory. Cannot proceed with file download.");
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
: null;
|
|
154
|
-
const newRootHashes = [];
|
|
155
|
-
for (let i = 0; i < rootHistory.length; i++) {
|
|
156
|
-
const { root_hash: rootHash } = rootHistory[i];
|
|
157
|
-
const datFilePath = path.join(this.storeDir, `${rootHash}.dat`);
|
|
158
|
-
await this.downloadFileFromPeers(`${rootHash}.dat`, datFilePath, forceDownload);
|
|
159
|
-
const datFileContent = JSON.parse(fs.readFileSync(datFilePath, "utf-8"));
|
|
160
|
-
if (datFileContent.root !== rootHash)
|
|
161
|
-
throw new Error("Root hash mismatch");
|
|
170
|
+
}
|
|
171
|
+
await this.downloadHeightFile(true);
|
|
172
|
+
const rootHistorySorted = rootHistory
|
|
173
|
+
.filter((item) => item.timestamp !== undefined)
|
|
174
|
+
.sort((a, b) => b.timestamp - a.timestamp);
|
|
175
|
+
// Process rootHistory sequentially
|
|
176
|
+
for (const rootInfo of rootHistorySorted) {
|
|
177
|
+
const peerIp = await DigNetwork.findPeerWithStoreKey(this.dataStore.StoreId, rootInfo.root_hash);
|
|
178
|
+
if (!peerIp) {
|
|
179
|
+
console.error(`No peer found with root hash ${rootInfo.root_hash}. Skipping download.`);
|
|
180
|
+
continue; // Skip to the next rootInfo
|
|
181
|
+
}
|
|
182
|
+
const digPeer = new DigPeer_1.DigPeer(peerIp, this.dataStore.StoreId);
|
|
183
|
+
const rootResponse = await digPeer.propagationServer.getStoreData(`${rootInfo.root_hash}.dat`);
|
|
184
|
+
const root = JSON.parse(rootResponse);
|
|
162
185
|
if (!skipData) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
186
|
+
// Use Object.entries() to iterate over the map (root.files)
|
|
187
|
+
await Promise.all(Object.entries(root.files).map(async ([storeKey, file]) => {
|
|
188
|
+
const filePath = (0, hashUtils_1.getFilePathFromSha256)(file.sha256, `${this.storeDir}/data`);
|
|
189
|
+
if (!fs.existsSync(filePath) || forceDownload) {
|
|
190
|
+
console.log(`Downloading file with sha256: ${file.sha256}...`);
|
|
191
|
+
await this.downloadFileFromPeers(`data/${file.sha256.match(/.{1,2}/g).join("/")}`, filePath, forceDownload);
|
|
192
|
+
}
|
|
193
|
+
}));
|
|
168
194
|
}
|
|
169
|
-
if (localManifestHashes[i] !== rootHash)
|
|
170
|
-
newRootHashes.push(rootHash);
|
|
171
|
-
progress?.increment();
|
|
172
195
|
}
|
|
173
|
-
|
|
174
|
-
fs.appendFileSync(localManifestPath, newRootHashes.join("\n") + "\n");
|
|
175
|
-
await this.downloadManifestFile(forceDownload);
|
|
176
|
-
progressBar?.stop();
|
|
196
|
+
await this.downloadManifestFile(true);
|
|
177
197
|
console.log("Syncing store complete.");
|
|
178
198
|
}
|
|
179
199
|
catch (error) {
|
|
@@ -198,6 +218,7 @@ class DigNetwork {
|
|
|
198
218
|
}
|
|
199
219
|
async downloadFileFromPeers(dataPath, filePath, overwrite) {
|
|
200
220
|
let digPeers = await this.fetchAvailablePeers();
|
|
221
|
+
const tempFilePath = `${filePath}.tmp`;
|
|
201
222
|
while (true) {
|
|
202
223
|
if (!overwrite && fs.existsSync(filePath))
|
|
203
224
|
return;
|
|
@@ -207,22 +228,24 @@ class DigNetwork {
|
|
|
207
228
|
continue;
|
|
208
229
|
try {
|
|
209
230
|
// Create directory if it doesn't exist
|
|
210
|
-
const directory = path.dirname(
|
|
231
|
+
const directory = path.dirname(tempFilePath);
|
|
211
232
|
if (!fs.existsSync(directory)) {
|
|
212
233
|
fs.mkdirSync(directory, { recursive: true });
|
|
213
234
|
}
|
|
214
|
-
// Stream the file data
|
|
215
|
-
const fileStream = fs.createWriteStream(
|
|
235
|
+
// Stream the file data to a temporary file
|
|
236
|
+
const fileStream = fs.createWriteStream(tempFilePath);
|
|
216
237
|
// Start streaming the data from the peer
|
|
217
238
|
const peerStream = await digPeer.propagationServer.streamStoreData(dataPath);
|
|
218
|
-
// Pipe the peer stream
|
|
239
|
+
// Pipe the peer stream to the temp file
|
|
219
240
|
await new Promise((resolve, reject) => {
|
|
220
241
|
peerStream.pipe(fileStream);
|
|
221
|
-
peerStream.on(
|
|
222
|
-
peerStream.on(
|
|
223
|
-
fileStream.on(
|
|
242
|
+
peerStream.on('end', resolve);
|
|
243
|
+
peerStream.on('error', reject);
|
|
244
|
+
fileStream.on('error', reject);
|
|
224
245
|
});
|
|
225
|
-
|
|
246
|
+
// Rename the temp file to the final file path after successful download
|
|
247
|
+
await rename(tempFilePath, filePath);
|
|
248
|
+
if (process.env.DIG_DEBUG === '1') {
|
|
226
249
|
console.log(`Downloaded ${dataPath} from ${digPeer.IpAddress}`);
|
|
227
250
|
}
|
|
228
251
|
return; // Exit the method if download succeeds
|
|
@@ -230,11 +253,15 @@ class DigNetwork {
|
|
|
230
253
|
catch (error) {
|
|
231
254
|
console.warn(`Failed to download ${dataPath} from ${digPeer.IpAddress}, blacklisting peer and trying next...`);
|
|
232
255
|
blacklist.add(digPeer.IpAddress);
|
|
256
|
+
// Clean up the temp file in case of failure
|
|
257
|
+
if (fs.existsSync(tempFilePath)) {
|
|
258
|
+
await unlink(tempFilePath);
|
|
259
|
+
}
|
|
233
260
|
}
|
|
234
261
|
}
|
|
235
262
|
this.peerBlacklist.set(dataPath, blacklist);
|
|
236
263
|
if (blacklist.size >= digPeers.length) {
|
|
237
|
-
if (process.env.DIG_DEBUG ===
|
|
264
|
+
if (process.env.DIG_DEBUG === '1') {
|
|
238
265
|
console.warn(`All peers blacklisted for ${dataPath}. Refreshing peers...`);
|
|
239
266
|
}
|
|
240
267
|
digPeers = await this.fetchAvailablePeers();
|
|
@@ -246,8 +273,6 @@ class DigNetwork {
|
|
|
246
273
|
}
|
|
247
274
|
async runProgressBar(total, name, task) {
|
|
248
275
|
// Using 'any' to work around TypeScript issues
|
|
249
|
-
const oldConsoleLog = console.log;
|
|
250
|
-
console.log = () => { }; // Suppress console.log output
|
|
251
276
|
const multiBar = new cli_progress_1.MultiBar({
|
|
252
277
|
clearOnComplete: false,
|
|
253
278
|
hideCursor: true,
|
|
@@ -257,7 +282,6 @@ class DigNetwork {
|
|
|
257
282
|
const progress = multiBar.create(total, 0, { name });
|
|
258
283
|
await task(progress).finally(() => {
|
|
259
284
|
multiBar.stop();
|
|
260
|
-
console.log = oldConsoleLog; // Restore console.log
|
|
261
285
|
});
|
|
262
286
|
}
|
|
263
287
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ContentServer } from "./ContentServer";
|
|
2
2
|
import { PropagationServer } from "./PropagationServer";
|
|
3
3
|
import { IncentiveServer } from "./IncentiveServer";
|
|
4
|
+
import { Output } from "@dignetwork/datalayer-driver";
|
|
4
5
|
export declare class DigPeer {
|
|
5
6
|
private ipAddress;
|
|
6
7
|
private storeId;
|
|
@@ -14,6 +15,9 @@ export declare class DigPeer {
|
|
|
14
15
|
get IpAddress(): string;
|
|
15
16
|
validateStore(rootHash: string, keys: string[]): Promise<boolean>;
|
|
16
17
|
isSynced(): Promise<boolean>;
|
|
17
|
-
|
|
18
|
+
static sendEqualBulkPayments(walletName: string, addresses: string[], totalAmount: bigint, memos: Buffer[]): Promise<void>;
|
|
19
|
+
static sendBulkPayments(walletName: string, outputs: Output[]): Promise<void>;
|
|
20
|
+
sendPayment(walletName: string, amount: bigint, memos?: Buffer[]): Promise<void>;
|
|
21
|
+
static createPaymentHint(storeId: Buffer): Buffer;
|
|
18
22
|
}
|
|
19
23
|
//# sourceMappingURL=DigPeer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DigPeer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigPeer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"DigPeer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigPeer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAKL,MAAM,EACP,MAAM,8BAA8B,CAAC;AAKtC,qBAAa,OAAO;IAClB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,gBAAgB,CAAkB;gBAE9B,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAS9C,IAAW,aAAa,IAAI,aAAa,CAExC;IAGD,IAAW,iBAAiB,IAAI,iBAAiB,CAEhD;IAGD,IAAW,eAAe,IAAI,eAAe,CAE5C;IAED,IAAW,SAAS,IAAI,MAAM,CAE7B;IAEY,aAAa,CACxB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,OAAO,CAAC;IAgHN,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;WA2B3B,qBAAqB,CACjC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EAAE,EACnB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC;WAuBI,gBAAgB,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,IAAI,CAAC;IAwCH,WAAW,CACtB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAM,EAAO,GACnB,OAAO,CAAC,IAAI,CAAC;WAYF,iBAAiB,CAAC,OAAO,EAAE,MAAM;CAoBhD"}
|
|
@@ -9,8 +9,8 @@ const ContentServer_1 = require("./ContentServer");
|
|
|
9
9
|
const PropagationServer_1 = require("./PropagationServer");
|
|
10
10
|
const IncentiveServer_1 = require("./IncentiveServer");
|
|
11
11
|
const blockchain_1 = require("../blockchain");
|
|
12
|
-
const
|
|
13
|
-
const datalayer_driver_1 = require("datalayer-driver");
|
|
12
|
+
const DataIntegrityTree_1 = require("../DataIntegrityTree");
|
|
13
|
+
const datalayer_driver_1 = require("@dignetwork/datalayer-driver");
|
|
14
14
|
const blockchain_2 = require("../blockchain");
|
|
15
15
|
const blockchain_3 = require("../blockchain");
|
|
16
16
|
const coins_1 = require("../blockchain/coins");
|
|
@@ -97,7 +97,7 @@ class DigPeer {
|
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
99
|
// Perform tree integrity validation using the datFileContent and the root hash
|
|
100
|
-
const treeCheck =
|
|
100
|
+
const treeCheck = DataIntegrityTree_1.DataIntegrityTree.validateKeyIntegrityWithForeignTree(key, fileData.sha256, datFileContent, rootHash);
|
|
101
101
|
if (!treeCheck) {
|
|
102
102
|
console.error(`Tree validation failed for file ${key}.`);
|
|
103
103
|
filesIntegrityIntact = false;
|
|
@@ -137,22 +137,31 @@ class DigPeer {
|
|
|
137
137
|
return false;
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
static sendEqualBulkPayments(walletName, addresses, totalAmount, memos) {
|
|
141
|
+
// Use a Set to ensure unique addresses
|
|
142
|
+
const uniqueAddresses = Array.from(new Set(addresses));
|
|
143
|
+
// Convert unique addresses to puzzle hashes
|
|
144
|
+
const puzzleHashes = uniqueAddresses.map((address) => (0, datalayer_driver_1.addressToPuzzleHash)(address));
|
|
145
|
+
// Calculate amount per puzzle hash
|
|
146
|
+
const amountPerPuzzleHash = totalAmount / BigInt(puzzleHashes.length);
|
|
147
|
+
// Create outputs array
|
|
148
|
+
const outputs = puzzleHashes.map((puzzleHash) => ({
|
|
149
|
+
puzzleHash,
|
|
150
|
+
amount: amountPerPuzzleHash,
|
|
151
|
+
memos,
|
|
152
|
+
}));
|
|
153
|
+
// Call the sendBulkPayments function with the generated outputs
|
|
154
|
+
return DigPeer.sendBulkPayments(walletName, outputs);
|
|
155
|
+
}
|
|
156
|
+
static async sendBulkPayments(walletName, outputs) {
|
|
157
|
+
const feePerCondition = BigInt(1000);
|
|
158
|
+
const totalFee = feePerCondition * BigInt(outputs.length);
|
|
144
159
|
const wallet = await blockchain_3.Wallet.load(walletName);
|
|
145
160
|
const publicSyntheticKey = await wallet.getPublicSyntheticKey();
|
|
146
161
|
const peer = await blockchain_2.FullNodePeer.connect();
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
const
|
|
150
|
-
{
|
|
151
|
-
puzzleHash: paymentAddressPuzzleHash,
|
|
152
|
-
amount: amount,
|
|
153
|
-
},
|
|
154
|
-
];
|
|
155
|
-
const coinSpends = await (0, datalayer_driver_1.sendXch)(publicSyntheticKey, coins, outputs, fee);
|
|
162
|
+
const totalAmount = outputs.reduce((acc, output) => acc + output.amount, BigInt(0));
|
|
163
|
+
const coins = await (0, coins_1.selectUnspentCoins)(peer, totalAmount, totalFee, [], walletName);
|
|
164
|
+
const coinSpends = await (0, datalayer_driver_1.sendXch)(publicSyntheticKey, coins, outputs, totalFee);
|
|
156
165
|
const sig = (0, datalayer_driver_1.signCoinSpends)(coinSpends, [await wallet.getPrivateSyntheticKey()], false);
|
|
157
166
|
const err = await peer.broadcastSpend(coinSpends, [sig]);
|
|
158
167
|
if (err) {
|
|
@@ -160,5 +169,31 @@ class DigPeer {
|
|
|
160
169
|
}
|
|
161
170
|
await blockchain_2.FullNodePeer.waitForConfirmation((0, datalayer_driver_1.getCoinId)(coins[0]));
|
|
162
171
|
}
|
|
172
|
+
async sendPayment(walletName, amount, memos = []) {
|
|
173
|
+
const paymentAddress = await this.contentServer.getPaymentAddress();
|
|
174
|
+
const paymentAddressPuzzleHash = (0, datalayer_driver_1.addressToPuzzleHash)(paymentAddress);
|
|
175
|
+
const output = {
|
|
176
|
+
puzzleHash: paymentAddressPuzzleHash,
|
|
177
|
+
amount,
|
|
178
|
+
memos,
|
|
179
|
+
};
|
|
180
|
+
return DigPeer.sendBulkPayments(walletName, [output]);
|
|
181
|
+
}
|
|
182
|
+
static createPaymentHint(storeId) {
|
|
183
|
+
// Ensure the input is a 32-byte buffer
|
|
184
|
+
if (!Buffer.isBuffer(storeId) || storeId.length !== 32) {
|
|
185
|
+
throw new Error("Invalid input. Must be a 32-byte buffer.");
|
|
186
|
+
}
|
|
187
|
+
// Define the seed
|
|
188
|
+
const seed = "digpayment";
|
|
189
|
+
// Combine the seed and the original buffer
|
|
190
|
+
const combinedBuffer = Buffer.concat([Buffer.from(seed), storeId]);
|
|
191
|
+
// Apply SHA-256 hash to the combined buffer
|
|
192
|
+
const hash = crypto_1.default.createHash("sha256");
|
|
193
|
+
hash.update(combinedBuffer);
|
|
194
|
+
const transformedBuffer = hash.digest();
|
|
195
|
+
// Return the 32-byte hash as a hex string
|
|
196
|
+
return transformedBuffer;
|
|
197
|
+
}
|
|
163
198
|
}
|
|
164
199
|
exports.DigPeer = DigPeer;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import http from 'http';
|
|
1
2
|
import { Readable } from "stream";
|
|
2
3
|
export declare class PropagationServer {
|
|
3
4
|
private ipAddress;
|
|
@@ -19,7 +20,12 @@ export declare class PropagationServer {
|
|
|
19
20
|
getStatus(): Promise<{
|
|
20
21
|
synced: boolean;
|
|
21
22
|
}>;
|
|
22
|
-
headStore(
|
|
23
|
+
headStore(options?: {
|
|
24
|
+
hasRootHash: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
success: boolean;
|
|
27
|
+
headers?: http.IncomingHttpHeaders;
|
|
28
|
+
}>;
|
|
23
29
|
isStoreSynced(): Promise<boolean>;
|
|
24
30
|
getUploadDetails(): Promise<{
|
|
25
31
|
nonce: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropagationServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/PropagationServer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PropagationServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/PropagationServer.ts"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,MAAM,CAAC;AAKxB,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,qBAAa,iBAAiB;IAC5B,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;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAK;IACvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAQ;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAS;IACzC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAO;gBAElC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAYjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB/D,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQrC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAK9B,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAMpD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK/C,SAAS,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAOzC,SAAS,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAA;KAAE,CAAC;IAW/G,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC;IAMjC,gBAAgB,IAAI,OAAO,CAAC;QACvC,KAAK,EAAE,MAAM,CAAC;QACd,gBAAgB,EAAE,MAAM,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;YAmBY,WAAW;YAyCX,kBAAkB;YAoElB,gBAAgB;YAgEhB,cAAc;YAiCd,KAAK;YAmDL,IAAI;YAmEJ,SAAS;YAuCT,2BAA2B;YAiC3B,gBAAgB;CAyC/B"}
|