Compare commits

...

8 Commits

Author SHA1 Message Date
sami7777 b50eecc56f Fix build: nMisbehavior is protected
Build All Platforms / build-windows-qt (push) Waiting to run
Build All Platforms / build-windows-daemon (push) Waiting to run
Build All Platforms / build-linux-qt (push) Waiting to run
Build All Platforms / build-linux-daemon (push) Waiting to run
Build All Platforms / build-macos (push) Waiting to run
Build All Platforms / release (push) Blocked by required conditions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:09:48 -07:00
sami7777 8953173403 Add comprehensive IBD diagnostics (IBD-DIAG prefix)
Verbose logging at every critical sync pipeline stage:
- Version handler: whether getblocks was sent and why
- Inv handler: count of new vs already-known blocks
- Block handler: every block received (throttled), ProcessBlock failures
- ProcessBlock: CheckBlock failures with details
- SendMessages: stall detection with queue sizes
- Periodic status: height, peers, askfor queue, orphan count
- Getblocks handler: what range the seed is serving

All lines prefixed with IBD-DIAG for easy grep.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:05:11 -07:00
sami7777 2f307c195c Disable checkpoint message relay and processing
DNS2 was sending a stale sync checkpoint (block 2,186,940) to DNS3
on connect. ProcessSyncCheckpoint then called PushGetBlocks with the
checkpoint hash as the stop point, and AskFor'd block 2,186,940
directly — overriding the normal sequential getblocks chain. DNS3
would request a block it can't process (missing 2M predecessors)
instead of syncing from genesis.

Fix: ignore incoming checkpoint messages entirely (master key was
already removed in V5 fork, no new checkpoints possible). Also stop
relaying stored checkpoint messages to new peers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 20:56:40 -07:00
sami7777 8c5024a78a Fix anti-spam check: use chain tip as fallback, add NULL safety
Instead of skipping the anti-spam difficulty check during IBD, fix it
properly:
- Fall back to pindexBest when sync checkpoint is genesis (height 0)
- Add NULL safety for GetLastBlockIndex in both PoS and PoW cases
- PoS case: if no PoS block exists yet (below 9001), skip gracefully
  since AcceptBlock already rejects PoS below MODIFIER_INTERVAL_SWITCH

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 20:24:48 -07:00
sami7777 3f823e8583 Skip anti-spam difficulty check during IBD
The anti-spam check in ProcessBlock used GetLastSyncCheckpoint() which
pointed to genesis after our reset. When processing PoS blocks,
GetLastBlockIndex(genesis, true) returned NULL (no PoS blocks at genesis),
causing a crash or Misbehaving(100) which banned the seed node.

Fix: skip the entire anti-spam check during IBD - hardcoded checkpoints
already guarantee chain integrity. Also add NULL safety for the PoS
case after IBD completes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 20:19:39 -07:00
sami7777 a4bfc6012a Fix display version: update DISPLAY_VERSION to 5.2.0
version.h had a separate DISPLAY_VERSION set (5.1.7.0) used by
version.cpp for the user-visible version string. clientversion.h
was updated but version.h was not, causing binaries to report
v5.1.7.0 despite being built from v5.2.0 source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 19:37:24 -07:00
sami7777 136d446157 Disable sync checkpoint system that blocks IBD
The sync checkpoint (hashSyncCheckpoint) was persisted in LevelDB pointing
to block 2,186,940. On startup it was loaded from DB, overriding any code
change to the initial value. CheckSync then rejected every block below
that height during IBD since they weren't in mapBlockIndex yet.

Three-pronged fix:
- CheckSync now always returns true (master key disabled, no new sync
  checkpoints will ever be broadcast)
- AcceptBlock no longer calls sync checkpoint enforcement
- LoadBlockIndex resets sync checkpoint to genesis if stored hash is
  not in the block index (prevents assert crash)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 18:32:11 -07:00
sami7777 1966f49ce2 Fix sync checkpoint blocking IBD, bump to v5.2.0
hashSyncCheckpoint was initialized to block 2,186,940 hash, causing
CheckSync to reject ALL blocks below that height during initial block
download (they aren't in mapBlockIndex yet when checked). Changed to
genesis hash so IBD can proceed from block 0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 18:09:38 -07:00
6 changed files with 118 additions and 105 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ on:
workflow_dispatch:
env:
VERSION: "5.1.9"
VERSION: "5.2.0"
jobs:
build-windows-qt:
+6 -26
View File
@@ -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
View File
@@ -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 9
#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.
+97 -71
View File
@@ -2471,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;
@@ -2558,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);
@@ -3270,14 +3265,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// 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) &&
(IsInitialBlockDownload() || 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
@@ -3287,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;
@@ -3398,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];
@@ -3414,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);
}
@@ -3522,7 +3523,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (pindex)
pindex = pindex->pnext;
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);
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)
@@ -3547,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")
@@ -3731,9 +3726,17 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> block;
uint256 hashBlock = block.GetHash();
if (!IsInitialBlockDownload())
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);
@@ -3742,22 +3745,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
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->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)
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 && !IsInitialBlockDownload())
SecureMsgScanBlock(block);
@@ -4194,27 +4204,43 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
//
// Stall detection: if IBD and no new blocks for 30 seconds, re-request
// 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) {
printf("IBD stall detected at height %d, re-requesting blocks\n", nBestHeight);
// Clear dedup filter so the request actually sends
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(); // reset timer
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");
+10 -3
View File
@@ -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
View File
@@ -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