fix(checkpoints): rebase canonical tip to 2,200,899 (last clean block) + bump v6.2.6.5
A strict UTXO replay of the complete on-disk history (genesis..2,224,763) shows heights 2,172,038..2,200,899 validate cleanly, while the chain from height 2,200,900 (2026-04-07) onward contains 805 coinstake inputs in 603 blocks that re-spend outputs already spent by earlier main-chain blocks (4 of them spend outputs that only ever existed on a discarded fork). Those blocks were accepted in April 2026 only because of the v5.8.x vSpent tracking bug; no correct node can validate them, which is why -reindex dies at exactly 2,200,900 and why the fleet fell over once the Aug-3 UTXO fixes shipped. - mapCheckpoints: keep the 2,172,037 pin, add 2,180,000 / 2,190,000 / 2,200,000 / 2,200,500 / 2,200,899 (new canonical tip). Hashes computed from blk0001.dat headers (X13) on the same chain that carried the old live-network pins 2,222,900..2,224,763. - mapSnapshotHashes: retire the 2,172,037 entry; placeholder for the 2,200,899 snapshot SHA256 to be filled in once dumputxoset runs at the new tip (build fails loudly until it is). - tests: Checkpoints_tests + consensus_safety_tests expect 2,200,899. - version 6.2.6.5. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168vbbZ1oyhv7tyPuTcUyww
This commit is contained in:
+23
-2
@@ -56,7 +56,24 @@ namespace Checkpoints
|
||||
// 2,172,037. Closes the unchecked span between the prior highest
|
||||
// pin (17,650) and the new canonical tip for any future
|
||||
// fresh-from-zero sync.
|
||||
{ 2172037, uint256("0x52b12f0970191505d9982449875822b78f075d7d76307abed45e7132f5fa2f16")}, // new canonical tip
|
||||
{ 2172037, uint256("0x52b12f0970191505d9982449875822b78f075d7d76307abed45e7132f5fa2f16")}, // cycle-33 rollback pin
|
||||
// Checkpoint rebase to 2,200,899 (2026-09-02). A strict UTXO
|
||||
// replay of the full on-disk history (genesis..2,224,763) shows
|
||||
// that heights 2,172,038..2,200,899 validate cleanly, while the
|
||||
// canonical chain from height 2,200,900 (2026-04-07) onward
|
||||
// contains 805 coinstake inputs (in 603 blocks) that re-spend
|
||||
// outputs already spent by earlier blocks — accepted at the time
|
||||
// only because of the v5.8.x vSpent tracking bug. No correct
|
||||
// node can ever validate that span, so 2,200,899 is the last
|
||||
// block that can be canonical. Pins below restore 10k-block
|
||||
// spacing across the recovered span. Hashes computed directly
|
||||
// from blk0001.dat headers (X13) and cross-checked against the
|
||||
// chain that all live-network pins (2,222,900..2,224,763) sat on.
|
||||
{ 2180000, uint256("0xe3d2780d838314cb759784757e7e84cd0f18a46d333d3e6aaa4f79d5060104a0")},
|
||||
{ 2190000, uint256("0x682baf783581468ba18f9967254a7f3944e8b8c4cc7101e7d99b68f4f9dd5271")},
|
||||
{ 2200000, uint256("0x0a8d0442f031f1258120f713f34e45f4f9a625fb753558e27b89b32ad5a9a740")},
|
||||
{ 2200500, uint256("0x68fd5eedbefe80431fba92ee4ea37993f3e5f22f88b38a564e582a5c4aa15db2")},
|
||||
{ 2200899, uint256("0x28e57e03c7f48df8ef0dedba2b93fd5176500729c955f86546c381be66952e55")}, // canonical tip (last clean block)
|
||||
};
|
||||
|
||||
// Published UTXO snapshot file SHA256, keyed by snapshot height.
|
||||
@@ -78,7 +95,11 @@ namespace Checkpoints
|
||||
// The compiled map below must contain only the canonical snapshot so
|
||||
// GetBestSnapshotHeight() returns 2,172,037 and DownloadUtxoSnapshot
|
||||
// selects the canonical file from bootstrap.cryptographic-triangles.org.
|
||||
{ 2172037, uint256("0xfc3b2035525564156f2489e8929e132b75e9be285d9129ad21bc89ecdc4c7977")}, // canonical
|
||||
// 2172037 snapshot (fc3b2035...977) retired 2026-09-02: it predates the
|
||||
// checkpoint rebase and would make GetBestSnapshotHeight() select a
|
||||
// stale state. Replace the placeholder below with the SHA256 of the
|
||||
// utxo-snapshot-2200899.utx produced by dumputxoset at the new tip.
|
||||
{ 2200899, uint256("0x__SNAPSHOT_SHA256_2200899__")}, // canonical
|
||||
};
|
||||
|
||||
static std::map<int, uint256> mapSnapshotHashesTestnet = {
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
#define CLIENT_VERSION_MAJOR 6
|
||||
#define CLIENT_VERSION_MINOR 2
|
||||
#define CLIENT_VERSION_REVISION 6
|
||||
#define CLIENT_VERSION_BUILD 4
|
||||
#define CLIENT_VERSION_BUILD 5
|
||||
|
||||
// Converts the parameter X to a string after macro replacement on X has been performed.
|
||||
// Don't merge these into one macro!
|
||||
|
||||
@@ -14,8 +14,9 @@ BOOST_AUTO_TEST_CASE(hardened_checkpoints_match_current_chain)
|
||||
// After the operator rollback to 2,172,037 (cycle-32, 2026-08-06), the
|
||||
// 2205000/2206004 pins are no longer in the map (those block heights are
|
||||
// above the new canonical tip and reference non-existent blocks). The new
|
||||
// highest entry is 2172037.
|
||||
// highest entry is 2200899.
|
||||
BOOST_CHECK(Checkpoints::CheckHardened(2172037, uint256("0x52b12f0970191505d9982449875822b78f075d7d76307abed45e7132f5fa2f16")));
|
||||
BOOST_CHECK(Checkpoints::CheckHardened(2200899, uint256("0x28e57e03c7f48df8ef0dedba2b93fd5176500729c955f86546c381be66952e55")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hardened_checkpoints_reject_wrong_hashes_and_allow_unknown_heights)
|
||||
@@ -25,6 +26,7 @@ BOOST_AUTO_TEST_CASE(hardened_checkpoints_reject_wrong_hashes_and_allow_unknown_
|
||||
BOOST_CHECK(!Checkpoints::CheckHardened(9000, wrongHash));
|
||||
BOOST_CHECK(!Checkpoints::CheckHardened(9001, wrongHash));
|
||||
BOOST_CHECK(!Checkpoints::CheckHardened(2172037, wrongHash));
|
||||
BOOST_CHECK(!Checkpoints::CheckHardened(2200899, wrongHash));
|
||||
|
||||
// 2186940/2186941 are no longer pinned (superseded by the 2205000+
|
||||
// pins), and after the cycle-32 operator rollback the 2205000+ pins
|
||||
@@ -40,7 +42,7 @@ BOOST_AUTO_TEST_CASE(total_blocks_estimate_tracks_latest_hardened_checkpoint)
|
||||
{
|
||||
// After operator rollback to 2,172,037, GetTotalBlocksEstimate() returns
|
||||
// 2,172,037 (the new highest compiled checkpoint).
|
||||
BOOST_CHECK_EQUAL(Checkpoints::GetTotalBlocksEstimate(), 2172037);
|
||||
BOOST_CHECK_EQUAL(Checkpoints::GetTotalBlocksEstimate(), 2200899);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -738,10 +738,10 @@ BOOST_AUTO_TEST_CASE(reorg_guard_offbyone_hardening)
|
||||
// checkpoint height on mainnet. Verified against the actual binary.
|
||||
int nCompiled = Checkpoints::GetLastCheckpointHeight();
|
||||
BOOST_CHECK(nCompiled > 0); // sanity: compiled map populated
|
||||
// Must equal the highest key in the compiled map (2172037 as of cycle-33;
|
||||
// Must equal the highest key in the compiled map (2200899 as of the 2026-09-02 rebase;
|
||||
// this assertion locks the value at the time the binary was built, so
|
||||
// a regression that drops a checkpoint would also fail here).
|
||||
BOOST_CHECK_EQUAL(nCompiled, 2172037);
|
||||
BOOST_CHECK_EQUAL(nCompiled, 2200899);
|
||||
}
|
||||
|
||||
// ─── Duplicate-guard detection: variable referenced only in allowed files ─
|
||||
|
||||
Reference in New Issue
Block a user