From 5d466098ff30f0dece5d7e64e1b8b701aa088649 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Thu, 15 Oct 2015 17:02:44 -0700 Subject: [PATCH] Rename ScanMidstateWorker to KernelWorker, move kernel scanning to separate module. --- novacoin-qt.pro | 2 + src/kernel.cpp | 475 +--------------------------------------------- src/kernel_worker.cpp | 388 +++++++++++++++++++++++++++++++++++++ src/kernel_worker.h | 39 ++++ src/makefile.bsd | 3 +- src/makefile.linux-mingw | 3 +- src/makefile.mingw | 3 +- src/makefile.osx | 3 +- src/makefile.unix | 3 +- 9 files changed, 443 insertions(+), 476 deletions(-) create mode 100644 src/kernel_worker.cpp create mode 100644 src/kernel_worker.h diff --git a/novacoin-qt.pro b/novacoin-qt.pro index 369a734..c27091b 100644 --- a/novacoin-qt.pro +++ b/novacoin-qt.pro @@ -201,6 +201,7 @@ HEADERS += src/qt/bitcoingui.h \ src/hash.h \ src/uint256.h \ src/kernel.h \ + src/kernel_worker.h \ src/scrypt.h \ src/serialize.h \ src/main.h \ @@ -335,6 +336,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/qt/rpcconsole.cpp \ src/noui.cpp \ src/kernel.cpp \ + src/kernel_worker.cpp \ src/qt/multisigaddressentry.cpp \ src/qt/multisiginputentry.cpp \ src/qt/multisigdialog.cpp \ diff --git a/src/kernel.cpp b/src/kernel.cpp index 978d4bb..e554aff 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; @@ -426,474 +427,6 @@ bool CheckStakeKernelHash(uint32_t nBits, const CBlock& blockFrom, uint32_t nTxP return true; } - -#ifdef USE_ASM - -#ifndef __i386__ -// kernel padding -static const uint32_t block1_suffix[9] = { 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0x000000e0 }; -// hash padding -static const uint32_t block2_suffix[8] = { 0x80000000, 0, 0, 0, 0, 0, 0, 0x00000100 }; -#endif - -// 4-way kernel padding -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 -}; - -// 4-way hash padding -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 -}; - -#ifdef __x86_64__ -// 8-way kernel padding -static const uint32_t block1_suffix_8way[8 * 9] = { - 0x80000000, 0x80000000, 0x80000000, 0x80000000, 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, 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, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0 -}; - -// 8-way hash padding -static const uint32_t block2_suffix_8way[8 * 8] = { - 0x80000000, 0x80000000, 0x80000000, 0x80000000, 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, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0 -}; -#endif - -// Sha256 initial state -static const uint32_t sha256_initial[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; - -#ifndef __i386__ -extern "C" void sha256_transform(uint32_t *state, const uint32_t *block, int swap); -#endif - -#if defined(__i386__) || defined(__x86_64__) -#include -extern "C" int sha256_use_ssse3(); -bool fUseSSSE3 = sha256_use_ssse3() != 0; - -inline void copyrow8_swap32(uint32_t *to, uint32_t *from) -{ - __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)); - _mm_storeu_si128((__m128i *)&to[4], _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)&from[4]), mask)); -} - -inline void copyrow4_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 copyrow4_swap32(uint32_t *to, uint32_t *from) -{ - for (int i = 0; i < 4; i++) - to[i] = __builtin_bswap32(from[i]); -} -#endif - -extern "C" int sha256_use_4way(); -extern "C" void sha256_init_4way(uint32_t *state); -extern "C" void sha256_transform_4way(uint32_t *state, const uint32_t *block, int swap); - -bool fUse4Way = sha256_use_4way() != 0; - -#ifdef __x86_64__ -extern "C" int sha256_use_8way(); -extern "C" void sha256_init_8way(uint32_t *state); -extern "C" void sha256_transform_8way(uint32_t *state, const uint32_t *block, int swap); - -bool fUse8Way = sha256_use_8way() != 0; -#endif - - -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 >(); - } - -#ifdef __x86_64__ - void Do_8way() - { - 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[8 * 16] __attribute__((aligned(16))); - uint32_t blocks2[8 * 16] __attribute__((aligned(16))); - uint32_t candidates[8 * 8] __attribute__((aligned(16))); - - vector vRow = vector(8); - uint32_t *pnKernel = (uint32_t *) kernel; - - for(int i = 0; i < 7; i++) - { - fill(vRow.begin(), vRow.end(), pnKernel[i]); - copyrow8_swap32(&blocks1[i*8], &vRow[0]); - } - - memcpy(&blocks1[56], &block1_suffix_8way[0], 36*8); // sha256 padding - memcpy(&blocks2[64], &block2_suffix_8way[0], 32*8); - - uint32_t nHashes[8]; - uint32_t nTimeStamps[8]; - - // 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])); - } - } - } - } -#endif - - 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]); - copyrow4_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 nHashes[4]; - uint32_t nTimeStamps[4]; - - // 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(); - -#ifdef __i386__ - SHA256_CTX ctx, workerCtx; - // Init new sha256 context and update it - // with first 24 bytes of kernel - SHA256_Init(&ctx); - SHA256_Update(&ctx, kernel, 8 + 16); - workerCtx = ctx; // save context - - // Sha256 result buffer - uint32_t hashProofOfStake[8]; - uint256 *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)); - } -#else - 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; - copyrow4_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)); - } -#endif - } - - void Do() - { -#ifdef __x86_64__ - if (false && fUse8Way) // disable for now - { - Do_8way(); - return; - } -#endif - if (fUse4Way) - { - Do_4way(); - return; - } - - 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) { @@ -903,15 +436,15 @@ bool ScanKernelForward(unsigned char *kernel, uint32_t nBits, uint32_t nInputTxT 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); } diff --git a/src/kernel_worker.cpp b/src/kernel_worker.cpp new file mode 100644 index 0000000..0c3b9d3 --- /dev/null +++ b/src/kernel_worker.cpp @@ -0,0 +1,388 @@ +#include +#include + +#include "uint256.h" +#include "bignum.h" +#include "kernel.h" +#include "kernel_worker.h" + +using namespace std; + +#ifdef USE_ASM + +#if defined(__i386__) || defined(__x86_64__) +#include +#endif + +#ifndef __i386__ +// kernel padding +static const uint32_t block1_suffix[9] = { 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0x000000e0 }; +// hash padding +static const uint32_t block2_suffix[8] = { 0x80000000, 0, 0, 0, 0, 0, 0, 0x00000100 }; + +// Sha256 initial state +static const uint32_t sha256_initial[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; + +extern "C" void sha256_transform(uint32_t *state, const uint32_t *block, int swap); +#endif + +// 4-way kernel padding +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 +}; + +// 4-way hash padding +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 +}; + +extern "C" int sha256_use_4way(); +extern "C" void sha256_init_4way(uint32_t *state); +extern "C" void sha256_transform_4way(uint32_t *state, const uint32_t *block, int swap); +bool fUse4Way = sha256_use_4way() != 0; + +#ifdef __x86_64__ +// 8-way kernel padding +static const uint32_t block1_suffix_8way[8 * 9] = { + 0x80000000, 0x80000000, 0x80000000, 0x80000000, 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, 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, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0 +}; + +// 8-way hash padding +static const uint32_t block2_suffix_8way[8 * 8] = { + 0x80000000, 0x80000000, 0x80000000, 0x80000000, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0, 0x000000e0 +}; + +extern "C" int sha256_use_8way(); +extern "C" void sha256_init_8way(uint32_t *state); +extern "C" void sha256_transform_8way(uint32_t *state, const uint32_t *block, int swap); +bool fUse8Way = sha256_use_8way() != 0; + +inline void copyrow8_swap32(uint32_t *to, uint32_t *from) +{ + // There are no AVX2 CPUs without SSSE3 support, so we don't need any conditions here. + __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)); + _mm_storeu_si128((__m128i *)&to[4], _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)&from[4]), mask)); +} +#endif + +#if defined(__i386__) || defined(__x86_64__) +extern "C" int sha256_use_ssse3(); +bool fUseSSSE3 = sha256_use_ssse3() != 0; + +inline void copyrow4_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 copyrow4_swap32(uint32_t *to, uint32_t *from) +{ + for (int i = 0; i < 4; i++) + to[i] = __builtin_bswap32(from[i]); +} +#endif +#endif + +KernelWorker::KernelWorker(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 >(); + } + +#ifdef USE_ASM +#ifdef __x86_64__ +void KernelWorker::Do_8way() +{ + 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[8 * 16] __attribute__((aligned(16))); + uint32_t blocks2[8 * 16] __attribute__((aligned(16))); + uint32_t candidates[8 * 8] __attribute__((aligned(16))); + + vector vRow = vector(8); + uint32_t *pnKernel = (uint32_t *) kernel; + + for(int i = 0; i < 7; i++) + { + fill(vRow.begin(), vRow.end(), pnKernel[i]); + copyrow8_swap32(&blocks1[i*8], &vRow[0]); + } + + memcpy(&blocks1[56], &block1_suffix_8way[0], 36*8); // sha256 padding + memcpy(&blocks2[64], &block2_suffix_8way[0], 32*8); + + uint32_t nHashes[8]; + uint32_t nTimeStamps[8]; + + // 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])); + } + } + } +} +#endif + +void KernelWorker::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]); + copyrow4_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 nHashes[4]; + uint32_t nTimeStamps[4]; + + // 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])); + } + } + } +} +#endif + +void KernelWorker::Do_generic() +{ + 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(); + +#if !defined(USE_ASM) || defined(__i386__) + SHA256_CTX ctx, workerCtx; + // Init new sha256 context and update it + // with first 24 bytes of kernel + SHA256_Init(&ctx); + SHA256_Update(&ctx, kernel, 8 + 16); + workerCtx = ctx; // save context + + // Sha256 result buffer + uint32_t hashProofOfStake[8]; + uint256 *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)); + } +#else + 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; + + for (int i = 0; i < 6; i++) + block1[i] = __builtin_bswap32(pnKernel[i]); + + // 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)); + } +#endif +} + +void KernelWorker::Do() +{ +#ifdef USE_ASM +#ifdef __x86_64__ + if (false && fUse8Way) // disable for now + { + Do_8way(); + return; + } +#endif + if (fUse4Way) + { + Do_4way(); + return; + } +#endif + + Do_generic(); +} + +vector >& KernelWorker::GetSolutions() +{ + return solutions; +} + diff --git a/src/kernel_worker.h b/src/kernel_worker.h new file mode 100644 index 0000000..63217b9 --- /dev/null +++ b/src/kernel_worker.h @@ -0,0 +1,39 @@ +#ifndef BITCOIN_HERNELWORKER_H +#define BITCOIN_HERNELWORKER_H + +class KernelWorker +{ +public: + KernelWorker() + { } + KernelWorker(unsigned char *kernel, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, uint32_t nIntervalBegin, uint32_t nIntervalEnd); + void Do(); + vector >& GetSolutions(); + +private: +#ifdef USE_ASM +#ifdef __x86_64__ + // AVX2 CPUs: 8-way hashing. + void Do_8way(); +#endif + // SSE2, Neon: 4-way hashing. + void Do_4way(); +#endif + // One way hashing. + void Do_generic(); + + // Kernel solutions. + std::vector > solutions; + + // Kernel metadaya + uint8_t *kernel; + uint32_t nBits; + uint32_t nInputTxTime; + CBigNum bnValueIn; + + // Interval boundaries. + uint32_t nIntervalBegin; + uint32_t nIntervalEnd; +}; + +#endif diff --git a/src/makefile.bsd b/src/makefile.bsd index 88f8b2b..53b66a4 100644 --- a/src/makefile.bsd +++ b/src/makefile.bsd @@ -133,7 +133,8 @@ OBJS= \ obj/wallet.o \ obj/walletdb.o \ obj/noui.o \ - obj/kernel.o + obj/kernel.o \ + obj/kernel_worker.o all: novacoind diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index fc1b93e..1a9167c 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -96,7 +96,8 @@ OBJS= \ obj/wallet.o \ obj/walletdb.o \ obj/noui.o \ - obj/kernel.o + obj/kernel.o \ + obj/kernel_worker.o all: novacoind.exe diff --git a/src/makefile.mingw b/src/makefile.mingw index d7552c2..3b9cc82 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -86,7 +86,8 @@ OBJS= \ obj/wallet.o \ obj/walletdb.o \ obj/noui.o \ - obj/kernel.o + obj/kernel.o \ + obj/kernel_worker.o all: novacoind.exe diff --git a/src/makefile.osx b/src/makefile.osx index 0903d6e..8074a27 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -93,7 +93,8 @@ OBJS= \ obj/wallet.o \ obj/walletdb.o \ obj/noui.o \ - obj/kernel.o + obj/kernel.o \ + obj/kernel_worker.o ifneq (${USE_IPV6}, -) DEFS += -DUSE_IPV6=$(USE_IPV6) diff --git a/src/makefile.unix b/src/makefile.unix index 191c4c9..feda579 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -134,7 +134,8 @@ OBJS= \ obj/wallet.o \ obj/walletdb.o \ obj/noui.o \ - obj/kernel.o + obj/kernel.o \ + obj/kernel_worker.o all: novacoind -- 1.7.1