diff --git a/README.md b/README.md index 2e32ea5..181bf2c 100644 --- a/README.md +++ b/README.md @@ -27,12 +27,14 @@ Triangles is a privacy-focused cryptocurrency featuring Proof-of-Stake consensus The Triangles network operates exclusively over Tor for privacy: **Tor v3 Seeds:** -- `gxvrhv3qitnc6kobrhsrse46bmcfitnybapor3or3oczzuxn6hfzxyid.onion:24112` -- `futmtrvh6j34t7s6yjdxfia6iwuyfzwh4k5eqfof5kfhoqk3xmi3qoqd.onion:24112` +- `jbpfhe7zw3qm67wy3j2ayysp3mnrjobopthnko3b3sgahqtecblwqmid.onion:24112` +- `uddaxjbo3lh2zskg7w6gwln4ty5cel7q4c5jbx7fdtv6zf2j47gdlyad.onion:24112` +- `el5sirhhleecuctpeeprelzubpqmoqivvra3rzlwbjttinxa4fq3wnid.onion:24112` +- `sj5dhybnlp3v4y5niyc5unrnd6s43lyx5ibup7rolyosjbi2u2hsbvyd.onion:24112` +- `i3kr5meha7se4ns3wss3h7v46m6uksfzv4wrohdqxpj6n35wyo2bvlid.onion:24112` -**DNS Seeds:** -- `seed1.cryptographic-triangles.org` -- `seed2.cryptographic-triangles.org` +**HTTP Seed List:** +- `seeds.cryptographic-triangles.org/seeds.txt` - Dynamically updated list of active onion peers ## Building from Source diff --git a/src/main.cpp b/src/main.cpp index 06f18e0..959b8e2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -116,8 +116,10 @@ static CCriticalSection cs_PostIbdWork; static bool fPostIbdWorkStarted = false; static const unsigned int MAX_HEADER_SYNC_CACHE = 50000; -static const unsigned int HEADER_DOWNLOAD_WINDOW = 128; +static const unsigned int HEADER_DOWNLOAD_WINDOW = 512; // Increased from 128 for parallel downloads +static const unsigned int HEADER_DOWNLOAD_PER_PEER = 64; // Max blocks to request from each peer static const int64_t HEADER_REQUEST_TIMEOUT_MICROS = 30 * 1000000; +static const int64_t HEADER_REDUNDANT_REQUEST_MICROS = 10 * 1000000; // Request from another peer after 10s static void ThreadPostIbdWork(void* parg) { @@ -405,6 +407,89 @@ static void ContinueHeaderSync(CNode* pfrom, const uint256& hashTip) pfrom->PushMessage("getheaders", locator, uint256(0)); } +// Parallel block downloading: distribute blocks across all available peers +static unsigned int QueueHeaderSyncBlocksParallel(unsigned int nWindow) +{ + if (hashBestHeaderSync == 0) + return 0; + + const std::vector vPath = GetHeaderSyncDownloadPath(hashBestHeaderSync); + if (vPath.empty()) + return 0; + + // Collect eligible peers + std::vector vEligiblePeers; + { + LOCK(cs_vNodes); + for (CNode* pnode : vNodes) + { + if (!pnode->fClient && pnode->nVersion != 0 && !pnode->fDisconnect) + vEligiblePeers.push_back(pnode); + } + } + + if (vEligiblePeers.empty()) + return 0; + + const int64_t nNow = GetTime() * 1000000; + unsigned int nInFlight = CountHeaderSyncInFlight(); + unsigned int nQueued = 0; + unsigned int nPeerIndex = 0; + + // Distribute blocks across peers in round-robin fashion + for (std::vector::const_iterator it = vPath.begin(); it != vPath.end(); ++it) + { + if (nInFlight + nQueued >= nWindow) + break; + + std::map::iterator mi = mapHeaderSync.find(*it); + if (mi == mapHeaderSync.end()) + continue; + + // Check if already requested recently + bool fNeedsRequest = false; + if (!mi->second.fRequested) + { + // Never requested - request now + fNeedsRequest = true; + } + else if (nNow - mi->second.nLastRequestTime >= HEADER_REQUEST_TIMEOUT_MICROS) + { + // Timeout expired - retry + fNeedsRequest = true; + } + else if (nNow - mi->second.nLastRequestTime >= HEADER_REDUNDANT_REQUEST_MICROS) + { + // Redundant request: ask another peer if original is slow + // This creates parallel downloads for slow blocks + fNeedsRequest = true; + } + + if (!fNeedsRequest) + continue; + + // Round-robin across peers to distribute load + CNode* pnode = vEligiblePeers[nPeerIndex % vEligiblePeers.size()]; + pnode->AskFor(CInv(MSG_BLOCK, *it)); + + // Update tracking (only on first request, not redundant) + if (!mi->second.fRequested || nNow - mi->second.nLastRequestTime >= HEADER_REQUEST_TIMEOUT_MICROS) + { + mi->second.fRequested = true; + mi->second.nLastRequestTime = nNow; + } + + ++nQueued; + ++nPeerIndex; + } + + if (nQueued > 0) + printf("IBD-DIAG: parallel queue distributed %u blocks across %zu peers (window=%u, inflight=%u)\n", + nQueued, vEligiblePeers.size(), nWindow, nInFlight); + + return nQueued; +} + } // namespace ////////////////////////////////////////////////////////////////////////////// @@ -3229,9 +3314,10 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) if (nBestHeight % 5000 == 0 || !IsInitialBlockDownload()) printf("ProcessBlock: ACCEPTED block %d\n", nBestHeight); - if (pfrom && hashBestHeaderSync != 0) + if (hashBestHeaderSync != 0) { - const unsigned int nQueued = QueueHeaderSyncBlocks(pfrom, HEADER_DOWNLOAD_WINDOW); + // Use parallel queue to distribute across all peers + const unsigned int nQueued = QueueHeaderSyncBlocksParallel(HEADER_DOWNLOAD_WINDOW); if (nQueued > 0) printf("IBD-DIAG: queued %u more blocks from header planner after accepting %s\n", nQueued, hash.ToString().substr(0,20).c_str()); @@ -4540,7 +4626,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) int nRequested = 0; if (hashBestHeaderSync != 0) - nRequested = QueueHeaderSyncBlocks(pfrom, HEADER_DOWNLOAD_WINDOW); + nRequested = QueueHeaderSyncBlocksParallel(HEADER_DOWNLOAD_WINDOW); if (nNewHeaders > 0 || nRequested > 0) printf("IBD-DIAG: accepted %d new headers, queued %d blocks from %zu headers (peer=%s bestHeader=%s)\n",