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