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