From 80144bb96b7f4fb8b467494364699c67977ed427 Mon Sep 17 00:00:00 2001 From: Scott Nadal Date: Tue, 19 Jun 2012 15:55:38 +0100 Subject: [PATCH] PPCoin: Force reorganization for synchronized checkpoint --- src/checkpoints.cpp | 73 +++++++++++++++++++++++++++++++++++++++++---------- src/main.cpp | 2 +- src/main.h | 1 + 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 888d106..283bbdd 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -86,7 +86,12 @@ namespace Checkpoints bool AcceptPendingSyncCheckpoint() { + bool fAccepted = false; + uint256 hashCheckpoint = 0; + CTxDB txdb; + CRITICAL_BLOCK(cs_hashSyncCheckpoint) + { if ((!checkpointMessagePending.IsNull()) && mapBlockIndex.count(checkpointMessagePending.hashCheckpoint)) { if (!ValidateSyncCheckpoint(checkpointMessagePending.hashCheckpoint)) @@ -95,22 +100,45 @@ namespace Checkpoints return false; } - CTxDB txdb; + txdb.TxnBegin(); if (!txdb.WriteSyncCheckpoint(checkpointMessagePending.hashCheckpoint)) + { + txdb.TxnAbort(); return error("AcceptPendingSyncCheckpoint() : failed to write to db sync checkpoint %s\n", checkpointMessagePending.hashCheckpoint.ToString().c_str()); - txdb.Close(); + } + if (!txdb.TxnCommit()) + return error("AcceptPendingSyncCheckpoint() : failed to commit to db sync checkpoint %s\n", checkpointMessagePending.hashCheckpoint.ToString().c_str()); hashSyncCheckpoint = checkpointMessagePending.hashCheckpoint; checkpointMessage = checkpointMessagePending; checkpointMessagePending.SetNull(); printf("AcceptPendingSyncCheckpoint : sync-checkpoint at %s\n", hashSyncCheckpoint.ToString().c_str()); - // relay the checkpoint - BOOST_FOREACH(CNode* pnode, vNodes) - checkpointMessage.RelayTo(pnode); - return true; + fAccepted = true; + hashCheckpoint = hashSyncCheckpoint; } + } - return false; + if (fAccepted) + { + CBlockIndex* pindexCheckpoint = mapBlockIndex[hashCheckpoint]; + if (!pindexCheckpoint->IsInMainChain()) + { + txdb.TxnBegin(); + if (!Reorganize(txdb, pindexCheckpoint)) + { + txdb.TxnAbort(); + return error("ProcessSyncCheckpoint: Reorganize failed for sync checkpoint %s", hashCheckpoint.ToString().c_str()); + } + } + } + txdb.Close(); + + // relay the checkpoint + CRITICAL_BLOCK(cs_hashSyncCheckpoint) + BOOST_FOREACH(CNode* pnode, vNodes) + checkpointMessage.RelayTo(pnode); + + return fAccepted; } uint256 AutoSelectSyncCheckpoint() @@ -276,13 +304,14 @@ bool CSyncCheckpoint::ProcessSyncCheckpoint(CNode* pfrom) if (!CheckSignature()) return false; + CTxDB txdb; CRITICAL_BLOCK(Checkpoints::cs_hashSyncCheckpoint) { if (!mapBlockIndex.count(hashCheckpoint)) { // We haven't accepted this block, keep the checkpoint as pending Checkpoints::checkpointMessagePending = *this; - printf("ProcessSyncCheckpoint : pending for sync-checkpoint %s\n", hashCheckpoint.ToString().c_str()); + printf("ProcessSyncCheckpoint: pending for sync-checkpoint %s\n", hashCheckpoint.ToString().c_str()); // Ask this guy to fill in what we're missing if (pfrom) pfrom->PushGetBlocks(pindexBest, hashCheckpoint); @@ -291,15 +320,31 @@ bool CSyncCheckpoint::ProcessSyncCheckpoint(CNode* pfrom) if (!Checkpoints::ValidateSyncCheckpoint(hashCheckpoint)) return false; - CTxDB txdb; - if (!txdb.WriteSyncCheckpoint(this->hashCheckpoint)) - return error("ProcessSyncCheckpoint() : failed to write to db sync checkpoint %s\n", this->hashCheckpoint.ToString().c_str()); - txdb.Close(); + txdb.TxnBegin(); + if (!txdb.WriteSyncCheckpoint(hashCheckpoint)) + { + txdb.TxnAbort(); + return error("ProcessSyncCheckpoint(): failed to write to db sync checkpoint %s", hashCheckpoint.ToString().c_str()); + } + if (!txdb.TxnCommit()) + return error("ProcessSyncCheckpoint(): failed to commit to db sync checkpoint %s", hashCheckpoint.ToString().c_str()); - Checkpoints::hashSyncCheckpoint = this->hashCheckpoint; + Checkpoints::hashSyncCheckpoint = hashCheckpoint; Checkpoints::checkpointMessage = *this; Checkpoints::checkpointMessagePending.SetNull(); - printf("ProcessSyncCheckpoint : sync-checkpoint at %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str()); + printf("ProcessSyncCheckpoint: sync-checkpoint at %s\n", hashCheckpoint.ToString().c_str()); + } + + CBlockIndex* pindexCheckpoint = mapBlockIndex[hashCheckpoint]; + if (!pindexCheckpoint->IsInMainChain()) + { + txdb.TxnBegin(); + if (!Reorganize(txdb, pindexCheckpoint)) + { + txdb.TxnAbort(); + return error("ProcessSyncCheckpoint: Reorganize failed for sync checkpoint %s", hashCheckpoint.ToString().c_str()); + } } + txdb.Close(); return true; } diff --git a/src/main.cpp b/src/main.cpp index b8d83b2..127ca29 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1125,7 +1125,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) return true; } -bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) +bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) { printf("REORGANIZE\n"); diff --git a/src/main.h b/src/main.h index 2baf7c4..feed1e2 100644 --- a/src/main.h +++ b/src/main.h @@ -107,6 +107,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 nTime); int GetNumBlocksOfPeers(); bool IsInitialBlockDownload(); std::string GetWarnings(std::string strFor); +bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew); -- 1.7.1