Skip to content

Commit 7c8e5da

Browse files
Merge pull request #136 from DIG-Network/release/v0.0.1-alpha.151
Release/v0.0.1 alpha.151
2 parents 1454b93 + 3ffe67b commit 7c8e5da

File tree

6 files changed

+145
-129
lines changed

6 files changed

+145
-129
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5+
### [0.0.1-alpha.151](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.150...v0.0.1-alpha.151) (2024-10-06)
6+
7+
8+
### Features
9+
10+
* improve network sync with peer ranker ([668b894](https://github.com/DIG-Network/dig-chia-sdk/commit/668b8944b5069caf6117526d4480e762a1ffcb46))
11+
512
### [0.0.1-alpha.150](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.149...v0.0.1-alpha.150) (2024-10-06)
613

714
### [0.0.1-alpha.149](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.148...v0.0.1-alpha.149) (2024-10-06)

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@dignetwork/dig-sdk",
3-
"version": "0.0.1-alpha.150",
3+
"version": "0.0.1-alpha.151",
44
"description": "",
55
"type": "commonjs",
66
"main": "./dist/index.js",

src/DigNetwork/DigNetwork.ts

Lines changed: 107 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from "path";
33
import { DigPeer } from "./DigPeer";
44
import { DataStore, ServerCoin } from "../blockchain";
55
import { DIG_FOLDER_PATH } from "../utils/config";
6-
import { withTimeout } from "../utils";
6+
import { withTimeout, PeerRanker, PeerMetrics } from "../utils";
77

88
export class DigNetwork {
99
private dataStore: DataStore;
@@ -27,99 +27,110 @@ export class DigNetwork {
2727
await digNetwork.syncStoreFromPeers();
2828
}
2929

30+
public static getAllNetworkDataStoreIds(): string[] {
31+
throw new Error("Method not implemented.");
32+
}
33+
3034
public static async getUdiContent(udi: string) {
31-
// TODO: Implement this method
35+
throw new Error("Method not implemented.");
3236
}
3337

3438
/**
35-
* Find a peer that has the store key and root hash.
39+
* Find a peer that has the store key and root hash, using ranked peers first and searching in groups of 5.
3640
*
3741
* @param {string} storeId - The ID of the store.
3842
* @param {string} rootHash - The root hash of the store.
3943
* @param {string} [key] - Optional key to check for in the store.
40-
* @param {string[]} [initialBlackList] - Initial list of blacklisted peer IPs.
4144
* @returns {Promise<DigPeer | null>} - A valid peer or null if none found.
4245
*/
4346
public static async findPeerWithStoreKey(
4447
storeId: string,
4548
rootHash: string,
46-
key?: string,
47-
initialBlackList: string[] = []
49+
key?: string
4850
): Promise<DigPeer | null> {
49-
const peerBlackList = new Set(initialBlackList);
5051
const serverCoin = new ServerCoin(storeId);
5152

52-
while (true) {
53-
try {
54-
// Sample 10 peers from the current epoch excluding blacklisted peers
55-
const digPeers = await serverCoin.sampleCurrentEpoch(
56-
10,
57-
Array.from(peerBlackList)
58-
);
53+
try {
54+
// Fetch all active peers for the current epoch
55+
const digPeers = await serverCoin.getActiveEpochPeers();
5956

60-
// If no peers are returned, break out of the loop
61-
if (digPeers.length === 0) {
62-
console.log("No more peers found.");
63-
break;
64-
}
57+
// If no peers are returned, exit early
58+
if (digPeers.length === 0) {
59+
console.log("No peers found.");
60+
return null;
61+
}
6562

66-
// Create a race of promises for all peers
67-
const peerPromises = digPeers.map((peerIp) => {
68-
return new Promise<DigPeer | null>(async (resolve) => {
69-
try {
70-
const digPeer = new DigPeer(peerIp, storeId);
71-
const { storeExists, rootHashExists } =
72-
await digPeer.propagationServer.checkStoreExists(rootHash);
73-
74-
// Check if the store and root hash exist on the peer
75-
if (storeExists && rootHashExists) {
76-
console.log(
77-
`Found Peer at ${peerIp} for storeId: ${storeId}, root hash ${rootHash}`
78-
);
79-
80-
// If no key is provided, resolve the peer
81-
if (!key) {
82-
return resolve(digPeer);
83-
}
84-
85-
// If key is provided, check if the peer has it
86-
const keyResponse = await digPeer.contentServer.headKey(
87-
key,
88-
rootHash
89-
);
90-
if (keyResponse.headers?.["x-key-exists"] === "true") {
91-
return resolve(digPeer);
92-
}
93-
}
94-
} catch (error) {
95-
console.error(`Error connecting to DIG Peer ${peerIp}.`);
96-
}
63+
// Initialize PeerRanker with the list of digPeers (IP addresses)
64+
const peerRanker = new PeerRanker(digPeers);
9765

98-
// If the peer does not meet the criteria, resolve with null
99-
resolve(null);
100-
});
101-
});
66+
// Rank the peers based on latency and bandwidth
67+
const rankedPeers = await peerRanker.rankPeers();
10268

103-
// Wait for the first valid peer that resolves
104-
const firstValidPeer = await Promise.race(peerPromises);
69+
// If no peers are returned after ranking, exit early
70+
if (rankedPeers.length === 0) {
71+
console.log("No valid peers found after ranking.");
72+
return null;
73+
}
74+
75+
// Define the iterator function to process each peer
76+
const iteratorFn = async (
77+
peerMetrics: PeerMetrics
78+
): Promise<DigPeer | null> => {
79+
const peerIp = peerMetrics.ip;
80+
try {
81+
const digPeer = new DigPeer(peerIp, storeId);
82+
83+
// Wrap the store check with a 10-second timeout
84+
const { storeExists, rootHashExists } = await withTimeout(
85+
digPeer.propagationServer.checkStoreExists(rootHash),
86+
10000,
87+
`Timeout while checking store on peer ${peerIp}`
88+
);
89+
90+
// Check if the store and root hash exist on the peer
91+
if (storeExists && rootHashExists) {
92+
console.log(
93+
`Found Peer at ${peerIp} for storeId: ${storeId}, root hash ${rootHash}`
94+
);
95+
96+
// If no key is provided, return the peer
97+
if (!key) {
98+
return digPeer;
99+
}
105100

106-
// If a valid peer is found, return it
107-
if (firstValidPeer) {
108-
return firstValidPeer;
101+
// If key is provided, wrap key check with a 10-second timeout
102+
const keyResponse = await withTimeout(
103+
digPeer.contentServer.headKey(key, rootHash),
104+
10000,
105+
`Timeout while checking key on peer ${peerIp}`
106+
);
107+
108+
if (keyResponse.headers?.["x-key-exists"] === "true") {
109+
return digPeer;
110+
}
111+
}
112+
} catch (error: any) {
113+
console.error(
114+
`Error connecting to DIG Peer ${peerIp}:`,
115+
error.message
116+
);
109117
}
110118

111-
// If none of the peers were valid, add them to the blacklist
112-
digPeers.forEach((peerIp) => peerBlackList.add(peerIp));
119+
// If the peer does not meet the criteria, return null
120+
return null;
121+
};
113122

114-
// Retry with the next set of peers
115-
console.log("No valid peers found, retrying with new peers...");
116-
} catch (error) {
117-
console.error("Error sampling peers. Resampling...");
118-
}
119-
}
123+
// Use Promise.race to return the first valid peer found
124+
const validPeer = await Promise.race(
125+
rankedPeers.map((peer) => iteratorFn(peer))
126+
);
120127

121-
// Return null if no valid peer was found after all attempts
122-
return null;
128+
// Return the first valid peer or null if none is found
129+
return validPeer || null;
130+
} catch (error) {
131+
console.error("Error sampling peers:", error);
132+
return null;
133+
}
123134
}
124135

125136
public static unsubscribeFromStore(storeId: string): void {
@@ -156,7 +167,6 @@ export class DigNetwork {
156167
}
157168
console.log("Starting network sync for store:", this.dataStore.StoreId);
158169
DigNetwork.networkSyncMap.set(this.dataStore.StoreId, true);
159-
let peerBlackList: string[] = [];
160170

161171
try {
162172
const rootHistory = await this.dataStore.getRootHistory();
@@ -189,61 +199,35 @@ export class DigNetwork {
189199

190200
// Process the root hashes sequentially
191201
for (const rootInfo of rootsToProcess) {
192-
let selectedPeer: DigPeer | null = null;
193-
194-
while (true) {
195-
try {
196-
// Find a peer with the store and root hash
197-
if (prioritizedPeer) {
198-
selectedPeer = prioritizedPeer;
199-
} else {
200-
selectedPeer = await DigNetwork.findPeerWithStoreKey(
201-
this.dataStore.StoreId,
202-
rootInfo.root_hash,
203-
undefined,
204-
peerBlackList
205-
);
206-
}
207-
208-
if (!selectedPeer) {
209-
console.error(
210-
`No peer found with root hash ${rootInfo.root_hash}. Moving to next root.`
211-
);
212-
break; // Exit the while loop to proceed to the next rootInfo
213-
}
214-
215-
// Check if the selected peer has the store and root hash
216-
const { storeExists, rootHashExists } =
217-
await selectedPeer.propagationServer.checkStoreExists(
218-
rootInfo.root_hash
219-
);
220-
221-
if (!storeExists || !rootHashExists) {
222-
console.warn(
223-
`Peer ${selectedPeer.IpAddress} does not have the required store or root hash. Trying another peer...`
224-
);
225-
peerBlackList.push(selectedPeer.IpAddress); // Blacklist and retry
226-
continue;
227-
}
202+
try {
203+
let selectedPeer: DigPeer | null = prioritizedPeer || null;
204+
205+
if (!selectedPeer) {
206+
// Use the `findPeerWithStoreKey` method to find a peer with the store and root hash
207+
selectedPeer = await DigNetwork.findPeerWithStoreKey(
208+
this.dataStore.StoreId,
209+
rootInfo.root_hash
210+
);
211+
}
228212

229-
// Download the store root and associated data
230-
await selectedPeer.downloadStoreRoot(rootInfo.root_hash);
231-
232-
// Clear the blacklist upon successful download
233-
peerBlackList = [];
234-
235-
// Break after successful download to proceed to next root hash
236-
break;
237-
} catch (error: any) {
238-
if (error.message)
239-
console.error(
240-
`Error downloading from peer ${selectedPeer?.IpAddress}. Retrying with another peer.`,
241-
error
242-
);
243-
if (selectedPeer) {
244-
peerBlackList.push(selectedPeer.IpAddress); // Blacklist and retry
245-
}
213+
if (!selectedPeer) {
214+
console.error(
215+
`No peer found with root hash ${rootInfo.root_hash}. Moving to next root.`
216+
);
217+
continue; // Move to the next rootInfo
246218
}
219+
220+
// Download the store root and associated data
221+
await selectedPeer.downloadStoreRoot(rootInfo.root_hash);
222+
223+
// Break after successful download to proceed to next root hash
224+
} catch (error: any) {
225+
if (error.message)
226+
console.error(
227+
`Error downloading from peer ${prioritizedPeer?.IpAddress}. Retrying with another peer.`,
228+
error
229+
);
230+
// Continue to next rootInfo in case of error
247231
}
248232
}
249233

src/blockchain/StoreMonitorRegistry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export class StoreMonitorRegistry {
155155
callback: StoreUpdateCallback
156156
): Promise<void> {
157157
let retryCount = 0;
158-
const maxRetryDelay = 60000; // 60 seconds
158+
const maxRetryDelay = 1000; // 60 seconds
159159

160160
while (this.activeMonitors.has(storeId)) {
161161
try {

0 commit comments

Comments
 (0)