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