Remove print() methods: all unused
[novacoin.git] / src / miner.cpp
index f12376a..aae9589 100644 (file)
@@ -7,6 +7,7 @@
 #include "txdb.h"
 #include "miner.h"
 #include "kernel.h"
+#include "kernel_worker.h"
 
 using namespace std;
 
@@ -69,14 +70,6 @@ public:
         ptx = ptxIn;
         dPriority = dFeePerKb = 0;
     }
-
-    void print() const
-    {
-        printf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n",
-               ptx->GetHash().ToString().substr(0,10).c_str(), dPriority, dFeePerKb);
-        BOOST_FOREACH(uint256 hash, setDependsOn)
-            printf("   setDependsOn %s\n", hash.ToString().substr(0,10).c_str());
-    }
 };
 
 
@@ -146,18 +139,18 @@ CBlock* CreateNewBlock(CWallet* pwallet, CTransaction *txCoinStake)
     }
 
     // Largest block you're willing to create:
-    unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2);
+    unsigned int nBlockMaxSize = GetArgUInt("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2);
     // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
-    nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
+    nBlockMaxSize = std::max(1000u, std::min(MAX_BLOCK_SIZE-1000u, nBlockMaxSize));
 
     // How much of the block should be dedicated to high-priority transactions,
     // included regardless of the fees they pay
-    unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000);
+    unsigned int nBlockPrioritySize = GetArgUInt("-blockprioritysize", 27000);
     nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
 
     // Minimum block size you want to create; block will be filled with free transactions
     // until there are no more or the block reaches this size:
-    unsigned int nBlockMinSize = GetArg("-blockminsize", 0);
+    unsigned int nBlockMinSize = GetArgUInt("-blockminsize", 0);
     nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
 
     // Fee-per-kilobyte amount considered the same as "free"
@@ -530,10 +523,10 @@ bool CheckStake(CBlock* pblock, CWallet& wallet)
 }
 
 // Precalculated SHA256 contexts and metadata
-// (txid, vout.n) => (SHA256_CTX, (tx.nTime, nAmount))
-typedef std::map<std::pair<uint256, unsigned int>, std::pair<SHA256_CTX, std::pair<uint32_t, uint64_t> > > MidstateMap;
+// (txid, vout.n) => (kernel, (tx.nTime, nAmount))
+typedef std::map<std::pair<uint256, unsigned int>, std::pair<std::vector<unsigned char>, std::pair<uint32_t, uint64_t> > > MidstateMap;
 
-// Fill the inputs map with precalculated states and metadata
+// Fill the inputs map with precalculated contexts and metadata
 bool FillMap(CWallet *pwallet, uint32_t nUpperTime, MidstateMap &inputsMap)
 {
     // Choose coins to use
@@ -589,22 +582,24 @@ bool FillMap(CWallet *pwallet, uint32_t nUpperTime, MidstateMap &inputsMap)
             if (nStakeMinAge + block.nTime > nTime - nMaxStakeSearchInterval)
                 continue;
 
+            // Get stake modifier
             uint64_t nStakeModifier = 0;
             if (!GetKernelStakeModifier(block.GetHash(), nStakeModifier))
                 continue;
 
-            SHA256_CTX ctx;
-            // Calculate midstate using (modifier, block time, tx offset, tx time, output number)
-            GetKernelMidstate(nStakeModifier, block.nTime, txindex.pos.nTxPos - txindex.pos.nBlockPos, pcoin->first->nTime, pcoin->second, ctx);
+            // Build static part of kernel
+            CDataStream ssKernel(SER_GETHASH, 0);
+            ssKernel << nStakeModifier;
+            ssKernel << block.nTime << (txindex.pos.nTxPos - txindex.pos.nBlockPos) << pcoin->first->nTime << pcoin->second;
 
-            // (txid, vout.n) => (SHA256_CTX, (tx.nTime, nAmount))
-            inputsMap[key] = make_pair(ctx, make_pair(pcoin->first->nTime, pcoin->first->vout[pcoin->second].nValue));
+            // (txid, vout.n) => (kernel, (tx.nTime, nAmount))
+            inputsMap[key] = make_pair(std::vector<unsigned char>(ssKernel.begin(), ssKernel.end()), make_pair(pcoin->first->nTime, pcoin->first->vout[pcoin->second].nValue));
         }
 
         nStakeInputsMapSize = inputsMap.size();
 
         if (fDebug)
-            printf("Stake miner: map of %" PRIu64 " precalculated contexts has been created\n", nStakeInputsMapSize);
+            printf("FillMap() : Map of %" PRIu64 " precalculated contexts has been created by stake miner\n", nStakeInputsMapSize);
     }
 
     return true;
@@ -624,13 +619,13 @@ bool ScanMap(const MidstateMap &inputsMap, uint32_t nBits, MidstateMap::key_type
         interval.first = nSearchTime;
         interval.second = nSearchTime - min(nSearchTime-nLastCoinStakeSearchTime, nMaxStakeSearchInterval);
 
-        // (txid, nout) => (SHA256_CTX, (tx.nTime, nAmount))
+        // (txid, nout) => (kernel, (tx.nTime, nAmount))
         for(MidstateMap::const_iterator input = inputsMap.begin(); input != inputsMap.end(); input++)
         {
-            SHA256_CTX ctx = input->second.first;
+            unsigned char *kernel = (unsigned char *) &input->second.first[0];
 
             // scan(State, Bits, Time, Amount, ...)
-            if (ScanMidstateBackward(ctx, nBits, input->second.second.first, input->second.second.second, interval, solution))
+            if (ScanKernelBackward(kernel, nBits, input->second.second.first, input->second.second.second, interval, solution))
             {
                 // Solution found
                 LuckyInput = input->first; // (txid, nout)
@@ -649,12 +644,14 @@ bool ScanMap(const MidstateMap &inputsMap, uint32_t nBits, MidstateMap::key_type
     return false;
 }
 
-void StakeMiner(CWallet *pwallet)
+// Stake miner thread
+void ThreadStakeMiner(void* parg)
 {
     SetThreadPriority(THREAD_PRIORITY_LOWEST);
 
     // Make this thread recognisable as the mining thread
     RenameThread("novacoin-miner");
+    CWallet* pwallet = (CWallet*)parg;
 
     MidstateMap inputsMap;
     if (!FillMap(pwallet, GetAdjustedTime(), inputsMap))
@@ -665,107 +662,128 @@ void StakeMiner(CWallet *pwallet)
     CBlockIndex* pindexPrev = pindexBest;
     uint32_t nBits = GetNextTargetRequired(pindexPrev, true);
 
-    while (true)
+    printf("ThreadStakeMinter started\n");
+
+    try
     {
-        if (fShutdown)
-            return;
+        vnThreadsRunning[THREAD_MINTER]++;
 
-        while (pwallet->IsLocked())
-        {
-            Sleep(1000);
-            if (fShutdown)
-                return;
-        }
+        MidstateMap::key_type LuckyInput;
+        std::pair<uint256, uint32_t> solution;
 
-        while (vNodes.empty() || IsInitialBlockDownload())
+        // Main miner loop
+        do
         {
-            fTrySync = true;
-
-            Sleep(1000);
             if (fShutdown)
-                return;
-        }
+                goto _endloop;
 
-        if (fTrySync)
-        {
-            fTrySync = false;
-            if (vNodes.size() < 3 || nBestHeight < GetNumBlocksOfPeers())
+            while (pwallet->IsLocked())
             {
                 Sleep(1000);
-                continue;
+                if (fShutdown)
+                    goto _endloop; // Don't be afraid to use a goto if that's the best option.
             }
-        }
 
-        MidstateMap::key_type LuckyInput;
-        std::pair<uint256, uint32_t> solution;
-
-        if (ScanMap(inputsMap, nBits, LuckyInput, solution))
-        {
-            SetThreadPriority(THREAD_PRIORITY_NORMAL);
-
-            // Remove lucky input from the map
-            inputsMap.erase(inputsMap.find(LuckyInput));
+            while (vNodes.empty() || IsInitialBlockDownload())
+            {
+                fTrySync = true;
 
-            CKey key;
-            CTransaction txCoinStake;
+                Sleep(1000);
+                if (fShutdown)
+                    goto _endloop;
+            }
 
-            // Create new coinstake transaction
-            if (!pwallet->CreateCoinStake(LuckyInput.first, LuckyInput.second, solution.second, nBits, txCoinStake, key))
+            if (fTrySync)
             {
-                string strMessage = _("Warning: Unable to create coinstake transaction, see debug.log for the details. Mining thread has been stopped.");
-                strMiscWarning = strMessage;
-                printf("*** %s\n", strMessage.c_str());
-
-                return;
+                // Don't try mine blocks unless we're at the top of chain and have at least three p2p connections.
+                fTrySync = false;
+                if (vNodes.size() < 3 || nBestHeight < GetNumBlocksOfPeers())
+                {
+                    Sleep(1000);
+                    continue;
+                }
             }
 
-            // Now we have new coinstake, it's time to create the block ...
-            CBlock* pblock;
-            pblock = CreateNewBlock(pwallet, &txCoinStake);
-            if (!pblock)
+            if (ScanMap(inputsMap, nBits, LuckyInput, solution))
             {
-                string strMessage = _("Warning: Unable to allocate memory for the new block object. Mining thread has been stopped.");
-                strMiscWarning = strMessage;
-                printf("*** %s\n", strMessage.c_str());
+                SetThreadPriority(THREAD_PRIORITY_NORMAL);
 
-                return;
-            }
+                // Remove lucky input from the map
+                inputsMap.erase(inputsMap.find(LuckyInput));
 
-            unsigned int nExtraNonce = 0;
-            IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
+                CKey key;
+                CTransaction txCoinStake;
 
-            // ... and sign it
-            if (!key.Sign(pblock->GetHash(), pblock->vchBlockSig))
-            {
-                string strMessage = _("Warning: Proof-of-Stake miner is unable to sign the block (locked wallet?). Mining thread has been stopped.");
-                strMiscWarning = strMessage;
-                printf("*** %s\n", strMessage.c_str());
+                // Create new coinstake transaction
+                if (!pwallet->CreateCoinStake(LuckyInput.first, LuckyInput.second, solution.second, nBits, txCoinStake, key))
+                {
+                    string strMessage = _("Warning: Unable to create coinstake transaction, see debug.log for the details. Mining thread has been stopped.");
+                    strMiscWarning = strMessage;
+                    printf("*** %s\n", strMessage.c_str());
 
-                return;
-            }
+                    break;
+                }
 
-            CheckStake(pblock, *pwallet);
-            SetThreadPriority(THREAD_PRIORITY_LOWEST);
-            Sleep(500);
-        }
+                // Now we have new coinstake, it's time to create the block ...
+                CBlock* pblock;
+                pblock = CreateNewBlock(pwallet, &txCoinStake);
+                if (!pblock)
+                {
+                    string strMessage = _("Warning: Unable to allocate memory for the new block object. Mining thread has been stopped.");
+                    strMiscWarning = strMessage;
+                    printf("*** %s\n", strMessage.c_str());
 
-        if (pindexPrev != pindexBest)
-        {
-            // The best block has been changed, we need to refill the map
-            if (FillMap(pwallet, GetAdjustedTime(), inputsMap))
-            {
-                pindexPrev = pindexBest;
-                nBits = GetNextTargetRequired(pindexPrev, true);
+                    break;
+                }
+
+                unsigned int nExtraNonce = 0;
+                IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
+
+                // ... and sign it
+                if (!key.Sign(pblock->GetHash(), pblock->vchBlockSig))
+                {
+                    string strMessage = _("Warning: Proof-of-Stake miner is unable to sign the block (locked wallet?). Mining thread has been stopped.");
+                    strMiscWarning = strMessage;
+                    printf("*** %s\n", strMessage.c_str());
+
+                    break;
+                }
+
+                CheckStake(pblock, *pwallet);
+                SetThreadPriority(THREAD_PRIORITY_LOWEST);
+                Sleep(500);
             }
-            else
+
+            if (pindexPrev != pindexBest)
             {
-                // Clear existent data if FillMap failed
-                inputsMap.clear();
+                // The best block has been changed, we need to refill the map
+                if (FillMap(pwallet, GetAdjustedTime(), inputsMap))
+                {
+                    pindexPrev = pindexBest;
+                    nBits = GetNextTargetRequired(pindexPrev, true);
+                }
+                else
+                {
+                    // Clear existent data if FillMap failed
+                    inputsMap.clear();
+                }
             }
-        }
 
-        Sleep(500);
+            Sleep(500);
+
+            _endloop:
+                (void)0; // do nothing
+        }
+        while(!fShutdown);
 
-        continue;
+        vnThreadsRunning[THREAD_MINTER]--;
+    }
+    catch (std::exception& e) {
+        vnThreadsRunning[THREAD_MINTER]--;
+        PrintException(&e, "ThreadStakeMinter()");
+    } catch (...) {
+        vnThreadsRunning[THREAD_MINTER]--;
+        PrintException(NULL, "ThreadStakeMinter()");
     }
+    printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
 }