PPCoin: Additional block/coinbase timestamp rules; various minor cleanups
authorSunny King <p2pcoin@gmail.com>
Fri, 6 Jan 2012 03:09:03 +0000 (03:09 +0000)
committerSunny King <p2pcoin@gmail.com>
Fri, 6 Jan 2012 03:09:03 +0000 (03:09 +0000)
src/checkpoints.cpp
src/checkpoints.h
src/main.cpp

index 8898ca1..69024e2 100644 (file)
@@ -59,13 +59,13 @@ namespace Checkpoints
         return error("Checkpoints: failed to find any ancestor on main chain for the new block - internal error");
     }
 
-    // ppcoin: get next auto checkpoint in the chain
+    // ppcoin: get next chain checkpoint
     int GetNextChainCheckpoint(const CBlockIndex *pindexLast)
     {
         CBigNum bnTarget;
         CBigNum bnTargetMax = 0;  // max target of all blocks since checkpoint
         CBigNum bnTargetMin = 0;  // min target of all candidate checkpoints
-        int nMinTargetHeight = 0; // min target height since checkpoint
+        int nMinTargetHeight = 0; // min target height of candidate checkpoints
         int nCheckpointMin = 0;   // minimum candidate checkpoint
         int nCheckpointMax = 0;   // maximum candidate checkpoint
         int nDepth = pindexLast->nHeight - pindexLast->nCheckpoint;
@@ -103,15 +103,21 @@ namespace Checkpoints
         if (bnTargetMin * 100 > bnTargetMax * 90)
             return nCheckpointMax;
         if (bnTarget * 100 > bnTargetMax * 90)
-            return std::min(nCheckpointMax, nMinTargetHeight);
+            return nMinTargetHeight;
         else
             return nCheckpointMin;
     }
 
+    // ppcoin: get next auto checkpoint from the new chain checkpoint
+    int GetNextAutoCheckpoint(int nCheckpoint)
+    {
+        return (std::max(nAutoCheckpoint, nCheckpoint));
+    }
+
     // ppcoin: advance to next automatic checkpoint
     void AdvanceAutoCheckpoint(int nCheckpoint)
     {
-        nAutoCheckpoint = std::max(nAutoCheckpoint, nCheckpoint);
+        nAutoCheckpoint = GetNextAutoCheckpoint(nCheckpoint);
         printf("Checkpoints: auto checkpoint now at height=%d\n", nAutoCheckpoint);
     }
 
index 21a4b4a..241039d 100644 (file)
@@ -29,6 +29,7 @@ namespace Checkpoints
     bool CheckAuto(const CBlockIndex *pindex);
 
     int  GetNextChainCheckpoint(const CBlockIndex *pindex);
+    int  GetNextAutoCheckpoint(int nCheckpoint);
     void AdvanceAutoCheckpoint(int nCheckpoint);
 
     // Return conservative estimate of total number of blocks, 0 if unknown
index f44e7f5..38f2a93 100644 (file)
@@ -668,7 +668,7 @@ int64 static GetBlockValue(unsigned int nBits, int64 nFees)
         CBigNum bnMidValue = (bnLowerBound + bnUpperBound) / 2;
         if (fDebug && GetBoolArg("-printcreation"))
             printf("GetBlockValue() : lower=%d upper=%d mid=%d\n", bnLowerBound.getint(), bnUpperBound.getint(), bnMidValue.getint());
-        if (bnMidValue * bnMidValue * bnMidValue * bnMidValue > bnSubsidyLimit * bnSubsidyLimit * bnSubsidyLimit * bnSubsidyLimit * bnTarget / bnTargetLimit)
+        if (bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnTargetLimit > bnSubsidyLimit * bnSubsidyLimit * bnSubsidyLimit * bnSubsidyLimit * bnTarget)
             bnUpperBound = bnMidValue;
         else
             bnLowerBound = bnMidValue;
@@ -685,6 +685,7 @@ int64 static GetBlockValue(unsigned int nBits, int64 nFees)
 static const int64 nTargetTimespan = 7 * 24 * 60 * 60; // one week
 static const int64 nTargetSpacing = 10 * 60;
 static const int64 nInterval = nTargetTimespan / nTargetSpacing;
+static const int64 nMaxClockDrift = 2 * 60 * 60; // 2 hours
 
 //
 // minimum amount of work that could possibly be required nTime after
@@ -1124,7 +1125,7 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
     }
     if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash()))
         return error("Reorganize() : WriteHashBestChain failed");
-    if (!txdb.WriteAutoCheckpoint(pindexNew->nCheckpoint))
+    if (!txdb.WriteAutoCheckpoint(Checkpoints::GetNextAutoCheckpoint(pindexNew->nCheckpoint)))
         return error("Reorganize() : WriteAutoCheckpoint failed");
 
     // Make sure it's successfully written to disk before changing memory structure
@@ -1161,7 +1162,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
     if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)
     {
         txdb.WriteHashBestChain(hash);
-        txdb.WriteAutoCheckpoint(pindexNew->nCheckpoint);
+        txdb.WriteAutoCheckpoint(Checkpoints::GetNextAutoCheckpoint(pindexNew->nCheckpoint));
         if (!txdb.TxnCommit())
             return error("SetBestChain() : TxnCommit failed");
         pindexGenesisBlock = pindexNew;
@@ -1169,7 +1170,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
     else if (hashPrevBlock == hashBestChain)
     {
         // Adding to current best branch
-        if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash) || !txdb.WriteAutoCheckpoint(pindexNew->nCheckpoint))
+        if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash) || !txdb.WriteAutoCheckpoint(Checkpoints::GetNextAutoCheckpoint(pindexNew->nCheckpoint)))
         {
             txdb.TxnAbort();
             InvalidChainFound(pindexNew);
@@ -1340,7 +1341,7 @@ bool CBlock::CheckBlock() const
         return DoS(50, error("CheckBlock() : proof of work failed"));
 
     // Check timestamp
-    if (GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
+    if (GetBlockTime() > GetAdjustedTime() + nMaxClockDrift)
         return error("CheckBlock() : block timestamp too far in the future");
 
     // First transaction must be coinbase, the rest must not be
@@ -1350,6 +1351,10 @@ bool CBlock::CheckBlock() const
         if (vtx[i].IsCoinBase())
             return DoS(100, error("CheckBlock() : more than one coinbase"));
 
+    // Check coinbase timestamp
+    if (GetBlockTime() > (int64)vtx[0].nTime + nMaxClockDrift)
+        return DoS(50, error("CheckBlock() : coinbase timestamp is too early"));
+
     // Check transactions
     BOOST_FOREACH(const CTransaction& tx, vtx)
     {
@@ -1390,7 +1395,7 @@ bool CBlock::AcceptBlock()
         return DoS(100, error("AcceptBlock() : incorrect proof of work"));
 
     // Check timestamp against prev
-    if (GetBlockTime() <= pindexPrev->GetMedianTimePast())
+    if (GetBlockTime() <= pindexPrev->GetMedianTimePast() || GetBlockTime() + nMaxClockDrift < pindexPrev->GetBlockTime())
         return error("AcceptBlock() : block's timestamp is too early");
 
     // Check that all transactions are finalized
@@ -1610,7 +1615,7 @@ bool LoadBlockIndex(bool fAllowNew)
         txNew.vin.resize(1);
         txNew.vout.resize(1);
         txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
-        txNew.vout[0].nValue = 9999 * COIN;
+        txNew.vout[0].nValue = GetBlockValue(bnProofOfWorkLimit.GetCompact(), 0);
         txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
         CBlock block;
         block.vtx.push_back(txNew);
@@ -2948,6 +2953,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
     pblock->hashMerkleRoot = pblock->BuildMerkleTree();
     pblock->nTime          = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
     pblock->nTime          = max(pblock->GetBlockTime(), pblock->GetMaxTransactionTime());
+    pblock->nTime          = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime() - nMaxClockDrift);
     pblock->nNonce         = 0;
 
     return pblock.release();
@@ -3191,7 +3197,10 @@ void static BitcoinMiner(CWallet *pwallet)
             // Update nTime every few seconds
             pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
             pblock->nTime = max(pblock->GetBlockTime(), pblock->GetMaxTransactionTime()); 
+            pblock->nTime = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime() - nMaxClockDrift);
             nBlockTime = ByteReverse(pblock->nTime);
+            if (pblock->GetBlockTime() >= (int64)pblock->vtx[0].nTime + nMaxClockDrift)
+                break;  // need to update coinbase timestamp
         }
     }
 }