PPCoin: target adjustment for both proof-of-work and proof-of-stake
authorSunny King <sunnyking9999@gmail.com>
Mon, 16 Apr 2012 22:11:12 +0000 (23:11 +0100)
committerSunny King <sunnyking9999@gmail.com>
Mon, 16 Apr 2012 22:11:12 +0000 (23:11 +0100)
src/db.cpp
src/main.cpp
src/main.h

index 6eece05..d4dae8d 100644 (file)
@@ -540,6 +540,8 @@ bool CTxDB::LoadBlockIndex()
             pindexNew->nBlockPos      = diskindex.nBlockPos;
             pindexNew->nChainTrust    = diskindex.nChainTrust;
             pindexNew->nHeight        = diskindex.nHeight;
+            pindexNew->nCheckpoint    = diskindex.nCheckpoint;
+            pindexNew->fProofOfStake  = diskindex.fProofOfStake;
             pindexNew->nVersion       = diskindex.nVersion;
             pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
             pindexNew->nTime          = diskindex.nTime;
index 950b893..818c677 100644 (file)
@@ -731,13 +731,27 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 nTime)
     return bnResult.GetCompact();
 }
 
-unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast)
+// ppcoin: find last block index up to pindex
+const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake)
+{
+    while (pindex && (pindex->IsProofOfStake() != fProofOfStake))
+        pindex = pindex->pprev;
+    return pindex;
+}
+
+unsigned int static GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
 {
     // Genesis block and first block
     if (pindexLast == NULL || pindexLast->pprev == NULL)
         return bnProofOfWorkLimit.GetCompact();
 
-    int64 nActualSpacing = pindexLast->GetBlockTime() - pindexLast->pprev->GetBlockTime();
+    const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
+    if (pindexPrev == NULL) 
+        return bnProofOfWorkLimit.GetCompact();
+    const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
+    if (pindexPrevPrev == NULL)
+        return bnProofOfWorkLimit.GetCompact();
+    int64 nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();
 
     // ppcoin: target change every block
     // ppcoin: retarget with exponential moving toward target spacing
@@ -1527,8 +1541,8 @@ bool CBlock::AcceptBlock()
     int nHeight = pindexPrev->nHeight+1;
 
     // Check proof of work
-    if (nBits != GetNextWorkRequired(pindexPrev))
-        return DoS(100, error("AcceptBlock() : incorrect proof of work"));
+    if (nBits != GetNextTargetRequired(pindexPrev, IsProofOfStake()))
+        return DoS(100, error("AcceptBlock() : incorrect proof-of-work/proof-of-stake"));
 
     // Check timestamp against prev
     if (GetBlockTime() <= pindexPrev->GetMedianTimePast() || GetBlockTime() + nMaxClockDrift < pindexPrev->GetBlockTime())
@@ -2958,8 +2972,6 @@ CBlock* CreateNewBlock(CWallet* pwallet)
     if (!pblock.get())
         return NULL;
 
-    pblock->nBits = GetNextWorkRequired(pindexPrev);
-
     // Create coinbase tx
     CTransaction txNew;
     txNew.vin.resize(1);
@@ -2971,9 +2983,12 @@ CBlock* CreateNewBlock(CWallet* pwallet)
     pblock->vtx.push_back(txNew);
 
     // ppcoin: if coinstake available add coinstake tx
+    pblock->nBits = GetNextTargetRequired(pindexPrev, true);
     CTransaction txCoinStake;
     if (pwallet->CreateCoinStake(txNew.vout[0].scriptPubKey, pblock->nBits, txCoinStake))
         pblock->vtx.push_back(txCoinStake);
+    else
+        pblock->nBits = GetNextTargetRequired(pindexPrev, false);
 
     // Collect memory pool transactions into the block
     int64 nFees = 0;
index ea73a0f..4e82e1b 100644 (file)
@@ -1116,6 +1116,7 @@ public:
     uint64 nChainTrust;// ppcoin: trust score of chain, in the unit of coin-days
     int nHeight;
     int nCheckpoint;    // ppcoin: chain auto checkpoint height
+    bool fProofOfStake; // ppcoin: is the block of proof-of-stake type
 
     // block header
     int nVersion;
@@ -1135,6 +1136,7 @@ public:
         nHeight = 0;
         nChainTrust = 0;
         nCheckpoint = 0;
+        fProofOfStake = true;
 
         nVersion       = 0;
         hashMerkleRoot = 0;
@@ -1153,6 +1155,7 @@ public:
         nHeight = 0;
         nChainTrust = 0;
         nCheckpoint = 0;
+        fProofOfStake = block.IsProofOfStake();
 
         nVersion       = block.nVersion;
         hashMerkleRoot = block.hashMerkleRoot;
@@ -1242,12 +1245,20 @@ public:
         return pindex->GetMedianTimePast();
     }
 
+    bool IsProofOfWork() const
+    {
+        return !fProofOfStake;
+    }
 
+    bool IsProofOfStake() const
+    {
+        return fProofOfStake;
+    }
 
     std::string ToString() const
     {
-        return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nChainTrust=%"PRI64d" nHeight=%d, nCheckpoint=%d, merkle=%s, hashBlock=%s)",
-            pprev, pnext, nFile, nBlockPos, nChainTrust, nHeight, nCheckpoint,
+        return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nChainTrust=%"PRI64d" nHeight=%d, nCheckpoint=%d, fProofOfStake=%d merkle=%s, hashBlock=%s)",
+            pprev, pnext, nFile, nBlockPos, nChainTrust, nHeight, nCheckpoint, fProofOfStake,
             hashMerkleRoot.ToString().substr(0,10).c_str(),
             GetBlockHash().ToString().substr(0,20).c_str());
     }
@@ -1292,6 +1303,7 @@ public:
         READWRITE(nChainTrust);
         READWRITE(nHeight);
         READWRITE(nCheckpoint);
+        READWRITE(fProofOfStake);
 
         // block header
         READWRITE(this->nVersion);