X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fkernel.cpp;h=b18ae2b7c180f836f687b46f019c134ba17cd513;hp=e253ce8c65b72921331682359cd02fa8ccd27eba;hb=89d4073d0a6545330af16bb8b2352881b6f55cf5;hpb=d32e0b108f1fb57e57e329b91b33fc55c59131ca diff --git a/src/kernel.cpp b/src/kernel.cpp index e253ce8..b18ae2b 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -8,6 +8,7 @@ #include #include "kernel.h" +#include "kernel_worker.h" #include "txdb.h" extern unsigned int nStakeMaxAge; @@ -36,6 +37,8 @@ static std::map mapStakeModifierCheckpoints = (149000, 0x48f2bdc4u ) (160000, 0x789df0f0u ) (200000, 0x01ec1503u ) + (221047, 0x0b39ef50u ) + (243100, 0xe928d83au ) ; // Hard checkpoints of stake modifiers to ensure they are deterministic (testNet) @@ -160,13 +163,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")) @@ -426,323 +429,28 @@ bool CheckStakeKernelHash(uint32_t nBits, const CBlock& blockFrom, uint32_t nTxP return true; } - -#ifdef USE_ASM - -// kernel padding -static const uint32_t block1_suffix[9] = { 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0x000000e0 }; -static const uint32_t block1_suffix_4way[4 * 9] = { - 0x80000000, 0x80000000, 0x80000000, 0x80000000, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0 -}; - -// hash padding -static const uint32_t block2_suffix[8] = { 0x80000000, 0, 0, 0, 0, 0, 0, 0x00000100 }; -static const uint32_t block2_suffix_4way[4 * 8] = { - 0x80000000, 0x80000000, 0x80000000, 0x80000000, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0x00000100, 0x00000100, 0x00000100, 0x00000100 -}; - -// Sha256 initial state -static const uint32_t sha256_initial[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; - -extern "C" int sha256_use_4way(); -extern "C" void sha256_init(uint32_t *state); -extern "C" void sha256_transform(uint32_t *state, const uint32_t *block, int swap); -extern "C" void sha256_init_4way(uint32_t *state); -extern "C" void sha256_transform_4way(uint32_t *state, const uint32_t *block, int swap); - -#ifdef USE_SSSE3 -#include - -extern "C" int sha256_use_ssse3(); -bool fUseSSSE3 = sha256_use_ssse3() != 0; - -inline void copyrow_swap32(uint32_t *to, uint32_t *from) -{ - if (!fUseSSSE3) - { - for (int i = 0; i < 4; i++) - to[i] = __builtin_bswap32(from[i]); - } - else - { - __m128i mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3); - _mm_storeu_si128((__m128i *)&to[0], _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)&from[0]), mask)); - } -} -#else -inline void copyrow_swap32(uint32_t *to, uint32_t *from) -{ - for (int i = 0; i < 4; i++) - to[i] = __builtin_bswap32(from[i]); -} -#endif - -bool fUse4Way = sha256_use_4way() != 0; - -class ScanMidstateWorker -{ -public: - ScanMidstateWorker() - { } - ScanMidstateWorker(unsigned char *kernel, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, uint32_t nIntervalBegin, uint32_t nIntervalEnd) - : kernel(kernel), nBits(nBits), nInputTxTime(nInputTxTime), bnValueIn(nValueIn), nIntervalBegin(nIntervalBegin), nIntervalEnd(nIntervalEnd) - { - solutions = vector >(); - } - - void Do_4way() - { - SetThreadPriority(THREAD_PRIORITY_LOWEST); - - // Compute maximum possible target to filter out majority of obviously insufficient hashes - CBigNum bnTargetPerCoinDay; - bnTargetPerCoinDay.SetCompact(nBits); - uint256 nMaxTarget = (bnTargetPerCoinDay * bnValueIn * nStakeMaxAge / COIN / nOneDay).getuint256(); - - uint32_t blocks1[4 * 16] __attribute__((aligned(16))); - uint32_t blocks2[4 * 16] __attribute__((aligned(16))); - uint32_t candidates[4 * 8] __attribute__((aligned(16))); - - vector vRow = vector(4); - uint32_t *pnKernel = (uint32_t *) kernel; - - for(int i = 0; i < 7; i++) - { - fill(vRow.begin(), vRow.end(), pnKernel[i]); - copyrow_swap32(&blocks1[i*4], &vRow[0]); - } - - memcpy(&blocks1[28], &block1_suffix_4way[0], 36*4); // sha256 padding - memcpy(&blocks2[32], &block2_suffix_4way[0], 32*4); - - uint32_t nTimeStamps[4] = {0, 0, 0, 0}; - uint32_t nHashes[4] = {0, 0, 0, 0}; - - // Search forward in time from the given timestamp - // Stopping search in case of shutting down - for (uint32_t nTimeTx=nIntervalBegin, nMaxTarget32 = nMaxTarget.Get32(7); nTimeTx= CBigNum(nHashProofOfStake)) - solutions.push_back(std::pair(nHashProofOfStake, nTimeStamps[nResult])); - } - } - } - } - - void Do_oneway() - { - SetThreadPriority(THREAD_PRIORITY_LOWEST); - - // Compute maximum possible target to filter out majority of obviously insufficient hashes - CBigNum bnTargetPerCoinDay; - bnTargetPerCoinDay.SetCompact(nBits); - uint256 nMaxTarget = (bnTargetPerCoinDay * bnValueIn * nStakeMaxAge / COIN / nOneDay).getuint256(); - - uint32_t block1[16] __attribute__((aligned(16))); - uint32_t block2[16] __attribute__((aligned(16))); - uint32_t candidate[8] __attribute__((aligned(16))); - - memcpy(&block1[7], &block1_suffix[0], 36); // sha256 padding - memcpy(&block2[8], &block2_suffix[0], 32); - - uint32_t *pnKernel = (uint32_t *) kernel; - copyrow_swap32(&block1[0], pnKernel); - block1[4] = __builtin_bswap32(pnKernel[4]); - block1[5] = __builtin_bswap32(pnKernel[5]); - - // Search forward in time from the given timestamp - // Stopping search in case of shutting down - for (uint32_t nTimeTx=nIntervalBegin, nMaxTarget32 = nMaxTarget.Get32(7); nTimeTx nMaxTarget32) - continue; - - uint256 nHashProofOfStake; - uint32_t *pnHashProofOfStake = (uint32_t *) &nHashProofOfStake; - - for (int i = 0; i < 7; i++) - pnHashProofOfStake[i] = __builtin_bswap32(candidate[i]); - pnHashProofOfStake[7] = nHash7; - - CBigNum bnCoinDayWeight = bnValueIn * GetWeight((int64_t)nInputTxTime, (int64_t)nTimeTx) / COIN / nOneDay; - CBigNum bnTargetProofOfStake = bnCoinDayWeight * bnTargetPerCoinDay; - - if (bnTargetProofOfStake >= CBigNum(nHashProofOfStake)) - solutions.push_back(std::pair(nHashProofOfStake, nTimeTx)); - } - } - - void Do() - { - if (fUse4Way) - Do_4way(); - else - Do_oneway(); - } - - vector >& GetSolutions() - { - return solutions; - } - -private: - std::vector > solutions; - - uint8_t *kernel; - uint32_t nBits; - uint32_t nInputTxTime; - CBigNum bnValueIn; - uint32_t nIntervalBegin; - uint32_t nIntervalEnd; -}; - -#else -class ScanMidstateWorker -{ -public: - ScanMidstateWorker() - { } - ScanMidstateWorker(unsigned char *kernel, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, uint32_t nIntervalBegin, uint32_t nIntervalEnd) - : nBits(nBits), nInputTxTime(nInputTxTime), bnValueIn(nValueIn), nIntervalBegin(nIntervalBegin), nIntervalEnd(nIntervalEnd) - { - // Init new sha256 context and update it - // with first 24 bytes of kernel - SHA256_Init(&workerCtx); - SHA256_Update(&workerCtx, kernel, 8 + 16); - solutions = vector >(); - } - - void Do() - { - SetThreadPriority(THREAD_PRIORITY_LOWEST); - SHA256_CTX ctx = workerCtx; - - // Sha256 result buffer - uint32_t hashProofOfStake[8]; - - // Compute maximum possible target to filter out majority of obviously insufficient hashes - CBigNum bnTargetPerCoinDay; - bnTargetPerCoinDay.SetCompact(nBits); - - uint256 nMaxTarget = (bnTargetPerCoinDay * bnValueIn * nStakeMaxAge / COIN / nOneDay).getuint256(), - *pnHashProofOfStake = (uint256 *)&hashProofOfStake; - - // Search forward in time from the given timestamp - // Stopping search in case of shutting down - for (uint32_t nTimeTx=nIntervalBegin, nMaxTarget32 = nMaxTarget.Get32(7); nTimeTx nMaxTarget32) - continue; - - CBigNum bnCoinDayWeight = bnValueIn * GetWeight((int64_t)nInputTxTime, (int64_t)nTimeTx) / COIN / nOneDay; - CBigNum bnTargetProofOfStake = bnCoinDayWeight * bnTargetPerCoinDay; - - if (bnTargetProofOfStake >= CBigNum(*pnHashProofOfStake)) - solutions.push_back(std::pair(*pnHashProofOfStake, nTimeTx)); - } - } - - vector >& GetSolutions() - { - return solutions; - } - -private: - SHA256_CTX workerCtx; - std::vector > solutions; - - uint32_t nBits; - uint32_t nInputTxTime; - CBigNum bnValueIn; - uint32_t nIntervalBegin; - uint32_t nIntervalEnd; -}; - -#endif // 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) { // TODO: custom threads amount uint32_t nThreads = boost::thread::hardware_concurrency(); + if (nThreads == 0) + { + nThreads = 1; + printf("Warning: hardware_concurrency() failed in %s:%d\n", __FILE__, __LINE__); + } uint32_t nPart = (SearchInterval.second - SearchInterval.first) / nThreads; - - ScanMidstateWorker *workers = new ScanMidstateWorker[nThreads]; + KernelWorker *workers = new KernelWorker[nThreads]; 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] = ScanMidstateWorker(kernel, nBits, nInputTxTime, nValueIn, nBegin, nEnd); - boost::function workerFnc = boost::bind(&ScanMidstateWorker::Do, &workers[i]); + workers[i] = KernelWorker(kernel, nBits, nInputTxTime, nValueIn, nBegin, nEnd); + boost::function workerFnc = boost::bind(&KernelWorker::Do, &workers[i]); group.create_thread(workerFnc); } @@ -766,53 +474,6 @@ bool ScanKernelForward(unsigned char *kernel, uint32_t nBits, uint32_t nInputTxT return true; } -// Scan given midstate for solution -bool ScanContextBackward(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 / nOneDay; - 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 / nOneDay; - 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) {