@dignetwork/dig-sdk 0.0.1-alpha.13 → 0.0.1-alpha.130

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.
Files changed (81) hide show
  1. package/dist/DataIntegrityTree/DataIntegrityTree.d.ts +11 -2
  2. package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -1
  3. package/dist/DataIntegrityTree/DataIntegrityTree.js +106 -15
  4. package/dist/DigNetwork/ContentServer.d.ts +12 -5
  5. package/dist/DigNetwork/ContentServer.d.ts.map +1 -1
  6. package/dist/DigNetwork/ContentServer.js +172 -24
  7. package/dist/DigNetwork/DigNetwork.d.ts +5 -9
  8. package/dist/DigNetwork/DigNetwork.d.ts.map +1 -1
  9. package/dist/DigNetwork/DigNetwork.js +117 -189
  10. package/dist/DigNetwork/DigPeer.d.ts +8 -3
  11. package/dist/DigNetwork/DigPeer.d.ts.map +1 -1
  12. package/dist/DigNetwork/DigPeer.js +68 -115
  13. package/dist/DigNetwork/IncentiveServer.d.ts.map +1 -1
  14. package/dist/DigNetwork/IncentiveServer.js +6 -5
  15. package/dist/DigNetwork/PropagationServer.d.ts +83 -33
  16. package/dist/DigNetwork/PropagationServer.d.ts.map +1 -1
  17. package/dist/DigNetwork/PropagationServer.js +610 -356
  18. package/dist/blockchain/DataStore.d.ts +25 -7
  19. package/dist/blockchain/DataStore.d.ts.map +1 -1
  20. package/dist/blockchain/DataStore.js +112 -157
  21. package/dist/blockchain/DataStoreSerializer.d.ts +1 -1
  22. package/dist/blockchain/DataStoreSerializer.d.ts.map +1 -1
  23. package/dist/blockchain/FullNodePeer.d.ts +94 -9
  24. package/dist/blockchain/FullNodePeer.d.ts.map +1 -1
  25. package/dist/blockchain/FullNodePeer.js +323 -121
  26. package/dist/blockchain/ServerCoin.d.ts +13 -5
  27. package/dist/blockchain/ServerCoin.d.ts.map +1 -1
  28. package/dist/blockchain/ServerCoin.js +90 -28
  29. package/dist/blockchain/StoreMonitorRegistry.d.ts +85 -0
  30. package/dist/blockchain/StoreMonitorRegistry.d.ts.map +1 -0
  31. package/dist/blockchain/StoreMonitorRegistry.js +242 -0
  32. package/dist/blockchain/Wallet.d.ts +2 -2
  33. package/dist/blockchain/Wallet.d.ts.map +1 -1
  34. package/dist/blockchain/Wallet.js +50 -18
  35. package/dist/blockchain/coins.d.ts +1 -2
  36. package/dist/blockchain/coins.d.ts.map +1 -1
  37. package/dist/blockchain/coins.js +1 -55
  38. package/dist/blockchain/index.d.ts +1 -0
  39. package/dist/blockchain/index.d.ts.map +1 -1
  40. package/dist/blockchain/index.js +1 -0
  41. package/dist/types.d.ts +2 -0
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/utils/ContentScanner.d.ts +63 -0
  44. package/dist/utils/ContentScanner.d.ts.map +1 -0
  45. package/dist/utils/ContentScanner.js +175 -0
  46. package/dist/utils/Environment.d.ts +21 -0
  47. package/dist/utils/Environment.d.ts.map +1 -0
  48. package/dist/utils/Environment.js +92 -0
  49. package/dist/utils/FileCache.d.ts +1 -1
  50. package/dist/utils/FileCache.d.ts.map +1 -1
  51. package/dist/utils/FileCache.js +2 -2
  52. package/dist/utils/FileTransfer.d.ts +47 -0
  53. package/dist/utils/FileTransfer.d.ts.map +1 -0
  54. package/dist/utils/FileTransfer.js +209 -0
  55. package/dist/utils/NconfManager.js +2 -1
  56. package/dist/utils/StoreArchiveManager.d.ts +45 -0
  57. package/dist/utils/StoreArchiveManager.d.ts.map +1 -0
  58. package/dist/utils/StoreArchiveManager.js +153 -0
  59. package/dist/utils/config.d.ts +4 -3
  60. package/dist/utils/config.d.ts.map +1 -1
  61. package/dist/utils/config.js +12 -7
  62. package/dist/utils/directoryUtils.d.ts +6 -0
  63. package/dist/utils/directoryUtils.d.ts.map +1 -1
  64. package/dist/utils/directoryUtils.js +31 -9
  65. package/dist/utils/index.d.ts +2 -1
  66. package/dist/utils/index.d.ts.map +1 -1
  67. package/dist/utils/index.js +2 -1
  68. package/dist/utils/merkle.d.ts +2 -0
  69. package/dist/utils/merkle.d.ts.map +1 -0
  70. package/dist/utils/merkle.js +28 -0
  71. package/dist/utils/network.d.ts +1 -0
  72. package/dist/utils/network.d.ts.map +1 -1
  73. package/dist/utils/network.js +38 -11
  74. package/dist/utils/promiseUtils.d.ts +17 -0
  75. package/dist/utils/promiseUtils.d.ts.map +1 -0
  76. package/dist/utils/promiseUtils.js +38 -0
  77. package/dist/utils/ssl.js +2 -2
  78. package/package.json +16 -5
  79. package/dist/utils/deltaUtils.d.ts +0 -2
  80. package/dist/utils/deltaUtils.d.ts.map +0 -1
  81. package/dist/utils/deltaUtils.js +0 -83
@@ -5,16 +5,12 @@ export declare class DigNetwork {
5
5
  private storeDir;
6
6
  private peerBlacklist;
7
7
  constructor(storeId: string);
8
- private uploadPreflight;
9
- uploadStoreHead(digPeer: DigPeer): Promise<void>;
10
- uploadStore(digPeer: DigPeer): Promise<void>;
11
8
  static subscribeToStore(storeId: string): Promise<void>;
9
+ static getUdiContent(udi: string): Promise<void>;
10
+ static findPeerWithStoreKey(storeId: string, rootHash: string, key?: string, intialBlackList?: string[]): Promise<DigPeer | null>;
12
11
  static unsubscribeFromStore(storeId: string): void;
13
- downloadFiles(forceDownload?: boolean, renderProgressBar?: boolean, skipData?: boolean): Promise<void>;
14
- private fetchAvailablePeers;
15
- private downloadHeightFile;
16
- private downloadManifestFile;
17
- private downloadFileFromPeers;
18
- private runProgressBar;
12
+ static pingNetworkOfUpdate(storeId: string, rootHash: string): Promise<void>;
13
+ syncStoreFromPeers(prioritizedPeer?: DigPeer, maxRootsToProcess?: number): Promise<void>;
14
+ fetchAvailablePeers(): Promise<DigPeer[]>;
19
15
  }
20
16
  //# sourceMappingURL=DigNetwork.d.ts.map
@@ -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;AAMpC,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;WAQtD,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;YAqFF,mBAAmB;YAWnB,kBAAkB;YASlB,oBAAoB;YASpB,qBAAqB;YAuErB,cAAc;CAoB7B"}
1
+ {"version":3,"file":"DigNetwork.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigNetwork.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA2B;gBAEpC,OAAO,EAAE,MAAM;WAOP,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAQhD,aAAa,CAAC,GAAG,EAAE,MAAM;WAIzB,oBAAoB,CACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,MAAM,EACZ,eAAe,GAAE,MAAM,EAAO,GAC7B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;WA2DZ,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;WAOrC,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5E,kBAAkB,CAC7B,eAAe,CAAC,EAAE,OAAO,EACzB,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,IAAI,CAAC;IAuGH,mBAAmB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;CAUvD"}
@@ -26,12 +26,13 @@ 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");
33
+ const util_1 = require("util");
34
+ const rename = (0, util_1.promisify)(fs.rename);
35
+ const unlink = (0, util_1.promisify)(fs.unlink);
35
36
  class DigNetwork {
36
37
  constructor(storeId) {
37
38
  this.dataStore = blockchain_1.DataStore.from(storeId);
@@ -39,88 +40,59 @@ class DigNetwork {
39
40
  this.storeDir = path.resolve(config_1.DIG_FOLDER_PATH, "stores", storeId);
40
41
  this.peerBlacklist = new Map(); // Initialize empty map for blacklists
41
42
  }
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
43
  static async subscribeToStore(storeId) {
119
44
  fs.mkdirSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId), {
120
45
  recursive: true,
121
46
  });
122
47
  const digNetwork = new DigNetwork(storeId);
123
- await digNetwork.downloadFiles(true);
48
+ await digNetwork.syncStoreFromPeers();
49
+ }
50
+ static async getUdiContent(udi) {
51
+ // TODO: Implement this method
52
+ }
53
+ static async findPeerWithStoreKey(storeId, rootHash, key, intialBlackList = []) {
54
+ const peerBlackList = intialBlackList;
55
+ const serverCoin = new blockchain_1.ServerCoin(storeId);
56
+ let peerIp = null;
57
+ // Keep sampling peers until an empty array is returned
58
+ while (true) {
59
+ try {
60
+ // Sample a peer from the current epoch
61
+ const digPeers = await serverCoin.sampleCurrentEpoch(1, peerBlackList);
62
+ // If no peers are returned, break out of the loop
63
+ if (digPeers.length === 0) {
64
+ console.log("No more peers found.");
65
+ break;
66
+ }
67
+ peerIp = digPeers[0];
68
+ const digPeer = new DigPeer_1.DigPeer(peerIp, storeId);
69
+ // Try to fetch the head store information
70
+ const { storeExists, rootHashExists } = await digPeer.propagationServer.checkStoreExists(rootHash);
71
+ // If the peer has the correct root hash, check if key is required
72
+ if (storeExists && rootHashExists) {
73
+ console.log(`Found Peer at ${peerIp} for storeId: ${storeId}, root hash ${rootHash}`);
74
+ // If no key is provided, return the peer
75
+ if (!key) {
76
+ return digPeer;
77
+ }
78
+ // If key is provided, check if the peer has it
79
+ const keyResponse = await digPeer.contentServer.headKey(key, rootHash);
80
+ if (keyResponse.headers?.["x-key-exists"] === "true") {
81
+ return digPeer;
82
+ }
83
+ }
84
+ // Add peer to blacklist if it doesn't meet criteria
85
+ peerBlackList.push(peerIp);
86
+ }
87
+ catch (error) {
88
+ console.error(`Error connecting to DIG Peer ${peerIp}. Resampling...`);
89
+ if (peerIp) {
90
+ peerBlackList.push(peerIp); // Add to blacklist if error occurs
91
+ }
92
+ }
93
+ }
94
+ // Return null if no valid peer was found
95
+ return null;
124
96
  }
125
97
  static unsubscribeFromStore(storeId) {
126
98
  fs.rmdirSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId), {
@@ -128,55 +100,80 @@ class DigNetwork {
128
100
  });
129
101
  fs.unlinkSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId + ".json"));
130
102
  }
131
- // Downloads files from the network based on the manifest
132
- async downloadFiles(forceDownload = false, renderProgressBar = true, skipData = false) {
103
+ static async pingNetworkOfUpdate(storeId, rootHash) {
104
+ const serverCoin = new blockchain_1.ServerCoin(storeId);
105
+ // When an update is made, ping 10 network peers to pull updates from this store
106
+ const digPeers = await serverCoin.sampleCurrentEpoch(10);
107
+ for (const peer of digPeers) {
108
+ const digPeer = new DigPeer_1.DigPeer(peer, storeId);
109
+ await (0, utils_1.withTimeout)(digPeer.propagationServer.pingUpdate(rootHash), 5000, `headKey timed out for peer ${digPeer.IpAddress}`);
110
+ }
111
+ }
112
+ async syncStoreFromPeers(prioritizedPeer, maxRootsToProcess) {
113
+ console.log("Starting file download process...");
114
+ let peerBlackList = [];
133
115
  try {
134
116
  const rootHistory = await this.dataStore.getRootHistory();
135
- if (!rootHistory.length)
117
+ if (!rootHistory.length) {
136
118
  throw new Error("No roots found in rootHistory. Cannot proceed with file download.");
137
- await this.downloadHeightFile(forceDownload);
138
- const localManifestPath = path.join(this.storeDir, "manifest.dat");
139
- const localManifestHashes = fs.existsSync(localManifestPath)
140
- ? fs.readFileSync(localManifestPath, "utf-8").trim().split("\n")
141
- : [];
142
- const progressBar = renderProgressBar
143
- ? new cli_progress_1.MultiBar({
144
- clearOnComplete: false,
145
- hideCursor: true,
146
- format: "Syncing Store | {bar} | {percentage}%",
147
- noTTYOutput: true,
148
- }, cli_progress_1.Presets.shades_classic)
149
- : null;
150
- const progress = progressBar
151
- ? progressBar.create(rootHistory.length, 0)
152
- : null;
153
- const newRootHashes = [];
154
- for (let i = 0; i < rootHistory.length; i++) {
155
- const { root_hash: rootHash } = rootHistory[i];
156
- const datFilePath = path.join(this.storeDir, `${rootHash}.dat`);
157
- await this.downloadFileFromPeers(`${rootHash}.dat`, datFilePath, forceDownload);
158
- const datFileContent = JSON.parse(fs.readFileSync(datFilePath, "utf-8"));
159
- if (datFileContent.root !== rootHash)
160
- throw new Error("Root hash mismatch");
161
- if (!skipData) {
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);
119
+ }
120
+ // Filter out rootInfo entries where the .dat file already exists
121
+ const rootHistoryFiltered = rootHistory
122
+ .filter((item) => item.timestamp !== undefined)
123
+ .filter((item) => !fs.existsSync(`${this.storeDir}/${item.root_hash}.dat`))
124
+ .reverse(); // Reverse to download the latest first
125
+ if (!rootHistoryFiltered.length) {
126
+ console.log("All root hashes already exist locally. No need for download.");
127
+ return;
128
+ }
129
+ // If maxRootsToProcess is specified, limit the number of roots processed
130
+ const rootsToProcess = maxRootsToProcess
131
+ ? rootHistoryFiltered.slice(0, maxRootsToProcess)
132
+ : rootHistoryFiltered;
133
+ // Process the root hashes sequentially
134
+ for (const rootInfo of rootsToProcess) {
135
+ let selectedPeer = null;
136
+ while (true) {
137
+ try {
138
+ // Find a peer with the store and root hash
139
+ if (prioritizedPeer) {
140
+ selectedPeer = prioritizedPeer;
141
+ }
142
+ else {
143
+ selectedPeer = await DigNetwork.findPeerWithStoreKey(this.dataStore.StoreId, rootInfo.root_hash, undefined, peerBlackList);
144
+ }
145
+ if (!selectedPeer) {
146
+ console.error(`No peer found with root hash ${rootInfo.root_hash}. Moving to next root.`);
147
+ break; // Exit the while loop to proceed to the next rootInfo
148
+ }
149
+ // Check if the selected peer has the store and root hash
150
+ const { storeExists, rootHashExists } = await selectedPeer.propagationServer.checkStoreExists(rootInfo.root_hash);
151
+ if (!storeExists || !rootHashExists) {
152
+ console.warn(`Peer ${selectedPeer.IpAddress} does not have the required store or root hash. Trying another peer...`);
153
+ peerBlackList.push(selectedPeer.IpAddress); // Blacklist and retry
154
+ continue;
155
+ }
156
+ // Download the store root and associated data
157
+ await selectedPeer.downloadStoreRoot(rootInfo.root_hash);
158
+ // Clear the blacklist upon successful download
159
+ peerBlackList = [];
160
+ // Break after successful download to proceed to next root hash
161
+ break;
162
+ }
163
+ catch (error) {
164
+ if (error.message)
165
+ console.error(`Error downloading from peer ${selectedPeer?.IpAddress}. Retrying with another peer.`, error);
166
+ if (selectedPeer) {
167
+ peerBlackList.push(selectedPeer.IpAddress); // Blacklist and retry
168
+ }
166
169
  }
167
170
  }
168
- if (localManifestHashes[i] !== rootHash)
169
- newRootHashes.push(rootHash);
170
- progress?.increment();
171
+ DigNetwork.pingNetworkOfUpdate(this.dataStore.StoreId, rootInfo.root_hash);
171
172
  }
172
- if (newRootHashes.length)
173
- fs.appendFileSync(localManifestPath, newRootHashes.join("\n") + "\n");
174
- await this.downloadManifestFile(forceDownload);
175
- progressBar?.stop();
176
173
  console.log("Syncing store complete.");
177
174
  }
178
175
  catch (error) {
179
- console.trace(error);
176
+ console.error("Error during syncing store from peers:", error);
180
177
  throw error;
181
178
  }
182
179
  }
@@ -187,74 +184,5 @@ class DigNetwork {
187
184
  const peers = await this.serverCoin.sampleCurrentEpoch(10, Array.from(this.peerBlacklist.keys()));
188
185
  return peers.map((ip) => new DigPeer_1.DigPeer(ip, this.dataStore.StoreId));
189
186
  }
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
187
  }
260
188
  exports.DigNetwork = DigNetwork;
@@ -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
- validateStore(rootHash: string, keys: string[]): Promise<boolean>;
16
- isSynced(): Promise<boolean>;
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(): 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":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAcpD,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;IA8GN,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAyB5B,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAmC5E"}
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,IAAI,OAAO,CAAC,IAAI,CAAC;IAc1B,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 DataIntegrityTree_1 = require("../DataIntegrityTree");
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
- async validateStore(rootHash, keys) {
41
- console.log(`Validating store ${this.storeId} on peer ${this.ipAddress}...`);
42
- try {
43
- const dataStore = blockchain_1.DataStore.from(this.storeId);
44
- // Fetch the root history from the propagation server
45
- const rootHistory = await dataStore.getRootHistory();
46
- if (rootHistory.length === 0) {
47
- console.error("No root history found for the store.");
48
- return false;
49
- }
50
- // Fetch the manifest.dat file content from the propagation server
51
- const manifestContent = await this.propagationServer.getStoreData("manifest.dat");
52
- const manifestHashes = manifestContent
53
- .split("\n")
54
- .filter(Boolean);
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 sendPayment(walletName, amount) {
141
- const paymentAddress = await this.contentServer.getPaymentAddress();
142
- console.log(`Sending ${amount} Mojos to ${paymentAddress}...`);
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 coins = await (0, coins_1.selectUnspentCoins)(peer, amount, fee, [], walletName);
148
- const paymentAddressPuzzleHash = (0, datalayer_driver_1.addressToPuzzleHash)(paymentAddress);
149
- const outputs = [
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,51 @@ 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() {
100
+ const dataStore = blockchain_1.DataStore.from(this.storeId);
101
+ const rootHistory = await dataStore.getRootHistory();
102
+ const localRootHistory = rootHistory
103
+ .filter((root) => Boolean(root.synced))
104
+ .reverse();
105
+ console.log(`Syncing store ${this.storeId} with ${this.IpAddress}`);
106
+ for (const item of localRootHistory) {
107
+ await this.pushStoreRoot(this.storeId, item.root_hash);
108
+ }
109
+ }
110
+ async pushStoreRoot(storeId, rootHash) {
111
+ await PropagationServer_1.PropagationServer.uploadStore(storeId, rootHash, this.IpAddress);
112
+ }
113
+ async downloadStoreRoot(rootHash) {
114
+ await PropagationServer_1.PropagationServer.downloadStore(this.storeId, rootHash, this.IpAddress);
115
+ }
163
116
  }
164
117
  exports.DigPeer = DigPeer;
@@ -1 +1 @@
1
- {"version":3,"file":"IncentiveServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/IncentiveServer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,IAAI,CAAgB;gBAEhB,SAAS,EAAE,MAAM;IAKhB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjE,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjE,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtD,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAO1D,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAOlE,WAAW;CA6C1B"}
1
+ {"version":3,"file":"IncentiveServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/IncentiveServer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGhD,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,IAAI,CAAgB;gBAEhB,SAAS,EAAE,MAAM;IAKhB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjE,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjE,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtD,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAO1D,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAOlE,WAAW;CA6C1B"}