25b73b8c37b3a854839234da9eace5fbe65cf1fb
[novacoin.git] / src / kernel_worker.cpp
1 #include <vector>
2 #include <inttypes.h>
3
4 #include "uint256.h"
5 #include "bignum.h"
6 #include "kernel.h"
7 #include "kernel_worker.h"
8
9 using namespace std;
10
11 KernelWorker::KernelWorker(uint8_t *kernel, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, uint32_t nIntervalBegin, uint32_t nIntervalEnd)
12         : kernel(kernel), nBits(nBits), nInputTxTime(nInputTxTime), bnValueIn(nValueIn), nIntervalBegin(nIntervalBegin), nIntervalEnd(nIntervalEnd)
13     {
14         solutions = vector<pair<uint256,uint32_t> >();
15     }
16
17 void KernelWorker::Do_generic()
18 {
19     SetThreadPriority(THREAD_PRIORITY_LOWEST);
20
21     // Compute maximum possible target to filter out majority of obviously insufficient hashes
22     CBigNum bnTargetPerCoinDay;
23     bnTargetPerCoinDay.SetCompact(nBits);
24     auto nMaxTarget = (bnTargetPerCoinDay * bnValueIn * nStakeMaxAge / COIN / nOneDay).getuint256();
25
26     SHA256_CTX ctx, workerCtx;
27     // Init new sha256 context and update it
28     //   with first 24 bytes of kernel
29     SHA256_Init(&ctx);
30     SHA256_Update(&ctx, kernel, 8 + 16);
31     workerCtx = ctx; // save context
32
33     // Sha256 result buffer
34     uint32_t hashProofOfStake[8];
35     auto pnHashProofOfStake = (uint256 *)&hashProofOfStake;
36
37     // Search forward in time from the given timestamp
38     // Stopping search in case of shutting down
39     for (auto nTimeTx=nIntervalBegin, nMaxTarget32 = nMaxTarget.Get32(7); nTimeTx<nIntervalEnd && !fShutdown; nTimeTx++)
40     {
41         // Complete first hashing iteration
42         uint256 hash1;
43         SHA256_Update(&ctx, (unsigned char*)&nTimeTx, 4);
44         SHA256_Final(hash1.begin(), &ctx);
45
46         // Restore context
47         ctx = workerCtx;
48
49         // Finally, calculate kernel hash
50         SHA256(hash1.begin(), sizeof(hashProofOfStake), (unsigned char*)&hashProofOfStake);
51
52         // Skip if hash doesn't satisfy the maximum target
53         if (hashProofOfStake[7] > nMaxTarget32)
54             continue;
55
56         auto bnCoinDayWeight = bnValueIn * GetWeight((int64_t)nInputTxTime, (int64_t)nTimeTx) / COIN / nOneDay;
57         auto bnTargetProofOfStake = bnCoinDayWeight * bnTargetPerCoinDay;
58
59         if (bnTargetProofOfStake >= CBigNum(*pnHashProofOfStake))
60             solutions.push_back(make_pair(*pnHashProofOfStake, nTimeTx));
61     }
62 }
63
64 void KernelWorker::Do()
65 {
66     Do_generic();
67 }
68
69 vector<pair<uint256,uint32_t> >& KernelWorker::GetSolutions()
70 {
71     return solutions;
72 }
73
74 // Scan given kernel for solutions
75
76 bool ScanKernelBackward(uint8_t *kernel, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, pair<uint32_t, uint32_t> &SearchInterval, pair<uint256, uint32_t> &solution)
77 {
78     CBigNum bnTargetPerCoinDay;
79     bnTargetPerCoinDay.SetCompact(nBits);
80
81     CBigNum bnValueIn(nValueIn);
82
83     // Get maximum possible target to filter out the majority of obviously insufficient hashes
84     auto nMaxTarget = (bnTargetPerCoinDay * bnValueIn * nStakeMaxAge / COIN / nOneDay).getuint256();
85
86     SHA256_CTX ctx, workerCtx;
87     // Init new sha256 context and update it
88     //   with first 24 bytes of kernel
89     SHA256_Init(&ctx);
90     SHA256_Update(&ctx, kernel, 8 + 16);
91     workerCtx = ctx; // save context
92
93     // Search backward in time from the given timestamp
94     // Stopping search in case of shutting down
95     for (auto nTimeTx=SearchInterval.first; nTimeTx>SearchInterval.second && !fShutdown; nTimeTx--)
96     {
97         // Complete first hashing iteration
98         uint256 hash1;
99         SHA256_Update(&ctx, (unsigned char*)&nTimeTx, 4);
100         SHA256_Final(hash1.begin(), &ctx);
101
102         // Restore context
103         ctx = workerCtx;
104
105         // Finally, calculate kernel hash
106         uint256 hashProofOfStake;
107         SHA256(hash1.begin(), hashProofOfStake.size(), hashProofOfStake.begin());
108
109         // Skip if hash doesn't satisfy the maximum target
110         if (hashProofOfStake > nMaxTarget)
111             continue;
112
113         auto bnCoinDayWeight = bnValueIn * GetWeight((int64_t)nInputTxTime, (int64_t)nTimeTx) / COIN / nOneDay;
114         auto bnTargetProofOfStake = bnCoinDayWeight * bnTargetPerCoinDay;
115
116         if (bnTargetProofOfStake >= CBigNum(hashProofOfStake))
117         {
118             solution = { hashProofOfStake, nTimeTx };
119             return true;
120         }
121     }
122
123     return false;
124 }