beb8aa71f7bf5841b8604881841a9377088c25cf
[novacoin.git] / src / kernelrecord.cpp
1 #include "kernelrecord.h"
2
3 #include "wallet.h"
4 #include "base58.h"
5
6 using namespace std;
7
8 bool KernelRecord::showTransaction(const CWalletTx &wtx)
9 {
10     if (wtx.IsCoinBase())
11     {
12         if (wtx.GetDepthInMainChain() < 2)
13         {
14             return false;
15         }
16     }
17
18     if(!wtx.IsTrusted())
19     {
20         return false;
21     }
22
23     return true;
24 }
25
26 /*
27  * Decompose CWallet transaction to model kernel records.
28  */
29 vector<KernelRecord> KernelRecord::decomposeOutput(const CWallet *wallet, const CWalletTx &wtx)
30 {
31     vector<KernelRecord> parts;
32     auto nTime = wtx.GetTxTime();
33     auto hash = wtx.GetHash();
34     auto mapValue = wtx.mapValue;
35     auto nDayWeight = (min((GetAdjustedTime() - nTime), (int64_t)(nStakeMaxAge+nStakeMinAge)) - nStakeMinAge); // DayWeight * 86400, чтобы был
36                                                                                                               // правильный расчёт CoinAge
37     if (showTransaction(wtx))
38     {
39         for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
40         {
41             CTxOut txOut = wtx.vout[nOut];
42             if( wallet->IsMine(txOut) ) {
43                 CTxDestination address;
44                 string addrStr;
45
46                 auto coinAge = max( (txOut.nValue * nDayWeight) / (COIN * nOneDay), (int64_t)0);
47
48                 if (ExtractDestination(txOut.scriptPubKey, address))
49                 {
50                     // Sent to Bitcoin Address
51                     addrStr = CBitcoinAddress(address).ToString();
52                 }
53                 else
54                 {
55                     // Sent to IP, or other non-address transaction like OP_EVAL
56                     addrStr = mapValue["to"];
57                 }
58
59                 parts.push_back(KernelRecord(hash, nTime, addrStr, txOut.nValue, wtx.IsSpent(nOut), coinAge));
60             }
61         }
62     }
63
64     return parts;
65 }
66
67 string KernelRecord::getTxID()
68 {
69     return hash.ToString() + strprintf("-%03d", idx);
70 }
71
72 int64_t KernelRecord::getAge() const
73 {
74     return (GetAdjustedTime() - nTime) / nOneDay;
75 }
76
77 uint64_t KernelRecord::getCoinDay() const
78 {
79     auto nWeight = GetAdjustedTime() - nTime - nStakeMinAge;
80     if( nWeight <  0)
81         return 0;
82     nWeight = min(nWeight, (int64_t)nStakeMaxAge);
83     return (nValue * nWeight ) / (COIN * nOneDay);
84 }
85
86 int64_t KernelRecord::getPoSReward(int nBits, int minutes)
87 {
88     auto nWeight = GetAdjustedTime() - nTime + minutes * 60;
89     if( nWeight <  nStakeMinAge)
90         return 0;
91     auto coinAge = (nValue * nWeight ) / (COIN * nOneDay);
92     return GetProofOfStakeReward(coinAge, nBits, GetAdjustedTime() + minutes * 60);
93 }
94
95 double KernelRecord::getProbToMintStake(double difficulty, int timeOffset) const
96 {
97     //double maxTarget = pow(static_cast<double>(2), 224);
98     //double target = maxTarget / difficulty;
99     //int dayWeight = (min((GetAdjustedTime() - nTime) + timeOffset, (int64_t)(nStakeMinAge+nStakeMaxAge)) - nStakeMinAge) / 86400;
100     //uint64_t coinAge = max(nValue * dayWeight / COIN, (int64_t)0);
101     //return target * coinAge / pow(static_cast<double>(2), 256);
102     auto Weight = (min((GetAdjustedTime() - nTime) + timeOffset, (int64_t)(nStakeMinAge+nStakeMaxAge)) - nStakeMinAge);
103     auto coinAge = max(nValue * Weight / (COIN * nOneDay), (int64_t)0);
104     return coinAge / (pow(static_cast<double>(2),32) * difficulty);
105 }
106
107 double KernelRecord::getProbToMintWithinNMinutes(double difficulty, int minutes)
108 {
109     if(difficulty != prevDifficulty || minutes != prevMinutes)
110     {
111         double prob = 1;
112         double p;
113         int d = minutes / (60 * 24); // Number of full days
114         int m = minutes % (60 * 24); // Number of minutes in the last day
115         int i, timeOffset;
116
117         // Probabilities for the first d days
118         for(i = 0; i < d; i++)
119         {
120             timeOffset = i * nOneDay;
121             p = pow(1 - getProbToMintStake(difficulty, timeOffset), nOneDay);
122             prob *= p;
123         }
124
125         // Probability for the m minutes of the last day
126         timeOffset = d * nOneDay;
127         p = pow(1 - getProbToMintStake(difficulty, timeOffset), 60 * m);
128         prob *= p;
129
130         prob = 1 - prob;
131         prevProbability = prob;
132         prevDifficulty = difficulty;
133         prevMinutes = minutes;
134     }
135     return prevProbability;
136 }