@dignetwork/dig-sdk 0.0.1-alpha.19 → 0.0.1-alpha.190
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 +10 -1
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -1
- package/dist/DataIntegrityTree/DataIntegrityTree.js +77 -10
- package/dist/DigNetwork/ContentServer.d.ts +20 -5
- package/dist/DigNetwork/ContentServer.d.ts.map +1 -1
- package/dist/DigNetwork/ContentServer.js +224 -28
- package/dist/DigNetwork/DigNetwork.d.ts +15 -9
- package/dist/DigNetwork/DigNetwork.d.ts.map +1 -1
- package/dist/DigNetwork/DigNetwork.js +129 -189
- package/dist/DigNetwork/DigPeer.d.ts +8 -3
- package/dist/DigNetwork/DigPeer.d.ts.map +1 -1
- package/dist/DigNetwork/DigPeer.js +72 -115
- package/dist/DigNetwork/IncentiveServer.d.ts.map +1 -1
- package/dist/DigNetwork/IncentiveServer.js +6 -5
- package/dist/DigNetwork/PropagationServer.d.ts +89 -33
- package/dist/DigNetwork/PropagationServer.d.ts.map +1 -1
- package/dist/DigNetwork/PropagationServer.js +625 -358
- package/dist/blockchain/DataStore.d.ts +25 -7
- package/dist/blockchain/DataStore.d.ts.map +1 -1
- package/dist/blockchain/DataStore.js +117 -159
- package/dist/blockchain/DataStoreSerializer.d.ts +1 -1
- package/dist/blockchain/DataStoreSerializer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.d.ts +95 -10
- package/dist/blockchain/FullNodePeer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.js +325 -115
- package/dist/blockchain/ServerCoin.d.ts +13 -5
- package/dist/blockchain/ServerCoin.d.ts.map +1 -1
- package/dist/blockchain/ServerCoin.js +89 -28
- package/dist/blockchain/StoreMonitorRegistry.d.ts +85 -0
- package/dist/blockchain/StoreMonitorRegistry.d.ts.map +1 -0
- package/dist/blockchain/StoreMonitorRegistry.js +238 -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/DigCache.d.ts +38 -0
- package/dist/utils/DigCache.d.ts.map +1 -0
- package/dist/utils/DigCache.js +236 -0
- package/dist/utils/Environment.d.ts +21 -0
- package/dist/utils/Environment.d.ts.map +1 -0
- package/dist/utils/Environment.js +93 -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.d.ts.map +1 -1
- package/dist/utils/NconfManager.js +16 -7
- package/dist/utils/PeerRanker.d.ts +55 -0
- package/dist/utils/PeerRanker.d.ts.map +1 -0
- package/dist/utils/PeerRanker.js +186 -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/Udi.d.ts +25 -0
- package/dist/utils/Udi.d.ts.map +1 -0
- package/dist/utils/Udi.js +144 -0
- package/dist/utils/config.d.ts +4 -3
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +13 -8
- package/dist/utils/directoryUtils.d.ts +16 -0
- package/dist/utils/directoryUtils.d.ts.map +1 -1
- package/dist/utils/directoryUtils.js +66 -0
- package/dist/utils/index.d.ts +5 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +5 -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 +2 -1
- package/dist/utils/network.d.ts.map +1 -1
- package/dist/utils/network.js +40 -15
- package/dist/utils/promiseUtils.d.ts +27 -0
- package/dist/utils/promiseUtils.d.ts.map +1 -0
- package/dist/utils/promiseUtils.js +69 -0
- package/dist/utils/ssl.js +2 -2
- package/package.json +31 -13
- package/dist/utils/deltaUtils.d.ts +0 -2
- package/dist/utils/deltaUtils.d.ts.map +0 -1
- package/dist/utils/deltaUtils.js +0 -83
|
@@ -4,17 +4,23 @@ export declare class DigNetwork {
|
|
|
4
4
|
private serverCoin;
|
|
5
5
|
private storeDir;
|
|
6
6
|
private peerBlacklist;
|
|
7
|
+
private static networkSyncMap;
|
|
7
8
|
constructor(storeId: string);
|
|
8
|
-
private uploadPreflight;
|
|
9
|
-
uploadStoreHead(digPeer: DigPeer): Promise<void>;
|
|
10
|
-
uploadStore(digPeer: DigPeer): Promise<void>;
|
|
11
9
|
static subscribeToStore(storeId: string): Promise<void>;
|
|
10
|
+
static getAllNetworkDataStoreIds(): string[];
|
|
11
|
+
static getUdiContent(udi: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Find a peer that has the store key and root hash, using ranked peers first and searching in groups of 5.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} storeId - The ID of the store.
|
|
16
|
+
* @param {string} rootHash - The root hash of the store.
|
|
17
|
+
* @param {string} [key] - Optional key to check for in the store.
|
|
18
|
+
* @returns {Promise<DigPeer | null>} - A valid peer or null if none found.
|
|
19
|
+
*/
|
|
20
|
+
static findPeerWithStoreKey(storeId: string, rootHash: string, key?: string): Promise<DigPeer | null>;
|
|
12
21
|
static unsubscribeFromStore(storeId: string): void;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
private downloadManifestFile;
|
|
17
|
-
private downloadFileFromPeers;
|
|
18
|
-
private runProgressBar;
|
|
22
|
+
static pingNetworkOfUpdate(storeId: string, rootHash: string): Promise<void>;
|
|
23
|
+
syncStoreFromPeers(prioritizedPeer?: DigPeer, maxRootsToProcess?: number): Promise<void>;
|
|
24
|
+
fetchAvailablePeers(): Promise<DigPeer[]>;
|
|
19
25
|
}
|
|
20
26
|
//# sourceMappingURL=DigNetwork.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DigNetwork.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigNetwork.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DigNetwork.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigNetwork.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA2B;IAChD,OAAO,CAAC,MAAM,CAAC,cAAc,CAAmC;gBAEpD,OAAO,EAAE,MAAM;WAOP,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAQtD,yBAAyB,IAAI,MAAM,EAAE;WAI/B,aAAa,CAAC,GAAG,EAAE,MAAM;IAI7C;;;;;;;OAOG;WACiB,oBAAoB,CACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;WAsFZ,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;WAOrC,mBAAmB,CACrC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAcH,kBAAkB,CAC7B,eAAe,CAAC,EAAE,OAAO,EACzB,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,IAAI,CAAC;IAqFH,mBAAmB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;CAUvD"}
|
|
@@ -26,12 +26,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.DigNetwork = void 0;
|
|
27
27
|
const fs = __importStar(require("fs"));
|
|
28
28
|
const path = __importStar(require("path"));
|
|
29
|
-
const cli_progress_1 = require("cli-progress");
|
|
30
29
|
const DigPeer_1 = require("./DigPeer");
|
|
31
|
-
const deltaUtils_1 = require("../utils/deltaUtils");
|
|
32
|
-
const hashUtils_1 = require("../utils/hashUtils");
|
|
33
30
|
const blockchain_1 = require("../blockchain");
|
|
34
31
|
const config_1 = require("../utils/config");
|
|
32
|
+
const utils_1 = require("../utils");
|
|
35
33
|
class DigNetwork {
|
|
36
34
|
constructor(storeId) {
|
|
37
35
|
this.dataStore = blockchain_1.DataStore.from(storeId);
|
|
@@ -39,88 +37,82 @@ class DigNetwork {
|
|
|
39
37
|
this.storeDir = path.resolve(config_1.DIG_FOLDER_PATH, "stores", storeId);
|
|
40
38
|
this.peerBlacklist = new Map(); // Initialize empty map for blacklists
|
|
41
39
|
}
|
|
42
|
-
async uploadPreflight(digPeer) {
|
|
43
|
-
// Preflight check is handled internally by PropagationServer if needed
|
|
44
|
-
const { lastUploadedHash, generationIndex } = await digPeer.propagationServer.getUploadDetails();
|
|
45
|
-
const rootHistory = await this.dataStore.getLocalRootHistory();
|
|
46
|
-
if (!rootHistory || rootHistory.length === 0) {
|
|
47
|
-
throw new Error("No root hashes found. Please commit your changes first.");
|
|
48
|
-
}
|
|
49
|
-
const lastLocalRootHash = rootHistory[rootHistory.length - 1].root_hash;
|
|
50
|
-
const localGenerationIndex = rootHistory.length - 1;
|
|
51
|
-
// Handle conditions based on the upload details
|
|
52
|
-
if (lastUploadedHash !== lastLocalRootHash &&
|
|
53
|
-
generationIndex === localGenerationIndex) {
|
|
54
|
-
throw new Error("The repository seems to be corrupted. Please pull the latest changes before pushing.");
|
|
55
|
-
}
|
|
56
|
-
if (lastUploadedHash === lastLocalRootHash &&
|
|
57
|
-
generationIndex === localGenerationIndex) {
|
|
58
|
-
throw new Error("No changes detected. Skipping push.");
|
|
59
|
-
}
|
|
60
|
-
if (lastUploadedHash !== lastLocalRootHash &&
|
|
61
|
-
generationIndex > localGenerationIndex) {
|
|
62
|
-
throw new Error("Remote repository is ahead of the local repository. Please pull the latest changes before pushing.");
|
|
63
|
-
}
|
|
64
|
-
return { generationIndex, lastLocalRootHash };
|
|
65
|
-
}
|
|
66
|
-
async uploadStoreHead(digPeer) {
|
|
67
|
-
// First make sure that the remote store is up to date.
|
|
68
|
-
const rootHistory = await this.dataStore.getRootHistory();
|
|
69
|
-
const localManifestHashes = await this.dataStore.getManifestHashes();
|
|
70
|
-
const remoteManifestFile = await digPeer.propagationServer.getStoreData("manifest.dat");
|
|
71
|
-
const remoteManifestHashes = remoteManifestFile.split("\n").filter(Boolean);
|
|
72
|
-
const onChainRootHashes = rootHistory.map((root) => root.root_hash);
|
|
73
|
-
// Check that remote manifest is one behind on-chain root hashes
|
|
74
|
-
if (remoteManifestHashes.length !== onChainRootHashes.length - 1) {
|
|
75
|
-
throw new Error("Remote manifest should be one behind the on-chain root. Cannot push head.");
|
|
76
|
-
}
|
|
77
|
-
// Compare each remote manifest hash with the corresponding on-chain root hash
|
|
78
|
-
for (let i = 0; i < remoteManifestHashes.length; i++) {
|
|
79
|
-
if (remoteManifestHashes[i] !== onChainRootHashes[i]) {
|
|
80
|
-
throw new Error(`Remote manifest does not match on-chain root at index ${i}. Cannot push head.`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
// Get the files for the latest local manifest hash
|
|
84
|
-
const filesToUpload = await this.dataStore.getFileSetForRootHash(localManifestHashes[localManifestHashes.length - 1]);
|
|
85
|
-
if (!filesToUpload.length) {
|
|
86
|
-
console.log("No files to upload.");
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
// Upload files to the remote peer with a progress bar
|
|
90
|
-
await this.runProgressBar(filesToUpload.length, "Store Data", async (progress) => {
|
|
91
|
-
for (const filePath of filesToUpload) {
|
|
92
|
-
const relativePath = path
|
|
93
|
-
.relative(this.storeDir, filePath)
|
|
94
|
-
.replace(/\\/g, "/");
|
|
95
|
-
await digPeer.propagationServer.pushFile(filePath, relativePath);
|
|
96
|
-
progress.increment();
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
// Uploads the store to a specific peer
|
|
101
|
-
async uploadStore(digPeer) {
|
|
102
|
-
const { generationIndex } = await this.uploadPreflight(digPeer);
|
|
103
|
-
const filesToUpload = await (0, deltaUtils_1.getDeltaFiles)(this.dataStore.StoreId, generationIndex, path.resolve(config_1.DIG_FOLDER_PATH, "stores"));
|
|
104
|
-
if (!filesToUpload.length) {
|
|
105
|
-
console.log("No files to upload.");
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
await this.runProgressBar(filesToUpload.length, "Store Data", async (progress) => {
|
|
109
|
-
for (const filePath of filesToUpload) {
|
|
110
|
-
const relativePath = path
|
|
111
|
-
.relative(this.storeDir, filePath)
|
|
112
|
-
.replace(/\\/g, "/");
|
|
113
|
-
await digPeer.propagationServer.pushFile(filePath, relativePath);
|
|
114
|
-
progress.increment();
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
40
|
static async subscribeToStore(storeId) {
|
|
119
41
|
fs.mkdirSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId), {
|
|
120
42
|
recursive: true,
|
|
121
43
|
});
|
|
122
44
|
const digNetwork = new DigNetwork(storeId);
|
|
123
|
-
await digNetwork.
|
|
45
|
+
await digNetwork.syncStoreFromPeers();
|
|
46
|
+
}
|
|
47
|
+
static getAllNetworkDataStoreIds() {
|
|
48
|
+
throw new Error("Method not implemented.");
|
|
49
|
+
}
|
|
50
|
+
static async getUdiContent(udi) {
|
|
51
|
+
throw new Error("Method not implemented.");
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Find a peer that has the store key and root hash, using ranked peers first and searching in groups of 5.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} storeId - The ID of the store.
|
|
57
|
+
* @param {string} rootHash - The root hash of the store.
|
|
58
|
+
* @param {string} [key] - Optional key to check for in the store.
|
|
59
|
+
* @returns {Promise<DigPeer | null>} - A valid peer or null if none found.
|
|
60
|
+
*/
|
|
61
|
+
static async findPeerWithStoreKey(storeId, rootHash, key) {
|
|
62
|
+
const serverCoin = new blockchain_1.ServerCoin(storeId);
|
|
63
|
+
try {
|
|
64
|
+
// Fetch all active peers for the current epoch
|
|
65
|
+
const digPeers = await serverCoin.getActiveEpochPeers();
|
|
66
|
+
// If no peers are returned, exit early
|
|
67
|
+
if (digPeers.length === 0) {
|
|
68
|
+
console.log("No peers found.");
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
// Initialize PeerRanker with the list of digPeers (IP addresses)
|
|
72
|
+
const peerRanker = new utils_1.PeerRanker(digPeers);
|
|
73
|
+
// Rank the peers based on latency and bandwidth
|
|
74
|
+
const rankedPeers = await peerRanker.rankPeers();
|
|
75
|
+
// If no peers are returned after ranking, exit early
|
|
76
|
+
if (rankedPeers.length === 0) {
|
|
77
|
+
console.log("No valid peers found after ranking.");
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
// Define the iterator function to process each peer
|
|
81
|
+
const iteratorFn = async (peerMetrics) => {
|
|
82
|
+
const peerIp = peerMetrics.ip;
|
|
83
|
+
try {
|
|
84
|
+
const digPeer = new DigPeer_1.DigPeer(peerIp, storeId);
|
|
85
|
+
// Wrap the store check with a 10-second timeout
|
|
86
|
+
const { storeExists, rootHashExists } = await (0, utils_1.withTimeout)(digPeer.propagationServer.checkStoreExists(rootHash), 10000, `Timeout while checking store on peer ${peerIp}`);
|
|
87
|
+
// Check if the store and root hash exist on the peer
|
|
88
|
+
if (storeExists && rootHashExists) {
|
|
89
|
+
console.log(`Found Peer at ${peerIp} for storeId: ${storeId}, root hash ${rootHash}`);
|
|
90
|
+
// If no key is provided, return the peer
|
|
91
|
+
if (!key) {
|
|
92
|
+
return digPeer;
|
|
93
|
+
}
|
|
94
|
+
// If key is provided, wrap key check with a 10-second timeout
|
|
95
|
+
const keyResponse = await (0, utils_1.withTimeout)(digPeer.contentServer.headKey(key, rootHash), 10000, `Timeout while checking key on peer ${peerIp}`);
|
|
96
|
+
if (keyResponse.headers?.["x-key-exists"] === "true") {
|
|
97
|
+
return digPeer;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
console.error(`Error connecting to DIG Peer ${peerIp}:`, error.message);
|
|
103
|
+
}
|
|
104
|
+
// If the peer does not meet the criteria, return null
|
|
105
|
+
return null;
|
|
106
|
+
};
|
|
107
|
+
// Use Promise.race to return the first valid peer found
|
|
108
|
+
const validPeer = await Promise.race(rankedPeers.map((peer) => iteratorFn(peer)));
|
|
109
|
+
// Return the first valid peer or null if none is found
|
|
110
|
+
return validPeer || null;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error("Error sampling peers:", error);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
124
116
|
}
|
|
125
117
|
static unsubscribeFromStore(storeId) {
|
|
126
118
|
fs.rmdirSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId), {
|
|
@@ -128,57 +120,73 @@ class DigNetwork {
|
|
|
128
120
|
});
|
|
129
121
|
fs.unlinkSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId + ".json"));
|
|
130
122
|
}
|
|
131
|
-
|
|
132
|
-
|
|
123
|
+
static async pingNetworkOfUpdate(storeId, rootHash) {
|
|
124
|
+
const serverCoin = new blockchain_1.ServerCoin(storeId);
|
|
125
|
+
// When an update is made, ping 10 network peers to pull updates from this store
|
|
126
|
+
const digPeers = await serverCoin.sampleCurrentEpoch(10);
|
|
127
|
+
for (const peer of digPeers) {
|
|
128
|
+
const digPeer = new DigPeer_1.DigPeer(peer, storeId);
|
|
129
|
+
await (0, utils_1.withTimeout)(digPeer.propagationServer.pingUpdate(rootHash), 5000, `headKey timed out for peer ${digPeer.IpAddress}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async syncStoreFromPeers(prioritizedPeer, maxRootsToProcess) {
|
|
133
|
+
// Check if synchronization is already active for this storeId
|
|
134
|
+
if (DigNetwork.networkSyncMap.get(this.dataStore.StoreId)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
console.log("Starting network sync for store:", this.dataStore.StoreId);
|
|
138
|
+
DigNetwork.networkSyncMap.set(this.dataStore.StoreId, true);
|
|
133
139
|
try {
|
|
134
140
|
const rootHistory = await this.dataStore.getRootHistory();
|
|
135
|
-
if (!rootHistory.length)
|
|
141
|
+
if (!rootHistory.length) {
|
|
136
142
|
throw new Error("No roots found in rootHistory. Cannot proceed with file download.");
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
for (const file of Object.keys(datFileContent.files)) {
|
|
163
|
-
const filePath = (0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[file].sha256, path.join(this.storeDir, "data"));
|
|
164
|
-
const isInDataDir = filePath.startsWith(path.join(this.storeDir, "data"));
|
|
165
|
-
await this.downloadFileFromPeers((0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[file].sha256, "data"), filePath, forceDownload || !isInDataDir);
|
|
143
|
+
}
|
|
144
|
+
// Filter out rootInfo entries where the .dat file already exists
|
|
145
|
+
const rootHistoryFiltered = rootHistory
|
|
146
|
+
.filter((item) => item.timestamp !== undefined)
|
|
147
|
+
.filter((item) => !fs.existsSync(`${this.storeDir}/${item.root_hash}.dat`))
|
|
148
|
+
.reverse(); // Reverse to download the latest first
|
|
149
|
+
if (!rootHistoryFiltered.length) {
|
|
150
|
+
console.log("All root hashes already exist locally. No need for download.");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// If maxRootsToProcess is specified, limit the number of roots processed
|
|
154
|
+
const rootsToProcess = maxRootsToProcess
|
|
155
|
+
? rootHistoryFiltered.slice(0, maxRootsToProcess)
|
|
156
|
+
: rootHistoryFiltered;
|
|
157
|
+
// Process the root hashes sequentially
|
|
158
|
+
for (const rootInfo of rootsToProcess) {
|
|
159
|
+
try {
|
|
160
|
+
let selectedPeer = prioritizedPeer || null;
|
|
161
|
+
if (!selectedPeer) {
|
|
162
|
+
// Use the `findPeerWithStoreKey` method to find a peer with the store and root hash
|
|
163
|
+
selectedPeer = await DigNetwork.findPeerWithStoreKey(this.dataStore.StoreId, rootInfo.root_hash);
|
|
164
|
+
}
|
|
165
|
+
if (!selectedPeer) {
|
|
166
|
+
console.error(`No peer found with root hash ${rootInfo.root_hash}. Moving to next root.`);
|
|
167
|
+
continue; // Move to the next rootInfo
|
|
166
168
|
}
|
|
169
|
+
// Download the store root and associated data
|
|
170
|
+
await selectedPeer.downloadStoreRoot(rootInfo.root_hash);
|
|
171
|
+
// Break after successful download to proceed to next root hash
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (error.message)
|
|
175
|
+
console.error(`Error downloading from peer ${prioritizedPeer?.IpAddress}. Retrying with another peer.`, error);
|
|
176
|
+
// Continue to next rootInfo in case of error
|
|
167
177
|
}
|
|
168
|
-
if (localManifestHashes[i] !== rootHash)
|
|
169
|
-
newRootHashes.push(rootHash);
|
|
170
|
-
progress?.increment();
|
|
171
178
|
}
|
|
172
|
-
if (newRootHashes.length)
|
|
173
|
-
fs.appendFileSync(localManifestPath, newRootHashes.join("\n") + "\n");
|
|
174
|
-
await this.downloadManifestFile(forceDownload);
|
|
175
|
-
progressBar?.stop();
|
|
176
179
|
console.log("Syncing store complete.");
|
|
177
180
|
}
|
|
178
181
|
catch (error) {
|
|
179
|
-
console.
|
|
182
|
+
console.error("Error during syncing store from peers:", error);
|
|
180
183
|
throw error;
|
|
181
184
|
}
|
|
185
|
+
finally {
|
|
186
|
+
// Mark synchronization as inactive for this storeId
|
|
187
|
+
DigNetwork.networkSyncMap.set(this.dataStore.StoreId, false);
|
|
188
|
+
console.log(`Network sync for storeId: ${this.dataStore.StoreId} has completed.`);
|
|
189
|
+
}
|
|
182
190
|
}
|
|
183
191
|
// Fetches available peers for the store
|
|
184
192
|
async fetchAvailablePeers() {
|
|
@@ -187,74 +195,6 @@ class DigNetwork {
|
|
|
187
195
|
const peers = await this.serverCoin.sampleCurrentEpoch(10, Array.from(this.peerBlacklist.keys()));
|
|
188
196
|
return peers.map((ip) => new DigPeer_1.DigPeer(ip, this.dataStore.StoreId));
|
|
189
197
|
}
|
|
190
|
-
async downloadHeightFile(forceDownload) {
|
|
191
|
-
const heightFilePath = path.join(this.storeDir, "height.json");
|
|
192
|
-
await this.downloadFileFromPeers("height.json", heightFilePath, forceDownload);
|
|
193
|
-
}
|
|
194
|
-
async downloadManifestFile(forceDownload) {
|
|
195
|
-
const heightFilePath = path.join(this.storeDir, "manifest.dat");
|
|
196
|
-
await this.downloadFileFromPeers("manifest.dat", heightFilePath, forceDownload);
|
|
197
|
-
}
|
|
198
|
-
async downloadFileFromPeers(dataPath, filePath, overwrite) {
|
|
199
|
-
let digPeers = await this.fetchAvailablePeers();
|
|
200
|
-
while (true) {
|
|
201
|
-
if (!overwrite && fs.existsSync(filePath))
|
|
202
|
-
return;
|
|
203
|
-
const blacklist = this.peerBlacklist.get(dataPath) || new Set();
|
|
204
|
-
for (const digPeer of digPeers) {
|
|
205
|
-
if (blacklist.has(digPeer.IpAddress))
|
|
206
|
-
continue;
|
|
207
|
-
try {
|
|
208
|
-
// Create directory if it doesn't exist
|
|
209
|
-
const directory = path.dirname(filePath);
|
|
210
|
-
if (!fs.existsSync(directory)) {
|
|
211
|
-
fs.mkdirSync(directory, { recursive: true });
|
|
212
|
-
}
|
|
213
|
-
// Stream the file data directly to the file system
|
|
214
|
-
const fileStream = fs.createWriteStream(filePath);
|
|
215
|
-
// Start streaming the data from the peer
|
|
216
|
-
const peerStream = await digPeer.propagationServer.streamStoreData(dataPath);
|
|
217
|
-
// Pipe the peer stream directly to the file system
|
|
218
|
-
await new Promise((resolve, reject) => {
|
|
219
|
-
peerStream.pipe(fileStream);
|
|
220
|
-
peerStream.on("end", resolve);
|
|
221
|
-
peerStream.on("error", reject);
|
|
222
|
-
fileStream.on("error", reject);
|
|
223
|
-
});
|
|
224
|
-
if (process.env.DIG_DEBUG === "1") {
|
|
225
|
-
console.log(`Downloaded ${dataPath} from ${digPeer.IpAddress}`);
|
|
226
|
-
}
|
|
227
|
-
return; // Exit the method if download succeeds
|
|
228
|
-
}
|
|
229
|
-
catch (error) {
|
|
230
|
-
console.warn(`Failed to download ${dataPath} from ${digPeer.IpAddress}, blacklisting peer and trying next...`);
|
|
231
|
-
blacklist.add(digPeer.IpAddress);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
this.peerBlacklist.set(dataPath, blacklist);
|
|
235
|
-
if (blacklist.size >= digPeers.length) {
|
|
236
|
-
if (process.env.DIG_DEBUG === "1") {
|
|
237
|
-
console.warn(`All peers blacklisted for ${dataPath}. Refreshing peers...`);
|
|
238
|
-
}
|
|
239
|
-
digPeers = await this.fetchAvailablePeers();
|
|
240
|
-
if (!digPeers.length) {
|
|
241
|
-
throw new Error(`Failed to download ${dataPath}: no peers available.`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
async runProgressBar(total, name, task) {
|
|
247
|
-
// Using 'any' to work around TypeScript issues
|
|
248
|
-
const multiBar = new cli_progress_1.MultiBar({
|
|
249
|
-
clearOnComplete: false,
|
|
250
|
-
hideCursor: true,
|
|
251
|
-
format: "{bar} | {percentage}% | {name}",
|
|
252
|
-
noTTYOutput: true,
|
|
253
|
-
}, cli_progress_1.Presets.shades_classic);
|
|
254
|
-
const progress = multiBar.create(total, 0, { name });
|
|
255
|
-
await task(progress).finally(() => {
|
|
256
|
-
multiBar.stop();
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
198
|
}
|
|
260
199
|
exports.DigNetwork = DigNetwork;
|
|
200
|
+
DigNetwork.networkSyncMap = new Map();
|
|
@@ -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;
|
|
@@ -12,8 +13,12 @@ export declare class DigPeer {
|
|
|
12
13
|
get propagationServer(): PropagationServer;
|
|
13
14
|
get incentiveServer(): IncentiveServer;
|
|
14
15
|
get IpAddress(): string;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
sendPayment(walletName: string, amount: bigint): Promise<void>;
|
|
16
|
+
static sendEqualBulkPayments(walletName: string, addresses: string[], totalAmount: bigint, memos: Buffer[]): Promise<void>;
|
|
17
|
+
static sendBulkPayments(walletName: string, outputs: Output[]): Promise<void>;
|
|
18
|
+
sendPayment(walletName: string, amount: bigint, memos?: Buffer[]): Promise<void>;
|
|
19
|
+
static createPaymentHint(storeId: Buffer): Buffer;
|
|
20
|
+
syncStore(order?: "asc" | "desc"): Promise<void>;
|
|
21
|
+
pushStoreRoot(storeId: string, rootHash: string): Promise<void>;
|
|
22
|
+
downloadStoreRoot(rootHash: string): Promise<void>;
|
|
18
23
|
}
|
|
19
24
|
//# sourceMappingURL=DigPeer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DigPeer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigPeer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DigPeer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigPeer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKpD,OAAO,EAKL,MAAM,EACP,MAAM,8BAA8B,CAAC;AAItC,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;WAEa,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;IAuCH,WAAW,CACtB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAM,EAAO,GACnB,OAAO,CAAC,IAAI,CAAC;WAiBF,iBAAiB,CAAC,OAAO,EAAE,MAAM;IAqBlC,SAAS,CAAC,KAAK,GAAE,KAAK,GAAG,MAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBxD,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAOhE"}
|
|
@@ -9,11 +9,9 @@ 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 datalayer_driver_1 = require("@dignetwork/datalayer-driver");
|
|
14
13
|
const blockchain_2 = require("../blockchain");
|
|
15
14
|
const blockchain_3 = require("../blockchain");
|
|
16
|
-
const coins_1 = require("../blockchain/coins");
|
|
17
15
|
class DigPeer {
|
|
18
16
|
constructor(ipAddress, storeId) {
|
|
19
17
|
this.ipAddress = ipAddress;
|
|
@@ -37,122 +35,31 @@ class DigPeer {
|
|
|
37
35
|
get IpAddress() {
|
|
38
36
|
return this.ipAddress;
|
|
39
37
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// Ensure all hashes in root history are present in the manifest in the same order
|
|
56
|
-
for (let i = 0; i < rootHistory.length; i++) {
|
|
57
|
-
if (rootHistory[i].root_hash !== manifestHashes[i]) {
|
|
58
|
-
console.error(`Hash mismatch at index ${i}: manifest hash ${manifestHashes[i]} does not match root history hash ${rootHistory[i].root_hash}`);
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
console.log("Manifest file validated.");
|
|
63
|
-
// Fetch the .dat file content for the specified root hash from the content server
|
|
64
|
-
const datFileContent = JSON.parse(await this.propagationServer.getStoreData(`${rootHash}.dat`));
|
|
65
|
-
if (datFileContent.root !== rootHash) {
|
|
66
|
-
console.error(`Root hash in .dat file does not match: ${datFileContent.root} !== ${rootHash}`);
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
let filesIntegrityIntact = true;
|
|
70
|
-
// Validate SHA256 hashes of the specified keys using streamStoreKey
|
|
71
|
-
for (const key of keys) {
|
|
72
|
-
const fileData = datFileContent.files[key];
|
|
73
|
-
if (!fileData) {
|
|
74
|
-
console.error(`File key ${key} not found in .dat file.`);
|
|
75
|
-
filesIntegrityIntact = false;
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
// Stream the file from the propagation server and calculate the SHA256 hash on the fly
|
|
79
|
-
const hash = crypto_1.default.createHash("sha256");
|
|
80
|
-
const fileStream = await this.contentServer.streamKey(Buffer.from(key, "hex").toString("utf-8"));
|
|
81
|
-
await new Promise((resolve, reject) => {
|
|
82
|
-
fileStream.on("data", (chunk) => {
|
|
83
|
-
hash.update(chunk); // Update the hash with each chunk of data
|
|
84
|
-
});
|
|
85
|
-
fileStream.on("end", () => {
|
|
86
|
-
const calculatedHash = hash.digest("hex");
|
|
87
|
-
// Compare the calculated hash with the expected hash
|
|
88
|
-
if (calculatedHash !== fileData.sha256) {
|
|
89
|
-
console.error(`File ${key} failed SHA256 validation.`);
|
|
90
|
-
filesIntegrityIntact = false;
|
|
91
|
-
}
|
|
92
|
-
resolve();
|
|
93
|
-
});
|
|
94
|
-
fileStream.on("error", (err) => {
|
|
95
|
-
console.error(`Failed to stream file ${key}: ${err.message}`);
|
|
96
|
-
reject(err);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
// Perform tree integrity validation using the datFileContent and the root hash
|
|
100
|
-
const treeCheck = DataIntegrityTree_1.DataIntegrityTree.validateKeyIntegrityWithForeignTree(key, fileData.sha256, datFileContent, rootHash);
|
|
101
|
-
if (!treeCheck) {
|
|
102
|
-
console.error(`Tree validation failed for file ${key}.`);
|
|
103
|
-
filesIntegrityIntact = false;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (!filesIntegrityIntact) {
|
|
107
|
-
console.error("Store Corrupted: Data failed SHA256 validation.");
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
console.log("Store validation successful.");
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
console.error(`Failed to validate store: ${error.message}`);
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
async isSynced() {
|
|
119
|
-
try {
|
|
120
|
-
// Fetch the root history from the propagation server
|
|
121
|
-
const dataStore = blockchain_1.DataStore.from(this.storeId);
|
|
122
|
-
const rootHistory = await dataStore.getRootHistory();
|
|
123
|
-
if (rootHistory.length === 0) {
|
|
124
|
-
console.error("No root history found for the store.");
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
// Fetch the manifest.dat file content from the content server
|
|
128
|
-
const manifestContent = await this.propagationServer.getStoreData("manifest.dat");
|
|
129
|
-
const manifestHashes = manifestContent
|
|
130
|
-
.split("\n")
|
|
131
|
-
.filter(Boolean);
|
|
132
|
-
// Compare lengths of root history and manifest
|
|
133
|
-
return rootHistory.length === manifestHashes.length;
|
|
134
|
-
}
|
|
135
|
-
catch (error) {
|
|
136
|
-
console.error(`Failed to check sync status: ${error.message}`);
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
38
|
+
static sendEqualBulkPayments(walletName, addresses, totalAmount, memos) {
|
|
39
|
+
// Use a Set to ensure unique addresses
|
|
40
|
+
const uniqueAddresses = Array.from(new Set(addresses));
|
|
41
|
+
// Convert unique addresses to puzzle hashes
|
|
42
|
+
const puzzleHashes = uniqueAddresses.map((address) => (0, datalayer_driver_1.addressToPuzzleHash)(address));
|
|
43
|
+
// Calculate amount per puzzle hash
|
|
44
|
+
const amountPerPuzzleHash = totalAmount / BigInt(puzzleHashes.length);
|
|
45
|
+
// Create outputs array
|
|
46
|
+
const outputs = puzzleHashes.map((puzzleHash) => ({
|
|
47
|
+
puzzleHash,
|
|
48
|
+
amount: amountPerPuzzleHash,
|
|
49
|
+
memos,
|
|
50
|
+
}));
|
|
51
|
+
// Call the sendBulkPayments function with the generated outputs
|
|
52
|
+
return DigPeer.sendBulkPayments(walletName, outputs);
|
|
139
53
|
}
|
|
140
|
-
async
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
const fee = BigInt(1000);
|
|
54
|
+
static async sendBulkPayments(walletName, outputs) {
|
|
55
|
+
const feePerCondition = BigInt(1000);
|
|
56
|
+
const totalFee = feePerCondition * BigInt(outputs.length);
|
|
144
57
|
const wallet = await blockchain_3.Wallet.load(walletName);
|
|
145
58
|
const publicSyntheticKey = await wallet.getPublicSyntheticKey();
|
|
146
59
|
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);
|
|
60
|
+
const totalAmount = outputs.reduce((acc, output) => acc + output.amount, BigInt(0));
|
|
61
|
+
const coins = await wallet.selectUnspentCoins(peer, totalAmount, totalFee, []);
|
|
62
|
+
const coinSpends = await (0, datalayer_driver_1.sendXch)(publicSyntheticKey, coins, outputs, totalFee);
|
|
156
63
|
const sig = (0, datalayer_driver_1.signCoinSpends)(coinSpends, [await wallet.getPrivateSyntheticKey()], false);
|
|
157
64
|
const err = await peer.broadcastSpend(coinSpends, [sig]);
|
|
158
65
|
if (err) {
|
|
@@ -160,5 +67,55 @@ class DigPeer {
|
|
|
160
67
|
}
|
|
161
68
|
await blockchain_2.FullNodePeer.waitForConfirmation((0, datalayer_driver_1.getCoinId)(coins[0]));
|
|
162
69
|
}
|
|
70
|
+
async sendPayment(walletName, amount, memos = []) {
|
|
71
|
+
const paymentAddress = await this.contentServer.getPaymentAddress();
|
|
72
|
+
if (!paymentAddress) {
|
|
73
|
+
throw new Error("Payment address not found.");
|
|
74
|
+
}
|
|
75
|
+
const paymentAddressPuzzleHash = (0, datalayer_driver_1.addressToPuzzleHash)(paymentAddress);
|
|
76
|
+
const output = {
|
|
77
|
+
puzzleHash: paymentAddressPuzzleHash,
|
|
78
|
+
amount,
|
|
79
|
+
memos,
|
|
80
|
+
};
|
|
81
|
+
return DigPeer.sendBulkPayments(walletName, [output]);
|
|
82
|
+
}
|
|
83
|
+
static createPaymentHint(storeId) {
|
|
84
|
+
// Ensure the input is a 32-byte buffer
|
|
85
|
+
if (!Buffer.isBuffer(storeId) || storeId.length !== 32) {
|
|
86
|
+
throw new Error("Invalid input. Must be a 32-byte buffer.");
|
|
87
|
+
}
|
|
88
|
+
// Define the seed
|
|
89
|
+
const seed = "digpayment";
|
|
90
|
+
// Combine the seed and the original buffer
|
|
91
|
+
const combinedBuffer = Buffer.concat([Buffer.from(seed), storeId]);
|
|
92
|
+
// Apply SHA-256 hash to the combined buffer
|
|
93
|
+
const hash = crypto_1.default.createHash("sha256");
|
|
94
|
+
hash.update(combinedBuffer);
|
|
95
|
+
const transformedBuffer = hash.digest();
|
|
96
|
+
// Return the 32-byte hash as a hex string
|
|
97
|
+
return transformedBuffer;
|
|
98
|
+
}
|
|
99
|
+
async syncStore(order = "desc") {
|
|
100
|
+
console.log('!');
|
|
101
|
+
const dataStore = blockchain_1.DataStore.from(this.storeId);
|
|
102
|
+
const rootHistory = await dataStore.getRootHistory();
|
|
103
|
+
let localRootHistory = rootHistory
|
|
104
|
+
.filter((root) => Boolean(root.synced))
|
|
105
|
+
.reverse();
|
|
106
|
+
if (order === "asc") {
|
|
107
|
+
localRootHistory = localRootHistory.reverse();
|
|
108
|
+
}
|
|
109
|
+
console.log(`Syncing store ${this.storeId} with ${this.IpAddress}`);
|
|
110
|
+
for (const item of localRootHistory) {
|
|
111
|
+
await this.pushStoreRoot(this.storeId, item.root_hash);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async pushStoreRoot(storeId, rootHash) {
|
|
115
|
+
await PropagationServer_1.PropagationServer.uploadStore(storeId, rootHash, this.IpAddress);
|
|
116
|
+
}
|
|
117
|
+
async downloadStoreRoot(rootHash) {
|
|
118
|
+
await PropagationServer_1.PropagationServer.downloadStore(this.storeId, rootHash, this.IpAddress);
|
|
119
|
+
}
|
|
163
120
|
}
|
|
164
121
|
exports.DigPeer = DigPeer;
|