map<COutPoint, CInPoint> mapNextTx;
map<uint256, CBlockIndex*> mapBlockIndex;
-set<COutPoint> setStakeSeen;
+set<pair<COutPoint, unsigned int> > setStakeSeen;
uint256 hashGenesisBlock("0x000000006d52486334316794cc38ffeb7ebf35a7ebd661fd39f5f46b0d001575");
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
const int nInitialBlockThreshold = 120; // Regard blocks up until N-threshold as "initial download"
map<uint256, CBlock*> mapOrphanBlocks;
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
-set<COutPoint> setStakeSeenOrphan;
+set<pair<COutPoint, unsigned int> > setStakeSeenOrphan;
map<uint256, CDataStream*> mapOrphanTransactions;
multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
return error("AddToBlockIndex() : new CBlockIndex failed");
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
if (pindexNew->fProofOfStake)
- setStakeSeen.insert(pindexNew->prevoutStake);
+ setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime));
pindexNew->phashBlock = &((*mi).first);
map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
if (GetBlockTime() > (int64)vtx[0].nTime + nMaxClockDrift)
return DoS(50, error("CheckBlock() : coinbase timestamp is too early"));
+ // Check coinstake timestamp
+ if (IsProofOfStake() && GetBlockTime() > (int64)vtx[1].nTime + nMaxClockDrift)
+ return DoS(50, error("CheckBlock() : coinstake timestamp is too early"));
+
// Check transactions
BOOST_FOREACH(const CTransaction& tx, vtx)
{
if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 140700))
pnode->PushInventory(CInv(MSG_BLOCK, hash));
+ // ppcoin: check pending sync-checkpoint
+ Checkpoints::AcceptPendingSyncCheckpoint(hash);
+
return true;
}
// 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))
- return error("ProcessBlock() : duplicate proof-of-stake (%s) for block %s", pblock->GetProofOfStake().ToString().c_str(), hash.ToString().c_str());
+ 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
if (!pblock->CheckBlock())
// 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))
- return error("ProcessBlock() : duplicate proof-of-stake (%s) for orphan block %s", pblock2->GetProofOfStake().ToString().c_str(), hash.ToString().c_str());
+ 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());
}
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
item.second.RelayTo(pfrom);
+ // ppcoin: relay sync-checkpoint
+ CRITICAL_BLOCK(Checkpoints::cs_hashSyncCheckpoint)
+ if (!Checkpoints::checkpointMessage.IsNull())
+ Checkpoints::checkpointMessage.RelayTo(pfrom);
+
pfrom->fSuccessfullyConnected = true;
printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight);
}
}
+ else if (strCommand == "checkpoint")
+ {
+ CSyncCheckpoint checkpoint;
+ vRecv >> checkpoint;
+
+ if (checkpoint.ProcessSyncCheckpoint(pfrom))
+ {
+ // Relay
+ pfrom->hashCheckpointKnown = checkpoint.hashCheckpoint;
+ CRITICAL_BLOCK(cs_vNodes)
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ checkpoint.RelayTo(pnode);
+ }
+ }
else
{
pblock->vtx.push_back(txNew);
// ppcoin: if coinstake available add coinstake tx
- static unsigned int nLastCoinStakeCheckTime = GetAdjustedTime() - nMaxClockDrift; // only initialized at startup
+ static unsigned int nLastCoinStakeCheckTime = GetAdjustedTime() - nMaxClockDrift + 60; // only initialized at startup
CBlockIndex* pindexPrev = pindexBest;
while (nLastCoinStakeCheckTime < GetAdjustedTime())
{
CTransaction txCoinStake;
CRITICAL_BLOCK(cs)
{
- nLastCoinStakeCheckTime++;
+ // mining may have been suspended for a while so
+ // need to take max to satisfy the timestamp protocol
+ nLastCoinStakeCheckTime = max(++nLastCoinStakeCheckTime, (unsigned int) (GetAdjustedTime() - nMaxClockDrift + 60));
txCoinStake.nTime = nLastCoinStakeCheckTime;
}
if (pwallet->CreateCoinStake(pblock->nBits, txCoinStake))