]>
Commit | Line | Data |
---|---|---|
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 | ||
8 | using namespace std; | |
9 | ||
2fdc3351 MF |
10 | /** |
11 | * CChain implementation | |
12 | */ | |
b7ae2c17 | 13 | void 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 | |
39 | bool 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 | 81 | uint256 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. | |
96 | uint256 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 | 161 | CBlockLocator 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 | ||
189 | const 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 | 199 | CChainPower::CChainPower(CBlockIndex *pblockIndex) |
200 | { | |
201 | nHeight = pblockIndex->GetHeight(); | |
202 | chainStake = arith_uint256(0); | |
203 | chainWork = arith_uint256(0); | |
204 | } | |
205 | ||
206 | CChainPower::CChainPower(CBlockIndex *pblockIndex, const arith_uint256 &stake, const arith_uint256 &work) | |
207 | { | |
208 | nHeight = pblockIndex->GetHeight(); | |
209 | chainStake = stake; | |
210 | chainWork = work; | |
211 | } | |
212 | ||
213 | bool 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 | ||
224 | bool 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 | ||
235 | bool 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 |
246 | CChainPower 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'. */ |
252 | int static inline InvertLowestOne(int n) { return n & (n - 1); } | |
253 | ||
254 | /** Compute what height to jump back to with the CBlockIndex::pskip pointer. */ | |
255 | int 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 | ||
265 | CBlockIndex* 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 | ||
292 | const CBlockIndex* CBlockIndex::GetAncestor(int height) const | |
293 | { | |
294 | return const_cast<CBlockIndex*>(this)->GetAncestor(height); | |
295 | } | |
296 | ||
297 | void 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 | } |