Add recent finality checkpoint at 2205000 (anti-fork); bump v5.9.12
Closes the unchecked span from block 17650 to the live tip. Nodes now reject stale-bootstrap / low-trust forks below 2205000. Hash taken from the canonical chain (PC wallet, verified via getblockhash).
This commit is contained in:
+445
-447
@@ -1,447 +1,445 @@
|
|||||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include "checkpoints.h"
|
#include "checkpoints.h"
|
||||||
|
|
||||||
#include "txdb.h"
|
#include "txdb.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
|
|
||||||
namespace Checkpoints
|
namespace Checkpoints
|
||||||
{
|
{
|
||||||
typedef std::map<int, uint256> MapCheckpoints;
|
typedef std::map<int, uint256> MapCheckpoints;
|
||||||
|
|
||||||
//
|
//
|
||||||
// What makes a good checkpoint block?
|
// What makes a good checkpoint block?
|
||||||
// + Is surrounded by blocks with reasonable timestamps
|
// + Is surrounded by blocks with reasonable timestamps
|
||||||
// (no blocks before with a timestamp after, none after with
|
// (no blocks before with a timestamp after, none after with
|
||||||
// timestamp before)
|
// timestamp before)
|
||||||
// + Contains no strange transactions
|
// + Contains no strange transactions
|
||||||
//
|
//
|
||||||
static MapCheckpoints mapCheckpoints = {
|
static MapCheckpoints mapCheckpoints = {
|
||||||
{ 0, hashGenesisBlockOfficial },
|
{ 0, hashGenesisBlockOfficial },
|
||||||
{ 2000, uint256("0x0000000000b5f20078bf46ebdf1500813bb6b2cb482065aa93b89e073b2c6467")},
|
{ 2000, uint256("0x0000000000b5f20078bf46ebdf1500813bb6b2cb482065aa93b89e073b2c6467")},
|
||||||
{ 2101, uint256("0xd4ea1ac45b63c8162a7fc8033cec441db8d532ba988202849d7831e32fe2d059")},
|
{ 2101, uint256("0xd4ea1ac45b63c8162a7fc8033cec441db8d532ba988202849d7831e32fe2d059")},
|
||||||
{ 2847, uint256("0xb5015e2835f13fd3bb6135cff9b31ac33310c9b77d694bdb592b8680d98d018e")},
|
{ 2847, uint256("0xb5015e2835f13fd3bb6135cff9b31ac33310c9b77d694bdb592b8680d98d018e")},
|
||||||
{ 3589, uint256("0xb12a2ca3db4e288cada98aa2139768532bd4474c49dd7b8158031032dac08d51")},
|
{ 3589, uint256("0xb12a2ca3db4e288cada98aa2139768532bd4474c49dd7b8158031032dac08d51")},
|
||||||
{ 3935, uint256("0xe16290c9757d1368b8d7c35de07d4f8f70c2c9f9c785b667df0c3bff85086ca6")},
|
{ 3935, uint256("0xe16290c9757d1368b8d7c35de07d4f8f70c2c9f9c785b667df0c3bff85086ca6")},
|
||||||
{ 5703, uint256("0x587db07bb2172ad7db72c5fabc2518262a1b27f503f99417510b2c6fafa6557b")},
|
{ 5703, uint256("0x587db07bb2172ad7db72c5fabc2518262a1b27f503f99417510b2c6fafa6557b")},
|
||||||
{ 9000, uint256("0x00000000019ef6b2f5e7c324c7d083ee94502305aabc7e9cd73a7fb2a57bb8db")},
|
{ 9000, uint256("0x00000000019ef6b2f5e7c324c7d083ee94502305aabc7e9cd73a7fb2a57bb8db")},
|
||||||
{ 9001, uint256("0x6d5c6c5f201cc9e59659ee0da30d1430dc6bf3b12a8ff4c3864ab8d6286b0007")},
|
{ 9001, uint256("0x6d5c6c5f201cc9e59659ee0da30d1430dc6bf3b12a8ff4c3864ab8d6286b0007")},
|
||||||
{ 9002, uint256("0xa1e20fb1d44688b763690cf74d6aefe859e4cc32981f9e3f2b2ae9702bbcf249")},
|
{ 9002, uint256("0xa1e20fb1d44688b763690cf74d6aefe859e4cc32981f9e3f2b2ae9702bbcf249")},
|
||||||
{ 10881, uint256("0x4b6554c45e1e6764a6f3c309c47baf53c9edd81f624e52b072518cd15da237e6")},
|
{ 10881, uint256("0x4b6554c45e1e6764a6f3c309c47baf53c9edd81f624e52b072518cd15da237e6")},
|
||||||
{ 17650, uint256("0x224940e1f986a202209b8e762728d1452ab45870c308abf84905674acf326a47")},
|
{ 17650, uint256("0x224940e1f986a202209b8e762728d1452ab45870c308abf84905674acf326a47")},
|
||||||
};
|
// Recent finality pin (PoS era). Closes the long unchecked span from
|
||||||
|
// 17650 to the live tip so stale-bootstrap / low-trust forks below this
|
||||||
// Published UTXO snapshot file SHA256, keyed by snapshot height.
|
// height are rejected outright. Hash taken from the canonical chain.
|
||||||
// Each entry binds height -> SHA256 of the canonical snapshot file produced by
|
{ 2205000, uint256("0x6bdd3c5e5a32e1dd9a70e705f1a28d1dd84929f89579bd2696d41bc87f39446f")},
|
||||||
// UtxoSnapshot::DumpSnapshot at that height. Used by SnapshotNet to verify
|
};
|
||||||
// P2P-delivered snapshots without trusting any peer.
|
|
||||||
//
|
// Published UTXO snapshot file SHA256, keyed by snapshot height.
|
||||||
// Maintainers: after producing a snapshot, sha256 the file and add an entry
|
// Each entry binds height -> SHA256 of the canonical snapshot file produced by
|
||||||
// here. The corresponding (height, blockhash) must already exist in
|
// UtxoSnapshot::DumpSnapshot at that height. Used by SnapshotNet to verify
|
||||||
// mapCheckpoints / mapCheckpointsTestnet.
|
// P2P-delivered snapshots without trusting any peer.
|
||||||
static std::map<int, uint256> mapSnapshotHashes = {
|
//
|
||||||
};
|
// Maintainers: after producing a snapshot, sha256 the file and add an entry
|
||||||
|
// here. The corresponding (height, blockhash) must already exist in
|
||||||
static std::map<int, uint256> mapSnapshotHashesTestnet = {
|
// mapCheckpoints / mapCheckpointsTestnet.
|
||||||
};
|
static std::map<int, uint256> mapSnapshotHashes = {
|
||||||
|
};
|
||||||
static MapCheckpoints mapCheckpointsTestnet = {
|
|
||||||
{ 0, hashGenesisBlockTestNet },
|
static std::map<int, uint256> mapSnapshotHashesTestnet = {
|
||||||
{ 2000, uint256("0x0000000000b5f20078bf46ebdf1500813bb6b2cb482065aa93b89e073b2c6467")},
|
};
|
||||||
{ 2101, uint256("0xd4ea1ac45b63c8162a7fc8033cec441db8d532ba988202849d7831e32fe2d059")},
|
|
||||||
{ 2847, uint256("0xb5015e2835f13fd3bb6135cff9b31ac33310c9b77d694bdb592b8680d98d018e")},
|
static MapCheckpoints mapCheckpointsTestnet = {
|
||||||
{ 3589, uint256("0xb12a2ca3db4e288cada98aa2139768532bd4474c49dd7b8158031032dac08d51")},
|
{ 0, hashGenesisBlockTestNet },
|
||||||
{ 3935, uint256("0xe16290c9757d1368b8d7c35de07d4f8f70c2c9f9c785b667df0c3bff85086ca6")},
|
{ 2000, uint256("0x0000000000b5f20078bf46ebdf1500813bb6b2cb482065aa93b89e073b2c6467")},
|
||||||
{ 5703, uint256("0x587db07bb2172ad7db72c5fabc2518262a1b27f503f99417510b2c6fafa6557b")},
|
{ 2101, uint256("0xd4ea1ac45b63c8162a7fc8033cec441db8d532ba988202849d7831e32fe2d059")},
|
||||||
{ 9000, uint256("0x00000000019ef6b2f5e7c324c7d083ee94502305aabc7e9cd73a7fb2a57bb8db")},
|
{ 2847, uint256("0xb5015e2835f13fd3bb6135cff9b31ac33310c9b77d694bdb592b8680d98d018e")},
|
||||||
{ 9001, uint256("0x6d5c6c5f201cc9e59659ee0da30d1430dc6bf3b12a8ff4c3864ab8d6286b0007")},
|
{ 3589, uint256("0xb12a2ca3db4e288cada98aa2139768532bd4474c49dd7b8158031032dac08d51")},
|
||||||
{ 9002, uint256("0xa1e20fb1d44688b763690cf74d6aefe859e4cc32981f9e3f2b2ae9702bbcf249")},
|
{ 3935, uint256("0xe16290c9757d1368b8d7c35de07d4f8f70c2c9f9c785b667df0c3bff85086ca6")},
|
||||||
{ 10881, uint256("0x4b6554c45e1e6764a6f3c309c47baf53c9edd81f624e52b072518cd15da237e6")},
|
{ 5703, uint256("0x587db07bb2172ad7db72c5fabc2518262a1b27f503f99417510b2c6fafa6557b")},
|
||||||
{ 17650, uint256("0x224940e1f986a202209b8e762728d1452ab45870c308abf84905674acf326a47")},
|
{ 9000, uint256("0x00000000019ef6b2f5e7c324c7d083ee94502305aabc7e9cd73a7fb2a57bb8db")},
|
||||||
};
|
{ 9001, uint256("0x6d5c6c5f201cc9e59659ee0da30d1430dc6bf3b12a8ff4c3864ab8d6286b0007")},
|
||||||
|
{ 9002, uint256("0xa1e20fb1d44688b763690cf74d6aefe859e4cc32981f9e3f2b2ae9702bbcf249")},
|
||||||
bool CheckHardened(int nHeight, const uint256& hash)
|
{ 10881, uint256("0x4b6554c45e1e6764a6f3c309c47baf53c9edd81f624e52b072518cd15da237e6")},
|
||||||
{
|
{ 17650, uint256("0x224940e1f986a202209b8e762728d1452ab45870c308abf84905674acf326a47")},
|
||||||
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
};
|
||||||
|
|
||||||
MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
|
bool CheckHardened(int nHeight, const uint256& hash)
|
||||||
if (i == checkpoints.end()) return true;
|
{
|
||||||
return hash == i->second;
|
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
||||||
}
|
|
||||||
|
MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
|
||||||
bool IsKnownCheckpoint(int nHeight, const uint256& hash)
|
if (i == checkpoints.end()) return true;
|
||||||
{
|
return hash == i->second;
|
||||||
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
}
|
||||||
MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
|
|
||||||
if (i == checkpoints.end()) return false;
|
bool IsKnownCheckpoint(int nHeight, const uint256& hash)
|
||||||
return hash == i->second;
|
{
|
||||||
}
|
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
||||||
|
MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
|
||||||
int GetTotalBlocksEstimate()
|
if (i == checkpoints.end()) return false;
|
||||||
{
|
return hash == i->second;
|
||||||
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
}
|
||||||
|
|
||||||
return checkpoints.rbegin()->first;
|
int GetTotalBlocksEstimate()
|
||||||
}
|
{
|
||||||
|
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
||||||
int GetBestSnapshotHeight()
|
|
||||||
{
|
return checkpoints.rbegin()->first;
|
||||||
std::map<int, uint256>& snaps = (fTestNet ? mapSnapshotHashesTestnet : mapSnapshotHashes);
|
}
|
||||||
if (snaps.empty()) return 0;
|
|
||||||
return snaps.rbegin()->first;
|
int GetBestSnapshotHeight()
|
||||||
}
|
{
|
||||||
|
std::map<int, uint256>& snaps = (fTestNet ? mapSnapshotHashesTestnet : mapSnapshotHashes);
|
||||||
bool GetSnapshotHash(int nHeight, uint256& fileHashOut)
|
if (snaps.empty()) return 0;
|
||||||
{
|
return snaps.rbegin()->first;
|
||||||
std::map<int, uint256>& snaps = (fTestNet ? mapSnapshotHashesTestnet : mapSnapshotHashes);
|
}
|
||||||
auto it = snaps.find(nHeight);
|
|
||||||
if (it == snaps.end()) return false;
|
bool GetSnapshotHash(int nHeight, uint256& fileHashOut)
|
||||||
fileHashOut = it->second;
|
{
|
||||||
return true;
|
std::map<int, uint256>& snaps = (fTestNet ? mapSnapshotHashesTestnet : mapSnapshotHashes);
|
||||||
}
|
auto it = snaps.find(nHeight);
|
||||||
|
if (it == snaps.end()) return false;
|
||||||
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
|
fileHashOut = it->second;
|
||||||
{
|
return true;
|
||||||
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
}
|
||||||
|
|
||||||
for (auto it = checkpoints.rbegin(); it != checkpoints.rend(); ++it)
|
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
|
||||||
{
|
{
|
||||||
const uint256& hash = it->second;
|
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
||||||
std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
|
|
||||||
if (t != mapBlockIndex.end())
|
for (auto it = checkpoints.rbegin(); it != checkpoints.rend(); ++it)
|
||||||
return t->second;
|
{
|
||||||
}
|
const uint256& hash = it->second;
|
||||||
return nullptr;
|
std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
|
||||||
}
|
if (t != mapBlockIndex.end())
|
||||||
|
return t->second;
|
||||||
// triangles: synchronized checkpoint (centrally broadcasted)
|
}
|
||||||
uint256 hashSyncCheckpoint = uint256("0x7e7a6e4dd5fe895106fca912dfbacaeaf2a89e76c6a588df8ff96e0e18b96021");
|
return nullptr;
|
||||||
uint256 hashPendingCheckpoint = uint256("0x7e7a6e4dd5fe895106fca912dfbacaeaf2a89e76c6a588df8ff96e0e18b96021");
|
}
|
||||||
CSyncCheckpoint checkpointMessage;
|
|
||||||
CSyncCheckpoint checkpointMessagePending;
|
// triangles: synchronized checkpoint (centrally broadcasted)
|
||||||
uint256 hashInvalidCheckpoint = 0;
|
uint256 hashSyncCheckpoint = uint256("0x7e7a6e4dd5fe895106fca912dfbacaeaf2a89e76c6a588df8ff96e0e18b96021");
|
||||||
CCriticalSection cs_hashSyncCheckpoint;
|
uint256 hashPendingCheckpoint = uint256("0x7e7a6e4dd5fe895106fca912dfbacaeaf2a89e76c6a588df8ff96e0e18b96021");
|
||||||
|
CSyncCheckpoint checkpointMessage;
|
||||||
// triangles: get last synchronized checkpoint
|
CSyncCheckpoint checkpointMessagePending;
|
||||||
CBlockIndex* GetLastSyncCheckpoint()
|
uint256 hashInvalidCheckpoint = 0;
|
||||||
{
|
CCriticalSection cs_hashSyncCheckpoint;
|
||||||
LOCK(cs_hashSyncCheckpoint);
|
|
||||||
if (!mapBlockIndex.count(hashSyncCheckpoint))
|
// triangles: get last synchronized checkpoint
|
||||||
error("GetSyncCheckpoint: block index missing for current sync-checkpoint %s", hashSyncCheckpoint.ToString().c_str());
|
CBlockIndex* GetLastSyncCheckpoint()
|
||||||
else
|
{
|
||||||
return mapBlockIndex[hashSyncCheckpoint];
|
LOCK(cs_hashSyncCheckpoint);
|
||||||
return nullptr;
|
if (!mapBlockIndex.count(hashSyncCheckpoint))
|
||||||
}
|
error("GetSyncCheckpoint: block index missing for current sync-checkpoint %s", hashSyncCheckpoint.ToString().c_str());
|
||||||
|
else
|
||||||
// triangles: only descendant of current sync-checkpoint is allowed
|
return mapBlockIndex[hashSyncCheckpoint];
|
||||||
bool ValidateSyncCheckpoint(uint256 hashCheckpoint)
|
return nullptr;
|
||||||
{
|
}
|
||||||
if (!mapBlockIndex.count(hashSyncCheckpoint))
|
|
||||||
return error("ValidateSyncCheckpoint: block index missing for current sync-checkpoint %s", hashSyncCheckpoint.ToString().c_str());
|
// triangles: only descendant of current sync-checkpoint is allowed
|
||||||
if (!mapBlockIndex.count(hashCheckpoint))
|
bool ValidateSyncCheckpoint(uint256 hashCheckpoint)
|
||||||
return error("ValidateSyncCheckpoint: block index missing for received sync-checkpoint %s", hashCheckpoint.ToString().c_str());
|
{
|
||||||
|
if (!mapBlockIndex.count(hashSyncCheckpoint))
|
||||||
CBlockIndex* pindexSyncCheckpoint = mapBlockIndex[hashSyncCheckpoint];
|
return error("ValidateSyncCheckpoint: block index missing for current sync-checkpoint %s", hashSyncCheckpoint.ToString().c_str());
|
||||||
CBlockIndex* pindexCheckpointRecv = mapBlockIndex[hashCheckpoint];
|
if (!mapBlockIndex.count(hashCheckpoint))
|
||||||
|
return error("ValidateSyncCheckpoint: block index missing for received sync-checkpoint %s", hashCheckpoint.ToString().c_str());
|
||||||
if (pindexCheckpointRecv->nHeight <= pindexSyncCheckpoint->nHeight)
|
|
||||||
{
|
CBlockIndex* pindexSyncCheckpoint = mapBlockIndex[hashSyncCheckpoint];
|
||||||
// Received an older checkpoint, trace back from current checkpoint
|
CBlockIndex* pindexCheckpointRecv = mapBlockIndex[hashCheckpoint];
|
||||||
// to the same height of the received checkpoint to verify
|
|
||||||
// that current checkpoint should be a descendant block
|
if (pindexCheckpointRecv->nHeight <= pindexSyncCheckpoint->nHeight)
|
||||||
CBlockIndex* pindex = pindexSyncCheckpoint;
|
{
|
||||||
while (pindex->nHeight > pindexCheckpointRecv->nHeight)
|
// Received an older checkpoint, trace back from current checkpoint
|
||||||
if (!(pindex = pindex->pprev))
|
// to the same height of the received checkpoint to verify
|
||||||
return error("ValidateSyncCheckpoint: pprev null - block index structure failure");
|
// that current checkpoint should be a descendant block
|
||||||
if (pindex->GetBlockHash() != hashCheckpoint)
|
CBlockIndex* pindex = pindexSyncCheckpoint;
|
||||||
{
|
while (pindex->nHeight > pindexCheckpointRecv->nHeight)
|
||||||
hashInvalidCheckpoint = hashCheckpoint;
|
if (!(pindex = pindex->pprev))
|
||||||
return error("ValidateSyncCheckpoint: new sync-checkpoint %s is conflicting with current sync-checkpoint %s", hashCheckpoint.ToString().c_str(), hashSyncCheckpoint.ToString().c_str());
|
return error("ValidateSyncCheckpoint: pprev null - block index structure failure");
|
||||||
}
|
if (pindex->GetBlockHash() != hashCheckpoint)
|
||||||
return false; // ignore older checkpoint
|
{
|
||||||
}
|
hashInvalidCheckpoint = hashCheckpoint;
|
||||||
|
return error("ValidateSyncCheckpoint: new sync-checkpoint %s is conflicting with current sync-checkpoint %s", hashCheckpoint.ToString().c_str(), hashSyncCheckpoint.ToString().c_str());
|
||||||
// Received checkpoint should be a descendant block of the current
|
}
|
||||||
// checkpoint. Trace back to the same height of current checkpoint
|
return false; // ignore older checkpoint
|
||||||
// to verify.
|
}
|
||||||
CBlockIndex* pindex = pindexCheckpointRecv;
|
|
||||||
while (pindex->nHeight > pindexSyncCheckpoint->nHeight)
|
// Received checkpoint should be a descendant block of the current
|
||||||
if (!(pindex = pindex->pprev))
|
// checkpoint. Trace back to the same height of current checkpoint
|
||||||
return error("ValidateSyncCheckpoint: pprev2 null - block index structure failure");
|
// to verify.
|
||||||
if (pindex->GetBlockHash() != hashSyncCheckpoint)
|
CBlockIndex* pindex = pindexCheckpointRecv;
|
||||||
{
|
while (pindex->nHeight > pindexSyncCheckpoint->nHeight)
|
||||||
hashInvalidCheckpoint = hashCheckpoint;
|
if (!(pindex = pindex->pprev))
|
||||||
return error("ValidateSyncCheckpoint: new sync-checkpoint %s is not a descendant of current sync-checkpoint %s", hashCheckpoint.ToString().c_str(), hashSyncCheckpoint.ToString().c_str());
|
return error("ValidateSyncCheckpoint: pprev2 null - block index structure failure");
|
||||||
}
|
if (pindex->GetBlockHash() != hashSyncCheckpoint)
|
||||||
return true;
|
{
|
||||||
}
|
hashInvalidCheckpoint = hashCheckpoint;
|
||||||
|
return error("ValidateSyncCheckpoint: new sync-checkpoint %s is not a descendant of current sync-checkpoint %s", hashCheckpoint.ToString().c_str(), hashSyncCheckpoint.ToString().c_str());
|
||||||
bool WriteSyncCheckpoint(const uint256& hashCheckpoint)
|
}
|
||||||
{
|
return true;
|
||||||
auto txdb_holder = MakeChainDB(); CTxDBBase& txdb = *txdb_holder;
|
}
|
||||||
txdb.TxnBegin();
|
|
||||||
if (!txdb.WriteSyncCheckpoint(hashCheckpoint))
|
bool WriteSyncCheckpoint(const uint256& hashCheckpoint)
|
||||||
{
|
{
|
||||||
txdb.TxnAbort();
|
auto txdb_holder = MakeChainDB(); CTxDBBase& txdb = *txdb_holder;
|
||||||
return error("WriteSyncCheckpoint(): failed to write to db sync checkpoint %s", hashCheckpoint.ToString().c_str());
|
txdb.TxnBegin();
|
||||||
}
|
if (!txdb.WriteSyncCheckpoint(hashCheckpoint))
|
||||||
if (!txdb.TxnCommit())
|
{
|
||||||
return error("WriteSyncCheckpoint(): failed to commit to db sync checkpoint %s", hashCheckpoint.ToString().c_str());
|
txdb.TxnAbort();
|
||||||
|
return error("WriteSyncCheckpoint(): failed to write to db sync checkpoint %s", hashCheckpoint.ToString().c_str());
|
||||||
Checkpoints::hashSyncCheckpoint = hashCheckpoint;
|
}
|
||||||
return true;
|
if (!txdb.TxnCommit())
|
||||||
}
|
return error("WriteSyncCheckpoint(): failed to commit to db sync checkpoint %s", hashCheckpoint.ToString().c_str());
|
||||||
|
|
||||||
bool AcceptPendingSyncCheckpoint()
|
Checkpoints::hashSyncCheckpoint = hashCheckpoint;
|
||||||
{
|
return true;
|
||||||
LOCK(cs_hashSyncCheckpoint);
|
}
|
||||||
if (hashPendingCheckpoint != 0 && mapBlockIndex.count(hashPendingCheckpoint))
|
|
||||||
{
|
bool AcceptPendingSyncCheckpoint()
|
||||||
if (!ValidateSyncCheckpoint(hashPendingCheckpoint))
|
{
|
||||||
{
|
LOCK(cs_hashSyncCheckpoint);
|
||||||
hashPendingCheckpoint = 0;
|
if (hashPendingCheckpoint != 0 && mapBlockIndex.count(hashPendingCheckpoint))
|
||||||
checkpointMessagePending.SetNull();
|
{
|
||||||
return false;
|
if (!ValidateSyncCheckpoint(hashPendingCheckpoint))
|
||||||
}
|
{
|
||||||
|
hashPendingCheckpoint = 0;
|
||||||
auto txdb_holder = MakeChainDB(); CTxDBBase& txdb = *txdb_holder;
|
checkpointMessagePending.SetNull();
|
||||||
CBlockIndex* pindexCheckpoint = mapBlockIndex[hashPendingCheckpoint];
|
return false;
|
||||||
if (!pindexCheckpoint->IsInMainChain())
|
}
|
||||||
{
|
|
||||||
CBlock block;
|
auto txdb_holder = MakeChainDB(); CTxDBBase& txdb = *txdb_holder;
|
||||||
if (!block.ReadFromDisk(pindexCheckpoint))
|
CBlockIndex* pindexCheckpoint = mapBlockIndex[hashPendingCheckpoint];
|
||||||
return error("AcceptPendingSyncCheckpoint: ReadFromDisk failed for sync checkpoint %s", hashPendingCheckpoint.ToString().c_str());
|
if (!pindexCheckpoint->IsInMainChain())
|
||||||
if (!block.SetBestChain(txdb, pindexCheckpoint))
|
{
|
||||||
{
|
CBlock block;
|
||||||
hashInvalidCheckpoint = hashPendingCheckpoint;
|
if (!block.ReadFromDisk(pindexCheckpoint))
|
||||||
return error("AcceptPendingSyncCheckpoint: SetBestChain failed for sync checkpoint %s", hashPendingCheckpoint.ToString().c_str());
|
return error("AcceptPendingSyncCheckpoint: ReadFromDisk failed for sync checkpoint %s", hashPendingCheckpoint.ToString().c_str());
|
||||||
}
|
if (!block.SetBestChain(txdb, pindexCheckpoint))
|
||||||
}
|
{
|
||||||
|
hashInvalidCheckpoint = hashPendingCheckpoint;
|
||||||
if (!WriteSyncCheckpoint(hashPendingCheckpoint))
|
return error("AcceptPendingSyncCheckpoint: SetBestChain failed for sync checkpoint %s", hashPendingCheckpoint.ToString().c_str());
|
||||||
return error("AcceptPendingSyncCheckpoint(): failed to write sync checkpoint %s", hashPendingCheckpoint.ToString().c_str());
|
}
|
||||||
hashPendingCheckpoint = 0;
|
}
|
||||||
checkpointMessage = checkpointMessagePending;
|
|
||||||
checkpointMessagePending.SetNull();
|
if (!WriteSyncCheckpoint(hashPendingCheckpoint))
|
||||||
printf("AcceptPendingSyncCheckpoint : sync-checkpoint at %s\n", hashSyncCheckpoint.ToString().c_str());
|
return error("AcceptPendingSyncCheckpoint(): failed to write sync checkpoint %s", hashPendingCheckpoint.ToString().c_str());
|
||||||
// relay the checkpoint
|
hashPendingCheckpoint = 0;
|
||||||
if (!checkpointMessage.IsNull())
|
checkpointMessage = checkpointMessagePending;
|
||||||
{
|
checkpointMessagePending.SetNull();
|
||||||
for (CNode* pnode : vNodes)
|
printf("AcceptPendingSyncCheckpoint : sync-checkpoint at %s\n", hashSyncCheckpoint.ToString().c_str());
|
||||||
checkpointMessage.RelayTo(pnode);
|
// relay the checkpoint
|
||||||
}
|
if (!checkpointMessage.IsNull())
|
||||||
return true;
|
{
|
||||||
}
|
for (CNode* pnode : vNodes)
|
||||||
return false;
|
checkpointMessage.RelayTo(pnode);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
// Automatically select a suitable sync-checkpoint
|
}
|
||||||
uint256 AutoSelectSyncCheckpoint()
|
return false;
|
||||||
{
|
}
|
||||||
const CBlockIndex *pindex = pindexBest;
|
|
||||||
// Search backward for a block within max span and maturity window
|
// Automatically select a suitable sync-checkpoint
|
||||||
while (pindex->pprev && (pindex->GetBlockTime() + CHECKPOINT_MAX_SPAN > pindexBest->GetBlockTime() || pindex->nHeight + 8 > pindexBest->nHeight))
|
uint256 AutoSelectSyncCheckpoint()
|
||||||
pindex = pindex->pprev;
|
{
|
||||||
return pindex->GetBlockHash();
|
const CBlockIndex *pindex = pindexBest;
|
||||||
}
|
// Search backward for a block within max span and maturity window
|
||||||
|
while (pindex->pprev && (pindex->GetBlockTime() + CHECKPOINT_MAX_SPAN > pindexBest->GetBlockTime() || pindex->nHeight + 8 > pindexBest->nHeight))
|
||||||
// Check against synchronized checkpoint
|
pindex = pindex->pprev;
|
||||||
// Disabled: master key removed in V5, no new sync checkpoints possible.
|
return pindex->GetBlockHash();
|
||||||
// Always returns true to prevent stale DB-persisted checkpoints from blocking IBD.
|
}
|
||||||
bool CheckSync(const uint256& hashBlock, const CBlockIndex* pindexPrev)
|
|
||||||
{
|
// Check against synchronized checkpoint
|
||||||
return true;
|
// 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)
|
||||||
bool WantedByPendingSyncCheckpoint(uint256 hashBlock)
|
{
|
||||||
{
|
return true;
|
||||||
LOCK(cs_hashSyncCheckpoint);
|
}
|
||||||
if (hashPendingCheckpoint == 0)
|
|
||||||
return false;
|
bool WantedByPendingSyncCheckpoint(uint256 hashBlock)
|
||||||
if (hashBlock == hashPendingCheckpoint)
|
{
|
||||||
return true;
|
LOCK(cs_hashSyncCheckpoint);
|
||||||
if (mapOrphanBlocks.count(hashPendingCheckpoint)
|
if (hashPendingCheckpoint == 0)
|
||||||
&& hashBlock == WantedByOrphan(mapOrphanBlocks[hashPendingCheckpoint].get()))
|
return false;
|
||||||
return true;
|
if (hashBlock == hashPendingCheckpoint)
|
||||||
return false;
|
return true;
|
||||||
}
|
if (mapOrphanBlocks.count(hashPendingCheckpoint)
|
||||||
|
&& hashBlock == WantedByOrphan(mapOrphanBlocks[hashPendingCheckpoint].get()))
|
||||||
// triangles: reset synchronized checkpoint to last hardened checkpoint
|
return true;
|
||||||
bool ResetSyncCheckpoint()
|
return false;
|
||||||
{
|
}
|
||||||
LOCK(cs_hashSyncCheckpoint);
|
|
||||||
const uint256& hash = mapCheckpoints.rbegin()->second;
|
// triangles: reset synchronized checkpoint to last hardened checkpoint
|
||||||
if (mapBlockIndex.count(hash) && !mapBlockIndex[hash]->IsInMainChain())
|
bool ResetSyncCheckpoint()
|
||||||
{
|
{
|
||||||
// checkpoint block accepted but not yet in main chain
|
LOCK(cs_hashSyncCheckpoint);
|
||||||
printf("ResetSyncCheckpoint: SetBestChain to hardened checkpoint %s\n", hash.ToString().c_str());
|
const uint256& hash = mapCheckpoints.rbegin()->second;
|
||||||
auto txdb_holder = MakeChainDB(); CTxDBBase& txdb = *txdb_holder;
|
if (mapBlockIndex.count(hash) && !mapBlockIndex[hash]->IsInMainChain())
|
||||||
CBlock block;
|
{
|
||||||
if (!block.ReadFromDisk(mapBlockIndex[hash]))
|
// checkpoint block accepted but not yet in main chain
|
||||||
return error("ResetSyncCheckpoint: ReadFromDisk failed for hardened checkpoint %s", hash.ToString().c_str());
|
printf("ResetSyncCheckpoint: SetBestChain to hardened checkpoint %s\n", hash.ToString().c_str());
|
||||||
if (!block.SetBestChain(txdb, mapBlockIndex[hash]))
|
auto txdb_holder = MakeChainDB(); CTxDBBase& txdb = *txdb_holder;
|
||||||
{
|
CBlock block;
|
||||||
return error("ResetSyncCheckpoint: SetBestChain failed for hardened checkpoint %s", hash.ToString().c_str());
|
if (!block.ReadFromDisk(mapBlockIndex[hash]))
|
||||||
}
|
return error("ResetSyncCheckpoint: ReadFromDisk failed for hardened checkpoint %s", hash.ToString().c_str());
|
||||||
}
|
if (!block.SetBestChain(txdb, mapBlockIndex[hash]))
|
||||||
else if(!mapBlockIndex.count(hash))
|
{
|
||||||
{
|
return error("ResetSyncCheckpoint: SetBestChain failed for hardened checkpoint %s", hash.ToString().c_str());
|
||||||
// checkpoint block not yet accepted
|
}
|
||||||
hashPendingCheckpoint = hash;
|
}
|
||||||
checkpointMessagePending.SetNull();
|
else if(!mapBlockIndex.count(hash))
|
||||||
printf("ResetSyncCheckpoint: pending for sync-checkpoint %s\n", hashPendingCheckpoint.ToString().c_str());
|
{
|
||||||
}
|
// checkpoint block not yet accepted
|
||||||
|
hashPendingCheckpoint = hash;
|
||||||
for (auto it = mapCheckpoints.rbegin(); it != mapCheckpoints.rend(); ++it)
|
checkpointMessagePending.SetNull();
|
||||||
{
|
printf("ResetSyncCheckpoint: pending for sync-checkpoint %s\n", hashPendingCheckpoint.ToString().c_str());
|
||||||
const uint256& hash = it->second;
|
}
|
||||||
if (mapBlockIndex.count(hash) && mapBlockIndex[hash]->IsInMainChain())
|
|
||||||
{
|
for (auto it = mapCheckpoints.rbegin(); it != mapCheckpoints.rend(); ++it)
|
||||||
if (!WriteSyncCheckpoint(hash))
|
{
|
||||||
return error("ResetSyncCheckpoint: failed to write sync checkpoint %s", hash.ToString().c_str());
|
const uint256& hash = it->second;
|
||||||
printf("ResetSyncCheckpoint: sync-checkpoint reset to %s\n", hashSyncCheckpoint.ToString().c_str());
|
if (mapBlockIndex.count(hash) && mapBlockIndex[hash]->IsInMainChain())
|
||||||
return true;
|
{
|
||||||
}
|
if (!WriteSyncCheckpoint(hash))
|
||||||
}
|
return error("ResetSyncCheckpoint: failed to write sync checkpoint %s", hash.ToString().c_str());
|
||||||
|
printf("ResetSyncCheckpoint: sync-checkpoint reset to %s\n", hashSyncCheckpoint.ToString().c_str());
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void AskForPendingSyncCheckpoint(CNode* pfrom)
|
|
||||||
{
|
return false;
|
||||||
LOCK(cs_hashSyncCheckpoint);
|
}
|
||||||
if (pfrom && hashPendingCheckpoint != 0 && (!mapBlockIndex.count(hashPendingCheckpoint)) && (!mapOrphanBlocks.count(hashPendingCheckpoint)))
|
|
||||||
pfrom->AskFor(CInv(MSG_BLOCK, hashPendingCheckpoint));
|
void AskForPendingSyncCheckpoint(CNode* pfrom)
|
||||||
}
|
{
|
||||||
|
LOCK(cs_hashSyncCheckpoint);
|
||||||
bool SetCheckpointPrivKey(std::string strPrivKey)
|
if (pfrom && hashPendingCheckpoint != 0 && (!mapBlockIndex.count(hashPendingCheckpoint)) && (!mapOrphanBlocks.count(hashPendingCheckpoint)))
|
||||||
{
|
pfrom->AskFor(CInv(MSG_BLOCK, hashPendingCheckpoint));
|
||||||
// Test signing a sync-checkpoint with genesis block
|
}
|
||||||
CSyncCheckpoint checkpoint;
|
|
||||||
checkpoint.hashCheckpoint = !fTestNet ? hashGenesisBlockOfficial : hashGenesisBlockTestNet;
|
bool SetCheckpointPrivKey(std::string strPrivKey)
|
||||||
CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
|
{
|
||||||
sMsg << (CUnsignedSyncCheckpoint)checkpoint;
|
// Test signing a sync-checkpoint with genesis block
|
||||||
checkpoint.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());
|
CSyncCheckpoint checkpoint;
|
||||||
|
checkpoint.hashCheckpoint = !fTestNet ? hashGenesisBlockOfficial : hashGenesisBlockTestNet;
|
||||||
std::vector<unsigned char> vchPrivKey = ParseHex(strPrivKey);
|
CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
CKey key;
|
sMsg << (CUnsignedSyncCheckpoint)checkpoint;
|
||||||
key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash
|
checkpoint.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());
|
||||||
if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig))
|
|
||||||
return false;
|
std::vector<unsigned char> vchPrivKey = ParseHex(strPrivKey);
|
||||||
|
CKey key;
|
||||||
// Test signing successful, proceed
|
key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash
|
||||||
CSyncCheckpoint::strMasterPrivKey = strPrivKey;
|
if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig))
|
||||||
return true;
|
return false;
|
||||||
}
|
|
||||||
|
// Test signing successful, proceed
|
||||||
bool SendSyncCheckpoint(uint256 hashCheckpoint)
|
CSyncCheckpoint::strMasterPrivKey = strPrivKey;
|
||||||
{
|
return true;
|
||||||
CSyncCheckpoint checkpoint;
|
}
|
||||||
checkpoint.hashCheckpoint = hashCheckpoint;
|
|
||||||
CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
|
bool SendSyncCheckpoint(uint256 hashCheckpoint)
|
||||||
sMsg << (CUnsignedSyncCheckpoint)checkpoint;
|
{
|
||||||
checkpoint.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());
|
CSyncCheckpoint checkpoint;
|
||||||
|
checkpoint.hashCheckpoint = hashCheckpoint;
|
||||||
if (CSyncCheckpoint::strMasterPrivKey.empty())
|
CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
return error("SendSyncCheckpoint: Checkpoint master key unavailable.");
|
sMsg << (CUnsignedSyncCheckpoint)checkpoint;
|
||||||
std::vector<unsigned char> vchPrivKey = ParseHex(CSyncCheckpoint::strMasterPrivKey);
|
checkpoint.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());
|
||||||
CKey key;
|
|
||||||
key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash
|
if (CSyncCheckpoint::strMasterPrivKey.empty())
|
||||||
if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig))
|
return error("SendSyncCheckpoint: Checkpoint master key unavailable.");
|
||||||
return error("SendSyncCheckpoint: Unable to sign checkpoint, check private key?");
|
std::vector<unsigned char> vchPrivKey = ParseHex(CSyncCheckpoint::strMasterPrivKey);
|
||||||
|
CKey key;
|
||||||
if(!checkpoint.ProcessSyncCheckpoint(nullptr))
|
key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash
|
||||||
{
|
if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig))
|
||||||
printf("WARNING: SendSyncCheckpoint: Failed to process checkpoint.\n");
|
return error("SendSyncCheckpoint: Unable to sign checkpoint, check private key?");
|
||||||
return false;
|
|
||||||
}
|
if(!checkpoint.ProcessSyncCheckpoint(nullptr))
|
||||||
|
{
|
||||||
// Relay checkpoint
|
printf("WARNING: SendSyncCheckpoint: Failed to process checkpoint.\n");
|
||||||
{
|
return false;
|
||||||
LOCK(cs_vNodes);
|
}
|
||||||
for (CNode* pnode : vNodes)
|
|
||||||
checkpoint.RelayTo(pnode);
|
// Relay checkpoint
|
||||||
}
|
{
|
||||||
return true;
|
LOCK(cs_vNodes);
|
||||||
}
|
for (CNode* pnode : vNodes)
|
||||||
|
checkpoint.RelayTo(pnode);
|
||||||
// Is the sync-checkpoint outside maturity window?
|
}
|
||||||
bool IsMatureSyncCheckpoint()
|
return true;
|
||||||
{
|
}
|
||||||
LOCK(cs_hashSyncCheckpoint);
|
|
||||||
if (!mapBlockIndex.count(hashSyncCheckpoint))
|
// Is the sync-checkpoint outside maturity window?
|
||||||
return true; // no valid sync checkpoint, treat as mature
|
bool IsMatureSyncCheckpoint()
|
||||||
const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint];
|
{
|
||||||
return (nBestHeight >= pindexSync->nHeight + nCoinbaseMaturity ||
|
LOCK(cs_hashSyncCheckpoint);
|
||||||
pindexSync->GetBlockTime() + nStakeMinAge < GetAdjustedTime());
|
if (!mapBlockIndex.count(hashSyncCheckpoint))
|
||||||
}
|
return true; // no valid sync checkpoint, treat as mature
|
||||||
}
|
const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint];
|
||||||
|
return (nBestHeight >= pindexSync->nHeight + nCoinbaseMaturity ||
|
||||||
// triangles: sync-checkpoint master key (DISABLED for decentralization - v5 hard fork)
|
pindexSync->GetBlockTime() + nStakeMinAge < GetAdjustedTime());
|
||||||
const std::string CSyncCheckpoint::strMasterPubKey = "";
|
}
|
||||||
|
}
|
||||||
std::string CSyncCheckpoint::strMasterPrivKey = "";
|
|
||||||
|
// triangles: sync-checkpoint master key (DISABLED for decentralization - v5 hard fork)
|
||||||
// triangles: verify signature of sync-checkpoint message
|
const std::string CSyncCheckpoint::strMasterPubKey = "";
|
||||||
// Master key system disabled - checkpoint signatures are no longer required
|
|
||||||
bool CSyncCheckpoint::CheckSignature()
|
std::string CSyncCheckpoint::strMasterPrivKey = "";
|
||||||
{
|
|
||||||
// Deserialize the checkpoint data without signature verification
|
// triangles: verify signature of sync-checkpoint message
|
||||||
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
|
// Master key system disabled - checkpoint signatures are no longer required
|
||||||
sMsg >> *(CUnsignedSyncCheckpoint*)this;
|
bool CSyncCheckpoint::CheckSignature()
|
||||||
return true;
|
{
|
||||||
}
|
// Deserialize the checkpoint data without signature verification
|
||||||
|
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
// triangles: process synchronized checkpoint
|
sMsg >> *(CUnsignedSyncCheckpoint*)this;
|
||||||
bool CSyncCheckpoint::ProcessSyncCheckpoint(CNode* pfrom)
|
return true;
|
||||||
{
|
}
|
||||||
if (!CheckSignature())
|
|
||||||
return false;
|
// triangles: process synchronized checkpoint
|
||||||
|
bool CSyncCheckpoint::ProcessSyncCheckpoint(CNode* pfrom)
|
||||||
LOCK(Checkpoints::cs_hashSyncCheckpoint);
|
{
|
||||||
if (!mapBlockIndex.count(hashCheckpoint))
|
if (!CheckSignature())
|
||||||
{
|
return false;
|
||||||
// We haven't received the checkpoint chain, keep the checkpoint as pending
|
|
||||||
Checkpoints::hashPendingCheckpoint = hashCheckpoint;
|
LOCK(Checkpoints::cs_hashSyncCheckpoint);
|
||||||
Checkpoints::checkpointMessagePending = *this;
|
if (!mapBlockIndex.count(hashCheckpoint))
|
||||||
printf("ProcessSyncCheckpoint: pending for sync-checkpoint %s\n", hashCheckpoint.ToString().c_str());
|
{
|
||||||
// Ask this guy to fill in what we're missing
|
// We haven't received the checkpoint chain, keep the checkpoint as pending
|
||||||
if (pfrom)
|
Checkpoints::hashPendingCheckpoint = hashCheckpoint;
|
||||||
{
|
Checkpoints::checkpointMessagePending = *this;
|
||||||
pfrom->PushGetBlocks(pindexBest, hashCheckpoint);
|
printf("ProcessSyncCheckpoint: pending for sync-checkpoint %s\n", hashCheckpoint.ToString().c_str());
|
||||||
// ask directly as well in case rejected earlier by duplicate
|
// Ask this guy to fill in what we're missing
|
||||||
// proof-of-stake because getblocks may not get it this time
|
if (pfrom)
|
||||||
pfrom->AskFor(CInv(MSG_BLOCK, mapOrphanBlocks.count(hashCheckpoint)? WantedByOrphan(mapOrphanBlocks[hashCheckpoint].get()) : hashCheckpoint));
|
{
|
||||||
}
|
pfrom->PushGetBlocks(pindexBest, hashCheckpoint);
|
||||||
return false;
|
// ask directly as well in case rejected earlier by duplicate
|
||||||
}
|
// proof-of-stake because getblocks may not get it this time
|
||||||
|
pfrom->AskFor(CInv(MSG_BLOCK, mapOrphanBlocks.count(hashCheckpoint)? WantedByOrphan(mapOrphanBlocks[hashCheckpoint].get()) : hashCheckpoint));
|
||||||
if (!Checkpoints::ValidateSyncCheckpoint(hashCheckpoint))
|
}
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
auto txdb_holder = MakeChainDB(); CTxDBBase& txdb = *txdb_holder;
|
|
||||||
CBlockIndex* pindexCheckpoint = mapBlockIndex[hashCheckpoint];
|
if (!Checkpoints::ValidateSyncCheckpoint(hashCheckpoint))
|
||||||
if (!pindexCheckpoint->IsInMainChain())
|
return false;
|
||||||
{
|
|
||||||
// checkpoint chain received but not yet main chain
|
auto txdb_holder = MakeChainDB(); CTxDBBase& txdb = *txdb_holder;
|
||||||
CBlock block;
|
CBlockIndex* pindexCheckpoint = mapBlockIndex[hashCheckpoint];
|
||||||
if (!block.ReadFromDisk(pindexCheckpoint))
|
if (!pindexCheckpoint->IsInMainChain())
|
||||||
return error("ProcessSyncCheckpoint: ReadFromDisk failed for sync checkpoint %s", hashCheckpoint.ToString().c_str());
|
{
|
||||||
if (!block.SetBestChain(txdb, pindexCheckpoint))
|
// checkpoint chain received but not yet main chain
|
||||||
{
|
CBlock block;
|
||||||
Checkpoints::hashInvalidCheckpoint = hashCheckpoint;
|
if (!block.ReadFromDisk(pindexCheckpoint))
|
||||||
return error("ProcessSyncCheckpoint: SetBestChain failed for sync checkpoint %s", hashCheckpoint.ToString().c_str());
|
return error("ProcessSyncCheckpoint: ReadFromDisk failed for sync checkpoint %s", hashCheckpoint.ToString().c_str());
|
||||||
}
|
if (!block.SetBestChain(txdb, pindexCheckpoint))
|
||||||
}
|
{
|
||||||
|
Checkpoints::hashInvalidCheckpoint = hashCheckpoint;
|
||||||
if (!Checkpoints::WriteSyncCheckpoint(hashCheckpoint))
|
return error("ProcessSyncCheckpoint: SetBestChain failed for sync checkpoint %s", hashCheckpoint.ToString().c_str());
|
||||||
return error("ProcessSyncCheckpoint(): failed to write sync checkpoint %s", hashCheckpoint.ToString().c_str());
|
}
|
||||||
Checkpoints::checkpointMessage = *this;
|
}
|
||||||
Checkpoints::hashPendingCheckpoint = 0;
|
|
||||||
Checkpoints::checkpointMessagePending.SetNull();
|
if (!Checkpoints::WriteSyncCheckpoint(hashCheckpoint))
|
||||||
printf("ProcessSyncCheckpoint: sync-checkpoint at %s\n", hashCheckpoint.ToString().c_str());
|
return error("ProcessSyncCheckpoint(
|
||||||
return true;
|
|
||||||
}
|
|
||||||
+19
-19
@@ -1,19 +1,19 @@
|
|||||||
#ifndef CLIENTVERSION_H
|
#ifndef CLIENTVERSION_H
|
||||||
#define CLIENTVERSION_H
|
#define CLIENTVERSION_H
|
||||||
|
|
||||||
//
|
//
|
||||||
// client versioning
|
// client versioning
|
||||||
//
|
//
|
||||||
|
|
||||||
// These need to be macros, as version.cpp's and triangles-qt.rc's voodoo requires it
|
// 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_MAJOR 5
|
||||||
#define CLIENT_VERSION_MINOR 9
|
#define CLIENT_VERSION_MINOR 9
|
||||||
#define CLIENT_VERSION_REVISION 11
|
#define CLIENT_VERSION_REVISION 12
|
||||||
#define CLIENT_VERSION_BUILD 0
|
#define CLIENT_VERSION_BUILD 0
|
||||||
|
|
||||||
// Converts the parameter X to a string after macro replacement on X has been performed.
|
// Converts the parameter X to a string after macro replacement on X has been performed.
|
||||||
// Don't merge these into one macro!
|
// Don't merge these into one macro!
|
||||||
#define STRINGIZE(X) DO_STRINGIZE(X)
|
#define STRINGIZE(X) DO_STRINGIZE(X)
|
||||||
#define DO_STRINGIZE(X) #X
|
#define DO_STRINGIZE(X) #X
|
||||||
|
|
||||||
#endif // CLIENTVERSION_H
|
#endif // CLIENTVERSION_H
|
||||||
|
|||||||
Reference in New Issue
Block a user