See https://github.com/bitcoin/bitcoin/pull/1767
[novacoin.git] / src / kernel.cpp
index 530b1ae..d31bfe9 100644 (file)
@@ -9,11 +9,13 @@
 #include "kernel_worker.h"
 #include "txdb.h"
 
-extern uint32_t nStakeMaxAge;
 extern uint32_t nStakeTargetSpacing;
 
 using namespace std;
 
+uint32_t nStakeMinAge = 30 * nOneDay; // 30 days as zero time weight
+uint32_t nStakeMaxAge = 90 * nOneDay; // 90 days as full weight
+
 // Protocol switch time for fixed kernel modifier interval
 uint32_t nModifierSwitchTime  = 1413763200;    // Mon, 20 Oct 2014 00:00:00 GMT
 uint32_t nModifierTestSwitchTime = 1397520000; // Tue, 15 Apr 2014 00:00:00 GMT
@@ -241,7 +243,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexCurrent, uint64_t& nStake
     const auto *pindex = pindexPrev;
     while (pindex && pindex->GetBlockTime() >= nSelectionIntervalStart)
     {
-        vSortedByTimestamp.push_back(make_pair(pindex->GetBlockTime(), pindex->GetBlockHash()));
+        vSortedByTimestamp.push_back({ pindex->GetBlockTime(), pindex->GetBlockHash() });
         pindex = pindex->pprev;
     }
     int nHeightFirstCandidate = pindex ? (pindex->nHeight + 1) : 0;
@@ -262,7 +264,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexCurrent, uint64_t& nStake
         // write the entropy bit of the selected block
         nStakeModifierNew |= (((uint64_t)pindex->GetStakeEntropyBit()) << nRound);
         // add the selected block from candidates to selected list
-        mapSelectedBlocks.insert(make_pair(pindex->GetBlockHash(), pindex));
+        mapSelectedBlocks.insert({ pindex->GetBlockHash(), pindex });
         if (fDebug && GetBoolArg("-printstakemodifier"))
             printf("ComputeNextStakeModifier: selected round %d stop=%s height=%d bit=%d\n", nRound, DateTimeStrFormat(nSelectionIntervalStop).c_str(), pindex->nHeight, pindex->GetStakeEntropyBit());
     }
@@ -301,7 +303,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexCurrent, uint64_t& nStake
 
 // The stake modifier used to hash for a stake kernel is chosen as the stake
 // modifier about a selection interval later than the coin generating the kernel
-static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64_t& nStakeModifier, int& nStakeModifierHeight, int64_t& nStakeModifierTime, bool fPrintProofOfStake)
+static bool GetKernelStakeModifier(const uint256 &hashBlockFrom, uint64_t& nStakeModifier, int& nStakeModifierHeight, int64_t& nStakeModifierTime, bool fPrintProofOfStake)
 {
     nStakeModifier = 0;
     if (!mapBlockIndex.count(hashBlockFrom))
@@ -333,7 +335,7 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64_t& nStakeModifi
     return true;
 }
 
-bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64_t& nStakeModifier)
+bool GetKernelStakeModifier(const uint256 &hashBlockFrom, uint64_t& nStakeModifier)
 {
     int nStakeModifierHeight;
     int64_t nStakeModifierTime;
@@ -425,39 +427,38 @@ bool CheckStakeKernelHash(uint32_t nBits, const CBlock& blockFrom, uint32_t nTxP
 // Scan given kernel for solution
 bool ScanKernelForward(unsigned char *kernel, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, pair<uint32_t, uint32_t> &SearchInterval, vector<pair<uint256, uint32_t> > &solutions)
 {
-    // TODO: custom threads amount
-
-    uint32_t nThreads = boost::thread::hardware_concurrency();
-    uint32_t nPart = (SearchInterval.second - SearchInterval.first) / nThreads;
-
+    solutions.clear();
+    {
+        using namespace boost;
 
-    KernelWorker *workers = new KernelWorker[nThreads];
+        auto nThreads = boost::thread::hardware_concurrency();
+        if (nThreads == 0) {
+           nThreads = 1;
+           printf("Warning: hardware_concurrency() failed in %s:%d\n", __FILE__, __LINE__);
+        }
+        auto vWorkers = vector<KernelWorker>(nThreads);
+        auto nPart = (SearchInterval.second - SearchInterval.first) / nThreads;
+        thread_group group;
 
-    boost::thread_group group;
-    for(size_t i = 0; i < nThreads; i++)
-    {
-        uint32_t nBegin = SearchInterval.first + nPart * i;
-        uint32_t nEnd = SearchInterval.first + nPart * (i + 1);
-        workers[i] = KernelWorker(kernel, nBits, nInputTxTime, nValueIn, nBegin, nEnd);
-        boost::function<void()> workerFnc = boost::bind(&KernelWorker::Do, &workers[i]);
-        group.create_thread(workerFnc);
-    }
+        for(size_t i = 0; i < vWorkers.size(); i++)
+        {
+            auto nBegin = SearchInterval.first + nPart * i;
+            auto nEnd = SearchInterval.first + nPart * (i + 1);
 
-    group.join_all();
-    solutions.clear();
+            vWorkers[i] = KernelWorker(kernel, nBits, nInputTxTime, nValueIn, nBegin, nEnd);
+            auto workerFnc = bind(&KernelWorker::Do, &vWorkers[i]);
+            group.create_thread(workerFnc);
+        }
 
-    for(size_t i = 0; i < nThreads; i++)
-    {
-        vector<pair<uint256, uint32_t> > ws = workers[i].GetSolutions();
-        solutions.insert(solutions.end(), ws.begin(), ws.end());
-    }
+        group.join_all();
 
-    delete [] workers;
+        for(auto& worker : vWorkers)
+        {
+            auto ws = worker.GetSolutions();
+            solutions.insert(solutions.end(), ws.begin(), ws.end());
+        }
 
-    if (solutions.size() == 0)
-    {
-        // no solutions
-        return false;
+        return (solutions.size() != 0);
     }
 
     return true;
@@ -509,14 +510,13 @@ uint32_t GetStakeModifierChecksum(const CBlockIndex* pindex)
     ss << pindex->nFlags << pindex->hashProofOfStake << pindex->nStakeModifier;
     auto hashChecksum = Hash(ss.begin(), ss.end());
     hashChecksum >>= (256 - 32);
-    return static_cast<uint32_t>(hashChecksum.Get64());
+    return hashChecksum.Get32();
 }
 
 // Check stake modifier hard checkpoints
 bool CheckStakeModifierCheckpoints(int nHeight, uint32_t nStakeModifierChecksum)
 {
     auto& checkpoints = (fTestNet ? mapStakeModifierCheckpointsTestNet : mapStakeModifierCheckpoints);
-
     if (checkpoints.count(nHeight))
         return nStakeModifierChecksum == checkpoints[nHeight];
     return true;