@dignetwork/dig-sdk 0.0.1-alpha.12 → 0.0.1-alpha.121
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 +106 -15
- 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 +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 +68 -115
- package/dist/DigNetwork/IncentiveServer.d.ts.map +1 -1
- package/dist/DigNetwork/IncentiveServer.js +6 -5
- package/dist/DigNetwork/PropagationServer.d.ts +73 -33
- package/dist/DigNetwork/PropagationServer.d.ts.map +1 -1
- package/dist/DigNetwork/PropagationServer.js +545 -360
- package/dist/blockchain/DataStore.d.ts +27 -7
- package/dist/blockchain/DataStore.d.ts.map +1 -1
- package/dist/blockchain/DataStore.js +163 -101
- package/dist/blockchain/DataStoreSerializer.d.ts +1 -1
- package/dist/blockchain/DataStoreSerializer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.d.ts +2 -1
- package/dist/blockchain/FullNodePeer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.js +39 -14
- 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/StoreInfoCacheUpdater.d.ts +16 -0
- package/dist/blockchain/StoreInfoCacheUpdater.d.ts.map +1 -0
- package/dist/blockchain/StoreInfoCacheUpdater.js +242 -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/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/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 +32 -14
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -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 +17 -0
- package/dist/utils/promiseUtils.d.ts.map +1 -0
- package/dist/utils/promiseUtils.js +38 -0
- package/dist/utils/ssl.js +2 -2
- package/package.json +15 -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
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { DataStore as DataStoreDriver, DataStoreMetadata } from "datalayer-driver";
|
|
1
|
+
import { DataStore as DataStoreDriver, DataStoreMetadata } from "@dignetwork/datalayer-driver";
|
|
2
2
|
import { RootHistoryItem } from "../types";
|
|
3
3
|
import { DataIntegrityTree, DataIntegrityTreeOptions } from "../DataIntegrityTree";
|
|
4
4
|
import { CreateStoreUserInputs } from "../types";
|
|
5
5
|
export declare class DataStore {
|
|
6
6
|
private storeId;
|
|
7
7
|
private tree;
|
|
8
|
+
private static activeMonitors;
|
|
8
9
|
constructor(storeId: string, options?: DataIntegrityTreeOptions);
|
|
9
10
|
get StoreId(): string;
|
|
10
11
|
get Tree(): DataIntegrityTree;
|
|
@@ -13,7 +14,7 @@ export declare class DataStore {
|
|
|
13
14
|
serialize(): string;
|
|
14
15
|
static getActiveStore(): Promise<DataStore | undefined>;
|
|
15
16
|
static deserialize(serialized: string): DataStore;
|
|
16
|
-
static from(storeId: string | Buffer): DataStore;
|
|
17
|
+
static from(storeId: string | Buffer, rootHash?: string): DataStore;
|
|
17
18
|
static create(inputs?: CreateStoreUserInputs): Promise<DataStore>;
|
|
18
19
|
private static mint;
|
|
19
20
|
/**
|
|
@@ -33,24 +34,43 @@ export declare class DataStore {
|
|
|
33
34
|
*/
|
|
34
35
|
private static calculateFolderSize;
|
|
35
36
|
static getAllStores(): DataStore[];
|
|
37
|
+
/**
|
|
38
|
+
* Monitors the store indefinitely by syncing it with a peer.
|
|
39
|
+
* Logs store retrieval and caching operations. If an error occurs, logs the error and restarts the process after a short delay.
|
|
40
|
+
* Only one monitor can be active per storeId.
|
|
41
|
+
* @param {string} storeId - The store identifier to monitor.
|
|
42
|
+
* @returns {Promise<void>} Never resolves; runs indefinitely.
|
|
43
|
+
*/
|
|
44
|
+
static monitorStoreIndefinitely(storeId: string): Promise<void>;
|
|
36
45
|
fetchCoinInfo(): Promise<{
|
|
37
46
|
latestStore: DataStoreDriver;
|
|
38
47
|
latestHeight: number;
|
|
39
48
|
latestHash: Buffer;
|
|
40
49
|
}>;
|
|
50
|
+
cacheStoreCreationHeight(): Promise<{
|
|
51
|
+
createdAtHeight: number;
|
|
52
|
+
createdAtHash: Buffer;
|
|
53
|
+
}>;
|
|
41
54
|
getCreationHeight(): Promise<{
|
|
42
55
|
createdAtHeight: number;
|
|
43
56
|
createdAtHash: Buffer;
|
|
44
57
|
}>;
|
|
45
58
|
private setCreationHeight;
|
|
46
|
-
getRootHistory(): Promise<RootHistoryItem[]>;
|
|
47
|
-
|
|
48
|
-
validate(): Promise<boolean>;
|
|
59
|
+
getRootHistory(bustCache?: boolean): Promise<RootHistoryItem[]>;
|
|
60
|
+
generateManifestFile(folderPath?: string): Promise<void>;
|
|
49
61
|
getMetaData(): Promise<DataStoreMetadata>;
|
|
50
62
|
isSynced(): Promise<boolean>;
|
|
51
63
|
hasMetaWritePermissions(publicSyntheticKey?: Buffer): Promise<boolean>;
|
|
52
64
|
updateMetadata(metadata: DataStoreMetadata): Promise<DataStoreDriver>;
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Retrieve the file set for a given root hash and validate file integrity.
|
|
67
|
+
*
|
|
68
|
+
* @param {string} rootHash - The root hash to fetch the file set.
|
|
69
|
+
* @returns {Promise<{ fileName: string, file: string }[]>} - An array of unique file objects.
|
|
70
|
+
*/
|
|
71
|
+
getFileSetForRootHash(rootHash: string, skipIntegirtyCheck?: boolean): Promise<{
|
|
72
|
+
name: string;
|
|
73
|
+
path: string;
|
|
74
|
+
}[]>;
|
|
55
75
|
}
|
|
56
76
|
//# sourceMappingURL=DataStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataStore.d.ts","sourceRoot":"","sources":["../../src/blockchain/DataStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,SAAS,IAAI,eAAe,EAE5B,iBAAiB,EAIlB,MAAM,
|
|
1
|
+
{"version":3,"file":"DataStore.d.ts","sourceRoot":"","sources":["../../src/blockchain/DataStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,SAAS,IAAI,eAAe,EAE5B,iBAAiB,EAIlB,MAAM,8BAA8B,CAAC;AAYtC,OAAO,EAAE,eAAe,EAAW,MAAM,UAAU,CAAC;AAGpD,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAgBjD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAoB;IAChC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAmC;gBAEpD,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,wBAAwB;IAqB/D,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED,IAAW,IAAI,IAAI,iBAAiB,CAEnC;IAEM,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;IAIlB,SAAS,IAAI,MAAM;WAMN,cAAc,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;WAOtD,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;WAK1C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;WAiBtD,MAAM,CACxB,MAAM,GAAE,qBAA0B,GACjC,OAAO,CAAC,SAAS,CAAC;mBAyCA,IAAI;IA4FzB;;;OAGG;IACU,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAK5C;;;OAGG;WACiB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxD;;;;OAIG;mBACkB,mBAAmB;WAqB1B,YAAY,IAAI,SAAS,EAAE;IAWxC;;;;;;MAME;WACkB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsHhE,aAAa,IAAI,OAAO,CAAC;QACpC,WAAW,EAAE,eAAe,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IAyGW,wBAAwB,IAAI,OAAO,CAAC;QAC/C,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IAiBW,iBAAiB,IAAI,OAAO,CAAC;QACxC,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;YA0BY,iBAAiB;IAYlB,cAAc,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA4C/D,oBAAoB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAexD,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAKzC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAM5B,uBAAuB,CAClC,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,OAAO,CAAC;IAkBN,cAAc,CACzB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,eAAe,CAAC;IAgD3B;;;;;OAKG;IACU,qBAAqB,CAChC,QAAQ,EAAE,MAAM,EAChB,kBAAkB,GAAE,OAAe,GAClC,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CA6C7C"}
|
|
@@ -6,18 +6,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.DataStore = void 0;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const datalayer_driver_1 = require("datalayer-driver");
|
|
9
|
+
const datalayer_driver_1 = require("@dignetwork/datalayer-driver");
|
|
10
10
|
const util_1 = require("util");
|
|
11
11
|
const FullNodePeer_1 = require("./FullNodePeer");
|
|
12
12
|
const Wallet_1 = require("./Wallet");
|
|
13
13
|
const config_1 = require("../utils/config");
|
|
14
14
|
const coins_1 = require("./coins");
|
|
15
|
-
const
|
|
15
|
+
const colorette_1 = require("colorette");
|
|
16
16
|
const hashUtils_1 = require("../utils/hashUtils");
|
|
17
17
|
const DataIntegrityTree_1 = require("../DataIntegrityTree");
|
|
18
18
|
const prompts_1 = require("../prompts");
|
|
19
19
|
const FileCache_1 = require("../utils/FileCache");
|
|
20
20
|
const DataStoreSerializer_1 = require("./DataStoreSerializer");
|
|
21
|
+
const node_cache_1 = __importDefault(require("node-cache"));
|
|
22
|
+
const config_2 = require("../utils/config");
|
|
23
|
+
const utils_1 = require("../utils");
|
|
24
|
+
// Initialize the cache with a TTL of 180 seconds (3 minutes)
|
|
25
|
+
const rootHistoryCache = new node_cache_1.default({ stdTTL: 180 });
|
|
21
26
|
const stat = (0, util_1.promisify)(fs_1.default.stat);
|
|
22
27
|
const readdir = (0, util_1.promisify)(fs_1.default.readdir);
|
|
23
28
|
class DataStore {
|
|
@@ -34,6 +39,9 @@ class DataStore {
|
|
|
34
39
|
};
|
|
35
40
|
}
|
|
36
41
|
this.tree = new DataIntegrityTree_1.DataIntegrityTree(storeId, _options);
|
|
42
|
+
if (!utils_1.Environment.CLI_MODE) {
|
|
43
|
+
DataStore.monitorStoreIndefinitely(this.storeId);
|
|
44
|
+
}
|
|
37
45
|
}
|
|
38
46
|
get StoreId() {
|
|
39
47
|
return this.storeId;
|
|
@@ -62,12 +70,15 @@ class DataStore {
|
|
|
62
70
|
const parsed = JSON.parse(serialized);
|
|
63
71
|
return new DataStore(parsed.storeId);
|
|
64
72
|
}
|
|
65
|
-
static from(storeId) {
|
|
73
|
+
static from(storeId, rootHash) {
|
|
66
74
|
const existingTreeOptions = {
|
|
67
75
|
storageMode: "local",
|
|
68
76
|
storeDir: config_1.STORE_PATH,
|
|
69
77
|
disableInitialize: true,
|
|
70
78
|
};
|
|
79
|
+
if (rootHash) {
|
|
80
|
+
existingTreeOptions.rootHash = rootHash;
|
|
81
|
+
}
|
|
71
82
|
if (storeId instanceof Buffer) {
|
|
72
83
|
return new DataStore(storeId.toString("hex"), existingTreeOptions);
|
|
73
84
|
}
|
|
@@ -107,7 +118,7 @@ class DataStore {
|
|
|
107
118
|
const wallet = await Wallet_1.Wallet.load("default");
|
|
108
119
|
const publicSyntheticKey = await wallet.getPublicSyntheticKey();
|
|
109
120
|
const ownerSyntheicPuzzleHash = (0, datalayer_driver_1.syntheticKeyToPuzzleHash)(publicSyntheticKey);
|
|
110
|
-
const storeCreationCoins = await
|
|
121
|
+
const storeCreationCoins = await wallet.selectUnspentCoins(peer, BigInt(1), BigInt(0));
|
|
111
122
|
const delegationLayers = [];
|
|
112
123
|
if (adminPublicSyntheticKey) {
|
|
113
124
|
delegationLayers.push((0, datalayer_driver_1.adminDelegatedPuzzleFromKey)(Buffer.from(adminPublicSyntheticKey, "hex")));
|
|
@@ -193,6 +204,79 @@ class DataStore {
|
|
|
193
204
|
fs_1.default.lstatSync(path_1.default.join(config_1.STORE_PATH, folder)).isDirectory());
|
|
194
205
|
return storIds.map((storeId) => DataStore.from(storeId));
|
|
195
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Monitors the store indefinitely by syncing it with a peer.
|
|
209
|
+
* Logs store retrieval and caching operations. If an error occurs, logs the error and restarts the process after a short delay.
|
|
210
|
+
* Only one monitor can be active per storeId.
|
|
211
|
+
* @param {string} storeId - The store identifier to monitor.
|
|
212
|
+
* @returns {Promise<void>} Never resolves; runs indefinitely.
|
|
213
|
+
*/
|
|
214
|
+
static async monitorStoreIndefinitely(storeId) {
|
|
215
|
+
// Check if a monitor is already running for this storeId
|
|
216
|
+
if (this.activeMonitors.get(storeId)) {
|
|
217
|
+
console.log(`Monitor already running for storeId: ${storeId}`);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// Set the monitor as active
|
|
221
|
+
this.activeMonitors.set(storeId, true);
|
|
222
|
+
const storeCoinCache = new FileCache_1.FileCache(`stores`);
|
|
223
|
+
// Clear the cache at the start
|
|
224
|
+
console.log(`Clearing cache for storeId: ${storeId}`);
|
|
225
|
+
storeCoinCache.delete(storeId);
|
|
226
|
+
while (true) {
|
|
227
|
+
try {
|
|
228
|
+
console.log(`Connecting to peer for storeId: ${storeId}`);
|
|
229
|
+
const peer = await FullNodePeer_1.FullNodePeer.connect();
|
|
230
|
+
const cachedInfo = storeCoinCache.get(storeId);
|
|
231
|
+
if (cachedInfo) {
|
|
232
|
+
// Log cached store info retrieval
|
|
233
|
+
console.log(`Cached store info found for storeId: ${storeId}, syncing...`);
|
|
234
|
+
// Deserialize cached info and wait for the coin to be spent
|
|
235
|
+
const previousStore = DataStoreSerializer_1.DataStoreSerializer.deserialize({
|
|
236
|
+
latestStore: cachedInfo.latestStore,
|
|
237
|
+
latestHeight: cachedInfo.latestHeight.toString(),
|
|
238
|
+
latestHash: cachedInfo.latestHash,
|
|
239
|
+
});
|
|
240
|
+
console.log(`Waiting for coin to be spent for storeId: ${storeId}...`);
|
|
241
|
+
await peer.waitForCoinToBeSpent((0, datalayer_driver_1.getCoinId)(previousStore.latestStore.coin), previousStore.latestHeight, previousStore.latestHash);
|
|
242
|
+
// Sync store and get updated details
|
|
243
|
+
console.log(`Syncing store for storeId: ${storeId}`);
|
|
244
|
+
const { latestStore, latestHeight } = await peer.syncStore(previousStore.latestStore, previousStore.latestHeight, previousStore.latestHash, false);
|
|
245
|
+
const latestHash = await peer.getHeaderHash(latestHeight);
|
|
246
|
+
// Serialize and cache the updated store info
|
|
247
|
+
const serializedLatestStore = new DataStoreSerializer_1.DataStoreSerializer(latestStore, latestHeight, latestHash).serialize();
|
|
248
|
+
console.log(`Caching updated store info for storeId: ${storeId}`);
|
|
249
|
+
storeCoinCache.set(storeId, {
|
|
250
|
+
latestStore: serializedLatestStore,
|
|
251
|
+
latestHeight,
|
|
252
|
+
latestHash: latestHash.toString("hex"),
|
|
253
|
+
});
|
|
254
|
+
continue; // Continue monitoring
|
|
255
|
+
}
|
|
256
|
+
// If no cached info exists, log and sync from the creation height
|
|
257
|
+
console.log(`No cached info found for storeId: ${storeId}. Retrieving creation height.`);
|
|
258
|
+
const dataStore = DataStore.from(storeId);
|
|
259
|
+
const { createdAtHeight, createdAtHash } = await dataStore.getCreationHeight();
|
|
260
|
+
// Sync store from the peer using launcher ID
|
|
261
|
+
console.log(`Syncing store from launcher ID for storeId: ${storeId}`);
|
|
262
|
+
const { latestStore, latestHeight } = await peer.syncStoreFromLauncherId(Buffer.from(storeId, "hex"), createdAtHeight, createdAtHash, false);
|
|
263
|
+
const latestHash = await peer.getHeaderHash(latestHeight);
|
|
264
|
+
// Serialize and cache the new store info
|
|
265
|
+
const serializedLatestStore = new DataStoreSerializer_1.DataStoreSerializer(latestStore, latestHeight, latestHash).serialize();
|
|
266
|
+
console.log(`Caching new store info for storeId: ${storeId}`);
|
|
267
|
+
storeCoinCache.set(storeId, {
|
|
268
|
+
latestStore: serializedLatestStore,
|
|
269
|
+
latestHeight,
|
|
270
|
+
latestHash: latestHash.toString("hex"),
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
console.error(`Error in monitorStoreIndefinitely for storeId: ${storeId} - ${error.message}`);
|
|
275
|
+
// Delay before restarting to avoid rapid retries
|
|
276
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
196
280
|
async fetchCoinInfo() {
|
|
197
281
|
try {
|
|
198
282
|
// Initialize the cache for the current storeId's coin info
|
|
@@ -257,22 +341,31 @@ class DataStore {
|
|
|
257
341
|
throw error;
|
|
258
342
|
}
|
|
259
343
|
}
|
|
344
|
+
async cacheStoreCreationHeight() {
|
|
345
|
+
const peer = await FullNodePeer_1.FullNodePeer.connect();
|
|
346
|
+
const createdAtHeight = await peer.getStoreCreationHeight(Buffer.from(this.storeId, "hex"), null, Buffer.from(config_2.MAIN_NET_GENISES_CHALLENGE, "hex"));
|
|
347
|
+
// Get just before created at height so we can find the coin
|
|
348
|
+
const justBeforeCreatedAtHeight = Number(createdAtHeight) - 1;
|
|
349
|
+
const createdAtHash = await peer.getHeaderHash(justBeforeCreatedAtHeight);
|
|
350
|
+
await this.setCreationHeight(justBeforeCreatedAtHeight, createdAtHash);
|
|
351
|
+
return { createdAtHeight: justBeforeCreatedAtHeight, createdAtHash };
|
|
352
|
+
}
|
|
260
353
|
async getCreationHeight() {
|
|
261
|
-
const defaultHeight = config_1.MIN_HEIGHT;
|
|
262
|
-
const defaultHash = Buffer.from(config_1.MIN_HEIGHT_HEADER_HASH, "hex");
|
|
263
354
|
// Initialize the FileCache for the height file
|
|
264
355
|
const fileCache = new FileCache_1.FileCache(`stores/${this.storeId}`);
|
|
265
356
|
// Try to retrieve the cached height information
|
|
266
357
|
const cachedHeightInfo = fileCache.get("height");
|
|
267
358
|
if (!cachedHeightInfo) {
|
|
268
|
-
// If no cache,
|
|
269
|
-
return
|
|
359
|
+
// If no cache, regenerate the cache
|
|
360
|
+
return this.cacheStoreCreationHeight();
|
|
270
361
|
}
|
|
271
362
|
// Parse the cached height and hash values
|
|
272
363
|
const { height, hash } = cachedHeightInfo;
|
|
364
|
+
const defaultHeight = config_1.MIN_HEIGHT;
|
|
365
|
+
const defaultHash = Buffer.from(config_1.MIN_HEIGHT_HEADER_HASH, "hex");
|
|
273
366
|
return {
|
|
274
367
|
createdAtHeight: height || defaultHeight,
|
|
275
|
-
createdAtHash: Buffer.from(hash
|
|
368
|
+
createdAtHash: hash ? Buffer.from(hash, "hex") : defaultHash,
|
|
276
369
|
};
|
|
277
370
|
}
|
|
278
371
|
async setCreationHeight(height, hash) {
|
|
@@ -283,98 +376,53 @@ class DataStore {
|
|
|
283
376
|
hash: hash.toString("hex"),
|
|
284
377
|
});
|
|
285
378
|
}
|
|
286
|
-
async getRootHistory() {
|
|
379
|
+
async getRootHistory(bustCache) {
|
|
380
|
+
if (bustCache) {
|
|
381
|
+
rootHistoryCache.del(this.storeId);
|
|
382
|
+
}
|
|
383
|
+
// Check if the root history is cached for this storeId
|
|
384
|
+
const cachedHistory = rootHistoryCache.get(this.storeId);
|
|
385
|
+
if (cachedHistory) {
|
|
386
|
+
return cachedHistory;
|
|
387
|
+
}
|
|
388
|
+
// Fetch root history from peer if not cached
|
|
287
389
|
const peer = await FullNodePeer_1.FullNodePeer.connect();
|
|
288
390
|
const { createdAtHeight, createdAtHash } = await this.getCreationHeight();
|
|
289
391
|
const { rootHashes, rootHashesTimestamps } = await peer.syncStoreFromLauncherId(Buffer.from(this.storeId, "hex"), createdAtHeight, createdAtHash, true);
|
|
290
392
|
if (!rootHashes) {
|
|
291
393
|
return [];
|
|
292
394
|
}
|
|
293
|
-
|
|
395
|
+
// Build the root history list
|
|
396
|
+
const rootHistory = rootHashes.map((rootHash, index) => ({
|
|
294
397
|
root_hash: rootHash.toString("hex"),
|
|
295
398
|
timestamp: Number(rootHashesTimestamps?.[index].toString()),
|
|
399
|
+
synced: fs_1.default.existsSync(path_1.default.join(config_1.STORE_PATH, this.storeId, `${rootHash.toString("hex")}.dat`)),
|
|
296
400
|
}));
|
|
401
|
+
// Store the root history in the cache
|
|
402
|
+
rootHistoryCache.set(this.storeId, rootHistory);
|
|
403
|
+
return rootHistory;
|
|
297
404
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
405
|
+
// Generates a fresh manifest file based on the current root history
|
|
406
|
+
// and what is currently on disk
|
|
407
|
+
async generateManifestFile(folderPath) {
|
|
408
|
+
if (!folderPath) {
|
|
409
|
+
folderPath = path_1.default.join(config_1.STORE_PATH, this.storeId, "data");
|
|
303
410
|
}
|
|
304
|
-
const manifestHashes = fs_1.default
|
|
305
|
-
.readFileSync(manifestFilePath, "utf-8")
|
|
306
|
-
.split("\n")
|
|
307
|
-
.filter(Boolean);
|
|
308
|
-
return manifestHashes.map((rootHash) => ({
|
|
309
|
-
root_hash: rootHash,
|
|
310
|
-
timestamp: 0, // Timestamps are not yet included in the manifest
|
|
311
|
-
}));
|
|
312
|
-
}
|
|
313
|
-
async validate() {
|
|
314
411
|
const rootHistory = await this.getRootHistory();
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const manifestHashes = fs_1.default
|
|
321
|
-
.readFileSync(manifestFilePath, "utf-8")
|
|
322
|
-
.split("\n")
|
|
323
|
-
.filter(Boolean);
|
|
324
|
-
if (manifestHashes.length > rootHistory.length) {
|
|
325
|
-
console.error("The store is corrupted: Manifest file has more hashes than the root history.");
|
|
326
|
-
return false;
|
|
327
|
-
}
|
|
328
|
-
if (rootHistory.length > manifestHashes.length) {
|
|
329
|
-
console.error("The store is not synced: Root history has more hashes than the manifest file.");
|
|
330
|
-
return false;
|
|
331
|
-
}
|
|
332
|
-
for (let i = 0; i < manifestHashes.length; i++) {
|
|
333
|
-
if (manifestHashes[i] !== rootHistory[i]?.root_hash) {
|
|
334
|
-
console.error(`Root hash mismatch at position ${i}: expected ${manifestHashes[i]} but found ${rootHistory[i]?.root_hash}`);
|
|
335
|
-
return false;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
let filesIntegrityIntact = true;
|
|
339
|
-
for (const rootHash of manifestHashes) {
|
|
340
|
-
const datFilePath = path_1.default.join(config_1.STORE_PATH, this.storeId, `${rootHash}.dat`);
|
|
341
|
-
if (!fs_1.default.existsSync(datFilePath)) {
|
|
342
|
-
console.error(`Data file for root hash ${rootHash} not found`);
|
|
343
|
-
return false;
|
|
344
|
-
}
|
|
345
|
-
const datFileContent = JSON.parse(fs_1.default.readFileSync(datFilePath, "utf-8"));
|
|
346
|
-
if (datFileContent.root !== rootHash) {
|
|
347
|
-
console.error(`Root hash in data file does not match: ${datFileContent.root} !== ${rootHash}`);
|
|
348
|
-
return false;
|
|
349
|
-
}
|
|
350
|
-
for (const [fileKey, fileData] of Object.entries(datFileContent.files)) {
|
|
351
|
-
const integrityCheck = (0, utils_1.validateFileSha256)(fileData.sha256, path_1.default.join(config_1.STORE_PATH, this.storeId, "data"));
|
|
352
|
-
if (!integrityCheck) {
|
|
353
|
-
filesIntegrityIntact = false;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
if (!filesIntegrityIntact) {
|
|
358
|
-
console.error("Store Corrupted: Data failed SHA256 validation.");
|
|
359
|
-
return false;
|
|
360
|
-
}
|
|
361
|
-
return true;
|
|
412
|
+
// Need this for the dataintegrity tree to work properly
|
|
413
|
+
fs_1.default.writeFileSync(path_1.default.join(folderPath, "manifest.dat"), rootHistory
|
|
414
|
+
.filter((root) => root.synced)
|
|
415
|
+
.map((root) => root.root_hash)
|
|
416
|
+
.join("\n"));
|
|
362
417
|
}
|
|
363
418
|
async getMetaData() {
|
|
364
419
|
const { latestStore } = await this.fetchCoinInfo();
|
|
365
420
|
return latestStore.metadata;
|
|
366
421
|
}
|
|
367
422
|
async isSynced() {
|
|
368
|
-
const
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
return false;
|
|
372
|
-
}
|
|
373
|
-
const manifestHashes = fs_1.default
|
|
374
|
-
.readFileSync(manifestFilePath, "utf-8")
|
|
375
|
-
.split("\n")
|
|
376
|
-
.filter(Boolean);
|
|
377
|
-
return rootHistory.length === manifestHashes.length;
|
|
423
|
+
const dataStore = await DataStore.from(this.storeId);
|
|
424
|
+
const rootHistory = await dataStore.getRootHistory();
|
|
425
|
+
return !rootHistory.some((root) => !root.synced);
|
|
378
426
|
}
|
|
379
427
|
async hasMetaWritePermissions(publicSyntheticKey) {
|
|
380
428
|
const wallet = await Wallet_1.Wallet.load("default");
|
|
@@ -394,7 +442,7 @@ class DataStore {
|
|
|
394
442
|
const { latestStore } = await this.fetchCoinInfo();
|
|
395
443
|
const updateStoreResponse = (0, datalayer_driver_1.updateStoreMetadata)(latestStore, metadata.rootHash, metadata.label, metadata.description, metadata.bytes, publicSyntheticKey, null, null);
|
|
396
444
|
const fee = await (0, coins_1.calculateFeeForCoinSpends)(peer, null);
|
|
397
|
-
const unspentCoins = await
|
|
445
|
+
const unspentCoins = await wallet.selectUnspentCoins(peer, BigInt(0), fee);
|
|
398
446
|
const feeCoinSpends = await (0, datalayer_driver_1.addFee)(publicSyntheticKey, unspentCoins, updateStoreResponse.coinSpends.map((coinSpend) => (0, datalayer_driver_1.getCoinId)(coinSpend.coin)), fee);
|
|
399
447
|
const combinedCoinSpends = [
|
|
400
448
|
...updateStoreResponse.coinSpends,
|
|
@@ -407,27 +455,41 @@ class DataStore {
|
|
|
407
455
|
}
|
|
408
456
|
return updateStoreResponse.newStore;
|
|
409
457
|
}
|
|
410
|
-
|
|
458
|
+
/**
|
|
459
|
+
* Retrieve the file set for a given root hash and validate file integrity.
|
|
460
|
+
*
|
|
461
|
+
* @param {string} rootHash - The root hash to fetch the file set.
|
|
462
|
+
* @returns {Promise<{ fileName: string, file: string }[]>} - An array of unique file objects.
|
|
463
|
+
*/
|
|
464
|
+
async getFileSetForRootHash(rootHash, skipIntegirtyCheck = false) {
|
|
411
465
|
const datFilePath = path_1.default.join(config_1.STORE_PATH, this.storeId, `${rootHash}.dat`);
|
|
412
466
|
const datFileContent = JSON.parse(fs_1.default.readFileSync(datFilePath, "utf-8"));
|
|
413
|
-
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
filesInvolved.push(manifestFilePath);
|
|
417
|
-
filesInvolved.push(datFilePath);
|
|
418
|
-
filesInvolved.push(heightDatFilePath);
|
|
467
|
+
// Use a Set to ensure uniqueness
|
|
468
|
+
const filesInvolved = new Set();
|
|
469
|
+
// Iterate over each file and perform an integrity check
|
|
419
470
|
for (const [fileKey, fileData] of Object.entries(datFileContent.files)) {
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
|
|
471
|
+
const filePath = (0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[fileKey].sha256, "data");
|
|
472
|
+
// Perform the integrity check
|
|
473
|
+
let integrityCheck;
|
|
474
|
+
if (!skipIntegirtyCheck) {
|
|
475
|
+
integrityCheck =
|
|
476
|
+
await DataIntegrityTree_1.DataIntegrityTree.validateKeyIntegrityWithForeignTree(fileKey, datFileContent.files[fileKey].sha256, datFileContent, rootHash, path_1.default.join(config_1.STORE_PATH, this.storeId, "data"));
|
|
477
|
+
}
|
|
478
|
+
if (integrityCheck || skipIntegirtyCheck) {
|
|
479
|
+
// Add the file to the Set
|
|
480
|
+
filesInvolved.add({
|
|
481
|
+
name: Buffer.from(fileKey, "hex").toString("utf-8"),
|
|
482
|
+
path: filePath,
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
console.error((0, colorette_1.red)(`File ${fileKey} failed the integrity check.`));
|
|
487
|
+
throw new Error(`Integrity check failed for file: ${fileKey}. Aborting.`);
|
|
488
|
+
}
|
|
423
489
|
}
|
|
424
|
-
return
|
|
425
|
-
|
|
426
|
-
getManifestHashes() {
|
|
427
|
-
const manifestFilePath = path_1.default.join(config_1.STORE_PATH, this.storeId, "manifest.dat");
|
|
428
|
-
return fs_1.default.existsSync(manifestFilePath)
|
|
429
|
-
? fs_1.default.readFileSync(manifestFilePath, "utf-8").split("\n").filter(Boolean)
|
|
430
|
-
: [];
|
|
490
|
+
// Convert Set to Array and return
|
|
491
|
+
return Array.from(filesInvolved);
|
|
431
492
|
}
|
|
432
493
|
}
|
|
433
494
|
exports.DataStore = DataStore;
|
|
495
|
+
DataStore.activeMonitors = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataStoreSerializer.d.ts","sourceRoot":"","sources":["../../src/blockchain/DataStoreSerializer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAKV,MAAM,
|
|
1
|
+
{"version":3,"file":"DataStoreSerializer.d.ts","sourceRoot":"","sources":["../../src/blockchain/DataStoreSerializer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAKV,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAS;gBAEf,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAOnE,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAgDF,WAAW,CACvB,IAAI,EAAE;QACJ,WAAW,EAAE,GAAG,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,GACA;QACD,WAAW,EAAE,SAAS,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB;CAuEF"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Peer } from "datalayer-driver";
|
|
1
|
+
import { Peer } from "@dignetwork/datalayer-driver";
|
|
2
2
|
export declare class FullNodePeer {
|
|
3
3
|
private static cachedPeer;
|
|
4
4
|
private static memoizedFetchNewPeerIPs;
|
|
5
5
|
private peer;
|
|
6
|
+
private static deprioritizedIps;
|
|
6
7
|
private constructor();
|
|
7
8
|
static connect(): Promise<Peer>;
|
|
8
9
|
private static isPortReachable;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FullNodePeer.d.ts","sourceRoot":"","sources":["../../src/blockchain/FullNodePeer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"FullNodePeer.d.ts","sourceRoot":"","sources":["../../src/blockchain/FullNodePeer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAO,MAAM,8BAA8B,CAAC;AAoBzD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAkD;IAC3E,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAA0B;IAChE,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAA0B;IAQzD,OAAO;WAIa,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5C,OAAO,CAAC,MAAM,CAAC,eAAe;IAiB9B,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAM/B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;mBASZ,eAAe;mBA6Df,UAAU;IA2B/B,OAAO,CAAC,MAAM,CAAC,eAAe;mBAyDT,WAAW;IAsGzB,OAAO,IAAI,IAAI;WAIF,mBAAmB,CACrC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC;CAwBpB"}
|
|
@@ -7,15 +7,16 @@ exports.FullNodePeer = void 0;
|
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const os_1 = __importDefault(require("os"));
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
|
-
const datalayer_driver_1 = require("datalayer-driver");
|
|
11
|
-
const chia_server_coin_1 = require("chia-server-coin");
|
|
10
|
+
const datalayer_driver_1 = require("@dignetwork/datalayer-driver");
|
|
12
11
|
const promises_1 = require("dns/promises");
|
|
13
12
|
const net_1 = __importDefault(require("net"));
|
|
14
13
|
const lodash_1 = require("lodash");
|
|
15
14
|
const nanospinner_1 = require("nanospinner");
|
|
16
15
|
const config_1 = require("../utils/config");
|
|
16
|
+
const Environment_1 = require("../utils/Environment");
|
|
17
17
|
const FULLNODE_PORT = 8444;
|
|
18
18
|
const LOCALHOST = "127.0.0.1";
|
|
19
|
+
const CHIA_NODES_HOST = "chia-nodes";
|
|
19
20
|
const DNS_HOSTS = [
|
|
20
21
|
"dns-introducer.chia.net",
|
|
21
22
|
"chia.ctrlaltdel.ch",
|
|
@@ -55,7 +56,7 @@ class FullNodePeer {
|
|
|
55
56
|
* @returns {string | null} The valid IP address or null if invalid
|
|
56
57
|
*/
|
|
57
58
|
static getTrustedFullNode() {
|
|
58
|
-
const trustedNodeIp =
|
|
59
|
+
const trustedNodeIp = Environment_1.Environment.TRUSTED_FULLNODE || null;
|
|
59
60
|
if (trustedNodeIp && FullNodePeer.isValidIpAddress(trustedNodeIp)) {
|
|
60
61
|
return trustedNodeIp;
|
|
61
62
|
}
|
|
@@ -64,15 +65,22 @@ class FullNodePeer {
|
|
|
64
65
|
static async fetchNewPeerIPs() {
|
|
65
66
|
const trustedNodeIp = FullNodePeer.getTrustedFullNode();
|
|
66
67
|
const priorityIps = [];
|
|
67
|
-
// Prioritize trustedNodeIp
|
|
68
|
+
// Prioritize trustedNodeIp unless it's deprioritized
|
|
68
69
|
if (trustedNodeIp &&
|
|
70
|
+
!FullNodePeer.deprioritizedIps.has(trustedNodeIp) &&
|
|
69
71
|
(await FullNodePeer.isPortReachable(trustedNodeIp, FULLNODE_PORT))) {
|
|
70
72
|
priorityIps.push(trustedNodeIp);
|
|
71
73
|
}
|
|
72
|
-
// Prioritize LOCALHOST
|
|
73
|
-
if (
|
|
74
|
+
// Prioritize LOCALHOST unless it's deprioritized
|
|
75
|
+
if (!FullNodePeer.deprioritizedIps.has(LOCALHOST) &&
|
|
76
|
+
(await FullNodePeer.isPortReachable(LOCALHOST, FULLNODE_PORT))) {
|
|
74
77
|
priorityIps.push(LOCALHOST);
|
|
75
78
|
}
|
|
79
|
+
// Prioritize CHIA_NODES_HOST unless it's deprioritized
|
|
80
|
+
if (!FullNodePeer.deprioritizedIps.has(CHIA_NODES_HOST) &&
|
|
81
|
+
(await FullNodePeer.isPortReachable(CHIA_NODES_HOST, FULLNODE_PORT))) {
|
|
82
|
+
priorityIps.push(CHIA_NODES_HOST);
|
|
83
|
+
}
|
|
76
84
|
if (priorityIps.length > 0) {
|
|
77
85
|
return priorityIps;
|
|
78
86
|
}
|
|
@@ -114,6 +122,8 @@ class FullNodePeer {
|
|
|
114
122
|
}
|
|
115
123
|
// @ts-ignore
|
|
116
124
|
if (FullNodePeer.memoizedFetchNewPeerIPs?.cache?.clear) {
|
|
125
|
+
// Clear cache and reset deprioritized IPs when cache is cleared
|
|
126
|
+
FullNodePeer.deprioritizedIps.clear();
|
|
117
127
|
// @ts-ignore
|
|
118
128
|
FullNodePeer.memoizedFetchNewPeerIPs.cache.clear();
|
|
119
129
|
}
|
|
@@ -147,10 +157,13 @@ class FullNodePeer {
|
|
|
147
157
|
}
|
|
148
158
|
catch (error) {
|
|
149
159
|
// If the error is WebSocket-related or timeout, reset the peer
|
|
150
|
-
if (error.message.includes("WebSocket") ||
|
|
160
|
+
if (error.message.includes("WebSocket") ||
|
|
161
|
+
error.message.includes("Operation timed out")) {
|
|
151
162
|
FullNodePeer.cachedPeer = null;
|
|
152
163
|
// @ts-ignore
|
|
153
164
|
FullNodePeer.memoizedFetchNewPeerIPs.cache.clear();
|
|
165
|
+
FullNodePeer.deprioritizedIps.clear();
|
|
166
|
+
console.info(`Fullnode Peer error, reconnecting to a new peer...`);
|
|
154
167
|
const newPeer = await FullNodePeer.getBestPeer();
|
|
155
168
|
return newPeer[prop](...args);
|
|
156
169
|
}
|
|
@@ -174,13 +187,21 @@ class FullNodePeer {
|
|
|
174
187
|
if (!fs_1.default.existsSync(sslFolder)) {
|
|
175
188
|
fs_1.default.mkdirSync(sslFolder, { recursive: true });
|
|
176
189
|
}
|
|
177
|
-
new
|
|
190
|
+
const tls = new datalayer_driver_1.Tls(certFile, keyFile);
|
|
178
191
|
const peerIPs = await FullNodePeer.getPeerIPs();
|
|
179
|
-
const trustedNodeIp =
|
|
192
|
+
const trustedNodeIp = Environment_1.Environment.TRUSTED_FULLNODE || null;
|
|
180
193
|
const peers = await Promise.all(peerIPs.map(async (ip) => {
|
|
181
194
|
if (ip) {
|
|
195
|
+
// Allow override of the trusted fullnode port if the override exists
|
|
196
|
+
let port = FULLNODE_PORT;
|
|
197
|
+
if (trustedNodeIp && ip === trustedNodeIp) {
|
|
198
|
+
const trustedFullNodePort = Environment_1.Environment.TRUSTED_FULLNODE_PORT;
|
|
199
|
+
if (trustedFullNodePort) {
|
|
200
|
+
port = trustedFullNodePort;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
182
203
|
try {
|
|
183
|
-
const peer = await datalayer_driver_1.Peer.new(`${ip}:${
|
|
204
|
+
const peer = await datalayer_driver_1.Peer.new(`${ip}:${port}`, false, tls);
|
|
184
205
|
return FullNodePeer.createPeerProxy(peer);
|
|
185
206
|
}
|
|
186
207
|
catch (error) {
|
|
@@ -206,16 +227,19 @@ class FullNodePeer {
|
|
|
206
227
|
throw new Error("No valid peak heights obtained from any peer.");
|
|
207
228
|
}
|
|
208
229
|
const highestPeak = Math.max(...validHeights);
|
|
209
|
-
// Prioritize LOCALHOST and
|
|
230
|
+
// Prioritize LOCALHOST, TRUSTED_NODE_IP, and CHIA_NODES_HOST if they have the highest peak height
|
|
210
231
|
let bestPeerIndex = validHeights.findIndex((height, index) => height === highestPeak &&
|
|
211
|
-
(peerIPs[index]
|
|
212
|
-
|
|
232
|
+
!FullNodePeer.deprioritizedIps.has(peerIPs[index]) && // Exclude deprioritized IPs
|
|
233
|
+
(peerIPs[index] === LOCALHOST ||
|
|
234
|
+
peerIPs[index] === trustedNodeIp ||
|
|
235
|
+
peerIPs[index] === CHIA_NODES_HOST));
|
|
236
|
+
// If LOCALHOST, TRUSTED_NODE_IP, or CHIA_NODES_HOST don't have the highest peak, select any peer with the highest peak
|
|
213
237
|
if (bestPeerIndex === -1) {
|
|
214
238
|
bestPeerIndex = validHeights.findIndex((height) => height === highestPeak);
|
|
215
239
|
}
|
|
216
240
|
const bestPeer = peers[bestPeerIndex];
|
|
217
241
|
FullNodePeer.cachedPeer = { peer: bestPeer, timestamp: now };
|
|
218
|
-
console.log(`Using Peer: ${peerIPs[bestPeerIndex]}`);
|
|
242
|
+
console.log(`Using Fullnode Peer: ${peerIPs[bestPeerIndex]}`);
|
|
219
243
|
return bestPeer;
|
|
220
244
|
}
|
|
221
245
|
getPeer() {
|
|
@@ -242,6 +266,7 @@ class FullNodePeer {
|
|
|
242
266
|
}
|
|
243
267
|
exports.FullNodePeer = FullNodePeer;
|
|
244
268
|
FullNodePeer.cachedPeer = null;
|
|
269
|
+
FullNodePeer.deprioritizedIps = new Set(); // New set for deprioritized IPs
|
|
245
270
|
(() => {
|
|
246
271
|
FullNodePeer.memoizedFetchNewPeerIPs = (0, lodash_1.memoize)(FullNodePeer.fetchNewPeerIPs);
|
|
247
272
|
})();
|