Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b50eecc56f | |||
| 8953173403 | |||
| 2f307c195c | |||
| 8c5024a78a | |||
| 3f823e8583 | |||
| a4bfc6012a | |||
| 136d446157 | |||
| 1966f49ce2 | |||
| a4da39f23c | |||
| 87bfc15712 | |||
| 6353e9d5fa |
@@ -9,7 +9,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
VERSION: "5.1.8"
|
||||
VERSION: "5.2.0"
|
||||
|
||||
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
|
||||
|
||||
|
||||
+6
-26
@@ -87,8 +87,8 @@ namespace Checkpoints
|
||||
}
|
||||
|
||||
// triangles: synchronized checkpoint (centrally broadcasted)
|
||||
uint256 hashSyncCheckpoint = uint256("0xbd952e8d4a612e336d840ad924a7e09395e36bcd9d929b302e47e60b5c3098c0");
|
||||
uint256 hashPendingCheckpoint = uint256("0xbd952e8d4a612e336d840ad924a7e09395e36bcd9d929b302e47e60b5c3098c0");
|
||||
uint256 hashSyncCheckpoint = uint256("0x7e7a6e4dd5fe895106fca912dfbacaeaf2a89e76c6a588df8ff96e0e18b96021");
|
||||
uint256 hashPendingCheckpoint = uint256("0x7e7a6e4dd5fe895106fca912dfbacaeaf2a89e76c6a588df8ff96e0e18b96021");
|
||||
CSyncCheckpoint checkpointMessage;
|
||||
CSyncCheckpoint checkpointMessagePending;
|
||||
uint256 hashInvalidCheckpoint = 0;
|
||||
@@ -218,30 +218,10 @@ namespace Checkpoints
|
||||
}
|
||||
|
||||
// Check against synchronized checkpoint
|
||||
// Disabled: master key removed in V5, no new sync checkpoints possible.
|
||||
// Always returns true to prevent stale DB-persisted checkpoints from blocking IBD.
|
||||
bool CheckSync(const uint256& hashBlock, const CBlockIndex* pindexPrev)
|
||||
{
|
||||
if (fTestNet) return true; // Testnet has no checkpoints
|
||||
int nHeight = pindexPrev->nHeight + 1;
|
||||
|
||||
LOCK(cs_hashSyncCheckpoint);
|
||||
// sync-checkpoint should always be accepted block
|
||||
assert(mapBlockIndex.count(hashSyncCheckpoint));
|
||||
const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint];
|
||||
|
||||
if (nHeight > pindexSync->nHeight)
|
||||
{
|
||||
// trace back to same height as sync-checkpoint
|
||||
const CBlockIndex* pindex = pindexPrev;
|
||||
while (pindex->nHeight > pindexSync->nHeight)
|
||||
if (!(pindex = pindex->pprev))
|
||||
return error("CheckSync: pprev null - block index structure failure");
|
||||
if (pindex->nHeight < pindexSync->nHeight || pindex->GetBlockHash() != hashSyncCheckpoint)
|
||||
return false; // only descendant of sync-checkpoint can pass check
|
||||
}
|
||||
if (nHeight == pindexSync->nHeight && hashBlock != hashSyncCheckpoint)
|
||||
return false; // same height with sync-checkpoint
|
||||
if (nHeight < pindexSync->nHeight && !mapBlockIndex.count(hashBlock))
|
||||
return false; // lower height than sync-checkpoint
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -361,8 +341,8 @@ namespace Checkpoints
|
||||
bool IsMatureSyncCheckpoint()
|
||||
{
|
||||
LOCK(cs_hashSyncCheckpoint);
|
||||
// sync-checkpoint should always be accepted block
|
||||
assert(mapBlockIndex.count(hashSyncCheckpoint));
|
||||
if (!mapBlockIndex.count(hashSyncCheckpoint))
|
||||
return true; // no valid sync checkpoint, treat as mature
|
||||
const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint];
|
||||
return (nBestHeight >= pindexSync->nHeight + nCoinbaseMaturity ||
|
||||
pindexSync->GetBlockTime() + nStakeMinAge < GetAdjustedTime());
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@
|
||||
|
||||
// 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_MINOR 2
|
||||
#define CLIENT_VERSION_REVISION 0
|
||||
#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");
|
||||
|
||||
+213
-95
@@ -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;
|
||||
}
|
||||
|
||||
@@ -2415,18 +2471,10 @@ bool CBlock::AcceptBlock()
|
||||
}
|
||||
}
|
||||
|
||||
// Before fork: enforce sync checkpoints for historical chain integrity
|
||||
// After fork: no sync checkpoint enforcement (decentralized)
|
||||
if (nHeight < FORK_HEIGHT_V5)
|
||||
{
|
||||
bool cpSatisfies = Checkpoints::CheckSync(hash, pindexPrev);
|
||||
|
||||
if (CheckpointsMode == Checkpoints::STRICT && !cpSatisfies)
|
||||
return error("AcceptBlock() : rejected by synchronized checkpoint");
|
||||
|
||||
if (CheckpointsMode == Checkpoints::ADVISORY && !cpSatisfies)
|
||||
strMiscWarning = _("WARNING: syncronized checkpoint violation detected, but skipped!");
|
||||
}
|
||||
// Sync checkpoint enforcement is disabled:
|
||||
// - Master key was removed in V5 fork, no new sync checkpoints will be broadcast
|
||||
// - Hardcoded checkpoints already guarantee chain integrity
|
||||
// - The persisted hashSyncCheckpoint in LevelDB blocks IBD from progressing
|
||||
|
||||
// Enforce rule that the coinbase starts with serialized block height
|
||||
CScript expect = CScript() << nHeight;
|
||||
@@ -2502,37 +2550,40 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
|
||||
// Skip block signature verification during initial block download (below checkpoint).
|
||||
// The hardcoded checkpoint guarantees historical chain integrity.
|
||||
if (!pblock->CheckBlock(true, true, !IsInitialBlockDownload()))
|
||||
return error("ProcessBlock() : CheckBlock FAILED");
|
||||
|
||||
CBlockIndex* pcheckpoint = Checkpoints::GetLastSyncCheckpoint();
|
||||
|
||||
if(pcheckpoint && fDebug)
|
||||
{
|
||||
const CBlockIndex* pindexLastPos = GetLastBlockIndex(pcheckpoint, true);
|
||||
if(pindexLastPos)
|
||||
{
|
||||
printf("ProcessBlock(): Last POS Block Height: %d \n", pindexLastPos->nHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ProcessBlock(): Previous POS block not found.\n");
|
||||
}
|
||||
printf("IBD-DIAG: CheckBlock FAILED for %s (PoS=%d, IBD=%d)\n",
|
||||
hash.ToString().substr(0,20).c_str(), pblock->IsProofOfStake(), IsInitialBlockDownload());
|
||||
return error("ProcessBlock() : CheckBlock FAILED");
|
||||
}
|
||||
|
||||
// Anti-spam: reject blocks with insufficient difficulty to prevent memory flooding.
|
||||
// Use sync checkpoint as reference; fall back to chain tip if checkpoint is genesis.
|
||||
CBlockIndex* pcheckpoint = Checkpoints::GetLastSyncCheckpoint();
|
||||
if (!pcheckpoint || pcheckpoint->nHeight == 0)
|
||||
pcheckpoint = pindexBest;
|
||||
|
||||
if (pcheckpoint && pblock->hashPrevBlock != hashBestChain && !Checkpoints::WantedByPendingSyncCheckpoint(hash))
|
||||
{
|
||||
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
|
||||
int64_t deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime;
|
||||
CBigNum bnNewBlock;
|
||||
bnNewBlock.SetCompact(pblock->nBits);
|
||||
CBigNum bnRequired;
|
||||
|
||||
if (pblock->IsProofOfStake())
|
||||
bnRequired.SetCompact(ComputeMinStake(GetLastBlockIndex(pcheckpoint, true)->nBits, deltaTime, pblock->nTime));
|
||||
{
|
||||
const CBlockIndex* pindexLastPos = GetLastBlockIndex(pcheckpoint, true);
|
||||
if (pindexLastPos)
|
||||
bnRequired.SetCompact(ComputeMinStake(pindexLastPos->nBits, deltaTime, pblock->nTime));
|
||||
// else: no PoS history yet (below block 9001), skip — AcceptBlock rejects PoS below MODIFIER_INTERVAL_SWITCH
|
||||
}
|
||||
else
|
||||
bnRequired.SetCompact(ComputeMinWork(GetLastBlockIndex(pcheckpoint, false)->nBits, deltaTime));
|
||||
{
|
||||
const CBlockIndex* pindexLastPow = GetLastBlockIndex(pcheckpoint, false);
|
||||
if (pindexLastPow)
|
||||
bnRequired.SetCompact(ComputeMinWork(pindexLastPow->nBits, deltaTime));
|
||||
}
|
||||
|
||||
if (bnNewBlock > bnRequired)
|
||||
if (bnRequired != 0 && bnNewBlock > bnRequired)
|
||||
{
|
||||
if (pfrom)
|
||||
pfrom->Misbehaving(100);
|
||||
@@ -2598,7 +2649,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,16 +3262,22 @@ 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 &&
|
||||
bool fShouldAsk = !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);
|
||||
printf("IBD-DIAG: version handler: peer=%s height=%d ourHeight=%d fClient=%d fOneShot=%d shouldAsk=%d nAskedForBlocks=%d IBD=%d\n",
|
||||
pfrom->addr.ToString().c_str(), pfrom->nStartingHeight, nBestHeight,
|
||||
pfrom->fClient, pfrom->fOneShot, fShouldAsk, nAskedForBlocks, IsInitialBlockDownload());
|
||||
if (fShouldAsk)
|
||||
{
|
||||
nAskedForBlocks++;
|
||||
pfrom->PushGetBlocks(pindexBest, uint256(0));
|
||||
printf("IBD-DIAG: sent getblocks from height %d to peer %s\n", nBestHeight, pfrom->addr.ToString().c_str());
|
||||
}
|
||||
|
||||
// Relay alerts
|
||||
@@ -3230,12 +3287,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
item.second.RelayTo(pfrom);
|
||||
}
|
||||
|
||||
// triangles: relay sync-checkpoint
|
||||
{
|
||||
LOCK(Checkpoints::cs_hashSyncCheckpoint);
|
||||
if (!Checkpoints::checkpointMessage.IsNull())
|
||||
Checkpoints::checkpointMessage.RelayTo(pfrom);
|
||||
}
|
||||
// Sync checkpoint relay disabled (master key removed in V5 fork).
|
||||
// Relaying stale checkpoints causes IBD nodes to request far-future blocks.
|
||||
|
||||
pfrom->fSuccessfullyConnected = true;
|
||||
|
||||
@@ -3341,13 +3394,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
|
||||
// find last block in inv vector
|
||||
unsigned int nLastBlock = (unsigned int)(-1);
|
||||
int nBlockInv = 0, nTxInv = 0;
|
||||
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) {
|
||||
if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK) {
|
||||
if (vInv[nInv].type == MSG_BLOCK) nBlockInv++;
|
||||
else nTxInv++;
|
||||
if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK && nLastBlock == (unsigned int)(-1)) {
|
||||
nLastBlock = vInv.size() - 1 - nInv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("IBD-DIAG: inv received: %d blocks, %d tx from %s (our height=%d)\n",
|
||||
nBlockInv, nTxInv, pfrom->addr.ToString().c_str(), nBestHeight);
|
||||
|
||||
CTxDB txdb("r");
|
||||
int nNew = 0, nAlready = 0;
|
||||
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
|
||||
{
|
||||
const CInv &inv = vInv[nInv];
|
||||
@@ -3357,25 +3416,24 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
pfrom->AddInventoryKnown(inv);
|
||||
|
||||
bool fAlreadyHave = AlreadyHave(txdb, inv);
|
||||
if (fDebug)
|
||||
printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
|
||||
if (inv.type == MSG_BLOCK) {
|
||||
if (fAlreadyHave) nAlready++; else nNew++;
|
||||
}
|
||||
|
||||
if (!fAlreadyHave)
|
||||
pfrom->AskFor(inv);
|
||||
else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
|
||||
pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
|
||||
} else if (nInv == nLastBlock) {
|
||||
// In case we are on a very long side-chain, it is possible that we already have
|
||||
// the last block in an inv bundle sent in response to getblocks. Try to detect
|
||||
// this situation and push another getblocks to continue.
|
||||
pfrom->PushGetBlocks(mapBlockIndex[inv.hash], uint256(0));
|
||||
if (fDebug)
|
||||
printf("force request: %s\n", inv.ToString().c_str());
|
||||
printf("IBD-DIAG: inv last block already known, pushing getblocks from %d\n",
|
||||
mapBlockIndex[inv.hash]->nHeight);
|
||||
}
|
||||
|
||||
// Track requests for our stuff
|
||||
Inventory(inv.hash);
|
||||
}
|
||||
if (nBlockInv > 0)
|
||||
printf("IBD-DIAG: inv result: %d new blocks requested, %d already have\n", nNew, nAlready);
|
||||
}
|
||||
|
||||
|
||||
@@ -3464,8 +3522,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
// Send the rest of the chain
|
||||
if (pindex)
|
||||
pindex = pindex->pnext;
|
||||
int nLimit = 500;
|
||||
printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit);
|
||||
int nLimit = IsInitialBlockDownload() ? 20000 : 500;
|
||||
printf("IBD-DIAG: getblocks request from peer %s: start=%d stop=%s limit=%d\n",
|
||||
pfrom->addr.ToString().c_str(), (pindex ? pindex->nHeight : -1),
|
||||
hashStop.ToString().substr(0,20).c_str(), nLimit);
|
||||
for (; pindex; pindex = pindex->pnext)
|
||||
{
|
||||
if (pindex->GetBlockHash() == hashStop)
|
||||
@@ -3490,17 +3550,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
}
|
||||
else if (strCommand == "checkpoint")
|
||||
{
|
||||
CSyncCheckpoint checkpoint;
|
||||
vRecv >> checkpoint;
|
||||
|
||||
if (checkpoint.ProcessSyncCheckpoint(pfrom))
|
||||
{
|
||||
// Relay
|
||||
pfrom->hashCheckpointKnown = checkpoint.hashCheckpoint;
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
checkpoint.RelayTo(pnode);
|
||||
}
|
||||
// Sync checkpoint system disabled (master key removed in V5 fork).
|
||||
// Ignore checkpoint messages — processing them during IBD causes the
|
||||
// node to request a single far-future block instead of syncing sequentially.
|
||||
}
|
||||
|
||||
else if (strCommand == "getheaders")
|
||||
@@ -3674,19 +3726,50 @@ 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());
|
||||
// block.print();
|
||||
// Log every block during IBD (with throttling after first 100)
|
||||
static int64_t nLastBlockLog = 0;
|
||||
static int nBlocksReceived = 0;
|
||||
nBlocksReceived++;
|
||||
bool fLogThis = (nBlocksReceived <= 20) || (nBestHeight % 500 == 0) || !IsInitialBlockDownload() || (GetTime() - nLastBlockLog >= 5);
|
||||
if (fLogThis) {
|
||||
printf("IBD-DIAG: block received #%d hash=%s from=%s ourHeight=%d\n",
|
||||
nBlocksReceived, hashBlock.ToString().substr(0,20).c_str(),
|
||||
pfrom->addr.ToString().c_str(), nBestHeight);
|
||||
nLastBlockLog = GetTime();
|
||||
}
|
||||
|
||||
CInv inv(MSG_BLOCK, hashBlock);
|
||||
pfrom->AddInventoryKnown(inv);
|
||||
|
||||
if (ProcessBlock(pfrom, &block))
|
||||
{
|
||||
mapAlreadyAskedFor.erase(inv);
|
||||
|
||||
if (block.nDoS)
|
||||
|
||||
if (IsInitialBlockDownload())
|
||||
{
|
||||
static int nBlocksSinceRequest = 0;
|
||||
if (++nBlocksSinceRequest >= 100)
|
||||
{
|
||||
nBlocksSinceRequest = 0;
|
||||
pfrom->pindexLastGetBlocksBegin = NULL;
|
||||
pfrom->PushGetBlocks(pindexBest, uint256(0));
|
||||
printf("IBD-DIAG: pipeline refill at height %d\n", nBestHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("IBD-DIAG: ProcessBlock FAILED for block %s (height after prev=%d, DoS=%d)\n",
|
||||
hashBlock.ToString().substr(0,20).c_str(), nBestHeight, block.nDoS);
|
||||
}
|
||||
|
||||
if (block.nDoS) {
|
||||
printf("IBD-DIAG: Misbehaving peer %s by %d\n",
|
||||
pfrom->addr.ToString().c_str(), block.nDoS);
|
||||
pfrom->Misbehaving(block.nDoS);
|
||||
|
||||
if (fSecMsgEnabled)
|
||||
}
|
||||
|
||||
if (fSecMsgEnabled && !IsInitialBlockDownload())
|
||||
SecureMsgScanBlock(block);
|
||||
}
|
||||
|
||||
@@ -4120,9 +4203,44 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
pto->PushMessage("inv", vInv);
|
||||
|
||||
|
||||
//
|
||||
// Stall detection: if IBD and no new blocks for 5 seconds, re-request
|
||||
//
|
||||
if (IsInitialBlockDownload() && !pto->fClient)
|
||||
{
|
||||
static int64_t nLastBlockReceived = 0;
|
||||
static int nLastHeight = 0;
|
||||
static int64_t nLastStallLog = 0;
|
||||
if (nBestHeight > nLastHeight) {
|
||||
nLastHeight = nBestHeight;
|
||||
nLastBlockReceived = GetTime();
|
||||
} else if (nLastBlockReceived > 0 && GetTime() - nLastBlockReceived > 5) {
|
||||
if (GetTime() - nLastStallLog >= 10) { // log every 10s max
|
||||
printf("IBD-DIAG: STALL at height %d for %ds, peer=%s askfor_queue=%d send_size=%d\n",
|
||||
nBestHeight, (int)(GetTime() - nLastBlockReceived),
|
||||
pto->addr.ToString().c_str(),
|
||||
(int)pto->mapAskFor.size(), (int)pto->nSendSize);
|
||||
nLastStallLog = GetTime();
|
||||
}
|
||||
pto->pindexLastGetBlocksBegin = NULL;
|
||||
pto->PushGetBlocks(pindexBest, uint256(0));
|
||||
nLastBlockReceived = GetTime();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Message: getdata
|
||||
//
|
||||
// Periodic IBD status
|
||||
if (IsInitialBlockDownload()) {
|
||||
static int64_t nLastStatus = 0;
|
||||
if (GetTime() - nLastStatus >= 15) {
|
||||
printf("IBD-DIAG: STATUS height=%d peers=%d askfor_queued=%d orphans=%d\n",
|
||||
nBestHeight, (int)vNodes.size(), (int)pto->mapAskFor.size(), (int)mapOrphanBlocks.size());
|
||||
nLastStatus = GetTime();
|
||||
}
|
||||
}
|
||||
|
||||
vector<CInv> vGetData;
|
||||
int64_t nNow = GetTime() * 1000000;
|
||||
CTxDB txdb("r");
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
|
||||
+10
-3
@@ -484,10 +484,17 @@ bool CTxDB::LoadBlockIndex()
|
||||
hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(nBestChainTrust).ToString().c_str(),
|
||||
DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
|
||||
|
||||
// triangles: load hashSyncCheckpoint
|
||||
// triangles: load hashSyncCheckpoint (best-effort, non-fatal)
|
||||
if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint))
|
||||
return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded");
|
||||
printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str());
|
||||
printf("LoadBlockIndex(): no sync checkpoint in DB, using default\n");
|
||||
else
|
||||
printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str());
|
||||
// If the stored checkpoint isn't in our index, reset to genesis so we don't assert-crash
|
||||
if (!mapBlockIndex.count(Checkpoints::hashSyncCheckpoint))
|
||||
{
|
||||
printf("LoadBlockIndex(): sync checkpoint not in index, resetting to genesis\n");
|
||||
Checkpoints::hashSyncCheckpoint = (!fTestNet ? hashGenesisBlockOfficial : hashGenesisBlockTestNet);
|
||||
}
|
||||
|
||||
// Load bnBestInvalidTrust, OK if it doesn't exist
|
||||
CBigNum bnBestInvalidTrust;
|
||||
|
||||
+2
-2
@@ -52,8 +52,8 @@ static const int BIP0031_VERSION = 60000;
|
||||
static const int MEMPOOL_GD_VERSION = 60002;
|
||||
|
||||
#define DISPLAY_VERSION_MAJOR 5
|
||||
#define DISPLAY_VERSION_MINOR 1
|
||||
#define DISPLAY_VERSION_REVISION 7
|
||||
#define DISPLAY_VERSION_MINOR 2
|
||||
#define DISPLAY_VERSION_REVISION 0
|
||||
#define DISPLAY_VERSION_BUILD 0
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user