]> Git Repo - VerusCoin.git/blame - src/txdb.cpp
Significant mining optimization and POS DAA modification
[VerusCoin.git] / src / txdb.cpp
CommitLineData
2d8a4829 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
78253fcb 3// Distributed under the MIT software license, see the accompanying
2d8a4829
PW
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
4ca60bba 6#include "txdb.h"
51ed9ec9 7
d698ef69
JT
8#include "chainparams.h"
9#include "hash.h"
8a893c94 10#include "main.h"
df852d2b 11#include "pow.h"
51ed9ec9
BD
12#include "uint256.h"
13
14#include <stdint.h>
2d8a4829 15
611116d4
PK
16#include <boost/thread.hpp>
17
2d8a4829
PW
18using namespace std;
19
9f25631d 20static const char DB_ANCHOR = 'A';
22de1602 21static const char DB_NULLIFIER = 's';
14d023f1
E
22static const char DB_COINS = 'c';
23static const char DB_BLOCK_FILES = 'f';
24static const char DB_TXINDEX = 't';
8b78a819
T
25static const char DB_ADDRESSINDEX = 'd';
26static const char DB_ADDRESSUNSPENTINDEX = 'u';
27static const char DB_TIMESTAMPINDEX = 'S';
28static const char DB_BLOCKHASHINDEX = 'z';
29static const char DB_SPENTINDEX = 'p';
14d023f1
E
30static const char DB_BLOCK_INDEX = 'b';
31
32static const char DB_BEST_BLOCK = 'B';
9f25631d 33static const char DB_BEST_ANCHOR = 'a';
14d023f1
E
34static const char DB_FLAG = 'F';
35static const char DB_REINDEX_FLAG = 'R';
36static const char DB_LAST_BLOCK = 'l';
37
38
9f25631d
SB
39void static BatchWriteAnchor(CLevelDBBatch &batch,
40 const uint256 &croot,
434f3284 41 const ZCIncrementalMerkleTree &tree,
9f25631d
SB
42 const bool &entered)
43{
44 if (!entered)
45 batch.Erase(make_pair(DB_ANCHOR, croot));
46 else {
434f3284 47 batch.Write(make_pair(DB_ANCHOR, croot), tree);
9f25631d
SB
48 }
49}
50
22de1602 51void static BatchWriteNullifier(CLevelDBBatch &batch, const uint256 &nf, const bool &entered) {
45d6bee9 52 if (!entered)
22de1602 53 batch.Erase(make_pair(DB_NULLIFIER, nf));
45d6bee9 54 else
22de1602 55 batch.Write(make_pair(DB_NULLIFIER, nf), true);
45d6bee9
SB
56}
57
2d8a4829
PW
58void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
59 if (coins.IsPruned())
14d023f1 60 batch.Erase(make_pair(DB_COINS, hash));
2d8a4829 61 else
14d023f1 62 batch.Write(make_pair(DB_COINS, hash), coins);
2d8a4829
PW
63}
64
65void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
14d023f1 66 batch.Write(DB_BEST_BLOCK, hash);
2d8a4829
PW
67}
68
9f25631d
SB
69void static BatchWriteHashBestAnchor(CLevelDBBatch &batch, const uint256 &hash) {
70 batch.Write(DB_BEST_ANCHOR, hash);
71}
72
c66c731a
JG
73CCoinsViewDB::CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / dbName, nCacheSize, fMemory, fWipe) {
74}
75
8b78a819 76CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, false, 64) {
2d8a4829
PW
77}
78
9f25631d 79
434f3284 80bool CCoinsViewDB::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const {
bf2e3122 81 if (rt == ZCIncrementalMerkleTree::empty_root()) {
434f3284
SB
82 ZCIncrementalMerkleTree new_tree;
83 tree = new_tree;
9f25631d
SB
84 return true;
85 }
86
434f3284 87 bool read = db.Read(make_pair(DB_ANCHOR, rt), tree);
9f25631d 88
434f3284 89 return read;
9f25631d
SB
90}
91
22de1602 92bool CCoinsViewDB::GetNullifier(const uint256 &nf) const {
45d6bee9 93 bool spent = false;
22de1602 94 bool read = db.Read(make_pair(DB_NULLIFIER, nf), spent);
45d6bee9 95
d66877af 96 return read;
45d6bee9
SB
97}
98
a3dc587a 99bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
14d023f1 100 return db.Read(make_pair(DB_COINS, txid), coins);
2d8a4829
PW
101}
102
a3dc587a 103bool CCoinsViewDB::HaveCoins(const uint256 &txid) const {
14d023f1 104 return db.Exists(make_pair(DB_COINS, txid));
2d8a4829
PW
105}
106
a3dc587a 107uint256 CCoinsViewDB::GetBestBlock() const {
2d8a4829 108 uint256 hashBestChain;
14d023f1 109 if (!db.Read(DB_BEST_BLOCK, hashBestChain))
4f152496 110 return uint256();
84674082 111 return hashBestChain;
2d8a4829
PW
112}
113
9f25631d
SB
114uint256 CCoinsViewDB::GetBestAnchor() const {
115 uint256 hashBestAnchor;
116 if (!db.Read(DB_BEST_ANCHOR, hashBestAnchor))
bf2e3122 117 return ZCIncrementalMerkleTree::empty_root();
9f25631d
SB
118 return hashBestAnchor;
119}
120
121bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins,
122 const uint256 &hashBlock,
123 const uint256 &hashAnchor,
45d6bee9 124 CAnchorsMap &mapAnchors,
bb64be52 125 CNullifiersMap &mapNullifiers) {
2d8a4829 126 CLevelDBBatch batch;
058b08c1
PW
127 size_t count = 0;
128 size_t changed = 0;
b0875eb3 129 for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
058b08c1
PW
130 if (it->second.flags & CCoinsCacheEntry::DIRTY) {
131 BatchWriteCoins(batch, it->first, it->second.coins);
132 changed++;
133 }
134 count++;
b0875eb3
PW
135 CCoinsMap::iterator itOld = it++;
136 mapCoins.erase(itOld);
137 }
9f25631d
SB
138
139 for (CAnchorsMap::iterator it = mapAnchors.begin(); it != mapAnchors.end();) {
140 if (it->second.flags & CAnchorsCacheEntry::DIRTY) {
141 BatchWriteAnchor(batch, it->first, it->second.tree, it->second.entered);
142 // TODO: changed++?
143 }
144 CAnchorsMap::iterator itOld = it++;
145 mapAnchors.erase(itOld);
146 }
147
bb64be52 148 for (CNullifiersMap::iterator it = mapNullifiers.begin(); it != mapNullifiers.end();) {
9e511dbb 149 if (it->second.flags & CNullifiersCacheEntry::DIRTY) {
22de1602 150 BatchWriteNullifier(batch, it->first, it->second.entered);
45d6bee9
SB
151 // TODO: changed++?
152 }
d889a287 153 CNullifiersMap::iterator itOld = it++;
bb64be52 154 mapNullifiers.erase(itOld);
45d6bee9
SB
155 }
156
4f152496 157 if (!hashBlock.IsNull())
84674082 158 BatchWriteHashBestChain(batch, hashBlock);
9f25631d
SB
159 if (!hashAnchor.IsNull())
160 BatchWriteHashBestAnchor(batch, hashAnchor);
2d8a4829 161
058b08c1 162 LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
2d8a4829
PW
163 return db.WriteBatch(batch);
164}
165
8b78a819 166CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe, bool compression, int maxOpenFiles) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe, compression, maxOpenFiles) {
e1bfbab8
PW
167}
168
2d8a4829 169bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
14d023f1 170 return Read(make_pair(DB_BLOCK_FILES, nFile), info);
2d8a4829
PW
171}
172
7fea4846
PW
173bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
174 if (fReindexing)
14d023f1 175 return Write(DB_REINDEX_FLAG, '1');
7fea4846 176 else
14d023f1 177 return Erase(DB_REINDEX_FLAG);
7fea4846
PW
178}
179
180bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
14d023f1 181 fReindexing = Exists(DB_REINDEX_FLAG);
7fea4846
PW
182 return true;
183}
184
2d8a4829 185bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
14d023f1 186 return Read(DB_LAST_BLOCK, nFile);
2d8a4829
PW
187}
188
a3dc587a
DK
189bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
190 /* It seems that there are no "const iterators" for LevelDB. Since we
191 only need read operations on it, use a const-cast to get around
192 that restriction. */
33dfbf57 193 boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
beeb5761
PW
194 pcursor->SeekToFirst();
195
e31aa7c9 196 CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
84674082 197 stats.hashBlock = GetBestBlock();
e31aa7c9 198 ss << stats.hashBlock;
a372168e 199 CAmount nTotalAmount = 0;
beeb5761 200 while (pcursor->Valid()) {
b31499ec 201 boost::this_thread::interruption_point();
beeb5761
PW
202 try {
203 leveldb::Slice slKey = pcursor->key();
204 CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
205 char chType;
206 ssKey >> chType;
14d023f1 207 if (chType == DB_COINS) {
beeb5761
PW
208 leveldb::Slice slValue = pcursor->value();
209 CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
210 CCoins coins;
211 ssValue >> coins;
212 uint256 txhash;
213 ssKey >> txhash;
e31aa7c9
PW
214 ss << txhash;
215 ss << VARINT(coins.nVersion);
96e5f61d 216 ss << (coins.fCoinBase ? 'c' : 'n');
e31aa7c9 217 ss << VARINT(coins.nHeight);
beeb5761 218 stats.nTransactions++;
e31aa7c9
PW
219 for (unsigned int i=0; i<coins.vout.size(); i++) {
220 const CTxOut &out = coins.vout[i];
221 if (!out.IsNull()) {
beeb5761 222 stats.nTransactionOutputs++;
e31aa7c9
PW
223 ss << VARINT(i+1);
224 ss << out;
225 nTotalAmount += out.nValue;
226 }
beeb5761
PW
227 }
228 stats.nSerializedSize += 32 + slValue.size();
e31aa7c9 229 ss << VARINT(0);
beeb5761
PW
230 }
231 pcursor->Next();
27df4123 232 } catch (const std::exception& e) {
5262fde0 233 return error("%s: Deserialize or I/O error - %s", __func__, e.what());
beeb5761
PW
234 }
235 }
a0455eca
WL
236 {
237 LOCK(cs_main);
238 stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight;
239 }
e31aa7c9
PW
240 stats.hashSerialized = ss.GetHash();
241 stats.nTotalAmount = nTotalAmount;
beeb5761
PW
242 return true;
243}
244
63d1ae55
PW
245bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
246 CLevelDBBatch batch;
247 for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
14d023f1 248 batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
63d1ae55 249 }
14d023f1 250 batch.Write(DB_LAST_BLOCK, nLastFile);
63d1ae55 251 for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
14d023f1 252 batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
63d1ae55
PW
253 }
254 return WriteBatch(batch, true);
255}
256
2d1fa42e 257bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
14d023f1 258 return Read(make_pair(DB_TXINDEX, txid), pos);
2d1fa42e
PW
259}
260
261bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
262 CLevelDBBatch batch;
263 for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
14d023f1 264 batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
2d1fa42e
PW
265 return WriteBatch(batch);
266}
267
8b78a819
T
268bool CBlockTreeDB::ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) {
269 return Read(make_pair(DB_SPENTINDEX, key), value);
270}
271
272bool CBlockTreeDB::UpdateSpentIndex(const std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> >&vect) {
273 CLevelDBBatch batch;
274 for (std::vector<std::pair<CSpentIndexKey,CSpentIndexValue> >::const_iterator it=vect.begin(); it!=vect.end(); it++) {
275 if (it->second.IsNull()) {
276 batch.Erase(make_pair(DB_SPENTINDEX, it->first));
277 } else {
278 batch.Write(make_pair(DB_SPENTINDEX, it->first), it->second);
279 }
280 }
281 return WriteBatch(batch);
282}
283
284bool CBlockTreeDB::UpdateAddressUnspentIndex(const std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue > >&vect) {
285 CLevelDBBatch batch;
286 for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=vect.begin(); it!=vect.end(); it++) {
287 if (it->second.IsNull()) {
288 batch.Erase(make_pair(DB_ADDRESSUNSPENTINDEX, it->first));
289 } else {
290 batch.Write(make_pair(DB_ADDRESSUNSPENTINDEX, it->first), it->second);
291 }
292 }
293 return WriteBatch(batch);
294}
295
296bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, int type,
297 std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs) {
298
299 boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
300
301 CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
302 ssKeySet << make_pair(DB_ADDRESSUNSPENTINDEX, CAddressIndexIteratorKey(type, addressHash));
303 pcursor->Seek(ssKeySet.str());
304
305 while (pcursor->Valid()) {
306 boost::this_thread::interruption_point();
307 try {
308 leveldb::Slice slKey = pcursor->key();
309 CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
310 char chType;
311 CAddressUnspentKey indexKey;
312 ssKey >> chType;
313 ssKey >> indexKey;
314 if (chType == DB_ADDRESSUNSPENTINDEX && indexKey.hashBytes == addressHash) {
315 try {
316 leveldb::Slice slValue = pcursor->value();
317 CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
318 CAddressUnspentValue nValue;
319 ssValue >> nValue;
320 unspentOutputs.push_back(make_pair(indexKey, nValue));
321 pcursor->Next();
322 } catch (const std::exception& e) {
323 return error("failed to get address unspent value");
324 }
325 } else {
326 break;
327 }
328 } catch (const std::exception& e) {
329 break;
330 }
331 }
332
333 return true;
334}
335
336bool CBlockTreeDB::WriteAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount > >&vect) {
337 CLevelDBBatch batch;
338 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
339 batch.Write(make_pair(DB_ADDRESSINDEX, it->first), it->second);
340 return WriteBatch(batch);
341}
342
343bool CBlockTreeDB::EraseAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount > >&vect) {
344 CLevelDBBatch batch;
345 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
346 batch.Erase(make_pair(DB_ADDRESSINDEX, it->first));
347 return WriteBatch(batch);
348}
349
350bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type,
351 std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
352 int start, int end) {
353
354 boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
355
356 CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
357 if (start > 0 && end > 0) {
358 ssKeySet << make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorHeightKey(type, addressHash, start));
359 } else {
360 ssKeySet << make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorKey(type, addressHash));
361 }
362 pcursor->Seek(ssKeySet.str());
363
364 while (pcursor->Valid()) {
365 boost::this_thread::interruption_point();
366 try {
367 leveldb::Slice slKey = pcursor->key();
368 CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
369 char chType;
370 CAddressIndexKey indexKey;
371 ssKey >> chType;
372 ssKey >> indexKey;
373 if (chType == DB_ADDRESSINDEX && indexKey.hashBytes == addressHash) {
374 if (end > 0 && indexKey.blockHeight > end) {
375 break;
376 }
377 try {
378 leveldb::Slice slValue = pcursor->value();
379 CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
380 CAmount nValue;
381 ssValue >> nValue;
382
383 addressIndex.push_back(make_pair(indexKey, nValue));
384 pcursor->Next();
385 } catch (const std::exception& e) {
386 return error("failed to get address index value");
387 }
388 } else {
389 break;
390 }
391 } catch (const std::exception& e) {
392 break;
393 }
394 }
395
396 return true;
397}
398
399bool CBlockTreeDB::WriteTimestampIndex(const CTimestampIndexKey &timestampIndex) {
400 CLevelDBBatch batch;
401 batch.Write(make_pair(DB_TIMESTAMPINDEX, timestampIndex), 0);
402 return WriteBatch(batch);
403}
404
405bool CBlockTreeDB::ReadTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector<std::pair<uint256, unsigned int> > &hashes) {
406
407 boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
408
409 CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
410 ssKeySet << make_pair(DB_TIMESTAMPINDEX, CTimestampIndexIteratorKey(low));
411 pcursor->Seek(ssKeySet.str());
412
413 while (pcursor->Valid()) {
414 boost::this_thread::interruption_point();
415 try {
416 leveldb::Slice slKey = pcursor->key();
417 CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
418 char chType;
419 CTimestampIndexKey indexKey;
420 ssKey >> chType;
421 ssKey >> indexKey;
422 if (chType == DB_TIMESTAMPINDEX && indexKey.timestamp < high) {
423 if (fActiveOnly) {
424 if (blockOnchainActive(indexKey.blockHash)) {
425 hashes.push_back(std::make_pair(indexKey.blockHash, indexKey.timestamp));
426 }
427 } else {
428 hashes.push_back(std::make_pair(indexKey.blockHash, indexKey.timestamp));
429 }
430
431 pcursor->Next();
432 } else {
433 break;
434 }
435 } catch (const std::exception& e) {
436 break;
437 }
438 }
439
440 return true;
441}
442
443bool CBlockTreeDB::WriteTimestampBlockIndex(const CTimestampBlockIndexKey &blockhashIndex, const CTimestampBlockIndexValue &logicalts) {
444 CLevelDBBatch batch;
445 batch.Write(make_pair(DB_BLOCKHASHINDEX, blockhashIndex), logicalts);
446 return WriteBatch(batch);
447}
448
449bool CBlockTreeDB::ReadTimestampBlockIndex(const uint256 &hash, unsigned int &ltimestamp) {
450
451 CTimestampBlockIndexValue(lts);
452 if (!Read(std::make_pair(DB_BLOCKHASHINDEX, hash), lts))
453 return false;
454
455 ltimestamp = lts.ltimestamp;
456 return true;
457}
458
2d1fa42e 459bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
14d023f1 460 return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
2d1fa42e
PW
461}
462
463bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
464 char ch;
14d023f1 465 if (!Read(std::make_pair(DB_FLAG, name), ch))
2d1fa42e
PW
466 return false;
467 fValue = ch == '1';
468 return true;
469}
470
5b39c60e 471void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height);
ddcdf567 472
8b78a819
T
473bool CBlockTreeDB::blockOnchainActive(const uint256 &hash) {
474 CBlockIndex* pblockindex = mapBlockIndex[hash];
475
476 if (!chainActive.Contains(pblockindex)) {
477 return false;
478 }
479
480 return true;
481}
482
2d8a4829
PW
483bool CBlockTreeDB::LoadBlockIndexGuts()
484{
5cbda4f1 485 boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
2d8a4829
PW
486
487 CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
14d023f1 488 ssKeySet << make_pair(DB_BLOCK_INDEX, uint256());
2d8a4829
PW
489 pcursor->Seek(ssKeySet.str());
490
491 // Load mapBlockIndex
492 while (pcursor->Valid()) {
b31499ec 493 boost::this_thread::interruption_point();
2d8a4829
PW
494 try {
495 leveldb::Slice slKey = pcursor->key();
496 CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
497 char chType;
498 ssKey >> chType;
14d023f1 499 if (chType == DB_BLOCK_INDEX) {
2d8a4829
PW
500 leveldb::Slice slValue = pcursor->value();
501 CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
502 CDiskBlockIndex diskindex;
503 ssValue >> diskindex;
504
505 // Construct block index object
506 CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
507 pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
508 pindexNew->nHeight = diskindex.nHeight;
509 pindexNew->nFile = diskindex.nFile;
510 pindexNew->nDataPos = diskindex.nDataPos;
511 pindexNew->nUndoPos = diskindex.nUndoPos;
b6961fc1 512 pindexNew->hashAnchor = diskindex.hashAnchor;
2d8a4829 513 pindexNew->nVersion = diskindex.nVersion;
81c5ec4f 514 pindexNew->hashReserved = diskindex.hashReserved;
2d8a4829 515 pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
15fb13f6 516 pindexNew->hashReserved = diskindex.hashReserved;
2d8a4829
PW
517 pindexNew->nTime = diskindex.nTime;
518 pindexNew->nBits = diskindex.nBits;
519 pindexNew->nNonce = diskindex.nNonce;
fdda3c50 520 pindexNew->nSolution = diskindex.nSolution;
2d8a4829 521 pindexNew->nStatus = diskindex.nStatus;
828940b1 522 pindexNew->nCachedBranchId = diskindex.nCachedBranchId;
2d8a4829 523 pindexNew->nTx = diskindex.nTx;
ad6a36ad 524 pindexNew->nSproutValue = diskindex.nSproutValue;
9000990c 525
704b7635 526 // Consistency checks
44488400 527 auto header = pindexNew->GetBlockHeader();
704b7635
JG
528 if (header.GetHash() != pindexNew->GetBlockHash())
529 return error("LoadBlockIndex(): block header inconsistency detected: on-disk = %s, in-memory = %s",
9000990c 530 diskindex.ToString(), pindexNew->ToString());
103fde35 531 if ( 0 ) // POW will be checked before any block is connected
532 {
533 uint8_t pubkey33[33];
534 komodo_index2pubkey33(pubkey33,pindexNew,pindexNew->nHeight);
1f722359 535 if (!CheckProofOfWork(header,pubkey33,pindexNew->nHeight,Params().GetConsensus()))
103fde35 536 return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());
537 }
2d8a4829
PW
538 pcursor->Next();
539 } else {
540 break; // if shutdown requested or finished loading block index
541 }
27df4123 542 } catch (const std::exception& e) {
5262fde0 543 return error("%s: Deserialize or I/O error - %s", __func__, e.what());
2d8a4829
PW
544 }
545 }
2d8a4829
PW
546
547 return true;
548}
This page took 0.353256 seconds and 4 git commands to generate.