PPCoin: Coin creation model - no coinbase reward in proof-of-stake block
authorSunny King <sunnyking9999@gmail.com>
Sun, 29 Apr 2012 19:44:36 +0000 (20:44 +0100)
committerSunny King <sunnyking9999@gmail.com>
Sun, 29 Apr 2012 19:48:00 +0000 (20:48 +0100)
        Coinbase output set to empty for proof-of-stake block

src/main.cpp
src/main.h

index 9fd19e3..6116daa 100644 (file)
@@ -324,9 +324,11 @@ bool CTransaction::CheckTransaction() const
 
     // Check for negative or overflow output values
     int64 nValueOut = 0;
-    for (int i = (IsCoinStake()? 1 : 0); i < vout.size(); i++)
+    for (int i = 0; i < vout.size(); i++)
     {
         const CTxOut& txout = vout[i];
+        if (txout.IsEmpty() && (!IsCoinBase()) && (!IsCoinStake()))
+            return DoS(100, error("CTransaction::CheckTransaction() : txout empty for user transaction"));
         if (txout.nValue < 0)
             return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue negative"));
         if (txout.nValue > MAX_MONEY)
@@ -1101,7 +1103,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
 
     // ppcoin: fees are not collected by miners as in bitcoin
     // ppcoin: fees are destroyed to compensate the entire network
-    if (vtx[0].GetValueOut() > GetProofOfWorkReward(nBits))
+    if (IsProofOfWork() && vtx[0].GetValueOut() > GetProofOfWorkReward(nBits))
         return false;
     if (fDebug && GetBoolArg("-printcreation"))
         printf("ConnectBlock() : destroy=%s nFees=%"PRI64d"\n", FormatMoney(nFees).c_str(), nFees);
@@ -1496,6 +1498,10 @@ bool CBlock::CheckBlock() const
         if (vtx[i].IsCoinStake())
             return DoS(100, error("CheckBlock() : coinstake in wrong position"));
 
+    // ppcoin: coinbase output should be empty if proof-of-stake block
+    if (IsProofOfStake() && !vtx[0].vout[0].IsEmpty())
+        return error("CheckBlock() : coinbase output not empty for proof-of-stake block");
+
     // Check coinbase timestamp
     if (GetBlockTime() > (int64)vtx[0].nTime + nMaxClockDrift)
         return DoS(50, error("CheckBlock() : coinbase timestamp is too early"));
@@ -3014,6 +3020,7 @@ CBlock* CreateNewBlock(CWallet* pwallet)
         if (pwallet->CreateCoinStake(txNew.vout[0].scriptPubKey, pblock->nBits, txCoinStake))
         {
             pblock->vtx.push_back(txCoinStake);
+            pblock->vtx[0].vout[0].SetEmpty();
             break;
         }
     }
index bd07ceb..2790201 100644 (file)
@@ -360,7 +360,13 @@ public:
         return (nValue == -1);
     }
 
-    bool IsCoinStake() const
+    bool SetEmpty()
+    {
+        nValue = 0;
+        scriptPubKey.clear();
+    }
+
+    bool IsEmpty() const
     {
         return (nValue == 0 && scriptPubKey.empty());
     }
@@ -383,7 +389,7 @@ public:
 
     std::string ToString() const
     {
-        if (IsCoinStake()) return "CTxOut(coinstake)";
+        if (IsEmpty()) return "CTxOut(empty)";
         if (scriptPubKey.size() < 6)
             return "CTxOut(error)";
         return strprintf("CTxOut(nValue=%s, scriptPubKey=%s)", FormatMoney(nValue).c_str(), scriptPubKey.ToString().substr(0,30).c_str());
@@ -504,7 +510,7 @@ public:
     bool IsCoinStake() const
     {
         // ppcoin: the coin stake transaction is marked with the first output empty
-        return (vout.size() == 2 && vout[0].IsCoinStake());
+        return ((!IsCoinBase()) && vout.size() == 2 && vout[0].IsEmpty());
     }
 
     int GetSigOpCount() const
@@ -632,7 +638,8 @@ public:
     std::string ToString() const
     {
         std::string str;
-        str += strprintf("CTransaction(hash=%s, nTime=%d, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
+        str += IsCoinBase()? "Coinbase" : (IsCoinStake()? "Coinstake" : "CTransaction");
+        str += strprintf("(hash=%s, nTime=%d, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
             GetHash().ToString().substr(0,10).c_str(),
             nTime,
             nVersion,
@@ -1037,8 +1044,9 @@ public:
     bool SignBlock(const CKeyStore& keystore)
     {
         std::vector<std::pair<opcodetype, valtype> > vSolution;
+        const CTxOut& txout = IsProofOfStake()? vtx[1].vout[1] : vtx[0].vout[0];
 
-        if (!Solver(vtx[0].vout[0].scriptPubKey, vSolution))
+        if (!Solver(txout.scriptPubKey, vSolution))
             return false;
         BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
         {
@@ -1063,8 +1071,9 @@ public:
             return vchBlockSig.empty();
 
         std::vector<std::pair<opcodetype, valtype> > vSolution;
+        const CTxOut& txout = IsProofOfStake()? vtx[1].vout[1] : vtx[0].vout[0];
 
-        if (!Solver(vtx[0].vout[0].scriptPubKey, vSolution))
+        if (!Solver(txout.scriptPubKey, vSolution))
             return false;
         BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
         {