Merge pull request #1052 from sipa/scopedlocks
[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 "headers.h"
7 #include "db.h"
8 #include "net.h"
9 #include <boost/version.hpp>
10 #include <boost/filesystem.hpp>
11 #include <boost/filesystem/fstream.hpp>
12
13 using namespace std;
14 using namespace boost;
15
16
17 unsigned int nWalletDBUpdated;
18 uint64 nAccountingEntryNumber = 0;
19
20
21
22 //
23 // CDB
24 //
25
26 static CCriticalSection cs_db;
27 static bool fDbEnvInit = false;
28 DbEnv dbenv(0);
29 static map<string, int> mapFileUseCount;
30 static map<string, Db*> mapDb;
31
32 static void EnvShutdown()
33 {
34     if (!fDbEnvInit)
35         return;
36
37     fDbEnvInit = false;
38     try
39     {
40         dbenv.close(0);
41     }
42     catch (const DbException& e)
43     {
44         printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
45     }
46     DbEnv(0).remove(GetDataDir().c_str(), 0);
47 }
48
49 class CDBInit
50 {
51 public:
52     CDBInit()
53     {
54     }
55     ~CDBInit()
56     {
57         EnvShutdown();
58     }
59 }
60 instance_of_cdbinit;
61
62
63 CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
64 {
65     int ret;
66     if (pszFile == NULL)
67         return;
68
69     fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
70     bool fCreate = strchr(pszMode, 'c');
71     unsigned int nFlags = DB_THREAD;
72     if (fCreate)
73         nFlags |= DB_CREATE;
74
75     {
76         LOCK(cs_db);
77         if (!fDbEnvInit)
78         {
79             if (fShutdown)
80                 return;
81             string strDataDir = GetDataDir();
82             filesystem::path pathLogDir(strDataDir + "/database");
83             pathLogDir.make_preferred();
84             filesystem::create_directory(pathLogDir);
85             filesystem::path pathErrorFile(strDataDir + "/db.log");
86             pathErrorFile.make_preferred();
87             printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str());
88
89             int nDbCache = GetArg("-dbcache", 25);
90             dbenv.set_lg_dir(pathLogDir.string().c_str());
91             dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1);
92             dbenv.set_lg_bsize(1048576);
93             dbenv.set_lg_max(10485760);
94             dbenv.set_lk_max_locks(10000);
95             dbenv.set_lk_max_objects(10000);
96             dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
97             dbenv.set_flags(DB_AUTO_COMMIT, 1);
98             dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
99             ret = dbenv.open(strDataDir.c_str(),
100                              DB_CREATE     |
101                              DB_INIT_LOCK  |
102                              DB_INIT_LOG   |
103                              DB_INIT_MPOOL |
104                              DB_INIT_TXN   |
105                              DB_THREAD     |
106                              DB_RECOVER,
107                              S_IRUSR | S_IWUSR);
108             if (ret > 0)
109                 throw runtime_error(strprintf("CDB() : error %d opening database environment", ret));
110             fDbEnvInit = true;
111         }
112
113         strFile = pszFile;
114         ++mapFileUseCount[strFile];
115         pdb = mapDb[strFile];
116         if (pdb == NULL)
117         {
118             pdb = new Db(&dbenv, 0);
119
120             ret = pdb->open(NULL,      // Txn pointer
121                             pszFile,   // Filename
122                             "main",    // Logical db name
123                             DB_BTREE,  // Database type
124                             nFlags,    // Flags
125                             0);
126
127             if (ret > 0)
128             {
129                 delete pdb;
130                 pdb = NULL;
131                 {
132                      LOCK(cs_db);
133                     --mapFileUseCount[strFile];
134                 }
135                 strFile = "";
136                 throw runtime_error(strprintf("CDB() : can't open database file %s, error %d", pszFile, ret));
137             }
138
139             if (fCreate && !Exists(string("version")))
140             {
141                 bool fTmp = fReadOnly;
142                 fReadOnly = false;
143                 WriteVersion(CLIENT_VERSION);
144                 fReadOnly = fTmp;
145             }
146
147             mapDb[strFile] = pdb;
148         }
149     }
150 }
151
152 void CDB::Close()
153 {
154     if (!pdb)
155         return;
156     if (!vTxn.empty())
157         vTxn.front()->abort();
158     vTxn.clear();
159     pdb = NULL;
160
161     // Flush database activity from memory pool to disk log
162     unsigned int nMinutes = 0;
163     if (fReadOnly)
164         nMinutes = 1;
165     if (strFile == "addr.dat")
166         nMinutes = 2;
167     if (strFile == "blkindex.dat" && IsInitialBlockDownload())
168         nMinutes = 5;
169
170     dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
171
172     {
173         LOCK(cs_db);
174         --mapFileUseCount[strFile];
175     }
176 }
177
178 void static CloseDb(const string& strFile)
179 {
180     {
181         LOCK(cs_db);
182         if (mapDb[strFile] != NULL)
183         {
184             // Close the database handle
185             Db* pdb = mapDb[strFile];
186             pdb->close(0);
187             delete pdb;
188             mapDb[strFile] = NULL;
189         }
190     }
191 }
192
193 bool CDB::Rewrite(const string& strFile, const char* pszSkip)
194 {
195     while (!fShutdown)
196     {
197         {
198             LOCK(cs_db);
199             if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
200             {
201                 // Flush log data to the dat file
202                 CloseDb(strFile);
203                 dbenv.txn_checkpoint(0, 0, 0);
204                 dbenv.lsn_reset(strFile.c_str(), 0);
205                 mapFileUseCount.erase(strFile);
206
207                 bool fSuccess = true;
208                 printf("Rewriting %s...\n", strFile.c_str());
209                 string strFileRes = strFile + ".rewrite";
210                 { // surround usage of db with extra {}
211                     CDB db(strFile.c_str(), "r");
212                     Db* pdbCopy = new Db(&dbenv, 0);
213     
214                     int ret = pdbCopy->open(NULL,                 // Txn pointer
215                                             strFileRes.c_str(),   // Filename
216                                             "main",    // Logical db name
217                                             DB_BTREE,  // Database type
218                                             DB_CREATE,    // Flags
219                                             0);
220                     if (ret > 0)
221                     {
222                         printf("Cannot create database file %s\n", strFileRes.c_str());
223                         fSuccess = false;
224                     }
225     
226                     Dbc* pcursor = db.GetCursor();
227                     if (pcursor)
228                         while (fSuccess)
229                         {
230                             CDataStream ssKey;
231                             CDataStream ssValue;
232                             int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
233                             if (ret == DB_NOTFOUND)
234                             {
235                                 pcursor->close();
236                                 break;
237                             }
238                             else if (ret != 0)
239                             {
240                                 pcursor->close();
241                                 fSuccess = false;
242                                 break;
243                             }
244                             if (pszSkip &&
245                                 strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0)
246                                 continue;
247                             if (strncmp(&ssKey[0], "\x07version", 8) == 0)
248                             {
249                                 // Update version:
250                                 ssValue.clear();
251                                 ssValue << CLIENT_VERSION;
252                             }
253                             Dbt datKey(&ssKey[0], ssKey.size());
254                             Dbt datValue(&ssValue[0], ssValue.size());
255                             int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE);
256                             if (ret2 > 0)
257                                 fSuccess = false;
258                         }
259                     if (fSuccess)
260                     {
261                         db.Close();
262                         CloseDb(strFile);
263                         if (pdbCopy->close(0))
264                             fSuccess = false;
265                         delete pdbCopy;
266                     }
267                 }
268                 if (fSuccess)
269                 {
270                     Db dbA(&dbenv, 0);
271                     if (dbA.remove(strFile.c_str(), NULL, 0))
272                         fSuccess = false;
273                     Db dbB(&dbenv, 0);
274                     if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0))
275                         fSuccess = false;
276                 }
277                 if (!fSuccess)
278                     printf("Rewriting of %s FAILED!\n", strFileRes.c_str());
279                 return fSuccess;
280             }
281         }
282         Sleep(100);
283     }
284     return false;
285 }
286
287
288 void DBFlush(bool fShutdown)
289 {
290     // Flush log data to the actual data file
291     //  on all files that are not in use
292     printf("DBFlush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
293     if (!fDbEnvInit)
294         return;
295     {
296         LOCK(cs_db);
297         map<string, int>::iterator mi = mapFileUseCount.begin();
298         while (mi != mapFileUseCount.end())
299         {
300             string strFile = (*mi).first;
301             int nRefCount = (*mi).second;
302             printf("%s refcount=%d\n", strFile.c_str(), nRefCount);
303             if (nRefCount == 0)
304             {
305                 // Move log data to the dat file
306                 CloseDb(strFile);
307                 dbenv.txn_checkpoint(0, 0, 0);
308                 printf("%s flush\n", strFile.c_str());
309                 dbenv.lsn_reset(strFile.c_str(), 0);
310                 mapFileUseCount.erase(mi++);
311             }
312             else
313                 mi++;
314         }
315         if (fShutdown)
316         {
317             char** listp;
318             if (mapFileUseCount.empty())
319             {
320                 dbenv.log_archive(&listp, DB_ARCH_REMOVE);
321                 EnvShutdown();
322             }
323         }
324     }
325 }
326
327
328
329
330
331
332 //
333 // CTxDB
334 //
335
336 bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex)
337 {
338     assert(!fClient);
339     txindex.SetNull();
340     return Read(make_pair(string("tx"), hash), txindex);
341 }
342
343 bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
344 {
345     assert(!fClient);
346     return Write(make_pair(string("tx"), hash), txindex);
347 }
348
349 bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight)
350 {
351     assert(!fClient);
352
353     // Add to tx index
354     uint256 hash = tx.GetHash();
355     CTxIndex txindex(pos, tx.vout.size());
356     return Write(make_pair(string("tx"), hash), txindex);
357 }
358
359 bool CTxDB::EraseTxIndex(const CTransaction& tx)
360 {
361     assert(!fClient);
362     uint256 hash = tx.GetHash();
363
364     return Erase(make_pair(string("tx"), hash));
365 }
366
367 bool CTxDB::ContainsTx(uint256 hash)
368 {
369     assert(!fClient);
370     return Exists(make_pair(string("tx"), hash));
371 }
372
373 bool CTxDB::ReadOwnerTxes(uint160 hash160, int nMinHeight, vector<CTransaction>& vtx)
374 {
375     assert(!fClient);
376     vtx.clear();
377
378     // Get cursor
379     Dbc* pcursor = GetCursor();
380     if (!pcursor)
381         return false;
382
383     unsigned int fFlags = DB_SET_RANGE;
384     loop
385     {
386         // Read next record
387         CDataStream ssKey;
388         if (fFlags == DB_SET_RANGE)
389             ssKey << string("owner") << hash160 << CDiskTxPos(0, 0, 0);
390         CDataStream ssValue;
391         int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
392         fFlags = DB_NEXT;
393         if (ret == DB_NOTFOUND)
394             break;
395         else if (ret != 0)
396         {
397             pcursor->close();
398             return false;
399         }
400
401         // Unserialize
402         string strType;
403         uint160 hashItem;
404         CDiskTxPos pos;
405         ssKey >> strType >> hashItem >> pos;
406         int nItemHeight;
407         ssValue >> nItemHeight;
408
409         // Read transaction
410         if (strType != "owner" || hashItem != hash160)
411             break;
412         if (nItemHeight >= nMinHeight)
413         {
414             vtx.resize(vtx.size()+1);
415             if (!vtx.back().ReadFromDisk(pos))
416             {
417                 pcursor->close();
418                 return false;
419             }
420         }
421     }
422
423     pcursor->close();
424     return true;
425 }
426
427 bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex)
428 {
429     assert(!fClient);
430     tx.SetNull();
431     if (!ReadTxIndex(hash, txindex))
432         return false;
433     return (tx.ReadFromDisk(txindex.pos));
434 }
435
436 bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx)
437 {
438     CTxIndex txindex;
439     return ReadDiskTx(hash, tx, txindex);
440 }
441
442 bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex)
443 {
444     return ReadDiskTx(outpoint.hash, tx, txindex);
445 }
446
447 bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx)
448 {
449     CTxIndex txindex;
450     return ReadDiskTx(outpoint.hash, tx, txindex);
451 }
452
453 bool CTxDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
454 {
455     return Write(make_pair(string("blockindex"), blockindex.GetBlockHash()), blockindex);
456 }
457
458 bool CTxDB::EraseBlockIndex(uint256 hash)
459 {
460     return Erase(make_pair(string("blockindex"), hash));
461 }
462
463 bool CTxDB::ReadHashBestChain(uint256& hashBestChain)
464 {
465     return Read(string("hashBestChain"), hashBestChain);
466 }
467
468 bool CTxDB::WriteHashBestChain(uint256 hashBestChain)
469 {
470     return Write(string("hashBestChain"), hashBestChain);
471 }
472
473 bool CTxDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork)
474 {
475     return Read(string("bnBestInvalidWork"), bnBestInvalidWork);
476 }
477
478 bool CTxDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork)
479 {
480     return Write(string("bnBestInvalidWork"), bnBestInvalidWork);
481 }
482
483 CBlockIndex static * InsertBlockIndex(uint256 hash)
484 {
485     if (hash == 0)
486         return NULL;
487
488     // Return existing
489     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
490     if (mi != mapBlockIndex.end())
491         return (*mi).second;
492
493     // Create new
494     CBlockIndex* pindexNew = new CBlockIndex();
495     if (!pindexNew)
496         throw runtime_error("LoadBlockIndex() : new CBlockIndex failed");
497     mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
498     pindexNew->phashBlock = &((*mi).first);
499
500     return pindexNew;
501 }
502
503 bool CTxDB::LoadBlockIndex()
504 {
505     // Get database cursor
506     Dbc* pcursor = GetCursor();
507     if (!pcursor)
508         return false;
509
510     // Load mapBlockIndex
511     unsigned int fFlags = DB_SET_RANGE;
512     loop
513     {
514         // Read next record
515         CDataStream ssKey;
516         if (fFlags == DB_SET_RANGE)
517             ssKey << make_pair(string("blockindex"), uint256(0));
518         CDataStream ssValue;
519         int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
520         fFlags = DB_NEXT;
521         if (ret == DB_NOTFOUND)
522             break;
523         else if (ret != 0)
524             return false;
525
526         // Unserialize
527         string strType;
528         ssKey >> strType;
529         if (strType == "blockindex")
530         {
531             CDiskBlockIndex diskindex;
532             ssValue >> diskindex;
533
534             // Construct block index object
535             CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
536             pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
537             pindexNew->pnext          = InsertBlockIndex(diskindex.hashNext);
538             pindexNew->nFile          = diskindex.nFile;
539             pindexNew->nBlockPos      = diskindex.nBlockPos;
540             pindexNew->nHeight        = diskindex.nHeight;
541             pindexNew->nVersion       = diskindex.nVersion;
542             pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
543             pindexNew->nTime          = diskindex.nTime;
544             pindexNew->nBits          = diskindex.nBits;
545             pindexNew->nNonce         = diskindex.nNonce;
546
547             // Watch for genesis block
548             if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
549                 pindexGenesisBlock = pindexNew;
550
551             if (!pindexNew->CheckIndex())
552                 return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
553         }
554         else
555         {
556             break;
557         }
558     }
559     pcursor->close();
560
561     // Calculate bnChainWork
562     vector<pair<int, CBlockIndex*> > vSortedByHeight;
563     vSortedByHeight.reserve(mapBlockIndex.size());
564     BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
565     {
566         CBlockIndex* pindex = item.second;
567         vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex));
568     }
569     sort(vSortedByHeight.begin(), vSortedByHeight.end());
570     BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
571     {
572         CBlockIndex* pindex = item.second;
573         pindex->bnChainWork = (pindex->pprev ? pindex->pprev->bnChainWork : 0) + pindex->GetBlockWork();
574     }
575
576     // Load hashBestChain pointer to end of best chain
577     if (!ReadHashBestChain(hashBestChain))
578     {
579         if (pindexGenesisBlock == NULL)
580             return true;
581         return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded");
582     }
583     if (!mapBlockIndex.count(hashBestChain))
584         return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index");
585     pindexBest = mapBlockIndex[hashBestChain];
586     nBestHeight = pindexBest->nHeight;
587     bnBestChainWork = pindexBest->bnChainWork;
588     printf("LoadBlockIndex(): hashBestChain=%s  height=%d\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight);
589
590     // Load bnBestInvalidWork, OK if it doesn't exist
591     ReadBestInvalidWork(bnBestInvalidWork);
592
593     // Verify blocks in the best chain
594     int nCheckLevel = GetArg("-checklevel", 1);
595     int nCheckDepth = GetArg( "-checkblocks", 2500);
596     if (nCheckDepth == 0)
597         nCheckDepth = 1000000000; // suffices until the year 19000
598     if (nCheckDepth > nBestHeight)
599         nCheckDepth = nBestHeight;
600     printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
601     CBlockIndex* pindexFork = NULL;
602     map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
603     for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
604     {
605         if (pindex->nHeight < nBestHeight-nCheckDepth)
606             break;
607         CBlock block;
608         if (!block.ReadFromDisk(pindex))
609             return error("LoadBlockIndex() : block.ReadFromDisk failed");
610         // check level 1: verify block validity
611         if (nCheckLevel>0 && !block.CheckBlock())
612         {
613             printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
614             pindexFork = pindex->pprev;
615         }
616         // check level 2: verify transaction index validity
617         if (nCheckLevel>1)
618         {
619             pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos);
620             mapBlockPos[pos] = pindex;
621             BOOST_FOREACH(const CTransaction &tx, block.vtx)
622             {
623                 uint256 hashTx = tx.GetHash();
624                 CTxIndex txindex;
625                 if (ReadTxIndex(hashTx, txindex))
626                 {
627                     // check level 3: checker transaction hashes
628                     if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos)
629                     {
630                         // either an error or a duplicate transaction
631                         CTransaction txFound;
632                         if (!txFound.ReadFromDisk(txindex.pos))
633                         {
634                             printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str());
635                             pindexFork = pindex->pprev;
636                         }
637                         else
638                             if (txFound.GetHash() != hashTx) // not a duplicate tx
639                             {
640                                 printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str());
641                                 pindexFork = pindex->pprev;
642                             }
643                     }
644                     // check level 4: check whether spent txouts were spent within the main chain
645                     int nOutput = 0;
646                     if (nCheckLevel>3)
647                         BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent)
648                         {
649                             if (!txpos.IsNull())
650                             {
651                                 pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos);
652                                 if (!mapBlockPos.count(posFind))
653                                 {
654                                     printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str());
655                                     pindexFork = pindex->pprev;
656                                 }
657                                 // check level 6: check whether spent txouts were spent by a valid transaction that consume them
658                                 if (nCheckLevel>5)
659                                 {
660                                     CTransaction txSpend;
661                                     if (!txSpend.ReadFromDisk(txpos))
662                                     {
663                                         printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput);
664                                         pindexFork = pindex->pprev;
665                                     }
666                                     else if (!txSpend.CheckTransaction())
667                                     {
668                                         printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput);
669                                         pindexFork = pindex->pprev;
670                                     }
671                                     else
672                                     {
673                                         bool fFound = false;
674                                         BOOST_FOREACH(const CTxIn &txin, txSpend.vin)
675                                             if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput)
676                                                 fFound = true;
677                                         if (!fFound)
678                                         {
679                                             printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput);
680                                             pindexFork = pindex->pprev;
681                                         }
682                                     }
683                                 }
684                             }
685                             nOutput++;
686                         }
687                 }
688                 // check level 5: check whether all prevouts are marked spent
689                 if (nCheckLevel>4)
690                      BOOST_FOREACH(const CTxIn &txin, tx.vin)
691                      {
692                           CTxIndex txindex;
693                           if (ReadTxIndex(txin.prevout.hash, txindex))
694                               if (txindex.vSpent.size()-1 < txin.prevout.n || txindex.vSpent[txin.prevout.n].IsNull())
695                               {
696                                   printf("LoadBlockIndex(): *** found unspent prevout %s:%i in %s\n", txin.prevout.hash.ToString().c_str(), txin.prevout.n, hashTx.ToString().c_str());
697                                   pindexFork = pindex->pprev;
698                               }
699                      }
700             }
701         }
702     }
703     if (pindexFork)
704     {
705         // Reorg back to the fork
706         printf("LoadBlockIndex() : *** moving best chain pointer back to block %d\n", pindexFork->nHeight);
707         CBlock block;
708         if (!block.ReadFromDisk(pindexFork))
709             return error("LoadBlockIndex() : block.ReadFromDisk failed");
710         CTxDB txdb;
711         block.SetBestChain(txdb, pindexFork);
712     }
713
714     return true;
715 }
716
717
718
719
720
721 //
722 // CAddrDB
723 //
724
725 bool CAddrDB::WriteAddrman(const CAddrMan& addrman)
726 {
727     return Write(string("addrman"), addrman);
728 }
729
730 bool CAddrDB::LoadAddresses()
731 {
732     if (Read(string("addrman"), addrman))
733     {
734         printf("Loaded %i addresses\n", addrman.size());
735         return true;
736     }
737     
738     // Read pre-0.6 addr records
739
740     vector<CAddress> vAddr;
741     vector<vector<unsigned char> > vDelete;
742
743     // Get cursor
744     Dbc* pcursor = GetCursor();
745     if (!pcursor)
746         return false;
747
748     loop
749     {
750         // Read next record
751         CDataStream ssKey;
752         CDataStream ssValue;
753         int ret = ReadAtCursor(pcursor, ssKey, ssValue);
754         if (ret == DB_NOTFOUND)
755             break;
756         else if (ret != 0)
757             return false;
758
759         // Unserialize
760         string strType;
761         ssKey >> strType;
762         if (strType == "addr")
763         {
764             CAddress addr;
765             ssValue >> addr;
766             vAddr.push_back(addr);
767         }
768     }
769     pcursor->close();
770
771     addrman.Add(vAddr, CNetAddr("0.0.0.0"));
772     printf("Loaded %i addresses\n", addrman.size());
773
774     // Note: old records left; we ran into hangs-on-startup
775     // bugs for some users who (we think) were running after
776     // an unclean shutdown.
777
778     return true;
779 }
780
781 bool LoadAddresses()
782 {
783     return CAddrDB("cr+").LoadAddresses();
784 }
785
786
787
788
789 //
790 // CWalletDB
791 //
792
793 bool CWalletDB::WriteName(const string& strAddress, const string& strName)
794 {
795     nWalletDBUpdated++;
796     return Write(make_pair(string("name"), strAddress), strName);
797 }
798
799 bool CWalletDB::EraseName(const string& strAddress)
800 {
801     // This should only be used for sending addresses, never for receiving addresses,
802     // receiving addresses must always have an address book entry if they're not change return.
803     nWalletDBUpdated++;
804     return Erase(make_pair(string("name"), strAddress));
805 }
806
807 bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
808 {
809     account.SetNull();
810     return Read(make_pair(string("acc"), strAccount), account);
811 }
812
813 bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account)
814 {
815     return Write(make_pair(string("acc"), strAccount), account);
816 }
817
818 bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry)
819 {
820     return Write(boost::make_tuple(string("acentry"), acentry.strAccount, ++nAccountingEntryNumber), acentry);
821 }
822
823 int64 CWalletDB::GetAccountCreditDebit(const string& strAccount)
824 {
825     list<CAccountingEntry> entries;
826     ListAccountCreditDebit(strAccount, entries);
827
828     int64 nCreditDebit = 0;
829     BOOST_FOREACH (const CAccountingEntry& entry, entries)
830         nCreditDebit += entry.nCreditDebit;
831
832     return nCreditDebit;
833 }
834
835 void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& entries)
836 {
837     bool fAllAccounts = (strAccount == "*");
838
839     Dbc* pcursor = GetCursor();
840     if (!pcursor)
841         throw runtime_error("CWalletDB::ListAccountCreditDebit() : cannot create DB cursor");
842     unsigned int fFlags = DB_SET_RANGE;
843     loop
844     {
845         // Read next record
846         CDataStream ssKey;
847         if (fFlags == DB_SET_RANGE)
848             ssKey << boost::make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64(0));
849         CDataStream ssValue;
850         int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
851         fFlags = DB_NEXT;
852         if (ret == DB_NOTFOUND)
853             break;
854         else if (ret != 0)
855         {
856             pcursor->close();
857             throw runtime_error("CWalletDB::ListAccountCreditDebit() : error scanning DB");
858         }
859
860         // Unserialize
861         string strType;
862         ssKey >> strType;
863         if (strType != "acentry")
864             break;
865         CAccountingEntry acentry;
866         ssKey >> acentry.strAccount;
867         if (!fAllAccounts && acentry.strAccount != strAccount)
868             break;
869
870         ssValue >> acentry;
871         entries.push_back(acentry);
872     }
873
874     pcursor->close();
875 }
876
877
878 int CWalletDB::LoadWallet(CWallet* pwallet)
879 {
880     pwallet->vchDefaultKey.clear();
881     int nFileVersion = 0;
882     vector<uint256> vWalletUpgrade;
883     bool fIsEncrypted = false;
884
885     //// todo: shouldn't we catch exceptions and try to recover and continue?
886     {
887         LOCK(pwallet->cs_wallet);
888         int nMinVersion = 0;
889         if (Read((string)"minversion", nMinVersion))
890         {
891             if (nMinVersion > CLIENT_VERSION)
892                 return DB_TOO_NEW;
893             pwallet->LoadMinVersion(nMinVersion);
894         }
895
896         // Get cursor
897         Dbc* pcursor = GetCursor();
898         if (!pcursor)
899         {
900             printf("Error getting wallet database cursor\n");
901             return DB_CORRUPT;
902         }
903
904         loop
905         {
906             // Read next record
907             CDataStream ssKey;
908             CDataStream ssValue;
909             int ret = ReadAtCursor(pcursor, ssKey, ssValue);
910             if (ret == DB_NOTFOUND)
911                 break;
912             else if (ret != 0)
913             {
914                 printf("Error reading next record from wallet database\n");
915                 return DB_CORRUPT;
916             }
917
918             // Unserialize
919             // Taking advantage of the fact that pair serialization
920             // is just the two items serialized one after the other
921             string strType;
922             ssKey >> strType;
923             if (strType == "name")
924             {
925                 string strAddress;
926                 ssKey >> strAddress;
927                 ssValue >> pwallet->mapAddressBook[strAddress];
928             }
929             else if (strType == "tx")
930             {
931                 uint256 hash;
932                 ssKey >> hash;
933                 CWalletTx& wtx = pwallet->mapWallet[hash];
934                 ssValue >> wtx;
935                 wtx.BindWallet(pwallet);
936
937                 if (wtx.GetHash() != hash)
938                     printf("Error in wallet.dat, hash mismatch\n");
939
940                 // Undo serialize changes in 31600
941                 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
942                 {
943                     if (!ssValue.empty())
944                     {
945                         char fTmp;
946                         char fUnused;
947                         ssValue >> fTmp >> fUnused >> wtx.strFromAccount;
948                         printf("LoadWallet() upgrading tx ver=%d %d '%s' %s\n", wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount.c_str(), hash.ToString().c_str());
949                         wtx.fTimeReceivedIsTxTime = fTmp;
950                     }
951                     else
952                     {
953                         printf("LoadWallet() repairing tx ver=%d %s\n", wtx.fTimeReceivedIsTxTime, hash.ToString().c_str());
954                         wtx.fTimeReceivedIsTxTime = 0;
955                     }
956                     vWalletUpgrade.push_back(hash);
957                 }
958
959                 //// debug print
960                 //printf("LoadWallet  %s\n", wtx.GetHash().ToString().c_str());
961                 //printf(" %12I64d  %s  %s  %s\n",
962                 //    wtx.vout[0].nValue,
963                 //    DateTimeStrFormat("%x %H:%M:%S", wtx.GetBlockTime()).c_str(),
964                 //    wtx.hashBlock.ToString().substr(0,20).c_str(),
965                 //    wtx.mapValue["message"].c_str());
966             }
967             else if (strType == "acentry")
968             {
969                 string strAccount;
970                 ssKey >> strAccount;
971                 uint64 nNumber;
972                 ssKey >> nNumber;
973                 if (nNumber > nAccountingEntryNumber)
974                     nAccountingEntryNumber = nNumber;
975             }
976             else if (strType == "key" || strType == "wkey")
977             {
978                 vector<unsigned char> vchPubKey;
979                 ssKey >> vchPubKey;
980                 CKey key;
981                 if (strType == "key")
982                 {
983                     CPrivKey pkey;
984                     ssValue >> pkey;
985                     key.SetPubKey(vchPubKey);
986                     key.SetPrivKey(pkey);
987                     if (key.GetPubKey() != vchPubKey)
988                     {
989                         printf("Error reading wallet database: CPrivKey pubkey inconsistency\n");
990                         return DB_CORRUPT;
991                     }
992                     if (!key.IsValid())
993                     {
994                         printf("Error reading wallet database: invalid CPrivKey\n");
995                         return DB_CORRUPT;
996                     }
997                 }
998                 else
999                 {
1000                     CWalletKey wkey;
1001                     ssValue >> wkey;
1002                     key.SetPubKey(vchPubKey);
1003                     key.SetPrivKey(wkey.vchPrivKey);
1004                     if (key.GetPubKey() != vchPubKey)
1005                     {
1006                         printf("Error reading wallet database: CWalletKey pubkey inconsistency\n");
1007                         return DB_CORRUPT;
1008                     }
1009                     if (!key.IsValid())
1010                     {
1011                         printf("Error reading wallet database: invalid CWalletKey\n");
1012                         return DB_CORRUPT;
1013                     }
1014                 }
1015                 if (!pwallet->LoadKey(key))
1016                 {
1017                     printf("Error reading wallet database: LoadKey failed\n");
1018                     return DB_CORRUPT;
1019                 }
1020             }
1021             else if (strType == "mkey")
1022             {
1023                 unsigned int nID;
1024                 ssKey >> nID;
1025                 CMasterKey kMasterKey;
1026                 ssValue >> kMasterKey;
1027                 if(pwallet->mapMasterKeys.count(nID) != 0)
1028                 {
1029                     printf("Error reading wallet database: duplicate CMasterKey id %u\n", nID);
1030                     return DB_CORRUPT;
1031                 }
1032                 pwallet->mapMasterKeys[nID] = kMasterKey;
1033                 if (pwallet->nMasterKeyMaxID < nID)
1034                     pwallet->nMasterKeyMaxID = nID;
1035             }
1036             else if (strType == "ckey")
1037             {
1038                 vector<unsigned char> vchPubKey;
1039                 ssKey >> vchPubKey;
1040                 vector<unsigned char> vchPrivKey;
1041                 ssValue >> vchPrivKey;
1042                 if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
1043                 {
1044                     printf("Error reading wallet database: LoadCryptedKey failed\n");
1045                     return DB_CORRUPT;
1046                 }
1047                 fIsEncrypted = true;
1048             }
1049             else if (strType == "defaultkey")
1050             {
1051                 ssValue >> pwallet->vchDefaultKey;
1052             }
1053             else if (strType == "pool")
1054             {
1055                 int64 nIndex;
1056                 ssKey >> nIndex;
1057                 pwallet->setKeyPool.insert(nIndex);
1058             }
1059             else if (strType == "version")
1060             {
1061                 ssValue >> nFileVersion;
1062                 if (nFileVersion == 10300)
1063                     nFileVersion = 300;
1064             }
1065             else if (strType == "cscript")
1066             {
1067                 uint160 hash;
1068                 ssKey >> hash;
1069                 CScript script;
1070                 ssValue >> script;
1071                 if (!pwallet->LoadCScript(script))
1072                 {
1073                     printf("Error reading wallet database: LoadCScript failed\n");
1074                     return DB_CORRUPT;
1075                 }
1076             }
1077         }
1078         pcursor->close();
1079     }
1080
1081     BOOST_FOREACH(uint256 hash, vWalletUpgrade)
1082         WriteTx(hash, pwallet->mapWallet[hash]);
1083
1084     printf("nFileVersion = %d\n", nFileVersion);
1085
1086
1087     // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
1088     if (fIsEncrypted && (nFileVersion == 40000 || nFileVersion == 50000))
1089         return DB_NEED_REWRITE;
1090
1091     if (nFileVersion < CLIENT_VERSION) // Update
1092     {
1093         // Get rid of old debug.log file in current directory
1094         if (nFileVersion <= 105 && !pszSetDataDir[0])
1095             unlink("debug.log");
1096
1097         WriteVersion(CLIENT_VERSION);
1098     }
1099
1100     return DB_LOAD_OK;
1101 }
1102
1103 void ThreadFlushWalletDB(void* parg)
1104 {
1105     const string& strFile = ((const string*)parg)[0];
1106     static bool fOneThread;
1107     if (fOneThread)
1108         return;
1109     fOneThread = true;
1110     if (!GetBoolArg("-flushwallet", true))
1111         return;
1112
1113     unsigned int nLastSeen = nWalletDBUpdated;
1114     unsigned int nLastFlushed = nWalletDBUpdated;
1115     int64 nLastWalletUpdate = GetTime();
1116     while (!fShutdown)
1117     {
1118         Sleep(500);
1119
1120         if (nLastSeen != nWalletDBUpdated)
1121         {
1122             nLastSeen = nWalletDBUpdated;
1123             nLastWalletUpdate = GetTime();
1124         }
1125
1126         if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
1127         {
1128             TRY_LOCK(cs_db,lockDb);
1129             if (lockDb)
1130             {
1131                 // Don't do this if any databases are in use
1132                 int nRefCount = 0;
1133                 map<string, int>::iterator mi = mapFileUseCount.begin();
1134                 while (mi != mapFileUseCount.end())
1135                 {
1136                     nRefCount += (*mi).second;
1137                     mi++;
1138                 }
1139
1140                 if (nRefCount == 0 && !fShutdown)
1141                 {
1142                     map<string, int>::iterator mi = mapFileUseCount.find(strFile);
1143                     if (mi != mapFileUseCount.end())
1144                     {
1145                         printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
1146                         printf("Flushing wallet.dat\n");
1147                         nLastFlushed = nWalletDBUpdated;
1148                         int64 nStart = GetTimeMillis();
1149
1150                         // Flush wallet.dat so it's self contained
1151                         CloseDb(strFile);
1152                         dbenv.txn_checkpoint(0, 0, 0);
1153                         dbenv.lsn_reset(strFile.c_str(), 0);
1154
1155                         mapFileUseCount.erase(mi++);
1156                         printf("Flushed wallet.dat %"PRI64d"ms\n", GetTimeMillis() - nStart);
1157                     }
1158                 }
1159             }
1160         }
1161     }
1162 }
1163
1164 bool BackupWallet(const CWallet& wallet, const string& strDest)
1165 {
1166     if (!wallet.fFileBacked)
1167         return false;
1168     while (!fShutdown)
1169     {
1170         {
1171             LOCK(cs_db);
1172             if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0)
1173             {
1174                 // Flush log data to the dat file
1175                 CloseDb(wallet.strWalletFile);
1176                 dbenv.txn_checkpoint(0, 0, 0);
1177                 dbenv.lsn_reset(wallet.strWalletFile.c_str(), 0);
1178                 mapFileUseCount.erase(wallet.strWalletFile);
1179
1180                 // Copy wallet.dat
1181                 filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile);
1182                 pathSrc.make_preferred();
1183                 filesystem::path pathDest(strDest);
1184                 pathDest.make_preferred();
1185                 if (filesystem::is_directory(pathDest))
1186                     pathDest = pathDest / wallet.strWalletFile;
1187
1188                 try {
1189 #if BOOST_VERSION >= 104000
1190                     filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
1191 #else
1192                     filesystem::copy_file(pathSrc, pathDest);
1193 #endif
1194                     printf("copied wallet.dat to %s\n", pathDest.string().c_str());
1195                     return true;
1196                 } catch(const filesystem::filesystem_error &e) {
1197                     printf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what());
1198                     return false;
1199                 }
1200             }
1201         }
1202         Sleep(100);
1203     }
1204     return false;
1205 }