{
txdb.TxnAbort();
hashInvalidCheckpoint = hashPendingCheckpoint;
- return error("ProcessSyncCheckpoint: Reorganize failed for sync checkpoint %s", hashPendingCheckpoint.ToString().c_str());
+ return error("AcceptPendingSyncCheckpoint: Reorganize failed for sync checkpoint %s", hashPendingCheckpoint.ToString().c_str());
}
}
txdb.Close();
return false;
}
+ // Automatically select a suitable sync-checkpoint
+ uint256 AutoSelectSyncCheckpoint()
+ {
+ // Proof-of-work blocks are immediately checkpointed
+ // to defend against 51% attack which rejects other miners block
+
+ // Select the last proof-of-work block
+ const CBlockIndex *pindex = GetLastBlockIndex(pindexBest, false);
+ // Search forward for a block within max span and maturity window
+ while (pindex->pnext && (pindex->GetBlockTime() + CHECKPOINT_MAX_SPAN <= pindexBest->GetBlockTime() || pindex->nHeight + COINBASE_MATURITY <= pindexBest->nHeight))
+ pindex = pindex->pnext;
+ return pindex->GetBlockHash();
+ }
+
+ // Check against synchronized checkpoint
bool CheckSync(const uint256& hashBlock, const CBlockIndex* pindexPrev)
{
if (fTestNet) return true; // Testnet has no checkpoints
#include "util.h"
#define STAKE_MIN_AGE (60 * 60 * 24) // minimum age for coin age
+#define CHECKPOINT_MAX_SPAN (60 * 60 * 4) // max 4 hours before latest block
class uint256;
class CBlockIndex;
CBlockIndex* GetLastSyncCheckpoint();
bool WriteSyncCheckpoint(const uint256& hashCheckpoint);
bool AcceptPendingSyncCheckpoint();
+ uint256 AutoSelectSyncCheckpoint();
bool CheckSync(const uint256& hashBlock, const CBlockIndex* pindexPrev);
bool WantedByPendingSyncCheckpoint(uint256 hashBlock);
bool ResetSyncCheckpoint();
// ppcoin: if responsible for sync-checkpoint send it
if (pfrom && !CSyncCheckpoint::strMasterPrivKey.empty())
- Checkpoints::SendSyncCheckpoint(hashBestChain);
+ Checkpoints::SendSyncCheckpoint(Checkpoints::AutoSelectSyncCheckpoint());
return true;
}