Update to 0.3.0 (New upstream + new RPC calls)
[novacoin.git] / src / db.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Copyright (c) 2011-2013 The PPCoin developers
4 // Distributed under the MIT/X11 software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6
7 #include "db.h"
8 #include "net.h"
9 #include "checkpoints.h"
10 #include "util.h"
11 #include "main.h"
12 #include "kernel.h"
13 #include <boost/version.hpp>
14 #include <boost/filesystem.hpp>
15 #include <boost/filesystem/fstream.hpp>
16
17 #ifndef WIN32
18 #include "sys/stat.h"
19 #endif
20
21 using namespace std;
22 using namespace boost;
23
24
25 unsigned int nWalletDBUpdated;
26
27
28
29 //
30 // CDB
31 //
32
33 CCriticalSection cs_db;
34 static bool fDbEnvInit = false;
35 bool fDetachDB = false;
36 DbEnv dbenv(0);
37 map<string, int> mapFileUseCount;
38 static map<string, Db*> mapDb;
39
40 static void EnvShutdown()
41 {
42     if (!fDbEnvInit)
43         return;
44
45     fDbEnvInit = false;
46     try
47     {
48         dbenv.close(0);
49     }
50     catch (const DbException& e)
51     {
52         printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
53     }
54     DbEnv(0).remove(GetDataDir().string().c_str(), 0);
55 }
56
57 class CDBInit
58 {
59 public:
60     CDBInit()
61     {
62     }
63     ~CDBInit()
64     {
65         EnvShutdown();
66     }
67 }
68 instance_of_cdbinit;
69
70
71 CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
72 {
73     int ret;
74     if (pszFile == NULL)
75         return;
76
77     fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
78     bool fCreate = strchr(pszMode, 'c');
79     unsigned int nFlags = DB_THREAD;
80     if (fCreate)
81         nFlags |= DB_CREATE;
82
83     {
84         LOCK(cs_db);
85         if (!fDbEnvInit)
86         {
87             if (fShutdown)
88                 return;
89             filesystem::path pathDataDir = GetDataDir();
90             filesystem::path pathLogDir = pathDataDir / "database";
91             filesystem::create_directory(pathLogDir);
92             filesystem::path pathErrorFile = pathDataDir / "db.log";
93             printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str());
94
95             int nDbCache = GetArg("-dbcache", 25);
96             dbenv.set_lg_dir(pathLogDir.string().c_str());
97             dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1);
98             dbenv.set_lg_bsize(1048576);
99             dbenv.set_lg_max(10485760);
100             dbenv.set_lk_max_locks(10000);
101             dbenv.set_lk_max_objects(10000);
102             dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
103             dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
104             dbenv.set_flags(DB_AUTO_COMMIT, 1);
105             dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
106             ret = dbenv.open(pathDataDir.string().c_str(),
107                              DB_CREATE     |
108                              DB_INIT_LOCK  |
109                              DB_INIT_LOG   |
110                              DB_INIT_MPOOL |
111                              DB_INIT_TXN   |
112                              DB_THREAD     |
113                              DB_RECOVER,
114                              S_IRUSR | S_IWUSR);
115             if (ret > 0)
116                 throw runtime_error(strprintf("CDB() : error %d opening database environment", ret));
117             fDbEnvInit = true;
118         }
119
120         strFile = pszFile;
121         ++mapFileUseCount[strFile];
122         pdb = mapDb[strFile];
123         if (pdb == NULL)
124         {
125             pdb = new Db(&dbenv, 0);
126
127             ret = pdb->open(NULL,      // Txn pointer
128                             pszFile,   // Filename
129                             "main",    // Logical db name
130                             DB_BTREE,  // Database type
131                             nFlags,    // Flags
132                             0);
133
134             if (ret > 0)
135             {
136                 delete pdb;
137                 pdb = NULL;
138                 {
139                      LOCK(cs_db);
140                     --mapFileUseCount[strFile];
141                 }
142                 strFile = "";
143                 throw runtime_error(strprintf("CDB() : can't open database file %s, error %d", pszFile, ret));
144             }
145
146             if (fCreate && !Exists(string("version")))
147             {
148                 bool fTmp = fReadOnly;
149                 fReadOnly = false;
150                 WriteVersion(CLIENT_VERSION);
151                 fReadOnly = fTmp;
152             }
153
154             mapDb[strFile] = pdb;
155         }
156     }
157 }
158
159 void CDB::Close()
160 {
161     if (!pdb)
162         return;
163     if (!vTxn.empty())
164         vTxn.front()->abort();
165     vTxn.clear();
166     pdb = NULL;
167
168     // Flush database activity from memory pool to disk log
169     unsigned int nMinutes = 0;
170     if (fReadOnly)
171         nMinutes = 1;
172     if (strFile == "addr.dat")
173         nMinutes = 2;
174     if (strFile == "blkindex.dat")
175         nMinutes = 2;
176     if (strFile == "blkindex.dat" && IsInitialBlockDownload())
177         nMinutes = 5;
178
179     dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
180
181     {
182         LOCK(cs_db);
183         --mapFileUseCount[strFile];
184     }
185 }
186
187 void CloseDb(const string& strFile)
188 {
189     {
190         LOCK(cs_db);
191         if (mapDb[strFile] != NULL)
192         {
193             // Close the database handle
194             Db* pdb = mapDb[strFile];
195             pdb->close(0);
196             delete pdb;
197             mapDb[strFile] = NULL;
198         }
199     }
200 }
201
202 bool CDB::Rewrite(const string& strFile, const char* pszSkip)
203 {
204     while (!fShutdown)
205     {
206         {
207             LOCK(cs_db);
208             if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
209             {
210                 // Flush log data to the dat file
211                 CloseDb(strFile);
212                 dbenv.txn_checkpoint(0, 0, 0);
213                 dbenv.lsn_reset(strFile.c_str(), 0);
214                 mapFileUseCount.erase(strFile);
215
216                 bool fSuccess = true;
217                 printf("Rewriting %s...\n", strFile.c_str());
218                 string strFileRes = strFile + ".rewrite";
219                 { // surround usage of db with extra {}
220                     CDB db(strFile.c_str(), "r");
221                     Db* pdbCopy = new Db(&dbenv, 0);
222     
223                     int ret = pdbCopy->open(NULL,                 // Txn pointer
224                                             strFileRes.c_str(),   // Filename
225                                             "main",    // Logical db name
226                                             DB_BTREE,  // Database type
227                                             DB_CREATE,    // Flags
228                                             0);
229                     if (ret > 0)
230                     {
231                         printf("Cannot create database file %s\n", strFileRes.c_str());
232                         fSuccess = false;
233                     }
234     
235                     Dbc* pcursor = db.GetCursor();
236                     if (pcursor)
237                         while (fSuccess)
238                         {
239                             CDataStream ssKey(SER_DISK, CLIENT_VERSION);
240                             CDataStream ssValue(SER_DISK, CLIENT_VERSION);
241                             int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
242                             if (ret == DB_NOTFOUND)
243                             {
244                                 pcursor->close();
245                                 break;
246                             }
247                             else if (ret != 0)
248                             {
249                                 pcursor->close();
250                                 fSuccess = false;
251                                 break;
252                             }
253                             if (pszSkip &&
254                                 strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0)
255                                 continue;
256                             if (strncmp(&ssKey[0], "\x07version", 8) == 0)
257                             {
258                                 // Update version:
259                                 ssValue.clear();
260                                 ssValue << CLIENT_VERSION;
261                             }
262                             Dbt datKey(&ssKey[0], ssKey.size());
263                             Dbt datValue(&ssValue[0], ssValue.size());
264                             int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE);
265                             if (ret2 > 0)
266                                 fSuccess = false;
267                         }
268                     if (fSuccess)
269                     {
270                         db.Close();
271                         CloseDb(strFile);
272                         if (pdbCopy->close(0))
273                             fSuccess = false;
274                         delete pdbCopy;
275                     }
276                 }
277                 if (fSuccess)
278                 {
279                     Db dbA(&dbenv, 0);
280                     if (dbA.remove(strFile.c_str(), NULL, 0))
281                         fSuccess = false;
282                     Db dbB(&dbenv, 0);
283                     if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0))
284                         fSuccess = false;
285                 }
286                 if (!fSuccess)
287                     printf("Rewriting of %s FAILED!\n", strFileRes.c_str());
288                 return fSuccess;
289             }
290         }
291         Sleep(100);
292     }
293     return false;
294 }
295
296
297 void DBFlush(bool fShutdown)
298 {
299     // Flush log data to the actual data file
300     //  on all files that are not in use
301     printf("DBFlush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
302     if (!fDbEnvInit)
303         return;
304     {
305         LOCK(cs_db);
306         map<string, int>::iterator mi = mapFileUseCount.begin();
307         while (mi != mapFileUseCount.end())
308         {
309             string strFile = (*mi).first;
310             int nRefCount = (*mi).second;
311             printf("%s refcount=%d\n", strFile.c_str(), nRefCount);
312             if (nRefCount == 0)
313             {
314                 // Move log data to the dat file
315                 CloseDb(strFile);
316                 printf("%s checkpoint\n", strFile.c_str());
317                 dbenv.txn_checkpoint(0, 0, 0);
318                 if ((strFile != "blkindex.dat" && strFile != "addr.dat") || fDetachDB) {
319                     printf("%s detach\n", strFile.c_str());
320                     dbenv.lsn_reset(strFile.c_str(), 0);
321                 }
322                 printf("%s closed\n", strFile.c_str());
323                 mapFileUseCount.erase(mi++);
324             }
325             else
326                 mi++;
327         }
328         if (fShutdown)
329         {
330             char** listp;
331             if (mapFileUseCount.empty())
332             {
333                 dbenv.log_archive(&listp, DB_ARCH_REMOVE);
334                 EnvShutdown();
335             }
336         }
337     }
338 }
339
340
341
342
343
344
345 //
346 // CTxDB
347 //
348
349 bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex)
350 {
351     assert(!fClient);
352     txindex.SetNull();
353     return Read(make_pair(string("tx"), hash), txindex);
354 }
355
356 bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
357 {
358     assert(!fClient);
359     return Write(make_pair(string("tx"), hash), txindex);
360 }
361
362 bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight)
363 {
364     assert(!fClient);
365
366     // Add to tx index
367     uint256 hash = tx.GetHash();
368     CTxIndex txindex(pos, tx.vout.size());
369     return Write(make_pair(string("tx"), hash), txindex);
370 }
371
372 bool CTxDB::EraseTxIndex(const CTransaction& tx)
373 {
374     assert(!fClient);
375     uint256 hash = tx.GetHash();
376
377     return Erase(make_pair(string("tx"), hash));
378 }
379
380 bool CTxDB::ContainsTx(uint256 hash)
381 {
382     assert(!fClient);
383     return Exists(make_pair(string("tx"), hash));
384 }
385
386 bool CTxDB::ReadOwnerTxes(uint160 hash160, int nMinHeight, vector<CTransaction>& vtx)
387 {
388     assert(!fClient);
389     vtx.clear();
390
391     // Get cursor
392     Dbc* pcursor = GetCursor();
393     if (!pcursor)
394         return false;
395
396     unsigned int fFlags = DB_SET_RANGE;
397     loop
398     {
399         // Read next record
400         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
401         if (fFlags == DB_SET_RANGE)
402             ssKey << string("owner") << hash160 << CDiskTxPos(0, 0, 0);
403         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
404         int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
405         fFlags = DB_NEXT;
406         if (ret == DB_NOTFOUND)
407             break;
408         else if (ret != 0)
409         {
410             pcursor->close();
411             return false;
412         }
413
414         // Unserialize
415         string strType;
416         uint160 hashItem;
417         CDiskTxPos pos;
418         int nItemHeight;
419
420         try {
421             ssKey >> strType >> hashItem >> pos;
422             ssValue >> nItemHeight;
423         }
424         catch (std::exception &e) {
425             return error("%s() : deserialize error", __PRETTY_FUNCTION__);
426         }
427
428         // Read transaction
429         if (strType != "owner" || hashItem != hash160)
430             break;
431         if (nItemHeight >= nMinHeight)
432         {
433             vtx.resize(vtx.size()+1);
434             if (!vtx.back().ReadFromDisk(pos))
435             {
436                 pcursor->close();
437                 return false;
438             }
439         }
440     }
441
442     pcursor->close();
443     return true;
444 }
445
446 bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex)
447 {
448     assert(!fClient);
449     tx.SetNull();
450     if (!ReadTxIndex(hash, txindex))
451         return false;
452     return (tx.ReadFromDisk(txindex.pos));
453 }
454
455 bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx)
456 {
457     CTxIndex txindex;
458     return ReadDiskTx(hash, tx, txindex);
459 }
460
461 bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex)
462 {
463     return ReadDiskTx(outpoint.hash, tx, txindex);
464 }
465
466 bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx)
467 {
468     CTxIndex txindex;
469     return ReadDiskTx(outpoint.hash, tx, txindex);
470 }
471
472 bool CTxDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
473 {
474     return Write(make_pair(string("blockindex"), blockindex.GetBlockHash()), blockindex);
475 }
476
477 bool CTxDB::EraseBlockIndex(uint256 hash)
478 {
479     return Erase(make_pair(string("blockindex"), hash));
480 }
481
482 bool CTxDB::ReadHashBestChain(uint256& hashBestChain)
483 {
484     return Read(string("hashBestChain"), hashBestChain);
485 }
486
487 bool CTxDB::WriteHashBestChain(uint256 hashBestChain)
488 {
489     return Write(string("hashBestChain"), hashBestChain);
490 }
491
492 bool CTxDB::ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust)
493 {
494     return Read(string("bnBestInvalidTrust"), bnBestInvalidTrust);
495 }
496
497 bool CTxDB::WriteBestInvalidTrust(CBigNum bnBestInvalidTrust)
498 {
499     return Write(string("bnBestInvalidTrust"), bnBestInvalidTrust);
500 }
501
502 bool CTxDB::ReadSyncCheckpoint(uint256& hashCheckpoint)
503 {
504     return Read(string("hashSyncCheckpoint"), hashCheckpoint);
505 }
506
507 bool CTxDB::WriteSyncCheckpoint(uint256 hashCheckpoint)
508 {
509     return Write(string("hashSyncCheckpoint"), hashCheckpoint);
510 }
511
512 bool CTxDB::ReadCheckpointPubKey(string& strPubKey)
513 {
514     return Read(string("strCheckpointPubKey"), strPubKey);
515 }
516
517 bool CTxDB::WriteCheckpointPubKey(const string& strPubKey)
518 {
519     return Write(string("strCheckpointPubKey"), strPubKey);
520 }
521
522 CBlockIndex static * InsertBlockIndex(uint256 hash)
523 {
524     if (hash == 0)
525         return NULL;
526
527     // Return existing
528     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
529     if (mi != mapBlockIndex.end())
530         return (*mi).second;
531
532     // Create new
533     CBlockIndex* pindexNew = new CBlockIndex();
534     if (!pindexNew)
535         throw runtime_error("LoadBlockIndex() : new CBlockIndex failed");
536     mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
537     pindexNew->phashBlock = &((*mi).first);
538
539     return pindexNew;
540 }
541
542 bool CTxDB::LoadBlockIndex()
543 {
544     // Get database cursor
545     Dbc* pcursor = GetCursor();
546     if (!pcursor)
547         return false;
548
549     // Load mapBlockIndex
550     unsigned int fFlags = DB_SET_RANGE;
551     loop
552     {
553         // Read next record
554         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
555         if (fFlags == DB_SET_RANGE)
556             ssKey << make_pair(string("blockindex"), uint256(0));
557         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
558         int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
559         fFlags = DB_NEXT;
560         if (ret == DB_NOTFOUND)
561             break;
562         else if (ret != 0)
563             return false;
564
565         // Unserialize
566
567         try {
568         string strType;
569         ssKey >> strType;
570         if (strType == "blockindex" && !fRequestShutdown)
571         {
572             CDiskBlockIndex diskindex;
573             ssValue >> diskindex;
574
575             // Construct block index object
576             CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
577             pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
578             pindexNew->pnext          = InsertBlockIndex(diskindex.hashNext);
579             pindexNew->nFile          = diskindex.nFile;
580             pindexNew->nBlockPos      = diskindex.nBlockPos;
581             pindexNew->nHeight        = diskindex.nHeight;
582             pindexNew->nMint          = diskindex.nMint;
583             pindexNew->nMoneySupply   = diskindex.nMoneySupply;
584             pindexNew->nFlags         = diskindex.nFlags;
585             pindexNew->nStakeModifier = diskindex.nStakeModifier;
586             pindexNew->prevoutStake   = diskindex.prevoutStake;
587             pindexNew->nStakeTime     = diskindex.nStakeTime;
588             pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
589             pindexNew->nVersion       = diskindex.nVersion;
590             pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
591             pindexNew->nTime          = diskindex.nTime;
592             pindexNew->nBits          = diskindex.nBits;
593             pindexNew->nNonce         = diskindex.nNonce;
594
595             // Watch for genesis block
596             if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
597                 pindexGenesisBlock = pindexNew;
598
599             if (!pindexNew->CheckIndex())
600                 return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
601
602             // ppcoin: build setStakeSeen
603             if (pindexNew->IsProofOfStake())
604                 setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime));
605         }
606         else
607         {
608             break; // if shutdown requested or finished loading block index
609         }
610         }    // try
611         catch (std::exception &e) {
612             return error("%s() : deserialize error", __PRETTY_FUNCTION__);
613         }
614     }
615     pcursor->close();
616
617     if (fRequestShutdown)
618         return true;
619
620     // Calculate bnChainTrust
621     vector<pair<int, CBlockIndex*> > vSortedByHeight;
622     vSortedByHeight.reserve(mapBlockIndex.size());
623     BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
624     {
625         CBlockIndex* pindex = item.second;
626         vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex));
627     }
628     sort(vSortedByHeight.begin(), vSortedByHeight.end());
629     BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
630     {
631         CBlockIndex* pindex = item.second;
632         pindex->bnChainTrust = (pindex->pprev ? pindex->pprev->bnChainTrust : 0) + pindex->GetBlockTrust();
633         // ppcoin: calculate stake modifier checksum
634         pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex);
635         if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum))
636             return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016"PRI64x, pindex->nHeight, pindex->nStakeModifier);
637     }
638
639     // Load hashBestChain pointer to end of best chain
640     if (!ReadHashBestChain(hashBestChain))
641     {
642         if (pindexGenesisBlock == NULL)
643             return true;
644         return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded");
645     }
646     if (!mapBlockIndex.count(hashBestChain))
647         return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index");
648     pindexBest = mapBlockIndex[hashBestChain];
649     nBestHeight = pindexBest->nHeight;
650     bnBestChainTrust = pindexBest->bnChainTrust;
651     printf("LoadBlockIndex(): hashBestChain=%s  height=%d  trust=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainTrust.ToString().c_str());
652
653     // ppcoin: load hashSyncCheckpoint
654     if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint))
655         return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded");
656     printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str());
657
658     // Load bnBestInvalidTrust, OK if it doesn't exist
659     ReadBestInvalidTrust(bnBestInvalidTrust);
660
661     // Verify blocks in the best chain
662     int nCheckLevel = GetArg("-checklevel", 1);
663     int nCheckDepth = GetArg( "-checkblocks", 2500);
664     if (nCheckDepth == 0)
665         nCheckDepth = 1000000000; // suffices until the year 19000
666     if (nCheckDepth > nBestHeight)
667         nCheckDepth = nBestHeight;
668     printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
669     CBlockIndex* pindexFork = NULL;
670     map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
671     for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
672     {
673         if (pindex->nHeight < nBestHeight-nCheckDepth)
674             break;
675         CBlock block;
676         if (!block.ReadFromDisk(pindex))
677             return error("LoadBlockIndex() : block.ReadFromDisk failed");
678         // check level 1: verify block validity
679         if (nCheckLevel>0 && !block.CheckBlock())
680         {
681             printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
682             pindexFork = pindex->pprev;
683         }
684         // check level 2: verify transaction index validity
685         if (nCheckLevel>1)
686         {
687             pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos);
688             mapBlockPos[pos] = pindex;
689             BOOST_FOREACH(const CTransaction &tx, block.vtx)
690             {
691                 uint256 hashTx = tx.GetHash();
692                 CTxIndex txindex;
693                 if (ReadTxIndex(hashTx, txindex))
694                 {
695                     // check level 3: checker transaction hashes
696                     if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos)
697                     {
698                         // either an error or a duplicate transaction
699                         CTransaction txFound;
700                         if (!txFound.ReadFromDisk(txindex.pos))
701                         {
702                             printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str());
703                             pindexFork = pindex->pprev;
704                         }
705                         else
706                             if (txFound.GetHash() != hashTx) // not a duplicate tx
707                             {
708                                 printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str());
709                                 pindexFork = pindex->pprev;
710                             }
711                     }
712                     // check level 4: check whether spent txouts were spent within the main chain
713                     unsigned int nOutput = 0;
714                     if (nCheckLevel>3)
715                     {
716                         BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent)
717                         {
718                             if (!txpos.IsNull())
719                             {
720                                 pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos);
721                                 if (!mapBlockPos.count(posFind))
722                                 {
723                                     printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str());
724                                     pindexFork = pindex->pprev;
725                                 }
726                                 // check level 6: check whether spent txouts were spent by a valid transaction that consume them
727                                 if (nCheckLevel>5)
728                                 {
729                                     CTransaction txSpend;
730                                     if (!txSpend.ReadFromDisk(txpos))
731                                     {
732                                         printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput);
733                                         pindexFork = pindex->pprev;
734                                     }
735                                     else if (!txSpend.CheckTransaction())
736                                     {
737                                         printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput);
738                                         pindexFork = pindex->pprev;
739                                     }
740                                     else
741                                     {
742                                         bool fFound = false;
743                                         BOOST_FOREACH(const CTxIn &txin, txSpend.vin)
744                                             if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput)
745                                                 fFound = true;
746                                         if (!fFound)
747                                         {
748                                             printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput);
749                                             pindexFork = pindex->pprev;
750                                         }
751                                     }
752                                 }
753                             }
754                             nOutput++;
755                         }
756                     }
757                 }
758                 // check level 5: check whether all prevouts are marked spent
759                 if (nCheckLevel>4)
760                 {
761                      BOOST_FOREACH(const CTxIn &txin, tx.vin)
762                      {
763                           CTxIndex txindex;
764                           if (ReadTxIndex(txin.prevout.hash, txindex))
765                               if (txindex.vSpent.size()-1 < txin.prevout.n || txindex.vSpent[txin.prevout.n].IsNull())
766                               {
767                                   printf("LoadBlockIndex(): *** found unspent prevout %s:%i in %s\n", txin.prevout.hash.ToString().c_str(), txin.prevout.n, hashTx.ToString().c_str());
768                                   pindexFork = pindex->pprev;
769                               }
770                      }
771                 }
772             }
773         }
774     }
775     if (pindexFork)
776     {
777         // Reorg back to the fork
778         printf("LoadBlockIndex() : *** moving best chain pointer back to block %d\n", pindexFork->nHeight);
779         CBlock block;
780         if (!block.ReadFromDisk(pindexFork))
781             return error("LoadBlockIndex() : block.ReadFromDisk failed");
782         CTxDB txdb;
783         block.SetBestChain(txdb, pindexFork);
784     }
785
786     return true;
787 }
788
789
790
791
792
793 //
794 // CAddrDB
795 //
796
797 bool CAddrDB::WriteAddrman(const CAddrMan& addrman)
798 {
799     return Write(string("addrman"), addrman);
800 }
801
802 bool CAddrDB::LoadAddresses()
803 {
804     if (Read(string("addrman"), addrman))
805     {
806         printf("Loaded %i addresses\n", addrman.size());
807         return true;
808     }
809     
810     // Read pre-0.6 addr records
811
812     vector<CAddress> vAddr;
813     vector<vector<unsigned char> > vDelete;
814
815     // Get cursor
816     Dbc* pcursor = GetCursor();
817     if (!pcursor)
818         return false;
819
820     loop
821     {
822         // Read next record
823         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
824         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
825         int ret = ReadAtCursor(pcursor, ssKey, ssValue);
826         if (ret == DB_NOTFOUND)
827             break;
828         else if (ret != 0)
829             return false;
830
831         // Unserialize
832         string strType;
833         ssKey >> strType;
834         if (strType == "addr")
835         {
836             CAddress addr;
837             ssValue >> addr;
838             vAddr.push_back(addr);
839         }
840     }
841     pcursor->close();
842
843     addrman.Add(vAddr, CNetAddr("0.0.0.0"));
844     printf("Loaded %i addresses\n", addrman.size());
845
846     // Note: old records left; we ran into hangs-on-startup
847     // bugs for some users who (we think) were running after
848     // an unclean shutdown.
849
850     return true;
851 }
852
853 bool LoadAddresses()
854 {
855     return CAddrDB("cr+").LoadAddresses();
856 }
857
858