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