Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4da39f23c | |||
| 87bfc15712 | |||
| 6353e9d5fa |
@@ -9,7 +9,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
VERSION: "5.1.8"
|
||||
VERSION: "5.1.9"
|
||||
|
||||
jobs:
|
||||
build-windows-qt:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Generated by qmake (3.1) (Qt 5.15.18)
|
||||
# Project: triangles-qt.pro
|
||||
# Template: app
|
||||
# Command: C:/msys64/mingw64/bin/qmake-qt5.exe -o Makefile triangles-qt.pro
|
||||
# Command: C:/msys64/mingw64/bin/qmake-qt5.exe -o Makefile triangles-qt.pro USE_QRCODE=1 USE_UPNP=-
|
||||
#############################################################################
|
||||
|
||||
MAKEFILE = Makefile
|
||||
@@ -156,7 +156,7 @@ Makefile: triangles-qt.pro C:/msys64/mingw64/share/qt5/mkspecs/win32-g++/qmake.c
|
||||
C:/msys64/mingw64/lib/qtmain.prl \
|
||||
C:/msys64/mingw64/share/qt5/mkspecs/features/build_pass.prf \
|
||||
src/qt/triangles.qrc
|
||||
$(QMAKE) -o Makefile triangles-qt.pro
|
||||
$(QMAKE) -o Makefile triangles-qt.pro USE_QRCODE=1 USE_UPNP=-
|
||||
C:/msys64/mingw64/share/qt5/mkspecs/features/spec_pre.prf:
|
||||
C:/msys64/mingw64/share/qt5/mkspecs/qdevice.pri:
|
||||
C:/msys64/mingw64/share/qt5/mkspecs/features/device_config.prf:
|
||||
@@ -244,7 +244,7 @@ C:/msys64/mingw64/lib/qtmain.prl:
|
||||
C:/msys64/mingw64/share/qt5/mkspecs/features/build_pass.prf:
|
||||
src/qt/triangles.qrc:
|
||||
qmake: FORCE
|
||||
@$(QMAKE) -o Makefile triangles-qt.pro
|
||||
@$(QMAKE) -o Makefile triangles-qt.pro USE_QRCODE=1 USE_UPNP=-
|
||||
|
||||
qmake_all: FORCE
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
// These need to be macros, as version.cpp's and triangles-qt.rc's voodoo requires it
|
||||
#define CLIENT_VERSION_MAJOR 5
|
||||
#define CLIENT_VERSION_MINOR 1
|
||||
#define CLIENT_VERSION_REVISION 8
|
||||
#define CLIENT_VERSION_REVISION 9
|
||||
#define CLIENT_VERSION_BUILD 0
|
||||
|
||||
// Converts the parameter X to a string after macro replacement on X has been performed.
|
||||
|
||||
@@ -140,6 +140,7 @@ void Shutdown(void* parg)
|
||||
if (fFirstThread)
|
||||
{
|
||||
fShutdown = true;
|
||||
|
||||
int64_t nDeferredWaitStart = GetTimeMillis();
|
||||
while (true)
|
||||
{
|
||||
@@ -180,6 +181,7 @@ void Shutdown(void* parg)
|
||||
fs::remove(GetPidFile());
|
||||
UnregisterWallet(pwalletMain);
|
||||
delete pwalletMain;
|
||||
// DB is flushed and wallet saved - safe to force-exit if something hangs
|
||||
NewThread(ExitTimeout, NULL);
|
||||
MilliSleep(50);
|
||||
printf("Triangles exited\n\n");
|
||||
|
||||
+126
-34
@@ -1639,6 +1639,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
|
||||
if (!CheckBlock(!fJustCheck, !fJustCheck, false))
|
||||
return false;
|
||||
|
||||
// Determine if this block is covered by the hardcoded checkpoint.
|
||||
// Below checkpoint: skip all input validation, FetchInputs, ConnectInputs,
|
||||
// and wallet sync. The checkpoint hash guarantees chain integrity for these blocks.
|
||||
bool fAssumeValid = (pindex->nHeight <= Checkpoints::GetTotalBlocksEstimate());
|
||||
bool fIsInitialDownload = IsInitialBlockDownload();
|
||||
|
||||
//// issue here: it doesn't know the version
|
||||
unsigned int nTxPos;
|
||||
if (fJustCheck)
|
||||
@@ -1658,6 +1664,20 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
|
||||
{
|
||||
uint256 hashTx = tx.GetHash();
|
||||
|
||||
CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos);
|
||||
if (!fJustCheck)
|
||||
nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
|
||||
|
||||
// Fast path: below checkpoint, skip all input validation and spent-tracking.
|
||||
// Just record where each transaction lives on disk (txindex).
|
||||
if (fAssumeValid)
|
||||
{
|
||||
mapQueuedChanges[hashTx] = CTxIndex(posThisTx, tx.vout.size());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Full validation path (above checkpoint)
|
||||
|
||||
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
|
||||
// unless those are already completely spent.
|
||||
// If such overwrites are allowed, coinbases and transactions depending upon those
|
||||
@@ -1681,10 +1701,6 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
|
||||
if (nSigOps > MAX_BLOCK_SIGOPS)
|
||||
return DoS(100, error("ConnectBlock() : too many sigops"));
|
||||
|
||||
CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos);
|
||||
if (!fJustCheck)
|
||||
nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
|
||||
|
||||
MapPrevTx mapInputs;
|
||||
if (tx.IsCoinBase())
|
||||
nValueOut += tx.GetValueOut();
|
||||
@@ -1717,20 +1733,18 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
|
||||
mapQueuedChanges[hashTx] = CTxIndex(posThisTx, tx.vout.size());
|
||||
}
|
||||
|
||||
if (IsProofOfWork() && pindex->nHeight > Checkpoints::GetTotalBlocksEstimate())
|
||||
if (!fAssumeValid)
|
||||
{
|
||||
int64_t nReward = GetProofOfWorkReward(nFees);
|
||||
// Check coinbase reward
|
||||
if (vtx[0].GetValueOut() > nReward)
|
||||
return DoS(50, error("ConnectBlock() : coinbase reward exceeded (actual=%"PRId64" vs calculated=%"PRId64")",
|
||||
vtx[0].GetValueOut(),
|
||||
nReward));
|
||||
}
|
||||
if (IsProofOfStake())
|
||||
if (IsProofOfWork())
|
||||
{
|
||||
// Skip expensive coin age calculation and reward validation for blocks
|
||||
// covered by the hardcoded checkpoint. The checkpoint guarantees chain integrity.
|
||||
if (pindex->nHeight > Checkpoints::GetTotalBlocksEstimate())
|
||||
int64_t nReward = GetProofOfWorkReward(nFees);
|
||||
// Check coinbase reward
|
||||
if (vtx[0].GetValueOut() > nReward)
|
||||
return DoS(50, error("ConnectBlock() : coinbase reward exceeded (actual=%"PRId64" vs calculated=%"PRId64")",
|
||||
vtx[0].GetValueOut(),
|
||||
nReward));
|
||||
}
|
||||
if (IsProofOfStake())
|
||||
{
|
||||
// triangles: coin stake tx earns reward instead of paying fee
|
||||
uint64_t nCoinAge;
|
||||
@@ -1760,8 +1774,8 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
|
||||
return error("ConnectBlock() : UpdateTxIndex failed");
|
||||
}
|
||||
|
||||
// Update address index
|
||||
if (fAddressIndex)
|
||||
// Update address index (skip during IBD - will be rebuilt on next start with -reindex)
|
||||
if (fAddressIndex && !fIsInitialDownload)
|
||||
{
|
||||
for (unsigned int i = 0; i < vtx.size(); i++)
|
||||
{
|
||||
@@ -1834,9 +1848,13 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
|
||||
return error("ConnectBlock() : WriteBlockIndex failed");
|
||||
}
|
||||
|
||||
// Watch for transactions paying to me
|
||||
BOOST_FOREACH(CTransaction& tx, vtx)
|
||||
SyncWithWallets(tx, this, true);
|
||||
// Skip wallet sync during IBD - a full wallet rescan runs when IBD completes.
|
||||
// This eliminates millions of per-transaction wallet lookups during sync.
|
||||
if (!fIsInitialDownload)
|
||||
{
|
||||
BOOST_FOREACH(CTransaction& tx, vtx)
|
||||
SyncWithWallets(tx, this, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2034,10 +2052,14 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
}
|
||||
}
|
||||
|
||||
// Update best block in wallet (so we can detect restored wallets)
|
||||
// Update best block in wallet (so we can detect restored wallets).
|
||||
// During IBD, skip this so the wallet knows it needs rescanning on restart.
|
||||
bool fIsInitialDownload = IsInitialBlockDownload();
|
||||
const CBlockLocator locator(pindexNew);
|
||||
::SetBestChain(locator);
|
||||
if (!fIsInitialDownload)
|
||||
{
|
||||
const CBlockLocator locator(pindexNew);
|
||||
::SetBestChain(locator);
|
||||
}
|
||||
|
||||
// New best block
|
||||
hashBestChain = hash;
|
||||
@@ -2050,8 +2072,8 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
|
||||
uint256 nBestBlockTrust = pindexBest->nHeight != 0 ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust;
|
||||
|
||||
// Log every 500 blocks during sync, every block once caught up
|
||||
if (nBestHeight % 500 == 0 || !IsInitialBlockDownload())
|
||||
// Log every 5000 blocks during sync, every block once caught up
|
||||
if (nBestHeight % 5000 == 0 || !IsInitialBlockDownload())
|
||||
printf("SetBestChain: new best=%s height=%d trust=%s blocktrust=%"PRId64" date=%s\n",
|
||||
hashBestChain.ToString().substr(0,20).c_str(), nBestHeight,
|
||||
CBigNum(nBestChainTrust).ToString().c_str(),
|
||||
@@ -2102,6 +2124,40 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
pNotificationQueue->Push(strBlockEvent);
|
||||
}
|
||||
|
||||
// Detect IBD-to-synced transition and trigger deferred work:
|
||||
// wallet rescan (since SyncWithWallets was skipped) and smsg chain scan.
|
||||
{
|
||||
static bool fWasInitialDownload = true;
|
||||
if (fWasInitialDownload && !fIsInitialDownload)
|
||||
{
|
||||
printf("*** Initial block download complete at height %d ***\n", nBestHeight);
|
||||
|
||||
// Update wallet best chain locator now that IBD is done
|
||||
const CBlockLocator locator(pindexBest);
|
||||
::SetBestChain(locator);
|
||||
|
||||
// Wallet rescan: SyncWithWallets was skipped during IBD, so scan
|
||||
// the entire chain to pick up all wallet transactions.
|
||||
if (pwalletMain)
|
||||
{
|
||||
printf("Starting post-IBD wallet rescan from genesis...\n");
|
||||
uiInterface.InitMessage(_("Rescanning wallet..."));
|
||||
int nFound = pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true);
|
||||
printf("Post-IBD wallet rescan complete: %d transactions found\n", nFound);
|
||||
}
|
||||
|
||||
// Secure messaging: scan chain for public keys needed to decrypt messages
|
||||
if (fSecMsgEnabled)
|
||||
{
|
||||
printf("Starting post-IBD secure message chain scan...\n");
|
||||
uiInterface.InitMessage(_("Scanning for secure messages..."));
|
||||
SecureMsgScanBlockChain();
|
||||
printf("Post-IBD secure message chain scan complete\n");
|
||||
}
|
||||
}
|
||||
fWasInitialDownload = fIsInitialDownload;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2598,7 +2654,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
|
||||
mapOrphanBlocksByPrev.erase(hashPrev);
|
||||
}
|
||||
|
||||
if (nBestHeight % 500 == 0 || !IsInitialBlockDownload())
|
||||
if (nBestHeight % 5000 == 0 || !IsInitialBlockDownload())
|
||||
printf("ProcessBlock: ACCEPTED block %d\n", nBestHeight);
|
||||
|
||||
// triangles: if responsible for sync-checkpoint send it
|
||||
@@ -3211,13 +3267,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
}
|
||||
}
|
||||
|
||||
// Ask the first connected node for block updates
|
||||
// Ask connected nodes for block updates
|
||||
// During IBD, always request blocks from any valid peer (critical for reconnection)
|
||||
static int nAskedForBlocks = 0;
|
||||
if (!pfrom->fClient && !pfrom->fOneShot &&
|
||||
(pfrom->nStartingHeight > (nBestHeight - 144)) &&
|
||||
(pfrom->nVersion < NOBLKS_VERSION_START ||
|
||||
pfrom->nVersion >= NOBLKS_VERSION_END) &&
|
||||
(nAskedForBlocks < 1 || vNodes.size() <= 1))
|
||||
(IsInitialBlockDownload() || nAskedForBlocks < 1 || vNodes.size() <= 1))
|
||||
{
|
||||
nAskedForBlocks++;
|
||||
pfrom->PushGetBlocks(pindexBest, uint256(0));
|
||||
@@ -3464,7 +3521,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
// Send the rest of the chain
|
||||
if (pindex)
|
||||
pindex = pindex->pnext;
|
||||
int nLimit = 500;
|
||||
int nLimit = IsInitialBlockDownload() ? 20000 : 500;
|
||||
printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit);
|
||||
for (; pindex; pindex = pindex->pnext)
|
||||
{
|
||||
@@ -3674,19 +3731,35 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
vRecv >> block;
|
||||
uint256 hashBlock = block.GetHash();
|
||||
|
||||
printf("received block %s\n", hashBlock.ToString().substr(0,20).c_str());
|
||||
if (!IsInitialBlockDownload())
|
||||
printf("received block %s\n", hashBlock.ToString().substr(0,20).c_str());
|
||||
// block.print();
|
||||
|
||||
CInv inv(MSG_BLOCK, hashBlock);
|
||||
pfrom->AddInventoryKnown(inv);
|
||||
|
||||
if (ProcessBlock(pfrom, &block))
|
||||
{
|
||||
mapAlreadyAskedFor.erase(inv);
|
||||
|
||||
|
||||
// During IBD, proactively request more blocks to keep the pipeline full.
|
||||
// With assumevalid, blocks process near-instantly, so request aggressively.
|
||||
if (IsInitialBlockDownload())
|
||||
{
|
||||
static int nBlocksSinceRequest = 0;
|
||||
if (++nBlocksSinceRequest >= 100)
|
||||
{
|
||||
nBlocksSinceRequest = 0;
|
||||
pfrom->pindexLastGetBlocksBegin = NULL; // clear dedup filter
|
||||
pfrom->PushGetBlocks(pindexBest, uint256(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block.nDoS)
|
||||
pfrom->Misbehaving(block.nDoS);
|
||||
|
||||
if (fSecMsgEnabled)
|
||||
|
||||
if (fSecMsgEnabled && !IsInitialBlockDownload())
|
||||
SecureMsgScanBlock(block);
|
||||
}
|
||||
|
||||
@@ -4120,6 +4193,25 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
pto->PushMessage("inv", vInv);
|
||||
|
||||
|
||||
//
|
||||
// Stall detection: if IBD and no new blocks for 30 seconds, re-request
|
||||
//
|
||||
if (IsInitialBlockDownload() && !pto->fClient)
|
||||
{
|
||||
static int64_t nLastBlockReceived = 0;
|
||||
static int nLastHeight = 0;
|
||||
if (nBestHeight > nLastHeight) {
|
||||
nLastHeight = nBestHeight;
|
||||
nLastBlockReceived = GetTime();
|
||||
} else if (nLastBlockReceived > 0 && GetTime() - nLastBlockReceived > 5) {
|
||||
printf("IBD stall detected at height %d, re-requesting blocks\n", nBestHeight);
|
||||
// Clear dedup filter so the request actually sends
|
||||
pto->pindexLastGetBlocksBegin = NULL;
|
||||
pto->PushGetBlocks(pindexBest, uint256(0));
|
||||
nLastBlockReceived = GetTime(); // reset timer
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Message: getdata
|
||||
//
|
||||
|
||||
+47
-20
@@ -6,6 +6,7 @@
|
||||
#include "irc.h"
|
||||
#include "db.h"
|
||||
#include "net.h"
|
||||
#include "main.h"
|
||||
#include "init.h"
|
||||
#include "strlcpy.h"
|
||||
#include "addrman.h"
|
||||
@@ -889,7 +890,7 @@ void ThreadSocketHandler2(void* parg)
|
||||
//
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 50000; // frequency to poll pnode->vSend
|
||||
timeout.tv_usec = IsInitialBlockDownload() ? 10000 : 50000; // faster polling during IBD
|
||||
|
||||
fd_set fdsetRecv;
|
||||
fd_set fdsetSend;
|
||||
@@ -1574,24 +1575,29 @@ void ThreadOpenConnections2(void* parg)
|
||||
if (fShutdown)
|
||||
return;
|
||||
|
||||
// Add seed nodes if IRC isn't working
|
||||
if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
|
||||
// Add hardcoded seed nodes when we have no connections.
|
||||
// Original check (addrman.size()==0) was too conservative - stale entries
|
||||
// in peers.dat would prevent fallback to working hardcoded IPs forever.
|
||||
{
|
||||
std::vector<CAddress> vAdd;
|
||||
for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
|
||||
{
|
||||
// It'll only connect to one or two seed nodes because once it connects,
|
||||
// it'll get a pile of addresses with newer timestamps.
|
||||
// Seed nodes are given a random 'last seen time' of between one and two
|
||||
// weeks ago.
|
||||
const int64_t nOneWeek = 7*24*60*60;
|
||||
struct in_addr ip;
|
||||
memcpy(&ip, &pnSeed[i], sizeof(ip));
|
||||
CAddress addr(CService(ip, GetDefaultPort()));
|
||||
addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
|
||||
vAdd.push_back(addr);
|
||||
LOCK(cs_vNodes);
|
||||
bool fNoOutbound = true;
|
||||
BOOST_FOREACH(CNode* pnode, vNodes) {
|
||||
if (!pnode->fInbound) { fNoOutbound = false; break; }
|
||||
}
|
||||
if (fNoOutbound && (GetTime() - nStart > 30) && !fTestNet)
|
||||
{
|
||||
std::vector<CAddress> vAdd;
|
||||
for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
|
||||
{
|
||||
struct in_addr ip;
|
||||
memcpy(&ip, &pnSeed[i], sizeof(ip));
|
||||
CAddress addr(CService(ip, GetDefaultPort()));
|
||||
addr.nTime = GetTime() - GetRand(60*60); // seen recently
|
||||
vAdd.push_back(addr);
|
||||
}
|
||||
addrman.Add(vAdd, CNetAddr("127.0.0.1"));
|
||||
printf("No outbound connections after 30s, added %d hardcoded seeds\n", (int)vAdd.size());
|
||||
}
|
||||
addrman.Add(vAdd, CNetAddr("127.0.0.1"));
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1809,6 +1815,7 @@ void ThreadMessageHandler2(void* parg)
|
||||
{
|
||||
printf("ThreadMessageHandler started\n");
|
||||
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
|
||||
bool fWasBoosted = false;
|
||||
while (!fShutdown)
|
||||
{
|
||||
vector<CNode*> vNodesCopy;
|
||||
@@ -1851,11 +1858,21 @@ void ThreadMessageHandler2(void* parg)
|
||||
pnode->Release();
|
||||
}
|
||||
|
||||
// Boost thread priority during IBD, restore when caught up
|
||||
if (IsInitialBlockDownload() && !fWasBoosted) {
|
||||
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
||||
fWasBoosted = true;
|
||||
} else if (!IsInitialBlockDownload() && fWasBoosted) {
|
||||
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
|
||||
fWasBoosted = false;
|
||||
}
|
||||
|
||||
// Wait and allow messages to bunch up.
|
||||
// During IBD, use a shorter sleep to maximize block processing throughput.
|
||||
// Reduce vnThreadsRunning so StopNode has permission to exit while
|
||||
// we're sleeping, but we must always check fShutdown after doing this.
|
||||
vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
|
||||
MilliSleep(100);
|
||||
MilliSleep(IsInitialBlockDownload() ? 10 : 100);
|
||||
if (fRequestShutdown)
|
||||
StartShutdown();
|
||||
vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
|
||||
@@ -2149,8 +2166,18 @@ bool StopNode()
|
||||
if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
|
||||
if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
|
||||
if (vnThreadsRunning[THREAD_STAKE_MINER] > 0) printf("ThreadStakeMiner still running\n");
|
||||
while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0)
|
||||
MilliSleep(20);
|
||||
{
|
||||
int64_t nWaitStart = GetTime();
|
||||
while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0)
|
||||
{
|
||||
if (GetTime() - nWaitStart > 10)
|
||||
{
|
||||
printf("Timed out waiting for message/RPC threads to stop\n");
|
||||
break;
|
||||
}
|
||||
MilliSleep(20);
|
||||
}
|
||||
}
|
||||
MilliSleep(50);
|
||||
DumpAddresses();
|
||||
return true;
|
||||
|
||||
@@ -22,12 +22,13 @@
|
||||
class CRequestTracker;
|
||||
class CNode;
|
||||
class CBlockIndex;
|
||||
bool IsInitialBlockDownload();
|
||||
extern int nBestHeight;
|
||||
|
||||
|
||||
|
||||
inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
|
||||
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
|
||||
inline unsigned int ReceiveFloodSize() { return (unsigned int)-1; }
|
||||
inline unsigned int SendBufferSize() { return (unsigned int)-1; }
|
||||
|
||||
void AddOneShot(std::string strDest);
|
||||
bool RecvLine(SOCKET hSocket, std::string& strLine);
|
||||
@@ -429,8 +430,12 @@ public:
|
||||
nNow = std::max(nNow, nLastTime);
|
||||
nLastTime = nNow;
|
||||
|
||||
// Each retry is 2 minutes after the last
|
||||
nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
|
||||
// During IBD, request immediately (no 2-minute retry delay)
|
||||
// Normal operation: each retry is 2 minutes after the last
|
||||
if (nRequestTime > 0 && IsInitialBlockDownload())
|
||||
nRequestTime = nNow;
|
||||
else
|
||||
nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
|
||||
mapAskFor.insert(std::make_pair(nRequestTime, inv));
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,9 @@ void ClientModel::updateTimer()
|
||||
int newNumBlocks = getNumBlocks();
|
||||
int newNumBlocksOfPeers = getNumBlocksOfPeers();
|
||||
|
||||
if(cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers)
|
||||
// Always emit during IBD so the speed/ETA display stays live
|
||||
if(cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers
|
||||
|| newNumBlocks < newNumBlocksOfPeers)
|
||||
{
|
||||
cachedNumBlocks = newNumBlocks;
|
||||
cachedNumBlocksOfPeers = newNumBlocksOfPeers;
|
||||
|
||||
+57
-13
@@ -751,24 +751,57 @@ void TrianglesGUI::setNumBlocks(int count, int nTotalBlocks)
|
||||
|
||||
QString tooltip;
|
||||
|
||||
QString importText;
|
||||
importText = tr("Synchronizing with network...");
|
||||
|
||||
if(count < nTotalBlocks)
|
||||
{
|
||||
// Calculate blocks/sec - only update rate when new blocks arrive
|
||||
static int lastCount = 0;
|
||||
static qint64 lastRateTime = 0;
|
||||
static float blocksPerSec = 0.0f;
|
||||
qint64 now = QDateTime::currentMSecsSinceEpoch();
|
||||
if (count > lastCount) {
|
||||
// New blocks arrived - recalculate speed
|
||||
if (lastRateTime > 0) {
|
||||
float elapsed = (now - lastRateTime) / 1000.0f;
|
||||
if (elapsed > 0.1f) {
|
||||
float instantRate = (count - lastCount) / elapsed;
|
||||
blocksPerSec = (blocksPerSec < 0.1f) ? instantRate : (blocksPerSec * 0.7f + instantRate * 0.3f);
|
||||
}
|
||||
}
|
||||
lastCount = count;
|
||||
lastRateTime = now;
|
||||
} else if (lastRateTime > 0 && (now - lastRateTime) > 10000) {
|
||||
// No blocks for 10+ seconds - show 0
|
||||
blocksPerSec = 0.0f;
|
||||
}
|
||||
|
||||
int nRemainingBlocks = nTotalBlocks - count;
|
||||
float nPercentageDone = count / (nTotalBlocks * 0.01f);
|
||||
|
||||
progressBarLabel->setText(importText);
|
||||
// Build informative status text
|
||||
QString speedText;
|
||||
if (blocksPerSec >= 1.0f) {
|
||||
int etaSeconds = (int)(nRemainingBlocks / blocksPerSec);
|
||||
QString etaStr;
|
||||
if (etaSeconds < 60)
|
||||
etaStr = tr("%n sec", "", etaSeconds);
|
||||
else if (etaSeconds < 3600)
|
||||
etaStr = tr("%n min", "", etaSeconds / 60);
|
||||
else
|
||||
etaStr = tr("%1h %2m").arg(etaSeconds / 3600).arg((etaSeconds % 3600) / 60);
|
||||
speedText = tr("Syncing: %1 blk/s ~%2 remaining").arg(blocksPerSec, 0, 'f', 1).arg(etaStr);
|
||||
} else {
|
||||
speedText = tr("Synchronizing with network...");
|
||||
}
|
||||
|
||||
progressBarLabel->setText(speedText);
|
||||
progressBarLabel->setVisible(true);
|
||||
progressBar->setFormat(tr("~%n block(s) remaining", "", nRemainingBlocks));
|
||||
progressBar->setFormat(tr("Block %1 / %2 (%3%)").arg(count).arg(nTotalBlocks).arg(nPercentageDone, 0, 'f', 2));
|
||||
progressBar->setMaximum(nTotalBlocks);
|
||||
progressBar->setValue(count);
|
||||
progressBar->setVisible(true);
|
||||
ui->label_blocks->setText(tr("%n blocks", "", count));
|
||||
ui->label_blocks->setVisible(true);
|
||||
ui->label_blocks->setVisible(false);
|
||||
|
||||
tooltip = tr("Downloaded %1 of %2 blocks of transaction history (%3% done).").arg(count).arg(nTotalBlocks).arg(nPercentageDone, 0, 'f', 2);
|
||||
tooltip = tr("Downloaded %1 of %2 blocks of transaction history (%3% done).").arg(count).arg(nTotalBlocks).arg(nPercentageDone, 0, 'f', 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -871,16 +904,27 @@ void TrianglesGUI::changeEvent(QEvent *e)
|
||||
|
||||
void TrianglesGUI::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
#ifndef Q_OS_MAC // Ignored on Mac
|
||||
if(clientModel)
|
||||
{
|
||||
#ifndef Q_OS_MAC // Ignored on Mac
|
||||
if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
|
||||
!clientModel->getOptionsModel()->getMinimizeOnClose())
|
||||
if(clientModel->getOptionsModel()->getMinimizeOnClose())
|
||||
{
|
||||
QApplication::quit();
|
||||
// Minimize to taskbar instead of closing
|
||||
QMainWindow::showMinimized();
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
if(clientModel->getOptionsModel()->getMinimizeToTray() && trayIcon)
|
||||
{
|
||||
// Hide to system tray instead of closing
|
||||
hide();
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
// Actually closing - quit the application
|
||||
QApplication::quit();
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user