X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fkernel.cpp;h=bd8c35757e09b50a1a54ab030854f3a2f7a5d043;hp=79d8e58096fd0aeaac830ebc7037a615a6be023b;hb=7483713823cea61963ae0051f3e17ffd4b9be706;hpb=144f5f66954f40fc37431916917a0f1d7d034533 diff --git a/src/kernel.cpp b/src/kernel.cpp index 79d8e58..bd8c357 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -1,10 +1,14 @@ // Copyright (c) 2012-2013 The PPCoin developers +// Copyright (c) 2013-2015 The Novacoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include "kernel.h" +#include "kernel_worker.h" #include "txdb.h" extern unsigned int nStakeMaxAge; @@ -27,12 +31,16 @@ typedef std::map MapModifierCheckpoints; // Hard checkpoints of stake modifiers to ensure they are deterministic static std::map mapStakeModifierCheckpoints = boost::assign::map_list_of - ( 0, 0x0e00670bu ) + ( 0, 0x0e00670bu ) ( 12661, 0x5d84115du ) (143990, 0x9c592c78u ) (149000, 0x48f2bdc4u ) (160000, 0x789df0f0u ) (200000, 0x01ec1503u ) + (221047, 0x0b39ef50u ) + (243100, 0xe928d83au ) + (532000, 0x3e5c2b81u ) + (561108, 0x9c1860b0u ) ; // Hard checkpoints of stake modifiers to ensure they are deterministic (testNet) @@ -157,13 +165,13 @@ static bool SelectBlockFromCandidates(vector >& vSortedBy if (fSelected && hashSelection < hashBest) { hashBest = hashSelection; - *pindexSelected = (const CBlockIndex*) pindex; + *pindexSelected = pindex; } else if (!fSelected) { fSelected = true; hashBest = hashSelection; - *pindexSelected = (const CBlockIndex*) pindex; + *pindexSelected = pindex; } } if (fDebug && GetBoolArg("-printstakemodifier")) @@ -377,7 +385,7 @@ bool CheckStakeKernelHash(uint32_t nBits, const CBlock& blockFrom, uint32_t nTxP uint256 hashBlockFrom = blockFrom.GetHash(); - CBigNum bnCoinDayWeight = CBigNum(nValueIn) * GetWeight((int64_t)txPrev.nTime, (int64_t)nTimeTx) / COIN / (24 * 60 * 60); + CBigNum bnCoinDayWeight = CBigNum(nValueIn) * GetWeight((int64_t)txPrev.nTime, (int64_t)nTimeTx) / COIN / nOneDay; targetProofOfStake = (bnCoinDayWeight * bnTargetPerCoinDay).getuint256(); // Calculate hash @@ -423,129 +431,42 @@ bool CheckStakeKernelHash(uint32_t nBits, const CBlock& blockFrom, uint32_t nTxP return true; } -// Precompute hashing state for static part of kernel -void GetKernelMidstate(uint64_t nStakeModifier, uint32_t nBlockTime, uint32_t nTxOffset, uint32_t nInputTxTime, uint32_t nOut, SHA256_CTX &ctx) -{ - // Build static part of kernel - CDataStream ssKernel(SER_GETHASH, 0); - ssKernel << nStakeModifier; - ssKernel << nBlockTime << nTxOffset << nInputTxTime << nOut; - CDataStream::const_iterator it = ssKernel.begin(); - - // Init sha256 context and update it - // with first 24 bytes of kernel - SHA256_Init(&ctx); - SHA256_Update(&ctx, (unsigned char*)&it[0], 8 + 16); -} - - -class ScanMidstateWorker +// Scan given kernel for solution +bool ScanKernelForward(unsigned char *kernel, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, std::pair &SearchInterval, std::vector > &solutions) { -public: - ScanMidstateWorker() - { } - ScanMidstateWorker(SHA256_CTX ctx, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, uint32_t nIntervalBegin, uint32_t nIntervalEnd) - { - workerSolutions = vector >(); - - workerCtx = ctx; - this->nBits = nBits; - this->nInputTxTime = nInputTxTime; - this->nValueIn = nValueIn; - this->nIntervalBegin = nIntervalBegin; - this->nIntervalEnd = nIntervalEnd; - } - - void Do() - { - CBigNum bnTargetPerCoinDay; - bnTargetPerCoinDay.SetCompact(nBits); - - // Get maximum possible target to filter out the majority of obviously insufficient hashes - CBigNum bnMaxTargetPerCoinDay = bnTargetPerCoinDay * CBigNum(nValueIn) * nStakeMaxAge / COIN / (24 * 60 * 60); - uint256 maxTarget = bnMaxTargetPerCoinDay.getuint256(); - - SHA256_CTX ctx = workerCtx; - - // Search forward in time from the given timestamp - // Stopping search in case of shutting down - for (uint32_t nTimeTx=nIntervalBegin; nTimeTx maxTarget) - continue; - - CBigNum bnCoinDayWeight = CBigNum(nValueIn) * GetWeight((int64_t)nInputTxTime, (int64_t)nTimeTx) / COIN / (24 * 60 * 60); - CBigNum bnTargetProofOfStake = bnCoinDayWeight * bnTargetPerCoinDay; - - if (bnTargetProofOfStake >= CBigNum(hashProofOfStake)) - { - workerSolutions.push_back(std::pair(hashProofOfStake, nTimeTx)); - } - } - } + // TODO: custom threads amount - vector > GetSolutions() + uint32_t nThreads = boost::thread::hardware_concurrency(); + if (nThreads == 0) { - return workerSolutions; + nThreads = 1; + printf("Warning: hardware_concurrency() failed in %s:%d\n", __FILE__, __LINE__); } + uint32_t nPart = (SearchInterval.second - SearchInterval.first) / nThreads; -private: - SHA256_CTX workerCtx; - std::vector > workerSolutions; - - uint32_t nBits; - uint32_t nInputTxTime; - int64_t nValueIn; - uint32_t nIntervalBegin; - uint32_t nIntervalEnd; -}; - -// Scan given midstate for solution -bool ScanMidstateForward(SHA256_CTX &ctx, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, std::pair &SearchInterval, std::vector > &solutions) -{ - // TODO: custom threads amount - - uint32_t nBegin = SearchInterval.first; - uint32_t nEnd = SearchInterval.second; - uint32_t nPart = (nEnd - nBegin) / 4; - - ScanMidstateWorker workers[4]; + KernelWorker *workers = new KernelWorker[nThreads]; boost::thread_group group; - for(int i = 0; i<4; i++) + for(size_t i = 0; i < nThreads; i++) { - uint32_t nIntervalBegin = nBegin + nPart * i; - uint32_t nIntervalEnd = nBegin + nPart * (i + 1); - - workers[i] = ScanMidstateWorker(ctx, nBits, nInputTxTime, nValueIn, nIntervalBegin, nIntervalEnd); - - boost::function workerFnc = boost::bind(&ScanMidstateWorker::Do, &workers[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 workerFnc = boost::bind(&KernelWorker::Do, &workers[i]); group.create_thread(workerFnc); } group.join_all(); solutions.clear(); - for(int i = 0; i<4; i++) + for(size_t i = 0; i < nThreads; i++) { std::vector > ws = workers[i].GetSolutions(); solutions.insert(solutions.end(), ws.begin(), ws.end()); } + delete [] workers; + if (solutions.size() == 0) { // no solutions @@ -555,53 +476,6 @@ bool ScanMidstateForward(SHA256_CTX &ctx, uint32_t nBits, uint32_t nInputTxTime, return true; } -// Scan given midstate for solution -bool ScanMidstateBackward(SHA256_CTX &ctx, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, std::pair &SearchInterval, std::pair &solution) -{ - CBigNum bnTargetPerCoinDay; - bnTargetPerCoinDay.SetCompact(nBits); - - // Get maximum possible target to filter out the majority of obviously insufficient hashes - CBigNum bnMaxTargetPerCoinDay = bnTargetPerCoinDay * CBigNum(nValueIn) * nStakeMaxAge / COIN / (24 * 60 * 60); - uint256 maxTarget = bnMaxTargetPerCoinDay.getuint256(); - - SHA256_CTX ctxCopy = ctx; - - // Search backward in time from the given timestamp - // Stopping search in case of shutting down - for (uint32_t nTimeTx=SearchInterval.first; nTimeTx>SearchInterval.second && !fShutdown; nTimeTx--) - { - // Complete first hashing iteration - uint256 hash1; - SHA256_Update(&ctxCopy, (unsigned char*)&nTimeTx, 4); - SHA256_Final((unsigned char*)&hash1, &ctxCopy); - - // Restore context - ctxCopy = ctx; - - // Finally, calculate kernel hash - uint256 hashProofOfStake; - SHA256((unsigned char*)&hash1, sizeof(hashProofOfStake), (unsigned char*)&hashProofOfStake); - - // Skip if hash doesn't satisfy the maximum target - if (hashProofOfStake > maxTarget) - continue; - - CBigNum bnCoinDayWeight = CBigNum(nValueIn) * GetWeight((int64_t)nInputTxTime, (int64_t)nTimeTx) / COIN / (24 * 60 * 60); - CBigNum bnTargetProofOfStake = bnCoinDayWeight * bnTargetPerCoinDay; - - if (bnTargetProofOfStake >= CBigNum(hashProofOfStake)) - { - solution.first = hashProofOfStake; - solution.second = nTimeTx; - - return true; - } - } - - return false; -} - // Check kernel hash target and coinstake signature bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake) {