From 2a1e2fa1bc6540d43a7f3afb545075db56dc5933 Mon Sep 17 00:00:00 2001 From: Scott Nadal Date: Mon, 18 Jun 2012 16:20:10 +0100 Subject: [PATCH] PPCoin: Synchronized checkpoint accepting descendant blocks only --- src/checkpoints.cpp | 21 ++++++++++++++++++--- src/checkpoints.h | 2 +- src/main.cpp | 4 ++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index d986b07..888d106 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -77,7 +77,8 @@ namespace Checkpoints CBlockIndex* pindex = pindexCheckpointRecv; while (pindex->nHeight > pindexSyncCheckpoint->nHeight) - pindex = pindex->pprev; + if (!(pindex = pindex->pprev)) + return error("ValidateSyncCheckpoint: pprev null - block index structure failure"); if (pindex->GetBlockHash() != hashSyncCheckpoint) 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 true; @@ -122,13 +123,27 @@ namespace Checkpoints } // Check against synchronized checkpoint - bool CheckSync(int nHeight, const uint256& hashBlock) + bool CheckSync(const uint256& hashBlock, const CBlockIndex* pindexPrev) { if (fTestNet) return true; // Testnet has no checkpoints + int nHeight = pindexPrev->nHeight + 1; CRITICAL_BLOCK(cs_hashSyncCheckpoint) { - CBlockIndex* pindexSync = mapBlockIndex[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)) diff --git a/src/checkpoints.h b/src/checkpoints.h index db3fe19..e90458e 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -137,7 +137,7 @@ namespace Checkpoints bool AcceptPendingSyncCheckpoint(); uint256 AutoSelectSyncCheckpoint(); - bool CheckSync(int nHeight, const uint256& hashBlock); + bool CheckSync(const uint256& hashBlock, const CBlockIndex* pindexPrev); // ppcoin: automatic checkpoint extern int nAutoCheckpoint; diff --git a/src/main.cpp b/src/main.cpp index 4de69bf..b8d83b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1579,8 +1579,8 @@ bool CBlock::AcceptBlock() return DoS(100, error("AcceptBlock() : rejected by automatic checkpoint at %d", Checkpoints::nAutoCheckpoint)); // ppcoin: check that the block satisfies synchronized checkpoint - if (!Checkpoints::CheckSync(nHeight, hash)) - return DoS(100, error("AcceptBlock() : rejected by synchronized checkpoint")); + if (!Checkpoints::CheckSync(hash, pindexPrev)) + return error("AcceptBlock() : rejected by synchronized checkpoint"); // Write block to history file if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK))) -- 1.7.1