return true;
}
+ bool IsPendingSyncCheckpoint(uint256 hashBlock)
+ {
+ CRITICAL_BLOCK(cs_hashSyncCheckpoint)
+ return ((!checkpointMessagePending.IsNull()) && hashBlock == checkpointMessagePending.hashCheckpoint);
+ }
+
// ppcoin: automatic checkpoint (represented by height of checkpoint)
int nAutoCheckpoint = 0;
int nBranchPoint = 0; // branch point to alternative branch
bool AcceptPendingSyncCheckpoint();
uint256 AutoSelectSyncCheckpoint();
bool CheckSync(const uint256& hashBlock, const CBlockIndex* pindexPrev);
+ bool IsPendingSyncCheckpoint(uint256 hashBlock);
// ppcoin: automatic checkpoint
extern int nAutoCheckpoint;
// ppcoin: check proof-of-stake
// Limited duplicity on stake: prevents block flood attack
// Duplicate stake allowed only when there is orphan child block
- if (pblock->IsProofOfStake() && setStakeSeen.count(pblock->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash))
+ if (pblock->IsProofOfStake() && setStakeSeen.count(pblock->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash) && !Checkpoints::IsPendingSyncCheckpoint(hash))
return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for block %s", pblock->GetProofOfStake().first.ToString().c_str(), pblock->GetProofOfStake().second, hash.ToString().c_str());
// Preliminary checks
{
// Limited duplicity on stake: prevents block flood attack
// Duplicate stake allowed only when there is orphan child block
- if (setStakeSeenOrphan.count(pblock2->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash))
+ if (setStakeSeenOrphan.count(pblock2->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash) && !Checkpoints::IsPendingSyncCheckpoint(hash))
return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for orphan block %s", pblock2->GetProofOfStake().first.ToString().c_str(), pblock2->GetProofOfStake().second, hash.ToString().c_str());
else
setStakeSeenOrphan.insert(pblock2->GetProofOfStake());