dc31005c5234d9dddd6542219d879769c6b33a71
[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     uint256 nTargetPerCoinDay;
79     nTargetPerCoinDay.SetCompact(nBits);
80
81     // Get maximum possible target to filter out the majority of obviously insufficient hashes
82     auto nMaxTarget = nTargetPerCoinDay * (uint64_t)nValueIn * (uint64_t)nStakeMaxAge / (uint64_t)COIN / (uint64_t)nOneDay;
83
84     SHA256_CTX ctx, workerCtx;
85     // Init new sha256 context and update it
86     //   with first 24 bytes of kernel
87     SHA256_Init(&ctx);
88     SHA256_Update(&ctx, kernel, 8 + 16);
89     workerCtx = ctx; // save context
90
91     // Search backward in time from the given timestamp
92     // Stopping search in case of shutting down
93     for (auto nTimeTx=SearchInterval.first; nTimeTx>SearchInterval.second && !fShutdown; nTimeTx--)
94     {
95         // Complete first hashing iteration
96         uint256 hash1;
97         SHA256_Update(&ctx, (unsigned char*)&nTimeTx, 4);
98         SHA256_Final(hash1.begin(), &ctx);
99
100         // Restore context
101         ctx = workerCtx;
102
103         // Finally, calculate kernel hash
104         uint256 hashProofOfStake;
105         SHA256(hash1.begin(), hashProofOfStake.size(), hashProofOfStake.begin());
106
107         // Skip if hash doesn't satisfy the maximum target
108         if (hashProofOfStake > nMaxTarget)
109             continue;
110
111         auto nCoinDayWeight = uint256(nValueIn) * (uint64_t)GetWeight((int64_t)nInputTxTime, (int64_t)nTimeTx) / (uint64_t)COIN / (uint64_t)nOneDay; // TODO: Stop using signed types for value, time, weight and so on, because all these casts are really stupid.
112         auto nTargetProofOfStake = nCoinDayWeight * nTargetPerCoinDay;
113
114         if (nTargetProofOfStake >= hashProofOfStake)
115         {
116             solution = { hashProofOfStake, nTimeTx };
117             return true;
118         }
119     }
120
121     return false;
122 }