PPCoin: Synchronized checkpoint accepting descendant blocks only
[novacoin.git] / src / checkpoints.cpp
index d986b07..888d106 100644 (file)
@@ -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))