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