]> Git Repo - VerusCoin.git/blame - src/chain.cpp
Import/Export fixes
[VerusCoin.git] / src / chain.cpp
CommitLineData
e8b5f0d5 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
7bec6dd2 3// Distributed under the MIT software license, see the accompanying
bc909a7a 4// file COPYING or https://www.opensource.org/licenses/mit-license.php .
e8b5f0d5 5
6#include "chain.h"
7
8using namespace std;
9
2fdc3351
MF
10/**
11 * CChain implementation
12 */
b7ae2c17 13void CChain::SetTip(CBlockIndex *pindex) {
37ad6886 14 lastTip = pindex;
e8b5f0d5 15 if (pindex == NULL) {
16 vChain.clear();
b2a98c42 17 mmr.Truncate(0);
b7ae2c17 18 return;
e8b5f0d5 19 }
b2a98c42 20 uint32_t modCount = 0;
4b729ec5 21 vChain.resize(pindex->GetHeight() + 1);
22 while (pindex && vChain[pindex->GetHeight()] != pindex) {
b2a98c42 23 modCount++;
4b729ec5 24 vChain[pindex->GetHeight()] = pindex;
e8b5f0d5 25 pindex = pindex->pprev;
26 }
b2a98c42
MT
27 mmr.Truncate(vChain.size() - modCount);
28 for (int i = (vChain.size() - modCount); i < vChain.size(); i++)
29 {
30 // add this block to the Merkle Mountain Range
56fe75cb 31 mmr.Add(vChain[i]->GetBlockMMRNode());
b2a98c42
MT
32 }
33}
34
35// returns false if unable to fast calculate the VerusPOSHash from the header.
36// if it returns false, value is set to 0, but it can still be calculated from the full block
37// in that case. the only difference between this and the POS hash for the contest is that it is not divided by the value out
38// this is used as a source of entropy
39bool CBlockIndex::GetRawVerusPOSHash(uint256 &ret) const
40{
41 // if below the required height or no storage space in the solution, we can't get
42 // a cached txid value to calculate the POSHash from the header
43 if (!(CPOSNonce::NewNonceActive(GetHeight()) && IsVerusPOSBlock()))
44 {
45 ret = uint256();
46 return false;
47 }
48
49 // if we can calculate, this assumes the protocol that the POSHash calculation is:
50 // hashWriter << ASSETCHAINS_MAGIC;
51 // hashWriter << nNonce; (nNonce is:
52 // (high 128 bits == low 128 bits of verus hash of low 128 bits of nonce)
53 // (low 32 bits == compact PoS difficult)
54 // (mid 96 bits == low 96 bits of HASH(pastHash, txid, voutnum)
55 // pastHash is hash of height - 100, either PoW hash of block or PoS hash, if new PoS
56 // )
57 // hashWriter << height;
58 // return hashWriter.GetHash();
59 if (nVersion == CBlockHeader::VERUS_V2)
60 {
61 CVerusHashV2Writer hashWriter = CVerusHashV2Writer(SER_GETHASH, PROTOCOL_VERSION);
62
63 hashWriter << ASSETCHAINS_MAGIC;
64 hashWriter << nNonce;
65 hashWriter << GetHeight();
66 ret = hashWriter.GetHash();
67 }
68 else
69 {
70 CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
71
72 hashWriter << ASSETCHAINS_MAGIC;
73 hashWriter << nNonce;
74 hashWriter << GetHeight();
75 ret = hashWriter.GetHash();
76 }
77 return true;
78}
79
80// depending on the height of the block and its type, this returns the POS hash or the POW hash
56fe75cb 81uint256 CBlockIndex::GetVerusEntropyHashComponent() const
b2a98c42
MT
82{
83 uint256 retVal;
84 // if we qualify as PoW, use PoW hash, regardless of PoS state
85 if (GetRawVerusPOSHash(retVal))
86 {
87 // POS hash
88 return retVal;
89 }
90 return GetBlockHash();
e8b5f0d5 91}
92
56fe75cb 93// if pointers are passed for the int output values, two of them will indicate the height that provides one of two
94// entropy values. the other will be -1. if pALTheight is not -1, its block type is the same as the other, which is
95// not -1.
96uint256 CChain::GetVerusEntropyHash(int forHeight, int *pPOSheight, int *pPOWheight, int *pALTheight) const
97{
98 uint256 retVal;
99 int height = forHeight - 100;
100
101 // we want the last value hashed to be a POW hash to make it difficult to predict at source tx creation, then we hash it with the
102 // POS entropy. for old version, we just do what we used to and return the type of hash with the -100 height
103 int _posh, _powh, _alth;
104 int &posh = pPOSheight ? *pPOSheight : _posh;
105 int &powh = pPOWheight ? *pPOWheight : _powh;
106 int &alth = pALTheight ? *pALTheight : _alth;
107 posh = powh = alth = -1;
108
109 if (!(height >= 0 && height < vChain.size()))
110 {
111 LogPrintf("%s: invalid height for entropy hash %d, chain height is %d\n", __func__, height, vChain.size() - 1);
112 return retVal;
113 }
114 if (CConstVerusSolutionVector::GetVersionByHeight(height) < CActivationHeight::ACTIVATE_EXTENDEDSTAKE || height <= 10)
115 {
116 if (vChain[height]->IsVerusPOSBlock())
117 {
118 posh = height;
119 }
120 else
121 {
122 powh = height;
123 }
124 return vChain[height]->GetVerusEntropyHashComponent();
125 }
126
af521e42 127 int i;
128 for (i = 0; i < 10; i++)
56fe75cb 129 {
130 if (posh == -1 && vChain[height - i]->IsVerusPOSBlock())
131 {
132 posh = height - i;
133 }
134 else if (powh == -1)
135 {
136 powh = height - i;
137 }
138 }
af521e42 139 // only pow, set alt
140 if (i == 10)
141 {
142 alth = height - i;
143 }
56fe75cb 144
145 CVerusHashV2Writer hashWriter = CVerusHashV2Writer(SER_GETHASH, 0);
146 if (posh != -1)
147 {
148 hashWriter << vChain[posh]->GetVerusEntropyHashComponent();
149 }
150 if (powh != -1)
151 {
152 hashWriter << vChain[powh]->GetVerusEntropyHashComponent();
153 }
154 if (alth != -1)
155 {
156 hashWriter << vChain[alth]->GetVerusEntropyHashComponent();
157 }
158 return hashWriter.GetHash();
159}
160
e8b5f0d5 161CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
162 int nStep = 1;
163 std::vector<uint256> vHave;
164 vHave.reserve(32);
165
166 if (!pindex)
167 pindex = Tip();
168 while (pindex) {
169 vHave.push_back(pindex->GetBlockHash());
170 // Stop when we have added the genesis block.
4b729ec5 171 if (pindex->GetHeight() == 0)
e8b5f0d5 172 break;
173 // Exponentially larger steps back, plus the genesis block.
4b729ec5 174 int nHeight = std::max(pindex->GetHeight() - nStep, 0);
e8b5f0d5 175 if (Contains(pindex)) {
176 // Use O(1) CChain index if possible.
177 pindex = (*this)[nHeight];
178 } else {
179 // Otherwise, use O(log n) skiplist.
180 pindex = pindex->GetAncestor(nHeight);
181 }
182 if (vHave.size() > 10)
183 nStep *= 2;
184 }
185
186 return CBlockLocator(vHave);
187}
188
189const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
df473cc2 190 if ( pindex == 0 )
191 return(0);
4b729ec5 192 if (pindex->GetHeight() > Height())
e8b5f0d5 193 pindex = pindex->GetAncestor(Height());
194 while (pindex && !Contains(pindex))
195 pindex = pindex->pprev;
196 return pindex;
197}
5ea3bc06 198
4b729ec5 199CChainPower::CChainPower(CBlockIndex *pblockIndex)
200{
201 nHeight = pblockIndex->GetHeight();
202 chainStake = arith_uint256(0);
203 chainWork = arith_uint256(0);
204}
205
206CChainPower::CChainPower(CBlockIndex *pblockIndex, const arith_uint256 &stake, const arith_uint256 &work)
207{
208 nHeight = pblockIndex->GetHeight();
209 chainStake = stake;
210 chainWork = work;
211}
212
213bool operator==(const CChainPower &p1, const CChainPower &p2)
214{
215 arith_uint256 bigZero = arith_uint256(0);
216 arith_uint256 workDivisor = p1.chainWork > p2.chainWork ? p1.chainWork : (p2.chainWork != bigZero ? p2.chainWork : 1);
217 arith_uint256 stakeDivisor = p1.chainStake > p2.chainStake ? p1.chainStake : (p2.chainStake != bigZero ? p2.chainStake : 1);
218
219 // use up 16 bits for precision
220 return ((p1.chainWork << 16) / workDivisor + (p1.chainStake << 16) / stakeDivisor) ==
221 ((p2.chainWork << 16) / workDivisor + (p2.chainStake << 16) / stakeDivisor);
222}
223
224bool operator<(const CChainPower &p1, const CChainPower &p2)
225{
226 arith_uint256 bigZero = arith_uint256(0);
227 arith_uint256 workDivisor = p1.chainWork > p2.chainWork ? p1.chainWork : (p2.chainWork != bigZero ? p2.chainWork : 1);
228 arith_uint256 stakeDivisor = p1.chainStake > p2.chainStake ? p1.chainStake : (p2.chainStake != bigZero ? p2.chainStake : 1);
229
230 // use up 16 bits for precision
231 return ((p1.chainWork << 16) / workDivisor + (p1.chainStake << 16) / stakeDivisor) <
232 ((p2.chainWork << 16) / workDivisor + (p2.chainStake << 16) / stakeDivisor);
233}
234
235bool operator<=(const CChainPower &p1, const CChainPower &p2)
236{
237 arith_uint256 bigZero = arith_uint256(0);
238 arith_uint256 workDivisor = p1.chainWork > p2.chainWork ? p1.chainWork : (p2.chainWork != bigZero ? p2.chainWork : 1);
239 arith_uint256 stakeDivisor = p1.chainStake > p2.chainStake ? p1.chainStake : (p2.chainStake != bigZero ? p2.chainStake : 1);
240
241 // use up 16 bits for precision
242 return ((p1.chainWork << 16) / workDivisor + (p1.chainStake << 16) / stakeDivisor) <=
243 ((p2.chainWork << 16) / workDivisor + (p2.chainStake << 16) / stakeDivisor);
244}
245
b2a98c42
MT
246CChainPower ExpandCompactPower(uint256 compactPower, uint32_t height)
247{
248 return CChainPower(height, UintToArith256(compactPower) >> 128, (UintToArith256(compactPower) << 128) >> 128);
249}
4b729ec5 250
5ea3bc06
PW
251/** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
252int static inline InvertLowestOne(int n) { return n & (n - 1); }
253
254/** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
255int static inline GetSkipHeight(int height) {
256 if (height < 2)
257 return 0;
258
259 // Determine which height to jump back to. Any number strictly lower than height is acceptable,
260 // but the following expression seems to perform well in simulations (max 110 steps to go back
261 // up to 2**18 blocks).
262 return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
263}
264
265CBlockIndex* CBlockIndex::GetAncestor(int height)
266{
4b729ec5 267 if (height > GetHeight() || height < 0)
5ea3bc06
PW
268 return NULL;
269
270 CBlockIndex* pindexWalk = this;
4b729ec5 271 int heightWalk = GetHeight();
5298d41f 272 while ( heightWalk > height && pindexWalk != 0 )
273 {
5ea3bc06
PW
274 int heightSkip = GetSkipHeight(heightWalk);
275 int heightSkipPrev = GetSkipHeight(heightWalk - 1);
bfa832c7
PW
276 if (pindexWalk->pskip != NULL &&
277 (heightSkip == height ||
278 (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
279 heightSkipPrev >= height)))) {
5ea3bc06
PW
280 // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
281 pindexWalk = pindexWalk->pskip;
282 heightWalk = heightSkip;
283 } else {
7b1acda3 284 assert(pindexWalk->pprev);
5ea3bc06
PW
285 pindexWalk = pindexWalk->pprev;
286 heightWalk--;
287 }
288 }
289 return pindexWalk;
290}
291
292const CBlockIndex* CBlockIndex::GetAncestor(int height) const
293{
294 return const_cast<CBlockIndex*>(this)->GetAncestor(height);
295}
296
297void CBlockIndex::BuildSkip()
298{
299 if (pprev)
08d46b7f 300 {
1403a5da 301 //printf("building skip - current:\n%s\nprev:\n%s\n", ToString().c_str(), pprev->ToString().c_str());
4b729ec5 302 pskip = pprev->GetAncestor(GetSkipHeight(GetHeight()));
08d46b7f 303 }
5ea3bc06 304}
This page took 0.216245 seconds and 4 git commands to generate.