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