PPCoin: a preliminary version of coinstake creation
authorScott Nadal <scott.nadal@gmail.com>
Sun, 15 Apr 2012 05:11:55 +0000 (06:11 +0100)
committerScott Nadal <scott.nadal@gmail.com>
Sun, 15 Apr 2012 05:11:55 +0000 (06:11 +0100)
src/main.cpp
src/wallet.cpp
src/wallet.h

index fc7ae08..950b893 100644 (file)
@@ -2958,6 +2958,8 @@ CBlock* CreateNewBlock(CWallet* pwallet)
     if (!pblock.get())
         return NULL;
 
+    pblock->nBits = GetNextWorkRequired(pindexPrev);
+
     // Create coinbase tx
     CTransaction txNew;
     txNew.vin.resize(1);
@@ -2970,7 +2972,7 @@ CBlock* CreateNewBlock(CWallet* pwallet)
 
     // ppcoin: if coinstake available add coinstake tx
     CTransaction txCoinStake;
-    if (pwallet->CreateCoinStake(txNew.vout[0].scriptPubKey, txCoinStake))
+    if (pwallet->CreateCoinStake(txNew.vout[0].scriptPubKey, pblock->nBits, txCoinStake))
         pblock->vtx.push_back(txCoinStake);
 
     // Collect memory pool transactions into the block
@@ -3092,7 +3094,6 @@ CBlock* CreateNewBlock(CWallet* pwallet)
             }
         }
     }
-    pblock->nBits          = GetNextWorkRequired(pindexPrev);
     pblock->vtx[0].vout[0].nValue = GetProofOfWorkReward(pblock->nBits);
 
     // Fill in header
index fd8e9c2..58e1baf 100644 (file)
@@ -7,6 +7,7 @@
 #include "headers.h"
 #include "db.h"
 #include "crypter.h"
+#include "checkpoints.h"
 
 using namespace std;
 
@@ -1061,8 +1062,11 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w
 }
 
 // ppcoin: create coin stake transaction
-bool CWallet::CreateCoinStake(CScript scriptPubKey, CTransaction& txNew)
+bool CWallet::CreateCoinStake(CScript scriptPubKey, unsigned int nBits, CTransaction& txNew)
 {
+    CBigNum bnTargetPerCoinDay;
+    bnTargetPerCoinDay.SetCompact(nBits);
+
     CRITICAL_BLOCK(cs_main)
     CRITICAL_BLOCK(cs_wallet)
     {
@@ -1085,19 +1089,33 @@ bool CWallet::CreateCoinStake(CScript scriptPubKey, CTransaction& txNew)
         int64 nCredit = 0;
         BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
         {
-            nCredit += pcoin.first->vout[pcoin.second].nValue;
-            // Only spend one tx for now
-            break;
+            CTxDB txdb("r");
+            CTxIndex txindex;
+            if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex))
+                continue;
+
+            // Read block header
+            CBlock block;
+            if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
+                continue;
+            if (block.GetBlockTime() + AUTO_CHECKPOINT_TRUST_SPAN > txNew.nTime)
+                continue; // only count coins from at least one week ago
+
+            int64 nValueIn = pcoin.first->vout[pcoin.second].nValue;
+            CBigNum bnCoinDay = CBigNum(nValueIn) * (txNew.nTime-pcoin.first->nTime) / COIN / (24 * 60 * 60);
+            // Calculate hash
+            CDataStream ss(SER_GETHASH, VERSION);
+            ss << nBits << block.nTime << pcoin.first->nTime << txNew.nTime;
+            if (CBigNum(Hash(ss.begin(), ss.end())) <= bnCoinDay * bnTargetPerCoinDay)
+            {
+                txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
+                nCredit += pcoin.first->vout[pcoin.second].nValue;
+                // Only spend one tx for now
+                break;
+            }
         }
         if (nCredit > nBalance - nBalanceReserve)
             return false;
-        // Fill vin
-        BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
-        {
-            txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
-            // Only spend one tx for now
-            break;
-        }
         // Calculate coin age reward
         {
             uint64 nCoinAge;
index 4beebb8..07b2b7c 100644 (file)
@@ -89,7 +89,7 @@ public:
     int64 GetStake() const;
     bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
     bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
-    bool CreateCoinStake(CScript scriptPubKey, CTransaction& txNew);
+    bool CreateCoinStake(CScript scriptPubKey, unsigned int nBits, CTransaction& txNew);
     bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
     bool BroadcastTransaction(CWalletTx& wtxNew);
     std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);