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