PPCoin: Lower coinstake combine threshold to improve security
authorSunny King <sunnyking9999@gmail.com>
Sat, 25 Aug 2012 18:19:09 +0000 (19:19 +0100)
committerSunny King <sunnyking9999@gmail.com>
Sat, 25 Aug 2012 18:19:09 +0000 (19:19 +0100)
src/main.cpp
src/main.h
src/wallet.cpp

index c4d7404..0390b9c 100644 (file)
@@ -822,7 +822,7 @@ uint256 WantedByOrphan(const CBlock* pblockOrphan)
     return pblockOrphan->hashPrevBlock;
 }
 
-int64 static GetProofOfWorkReward(unsigned int nBits)
+int64 GetProofOfWorkReward(unsigned int nBits)
 {
     CBigNum bnSubsidyLimit = MAX_MINT_PROOF_OF_WORK;
     CBigNum bnTarget;
@@ -1673,7 +1673,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
 
 
 // ppcoin: coinstake must meet hash target according to the protocol:
-// input 0 must meet the formula
+// kernel (input 0) must meet the formula
 //     hash(nBits + txPrev.block.nTime + txPrev.offset + txPrev.nTime + txPrev.vout.n + nTime) < bnTarget * nCoinDay
 // this ensures that the chance of getting a coinstake is proportional to the
 // amount of coin age one owns.
@@ -1700,7 +1700,7 @@ bool CTransaction::CheckProofOfStake(unsigned int nBits) const
     if (!IsCoinStake())
         return true;
 
-    // Input 0 must match the stake hash target per coin age (nBits)
+    // Kernel (input 0) must match the stake hash target per coin age (nBits)
     const CTxIn& txin = vin[0];
 
     // First try finding the previous transaction in database
index 5232a93..c7f518a 100644 (file)
@@ -105,6 +105,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
 void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
 bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
 bool CheckProofOfWork(uint256 hash, unsigned int nBits);
+int64 GetProofOfWorkReward(unsigned int nBits);
 int64 GetProofOfStakeReward(int64 nCoinAge);
 unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
 int GetNumBlocksOfPeers();
index c5178d2..4dbc6af 100644 (file)
@@ -1299,20 +1299,24 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, CTr
     }
     if (nCredit == 0 || nCredit > nBalance - nReserveBalance)
         return false;
+    // The following combine threshold is important to network security
+    // Should not be adjusted if you don't understand the consequences
+    int64 nCombineThreshold = GetProofOfWorkReward(GetLastBlockIndex(pindexBest, false)->nBits);
     BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
     {
         // Attempt to add more inputs
         // Only add coins of the same key/address as kernel
-        if (pcoin.first->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel && pcoin.first->GetHash() != txNew.vin[0].prevout.hash)
+        if ((pcoin.first->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel || pcoin.first->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey)
+            && pcoin.first->GetHash() != txNew.vin[0].prevout.hash)
         {
             // Stop adding more inputs if value is already pretty significant
-            if (nCredit > MAX_MINT_PROOF_OF_WORK)
+            if (nCredit > nCombineThreshold)
                 break;
             // Stop adding inputs if reached reserve limit
             if (nCredit + pcoin.first->vout[pcoin.second].nValue > nBalance - nReserveBalance)
                 break;
             // Do not add additional significant input
-            if (pcoin.first->vout[pcoin.second].nValue > MAX_MINT_PROOF_OF_WORK)
+            if (pcoin.first->vout[pcoin.second].nValue > nCombineThreshold)
                 continue;
             txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
             nCredit += pcoin.first->vout[pcoin.second].nValue;