@dignetwork/dig-sdk 0.0.1-alpha.2
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/LICENSE +7 -0
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts +160 -0
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -0
- package/dist/DataIntegrityTree/DataIntegrityTree.js +648 -0
- package/dist/DataIntegrityTree/DataLayerError.d.ts +6 -0
- package/dist/DataIntegrityTree/DataLayerError.d.ts.map +1 -0
- package/dist/DataIntegrityTree/DataLayerError.js +17 -0
- package/dist/DataIntegrityTree/index.d.ts +2 -0
- package/dist/DataIntegrityTree/index.d.ts.map +1 -0
- package/dist/DataIntegrityTree/index.js +17 -0
- package/dist/DigNetwork/ContentServer.d.ts +28 -0
- package/dist/DigNetwork/ContentServer.d.ts.map +1 -0
- package/dist/DigNetwork/ContentServer.js +243 -0
- package/dist/DigNetwork/DigChallenge.d.ts +82 -0
- package/dist/DigNetwork/DigChallenge.d.ts.map +1 -0
- package/dist/DigNetwork/DigChallenge.js +144 -0
- package/dist/DigNetwork/DigNetwork.d.ts +19 -0
- package/dist/DigNetwork/DigNetwork.d.ts.map +1 -0
- package/dist/DigNetwork/DigNetwork.js +222 -0
- package/dist/DigNetwork/DigPeer.d.ts +19 -0
- package/dist/DigNetwork/DigPeer.d.ts.map +1 -0
- package/dist/DigNetwork/DigPeer.js +164 -0
- package/dist/DigNetwork/IncentiveServer.d.ts +13 -0
- package/dist/DigNetwork/IncentiveServer.d.ts.map +1 -0
- package/dist/DigNetwork/IncentiveServer.js +76 -0
- package/dist/DigNetwork/PropagationServer.d.ts +41 -0
- package/dist/DigNetwork/PropagationServer.d.ts.map +1 -0
- package/dist/DigNetwork/PropagationServer.js +415 -0
- package/dist/DigNetwork/index.d.ts +4 -0
- package/dist/DigNetwork/index.d.ts.map +1 -0
- package/dist/DigNetwork/index.js +19 -0
- package/dist/blockchain/DataStore.d.ts +54 -0
- package/dist/blockchain/DataStore.d.ts.map +1 -0
- package/dist/blockchain/DataStore.js +410 -0
- package/dist/blockchain/DataStoreSerializer.d.ts +52 -0
- package/dist/blockchain/DataStoreSerializer.d.ts.map +1 -0
- package/dist/blockchain/DataStoreSerializer.js +109 -0
- package/dist/blockchain/FullNodePeer.d.ts +17 -0
- package/dist/blockchain/FullNodePeer.d.ts.map +1 -0
- package/dist/blockchain/FullNodePeer.js +215 -0
- package/dist/blockchain/ServerCoin.d.ts +21 -0
- package/dist/blockchain/ServerCoin.d.ts.map +1 -0
- package/dist/blockchain/ServerCoin.js +261 -0
- package/dist/blockchain/Wallet.d.ts +28 -0
- package/dist/blockchain/Wallet.d.ts.map +1 -0
- package/dist/blockchain/Wallet.js +220 -0
- package/dist/blockchain/coins.d.ts +6 -0
- package/dist/blockchain/coins.d.ts.map +1 -0
- package/dist/blockchain/coins.js +101 -0
- package/dist/blockchain/index.d.ts +8 -0
- package/dist/blockchain/index.d.ts.map +1 -0
- package/dist/blockchain/index.js +36 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/prompts.d.ts +21 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +149 -0
- package/dist/types.d.ts +62 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/utils/FileCache.d.ts +11 -0
- package/dist/utils/FileCache.d.ts.map +1 -0
- package/dist/utils/FileCache.js +58 -0
- package/dist/utils/NconfManager.d.ts +11 -0
- package/dist/utils/NconfManager.d.ts.map +1 -0
- package/dist/utils/NconfManager.js +55 -0
- package/dist/utils/config.d.ts +67 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +223 -0
- package/dist/utils/connectionUtils.d.ts +10 -0
- package/dist/utils/connectionUtils.d.ts.map +1 -0
- package/dist/utils/connectionUtils.js +18 -0
- package/dist/utils/credentialsUtils.d.ts +8 -0
- package/dist/utils/credentialsUtils.d.ts.map +1 -0
- package/dist/utils/credentialsUtils.js +122 -0
- package/dist/utils/deltaUtils.d.ts +2 -0
- package/dist/utils/deltaUtils.d.ts.map +1 -0
- package/dist/utils/deltaUtils.js +83 -0
- package/dist/utils/directoryUtils.d.ts +15 -0
- package/dist/utils/directoryUtils.d.ts.map +1 -0
- package/dist/utils/directoryUtils.js +91 -0
- package/dist/utils/encryption.d.ts +8 -0
- package/dist/utils/encryption.d.ts.map +1 -0
- package/dist/utils/encryption.js +55 -0
- package/dist/utils/hashUtils.d.ts +8 -0
- package/dist/utils/hashUtils.d.ts.map +1 -0
- package/dist/utils/hashUtils.js +44 -0
- package/dist/utils/index.d.ts +14 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +29 -0
- package/dist/utils/network.d.ts +2 -0
- package/dist/utils/network.d.ts.map +1 -0
- package/dist/utils/network.js +38 -0
- package/dist/utils/spinnerUtils.d.ts +2 -0
- package/dist/utils/spinnerUtils.d.ts.map +1 -0
- package/dist/utils/spinnerUtils.js +47 -0
- package/dist/utils/ssl.d.ts +5 -0
- package/dist/utils/ssl.d.ts.map +1 -0
- package/dist/utils/ssl.js +50 -0
- package/dist/utils/validationUtils.d.ts +9 -0
- package/dist/utils/validationUtils.d.ts.map +1 -0
- package/dist/utils/validationUtils.js +55 -0
- package/package.json +64 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DigNetwork = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const cli_progress_1 = require("cli-progress");
|
|
30
|
+
const DigPeer_1 = require("./DigPeer");
|
|
31
|
+
const deltaUtils_1 = require("../utils/deltaUtils");
|
|
32
|
+
const hashUtils_1 = require("../utils/hashUtils");
|
|
33
|
+
const blockchain_1 = require("../blockchain");
|
|
34
|
+
const config_1 = require("../utils/config");
|
|
35
|
+
class DigNetwork {
|
|
36
|
+
constructor(storeId) {
|
|
37
|
+
this.dataStore = blockchain_1.DataStore.from(storeId);
|
|
38
|
+
this.serverCoin = new blockchain_1.ServerCoin(storeId);
|
|
39
|
+
this.storeDir = path.resolve(config_1.DIG_FOLDER_PATH, "stores", storeId);
|
|
40
|
+
this.peerBlacklist = new Map(); // Initialize empty map for blacklists
|
|
41
|
+
}
|
|
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
|
+
// Uploads the store to a specific peer
|
|
67
|
+
async uploadStore(digPeer) {
|
|
68
|
+
const { generationIndex } = await this.uploadPreflight(digPeer);
|
|
69
|
+
const filesToUpload = await (0, deltaUtils_1.getDeltaFiles)(this.dataStore.StoreId, generationIndex, path.resolve(config_1.DIG_FOLDER_PATH, "stores"));
|
|
70
|
+
console.log(filesToUpload);
|
|
71
|
+
if (!filesToUpload.length) {
|
|
72
|
+
console.log("No files to upload.");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
await this.runProgressBar(filesToUpload.length, "Store Data", async (progress) => {
|
|
76
|
+
for (const filePath of filesToUpload) {
|
|
77
|
+
console.log(`Uploading ${filePath}...`);
|
|
78
|
+
const relativePath = path
|
|
79
|
+
.relative(this.storeDir, filePath)
|
|
80
|
+
.replace(/\\/g, "/");
|
|
81
|
+
await digPeer.propagationServer.pushFile(filePath, relativePath);
|
|
82
|
+
progress.increment();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
static async subscribeToStore(storeId) {
|
|
87
|
+
fs.mkdirSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId), {
|
|
88
|
+
recursive: true,
|
|
89
|
+
});
|
|
90
|
+
const digNetwork = new DigNetwork(storeId);
|
|
91
|
+
await digNetwork.downloadFiles(true);
|
|
92
|
+
}
|
|
93
|
+
static unsubscribeFromStore(storeId) {
|
|
94
|
+
fs.rmdirSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId), { recursive: true });
|
|
95
|
+
fs.unlinkSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId + ".json"));
|
|
96
|
+
}
|
|
97
|
+
// Downloads files from the network based on the manifest
|
|
98
|
+
async downloadFiles(forceDownload = false, renderProgressBar = true) {
|
|
99
|
+
try {
|
|
100
|
+
const rootHistory = await this.dataStore.getRootHistory();
|
|
101
|
+
if (!rootHistory.length)
|
|
102
|
+
throw new Error("No roots found in rootHistory. Cannot proceed with file download.");
|
|
103
|
+
await this.downloadHeightFile(forceDownload);
|
|
104
|
+
const localManifestPath = path.join(this.storeDir, "manifest.dat");
|
|
105
|
+
const localManifestHashes = fs.existsSync(localManifestPath)
|
|
106
|
+
? fs.readFileSync(localManifestPath, "utf-8").trim().split("\n")
|
|
107
|
+
: [];
|
|
108
|
+
const progressBar = renderProgressBar
|
|
109
|
+
? new cli_progress_1.MultiBar({
|
|
110
|
+
clearOnComplete: false,
|
|
111
|
+
hideCursor: true,
|
|
112
|
+
format: "Syncing Store | {bar} | {percentage}%",
|
|
113
|
+
noTTYOutput: true,
|
|
114
|
+
}, cli_progress_1.Presets.shades_classic)
|
|
115
|
+
: null;
|
|
116
|
+
const progress = progressBar
|
|
117
|
+
? progressBar.create(rootHistory.length, 0)
|
|
118
|
+
: null;
|
|
119
|
+
const newRootHashes = [];
|
|
120
|
+
for (let i = 0; i < rootHistory.length; i++) {
|
|
121
|
+
const { root_hash: rootHash } = rootHistory[i];
|
|
122
|
+
const datFilePath = path.join(this.storeDir, `${rootHash}.dat`);
|
|
123
|
+
await this.downloadFileFromPeers(`${rootHash}.dat`, datFilePath, forceDownload);
|
|
124
|
+
const datFileContent = JSON.parse(fs.readFileSync(datFilePath, "utf-8"));
|
|
125
|
+
if (datFileContent.root !== rootHash)
|
|
126
|
+
throw new Error("Root hash mismatch");
|
|
127
|
+
for (const file of Object.keys(datFileContent.files)) {
|
|
128
|
+
const filePath = (0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[file].sha256, path.join(this.storeDir, "data"));
|
|
129
|
+
const isInDataDir = filePath.startsWith(path.join(this.storeDir, "data"));
|
|
130
|
+
await this.downloadFileFromPeers((0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[file].sha256, "data"), filePath, forceDownload || !isInDataDir);
|
|
131
|
+
}
|
|
132
|
+
if (localManifestHashes[i] !== rootHash)
|
|
133
|
+
newRootHashes.push(rootHash);
|
|
134
|
+
progress?.increment();
|
|
135
|
+
}
|
|
136
|
+
if (newRootHashes.length)
|
|
137
|
+
fs.appendFileSync(localManifestPath, newRootHashes.join("\n") + "\n");
|
|
138
|
+
await this.downloadManifestFile(forceDownload);
|
|
139
|
+
progressBar?.stop();
|
|
140
|
+
console.log("Syncing store complete.");
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.trace(error);
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Fetches available peers for the store
|
|
148
|
+
async fetchAvailablePeers() {
|
|
149
|
+
//const publicIp: string | null | undefined =
|
|
150
|
+
// await nconfManager.getConfigValue("publicIp");
|
|
151
|
+
const peers = await this.serverCoin.sampleCurrentEpoch(10, Array.from(this.peerBlacklist.keys()));
|
|
152
|
+
return peers.map((ip) => new DigPeer_1.DigPeer(ip, this.dataStore.StoreId));
|
|
153
|
+
}
|
|
154
|
+
async downloadHeightFile(forceDownload) {
|
|
155
|
+
const heightFilePath = path.join(this.storeDir, "height.json");
|
|
156
|
+
await this.downloadFileFromPeers("height.json", heightFilePath, forceDownload);
|
|
157
|
+
}
|
|
158
|
+
async downloadManifestFile(forceDownload) {
|
|
159
|
+
const heightFilePath = path.join(this.storeDir, "manifest.dat");
|
|
160
|
+
await this.downloadFileFromPeers("manifest.dat", heightFilePath, forceDownload);
|
|
161
|
+
}
|
|
162
|
+
async downloadFileFromPeers(dataPath, filePath, overwrite) {
|
|
163
|
+
let digPeers = await this.fetchAvailablePeers();
|
|
164
|
+
while (true) {
|
|
165
|
+
if (!overwrite && fs.existsSync(filePath))
|
|
166
|
+
return;
|
|
167
|
+
const blacklist = this.peerBlacklist.get(dataPath) || new Set();
|
|
168
|
+
for (const digPeer of digPeers) {
|
|
169
|
+
if (blacklist.has(digPeer.IpAddress))
|
|
170
|
+
continue;
|
|
171
|
+
try {
|
|
172
|
+
// Create directory if it doesn't exist
|
|
173
|
+
const directory = path.dirname(filePath);
|
|
174
|
+
if (!fs.existsSync(directory)) {
|
|
175
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
176
|
+
}
|
|
177
|
+
// Stream the file data directly to the file system
|
|
178
|
+
const fileStream = fs.createWriteStream(filePath);
|
|
179
|
+
// Start streaming the data from the peer
|
|
180
|
+
const peerStream = await digPeer.propagationServer.streamStoreData(dataPath);
|
|
181
|
+
// Pipe the peer stream directly to the file system
|
|
182
|
+
await new Promise((resolve, reject) => {
|
|
183
|
+
peerStream.pipe(fileStream);
|
|
184
|
+
peerStream.on("end", resolve);
|
|
185
|
+
peerStream.on("error", reject);
|
|
186
|
+
fileStream.on("error", reject);
|
|
187
|
+
});
|
|
188
|
+
if (process.env.DIG_DEBUG === "1") {
|
|
189
|
+
console.log(`Downloaded ${dataPath} from ${digPeer.IpAddress}`);
|
|
190
|
+
}
|
|
191
|
+
return; // Exit the method if download succeeds
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
console.warn(`Failed to download ${dataPath} from ${digPeer.IpAddress}, blacklisting peer and trying next...`);
|
|
195
|
+
blacklist.add(digPeer.IpAddress);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
this.peerBlacklist.set(dataPath, blacklist);
|
|
199
|
+
if (blacklist.size >= digPeers.length) {
|
|
200
|
+
if (process.env.DIG_DEBUG === "1") {
|
|
201
|
+
console.warn(`All peers blacklisted for ${dataPath}. Refreshing peers...`);
|
|
202
|
+
}
|
|
203
|
+
digPeers = await this.fetchAvailablePeers();
|
|
204
|
+
if (!digPeers.length) {
|
|
205
|
+
throw new Error(`Failed to download ${dataPath}: no peers available.`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async runProgressBar(total, name, task) {
|
|
211
|
+
// Using 'any' to work around TypeScript issues
|
|
212
|
+
const multiBar = new cli_progress_1.MultiBar({
|
|
213
|
+
clearOnComplete: false,
|
|
214
|
+
hideCursor: true,
|
|
215
|
+
format: "{bar} | {percentage}% | {name}",
|
|
216
|
+
noTTYOutput: true,
|
|
217
|
+
}, cli_progress_1.Presets.shades_classic);
|
|
218
|
+
const progress = multiBar.create(total, 0, { name });
|
|
219
|
+
await task(progress).finally(() => multiBar.stop());
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
exports.DigNetwork = DigNetwork;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ContentServer } from "./ContentServer";
|
|
2
|
+
import { PropagationServer } from "./PropagationServer";
|
|
3
|
+
import { IncentiveServer } from "./IncentiveServer";
|
|
4
|
+
export declare class DigPeer {
|
|
5
|
+
private ipAddress;
|
|
6
|
+
private storeId;
|
|
7
|
+
private _contentServer;
|
|
8
|
+
private _propagationServer;
|
|
9
|
+
private _incentiveServer;
|
|
10
|
+
constructor(ipAddress: string, storeId: string);
|
|
11
|
+
get contentServer(): ContentServer;
|
|
12
|
+
get propagationServer(): PropagationServer;
|
|
13
|
+
get incentiveServer(): IncentiveServer;
|
|
14
|
+
get IpAddress(): string;
|
|
15
|
+
validateStore(rootHash: string, keys: string[]): Promise<boolean>;
|
|
16
|
+
isSynced(): Promise<boolean>;
|
|
17
|
+
sendPayment(walletName: string, amount: bigint): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=DigPeer.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DigPeer = void 0;
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
const ContentServer_1 = require("./ContentServer");
|
|
9
|
+
const PropagationServer_1 = require("./PropagationServer");
|
|
10
|
+
const IncentiveServer_1 = require("./IncentiveServer");
|
|
11
|
+
const blockchain_1 = require("../blockchain");
|
|
12
|
+
const DataIntegrityTree_1 = require("../DataIntegrityTree");
|
|
13
|
+
const datalayer_driver_1 = require("datalayer-driver");
|
|
14
|
+
const blockchain_2 = require("../blockchain");
|
|
15
|
+
const blockchain_3 = require("../blockchain");
|
|
16
|
+
const coins_1 = require("../blockchain/coins");
|
|
17
|
+
class DigPeer {
|
|
18
|
+
constructor(ipAddress, storeId) {
|
|
19
|
+
this.ipAddress = ipAddress;
|
|
20
|
+
this.storeId = storeId;
|
|
21
|
+
this._contentServer = new ContentServer_1.ContentServer(ipAddress, storeId);
|
|
22
|
+
this._propagationServer = new PropagationServer_1.PropagationServer(ipAddress, storeId);
|
|
23
|
+
this._incentiveServer = new IncentiveServer_1.IncentiveServer(ipAddress);
|
|
24
|
+
}
|
|
25
|
+
// Getter for ContentServer
|
|
26
|
+
get contentServer() {
|
|
27
|
+
return this._contentServer;
|
|
28
|
+
}
|
|
29
|
+
// Getter for PropagationServer
|
|
30
|
+
get propagationServer() {
|
|
31
|
+
return this._propagationServer;
|
|
32
|
+
}
|
|
33
|
+
// Getter for IncentiveServer
|
|
34
|
+
get incentiveServer() {
|
|
35
|
+
return this._incentiveServer;
|
|
36
|
+
}
|
|
37
|
+
get IpAddress() {
|
|
38
|
+
return this.ipAddress;
|
|
39
|
+
}
|
|
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
|
+
}
|
|
139
|
+
}
|
|
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);
|
|
144
|
+
const wallet = await blockchain_3.Wallet.load(walletName);
|
|
145
|
+
const publicSyntheticKey = await wallet.getPublicSyntheticKey();
|
|
146
|
+
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);
|
|
156
|
+
const sig = (0, datalayer_driver_1.signCoinSpends)(coinSpends, [await wallet.getPrivateSyntheticKey()], false);
|
|
157
|
+
const err = await peer.broadcastSpend(coinSpends, [sig]);
|
|
158
|
+
if (err) {
|
|
159
|
+
throw new Error(err);
|
|
160
|
+
}
|
|
161
|
+
await blockchain_2.FullNodePeer.waitForConfirmation((0, datalayer_driver_1.getCoinId)(coins[0]));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.DigPeer = DigPeer;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IncentiveProgramData } from "../types";
|
|
2
|
+
export declare class IncentiveServer {
|
|
3
|
+
private ipAddress;
|
|
4
|
+
private port;
|
|
5
|
+
constructor(ipAddress: string);
|
|
6
|
+
createIncentiveProgram(data: IncentiveProgramData): Promise<void>;
|
|
7
|
+
updateIncentiveProgram(data: IncentiveProgramData): Promise<void>;
|
|
8
|
+
deleteIncentiveProgram(storeId: string): Promise<void>;
|
|
9
|
+
getAllIncentivePrograms(): Promise<IncentiveProgramData[]>;
|
|
10
|
+
getIncentiveProgram(storeId: string): Promise<IncentiveProgramData>;
|
|
11
|
+
private makeRequest;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=IncentiveServer.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.IncentiveServer = void 0;
|
|
7
|
+
const https_1 = __importDefault(require("https"));
|
|
8
|
+
const url_1 = require("url");
|
|
9
|
+
class IncentiveServer {
|
|
10
|
+
constructor(ipAddress) {
|
|
11
|
+
this.port = 4160;
|
|
12
|
+
this.ipAddress = ipAddress;
|
|
13
|
+
}
|
|
14
|
+
// Method to create a new incentive program
|
|
15
|
+
async createIncentiveProgram(data) {
|
|
16
|
+
const url = `https://${this.ipAddress}:${this.port}/incentive`;
|
|
17
|
+
await this.makeRequest(url, "POST", data);
|
|
18
|
+
}
|
|
19
|
+
// Method to update an existing incentive program
|
|
20
|
+
async updateIncentiveProgram(data) {
|
|
21
|
+
const url = `https://${this.ipAddress}:${this.port}/incentive`;
|
|
22
|
+
await this.makeRequest(url, "PUT", data);
|
|
23
|
+
}
|
|
24
|
+
// Method to delete an incentive program by storeId
|
|
25
|
+
async deleteIncentiveProgram(storeId) {
|
|
26
|
+
const url = `https://${this.ipAddress}:${this.port}/incentive`;
|
|
27
|
+
await this.makeRequest(url, "DELETE", { storeId });
|
|
28
|
+
}
|
|
29
|
+
// Method to get all incentive programs
|
|
30
|
+
async getAllIncentivePrograms() {
|
|
31
|
+
const url = `https://${this.ipAddress}:${this.port}/incentive`;
|
|
32
|
+
return this.makeRequest(url, "GET");
|
|
33
|
+
}
|
|
34
|
+
// Method to get a specific incentive program by storeId
|
|
35
|
+
async getIncentiveProgram(storeId) {
|
|
36
|
+
const url = `https://${this.ipAddress}:${this.port}/incentive/${storeId}`;
|
|
37
|
+
return this.makeRequest(url, "GET");
|
|
38
|
+
}
|
|
39
|
+
// Helper method to handle the HTTPS request
|
|
40
|
+
async makeRequest(url, method, data) {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const urlObj = new url_1.URL(url);
|
|
43
|
+
const options = {
|
|
44
|
+
hostname: urlObj.hostname,
|
|
45
|
+
port: urlObj.port,
|
|
46
|
+
path: urlObj.pathname + urlObj.search,
|
|
47
|
+
method: method,
|
|
48
|
+
headers: {
|
|
49
|
+
"Content-Type": "application/json",
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
const req = https_1.default.request(options, (res) => {
|
|
53
|
+
let responseData = "";
|
|
54
|
+
res.on("data", (chunk) => {
|
|
55
|
+
responseData += chunk;
|
|
56
|
+
});
|
|
57
|
+
res.on("end", () => {
|
|
58
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
59
|
+
resolve(responseData ? JSON.parse(responseData) : undefined);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
reject(new Error(`Request failed with status ${res.statusCode}: ${res.statusMessage}`));
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
req.on("error", (err) => {
|
|
67
|
+
reject(err);
|
|
68
|
+
});
|
|
69
|
+
if (data) {
|
|
70
|
+
req.write(JSON.stringify(data));
|
|
71
|
+
}
|
|
72
|
+
req.end();
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.IncentiveServer = IncentiveServer;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Readable } from "stream";
|
|
2
|
+
export declare class PropagationServer {
|
|
3
|
+
private ipAddress;
|
|
4
|
+
private storeId;
|
|
5
|
+
private static certPath;
|
|
6
|
+
private static keyPath;
|
|
7
|
+
private static readonly port;
|
|
8
|
+
private static readonly maxRetries;
|
|
9
|
+
private static readonly initialDelay;
|
|
10
|
+
private static readonly maxDelay;
|
|
11
|
+
private static readonly delayMultiplier;
|
|
12
|
+
constructor(ipAddress: string, storeId: string);
|
|
13
|
+
pushFile(filePath: string, relativePath: string): Promise<void>;
|
|
14
|
+
subscribeToStore(): Promise<void>;
|
|
15
|
+
unsubscribeFromStore(): Promise<void>;
|
|
16
|
+
getStoreStatus(): Promise<any>;
|
|
17
|
+
streamStoreData(dataPath: string): Promise<Readable>;
|
|
18
|
+
getStoreData(dataPath: string): Promise<string>;
|
|
19
|
+
getStatus(): Promise<{
|
|
20
|
+
synced: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
headStore(): Promise<boolean>;
|
|
23
|
+
isStoreSynced(): Promise<boolean>;
|
|
24
|
+
getUploadDetails(): Promise<{
|
|
25
|
+
nonce: string;
|
|
26
|
+
lastUploadedHash: string;
|
|
27
|
+
generationIndex: number;
|
|
28
|
+
username: string;
|
|
29
|
+
password: string;
|
|
30
|
+
}>;
|
|
31
|
+
private postRequest;
|
|
32
|
+
private fetchUploadDetails;
|
|
33
|
+
private uploadFileDirect;
|
|
34
|
+
private retryOperation;
|
|
35
|
+
private fetch;
|
|
36
|
+
private head;
|
|
37
|
+
private fetchJson;
|
|
38
|
+
private createReadStreamWithRetries;
|
|
39
|
+
private createReadStream;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=PropagationServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PropagationServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/PropagationServer.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAChC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAS;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAQ;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAK;IACvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAQ;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAS;IACzC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAO;gBAElC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAYjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB/D,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQrC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAK9B,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAMpD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK/C,SAAS,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAOzC,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAM7B,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC;IAMjC,gBAAgB,IAAI,OAAO,CAAC;QACvC,KAAK,EAAE,MAAM,CAAC;QACd,gBAAgB,EAAE,MAAM,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;YAmBY,WAAW;YAyCX,kBAAkB;YA0ElB,gBAAgB;YAgEhB,cAAc;YAiCd,KAAK;YAmDL,IAAI;YAgCJ,SAAS;YAuCT,2BAA2B;YAiC3B,gBAAgB;CAyC/B"}
|