raw
genesis                 1 // Copyright (c) 2009-2010 Satoshi Nakamoto
genesis 2 // Copyright (c) 2011 The Bitcoin developers
genesis 3 // Distributed under the MIT/X11 software license, see the accompanying
genesis 4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
genesis 5 #ifndef BITCOIN_DB_H
genesis 6 #define BITCOIN_DB_H
genesis 7
genesis 8 #include "key.h"
genesis 9
genesis 10 #include <map>
genesis 11 #include <string>
genesis 12 #include <vector>
genesis 13
genesis 14 #include <db_cxx.h>
genesis 15
genesis 16 class CTxIndex;
genesis 17 class CDiskBlockIndex;
genesis 18 class CDiskTxPos;
genesis 19 class COutPoint;
genesis 20 class CAddress;
genesis 21 class CWalletTx;
genesis 22 class CWallet;
genesis 23 class CAccount;
genesis 24 class CAccountingEntry;
genesis 25 class CBlockLocator;
genesis 26
genesis 27
genesis 28 extern unsigned int nWalletDBUpdated;
genesis 29 extern DbEnv dbenv;
genesis 30
genesis 31 extern void DBFlush(bool fShutdown);
genesis 32 void ThreadFlushWalletDB(void* parg);
genesis 33 bool BackupWallet(const CWallet& wallet, const std::string& strDest);
genesis 34
genesis 35
genesis 36
genesis 37 class CDB
genesis 38 {
genesis 39 protected:
genesis 40 Db* pdb;
genesis 41 std::string strFile;
genesis 42 std::vector<DbTxn*> vTxn;
genesis 43 bool fReadOnly;
genesis 44
genesis 45 explicit CDB(const char* pszFile, const char* pszMode="r+");
genesis 46 ~CDB() { Close(); }
genesis 47 public:
genesis 48 void Close();
genesis 49 private:
genesis 50 CDB(const CDB&);
genesis 51 void operator=(const CDB&);
genesis 52
genesis 53 protected:
genesis 54 template<typename K, typename T>
genesis 55 bool Read(const K& key, T& value)
genesis 56 {
genesis 57 if (!pdb)
genesis 58 return false;
genesis 59
genesis 60 // Key
genesis 61 CDataStream ssKey(SER_DISK);
genesis 62 ssKey.reserve(1000);
genesis 63 ssKey << key;
genesis 64 Dbt datKey(&ssKey[0], ssKey.size());
genesis 65
genesis 66 // Read
genesis 67 Dbt datValue;
genesis 68 datValue.set_flags(DB_DBT_MALLOC);
genesis 69 int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
genesis 70 memset(datKey.get_data(), 0, datKey.get_size());
genesis 71 if (datValue.get_data() == NULL)
genesis 72 return false;
genesis 73
genesis 74 // Unserialize value
genesis 75 CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
genesis 76 ssValue >> value;
genesis 77
genesis 78 // Clear and free memory
genesis 79 memset(datValue.get_data(), 0, datValue.get_size());
genesis 80 free(datValue.get_data());
genesis 81 return (ret == 0);
genesis 82 }
genesis 83
genesis 84 template<typename K, typename T>
genesis 85 bool Write(const K& key, const T& value, bool fOverwrite=true)
genesis 86 {
genesis 87 if (!pdb)
genesis 88 return false;
genesis 89 if (fReadOnly)
genesis 90 assert(!"Write called on database in read-only mode");
genesis 91
genesis 92 // Key
genesis 93 CDataStream ssKey(SER_DISK);
genesis 94 ssKey.reserve(1000);
genesis 95 ssKey << key;
genesis 96 Dbt datKey(&ssKey[0], ssKey.size());
genesis 97
genesis 98 // Value
genesis 99 CDataStream ssValue(SER_DISK);
genesis 100 ssValue.reserve(10000);
genesis 101 ssValue << value;
genesis 102 Dbt datValue(&ssValue[0], ssValue.size());
genesis 103
genesis 104 // Write
genesis 105 int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
genesis 106
genesis 107 // Clear memory in case it was a private key
genesis 108 memset(datKey.get_data(), 0, datKey.get_size());
genesis 109 memset(datValue.get_data(), 0, datValue.get_size());
genesis 110 return (ret == 0);
genesis 111 }
genesis 112
genesis 113 template<typename K>
genesis 114 bool Erase(const K& key)
genesis 115 {
genesis 116 if (!pdb)
genesis 117 return false;
genesis 118 if (fReadOnly)
genesis 119 assert(!"Erase called on database in read-only mode");
genesis 120
genesis 121 // Key
genesis 122 CDataStream ssKey(SER_DISK);
genesis 123 ssKey.reserve(1000);
genesis 124 ssKey << key;
genesis 125 Dbt datKey(&ssKey[0], ssKey.size());
genesis 126
genesis 127 // Erase
genesis 128 int ret = pdb->del(GetTxn(), &datKey, 0);
genesis 129
genesis 130 // Clear memory
genesis 131 memset(datKey.get_data(), 0, datKey.get_size());
genesis 132 return (ret == 0 || ret == DB_NOTFOUND);
genesis 133 }
genesis 134
genesis 135 template<typename K>
genesis 136 bool Exists(const K& key)
genesis 137 {
genesis 138 if (!pdb)
genesis 139 return false;
genesis 140
genesis 141 // Key
genesis 142 CDataStream ssKey(SER_DISK);
genesis 143 ssKey.reserve(1000);
genesis 144 ssKey << key;
genesis 145 Dbt datKey(&ssKey[0], ssKey.size());
genesis 146
genesis 147 // Exists
genesis 148 int ret = pdb->exists(GetTxn(), &datKey, 0);
genesis 149
genesis 150 // Clear memory
genesis 151 memset(datKey.get_data(), 0, datKey.get_size());
genesis 152 return (ret == 0);
genesis 153 }
genesis 154
genesis 155 Dbc* GetCursor()
genesis 156 {
genesis 157 if (!pdb)
genesis 158 return NULL;
genesis 159 Dbc* pcursor = NULL;
genesis 160 int ret = pdb->cursor(NULL, &pcursor, 0);
genesis 161 if (ret != 0)
genesis 162 return NULL;
genesis 163 return pcursor;
genesis 164 }
genesis 165
genesis 166 int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
genesis 167 {
genesis 168 // Read at cursor
genesis 169 Dbt datKey;
genesis 170 if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
genesis 171 {
genesis 172 datKey.set_data(&ssKey[0]);
genesis 173 datKey.set_size(ssKey.size());
genesis 174 }
genesis 175 Dbt datValue;
genesis 176 if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
genesis 177 {
genesis 178 datValue.set_data(&ssValue[0]);
genesis 179 datValue.set_size(ssValue.size());
genesis 180 }
genesis 181 datKey.set_flags(DB_DBT_MALLOC);
genesis 182 datValue.set_flags(DB_DBT_MALLOC);
genesis 183 int ret = pcursor->get(&datKey, &datValue, fFlags);
genesis 184 if (ret != 0)
genesis 185 return ret;
genesis 186 else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
genesis 187 return 99999;
genesis 188
genesis 189 // Convert to streams
genesis 190 ssKey.SetType(SER_DISK);
genesis 191 ssKey.clear();
genesis 192 ssKey.write((char*)datKey.get_data(), datKey.get_size());
genesis 193 ssValue.SetType(SER_DISK);
genesis 194 ssValue.clear();
genesis 195 ssValue.write((char*)datValue.get_data(), datValue.get_size());
genesis 196
genesis 197 // Clear and free memory
genesis 198 memset(datKey.get_data(), 0, datKey.get_size());
genesis 199 memset(datValue.get_data(), 0, datValue.get_size());
genesis 200 free(datKey.get_data());
genesis 201 free(datValue.get_data());
genesis 202 return 0;
genesis 203 }
genesis 204
genesis 205 DbTxn* GetTxn()
genesis 206 {
genesis 207 if (!vTxn.empty())
genesis 208 return vTxn.back();
genesis 209 else
genesis 210 return NULL;
genesis 211 }
genesis 212
genesis 213 public:
genesis 214 bool TxnBegin()
genesis 215 {
genesis 216 if (!pdb)
genesis 217 return false;
genesis 218 DbTxn* ptxn = NULL;
genesis 219 int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
genesis 220 if (!ptxn || ret != 0)
genesis 221 return false;
genesis 222 vTxn.push_back(ptxn);
genesis 223 return true;
genesis 224 }
genesis 225
genesis 226 bool TxnCommit()
genesis 227 {
genesis 228 if (!pdb)
genesis 229 return false;
genesis 230 if (vTxn.empty())
genesis 231 return false;
genesis 232 int ret = vTxn.back()->commit(0);
genesis 233 vTxn.pop_back();
genesis 234 return (ret == 0);
genesis 235 }
genesis 236
genesis 237 bool TxnAbort()
genesis 238 {
genesis 239 if (!pdb)
genesis 240 return false;
genesis 241 if (vTxn.empty())
genesis 242 return false;
genesis 243 int ret = vTxn.back()->abort();
genesis 244 vTxn.pop_back();
genesis 245 return (ret == 0);
genesis 246 }
genesis 247
genesis 248 bool ReadVersion(int& nVersion)
genesis 249 {
genesis 250 nVersion = 0;
genesis 251 return Read(std::string("version"), nVersion);
genesis 252 }
genesis 253
genesis 254 bool WriteVersion(int nVersion)
genesis 255 {
genesis 256 return Write(std::string("version"), nVersion);
genesis 257 }
genesis 258
genesis 259 bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
genesis 260 };
genesis 261
genesis 262
genesis 263
genesis 264
genesis 265
genesis 266
genesis 267
genesis 268
genesis 269 class CTxDB : public CDB
genesis 270 {
genesis 271 public:
genesis 272 CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { }
genesis 273 private:
genesis 274 CTxDB(const CTxDB&);
genesis 275 void operator=(const CTxDB&);
genesis 276 public:
genesis 277 bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
genesis 278 bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
genesis 279 bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
genesis 280 bool EraseTxIndex(const CTransaction& tx);
genesis 281 bool ContainsTx(uint256 hash);
genesis 282 bool ReadOwnerTxes(uint160 hash160, int nHeight, std::vector<CTransaction>& vtx);
genesis 283 bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
genesis 284 bool ReadDiskTx(uint256 hash, CTransaction& tx);
genesis 285 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
genesis 286 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
genesis 287 bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
genesis 288 bool EraseBlockIndex(uint256 hash);
genesis 289 bool ReadHashBestChain(uint256& hashBestChain);
genesis 290 bool WriteHashBestChain(uint256 hashBestChain);
genesis 291 bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
genesis 292 bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
genesis 293 bool LoadBlockIndex();
genesis 294 };
genesis 295
genesis 296
genesis 297
genesis 298
genesis 299
genesis 300 class CAddrDB : public CDB
genesis 301 {
genesis 302 public:
genesis 303 CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
genesis 304 private:
genesis 305 CAddrDB(const CAddrDB&);
genesis 306 void operator=(const CAddrDB&);
genesis 307 public:
genesis 308 bool WriteAddress(const CAddress& addr);
genesis 309 bool EraseAddress(const CAddress& addr);
genesis 310 bool LoadAddresses();
genesis 311 };
genesis 312
genesis 313 bool LoadAddresses();
genesis 314
genesis 315
genesis 316
genesis 317 class CKeyPool
genesis 318 {
genesis 319 public:
genesis 320 int64 nTime;
genesis 321 std::vector<unsigned char> vchPubKey;
genesis 322
genesis 323 CKeyPool()
genesis 324 {
genesis 325 nTime = GetTime();
genesis 326 }
genesis 327
genesis 328 CKeyPool(const std::vector<unsigned char>& vchPubKeyIn)
genesis 329 {
genesis 330 nTime = GetTime();
genesis 331 vchPubKey = vchPubKeyIn;
genesis 332 }
genesis 333
genesis 334 IMPLEMENT_SERIALIZE
genesis 335 (
genesis 336 if (!(nType & SER_GETHASH))
genesis 337 READWRITE(nVersion);
genesis 338 READWRITE(nTime);
genesis 339 READWRITE(vchPubKey);
genesis 340 )
genesis 341 };
genesis 342
genesis 343
genesis 344
genesis 345
genesis 346 enum DBErrors
genesis 347 {
genesis 348 DB_LOAD_OK,
genesis 349 DB_CORRUPT,
genesis 350 DB_TOO_NEW,
genesis 351 DB_LOAD_FAIL,
genesis 352 DB_NEED_REWRITE
genesis 353 };
genesis 354
genesis 355 class CWalletDB : public CDB
genesis 356 {
genesis 357 public:
genesis 358 CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode)
genesis 359 {
genesis 360 }
genesis 361 private:
genesis 362 CWalletDB(const CWalletDB&);
genesis 363 void operator=(const CWalletDB&);
genesis 364 public:
genesis 365 bool ReadName(const std::string& strAddress, std::string& strName)
genesis 366 {
genesis 367 strName = "";
genesis 368 return Read(std::make_pair(std::string("name"), strAddress), strName);
genesis 369 }
genesis 370
genesis 371 bool WriteName(const std::string& strAddress, const std::string& strName);
genesis 372
genesis 373 bool EraseName(const std::string& strAddress);
genesis 374
genesis 375 bool ReadTx(uint256 hash, CWalletTx& wtx)
genesis 376 {
genesis 377 return Read(std::make_pair(std::string("tx"), hash), wtx);
genesis 378 }
genesis 379
genesis 380 bool WriteTx(uint256 hash, const CWalletTx& wtx)
genesis 381 {
genesis 382 nWalletDBUpdated++;
genesis 383 return Write(std::make_pair(std::string("tx"), hash), wtx);
genesis 384 }
genesis 385
genesis 386 bool EraseTx(uint256 hash)
genesis 387 {
genesis 388 nWalletDBUpdated++;
genesis 389 return Erase(std::make_pair(std::string("tx"), hash));
genesis 390 }
genesis 391
genesis 392 bool ReadKey(const std::vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
genesis 393 {
genesis 394 vchPrivKey.clear();
genesis 395 return Read(std::make_pair(std::string("key"), vchPubKey), vchPrivKey);
genesis 396 }
genesis 397
genesis 398 bool WriteKey(const std::vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
genesis 399 {
genesis 400 nWalletDBUpdated++;
genesis 401 return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
genesis 402 }
genesis 403
genesis 404 bool WriteCryptedKey(const std::vector<unsigned char>& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, bool fEraseUnencryptedKey = true)
genesis 405 {
genesis 406 nWalletDBUpdated++;
genesis 407 if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
genesis 408 return false;
genesis 409 if (fEraseUnencryptedKey)
genesis 410 {
genesis 411 Erase(std::make_pair(std::string("key"), vchPubKey));
genesis 412 Erase(std::make_pair(std::string("wkey"), vchPubKey));
genesis 413 }
genesis 414 return true;
genesis 415 }
genesis 416
genesis 417 bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
genesis 418 {
genesis 419 nWalletDBUpdated++;
genesis 420 return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
genesis 421 }
genesis 422
genesis 423 bool WriteBestBlock(const CBlockLocator& locator)
genesis 424 {
genesis 425 nWalletDBUpdated++;
genesis 426 return Write(std::string("bestblock"), locator);
genesis 427 }
genesis 428
genesis 429 bool ReadBestBlock(CBlockLocator& locator)
genesis 430 {
genesis 431 return Read(std::string("bestblock"), locator);
genesis 432 }
genesis 433
genesis 434 bool ReadDefaultKey(std::vector<unsigned char>& vchPubKey)
genesis 435 {
genesis 436 vchPubKey.clear();
genesis 437 return Read(std::string("defaultkey"), vchPubKey);
genesis 438 }
genesis 439
genesis 440 bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
genesis 441 {
genesis 442 nWalletDBUpdated++;
genesis 443 return Write(std::string("defaultkey"), vchPubKey);
genesis 444 }
genesis 445
genesis 446 bool ReadPool(int64 nPool, CKeyPool& keypool)
genesis 447 {
genesis 448 return Read(std::make_pair(std::string("pool"), nPool), keypool);
genesis 449 }
genesis 450
genesis 451 bool WritePool(int64 nPool, const CKeyPool& keypool)
genesis 452 {
genesis 453 nWalletDBUpdated++;
genesis 454 return Write(std::make_pair(std::string("pool"), nPool), keypool);
genesis 455 }
genesis 456
genesis 457 bool ErasePool(int64 nPool)
genesis 458 {
genesis 459 nWalletDBUpdated++;
genesis 460 return Erase(std::make_pair(std::string("pool"), nPool));
genesis 461 }
genesis 462
genesis 463 template<typename T>
genesis 464 bool ReadSetting(const std::string& strKey, T& value)
genesis 465 {
genesis 466 return Read(std::make_pair(std::string("setting"), strKey), value);
genesis 467 }
genesis 468
genesis 469 template<typename T>
genesis 470 bool WriteSetting(const std::string& strKey, const T& value)
genesis 471 {
genesis 472 nWalletDBUpdated++;
genesis 473 return Write(std::make_pair(std::string("setting"), strKey), value);
genesis 474 }
genesis 475
genesis 476 bool ReadAccount(const std::string& strAccount, CAccount& account);
genesis 477 bool WriteAccount(const std::string& strAccount, const CAccount& account);
genesis 478 bool WriteAccountingEntry(const CAccountingEntry& acentry);
genesis 479 int64 GetAccountCreditDebit(const std::string& strAccount);
genesis 480 void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
genesis 481
genesis 482 int LoadWallet(CWallet* pwallet);
genesis 483 };
genesis 484
genesis 485 #endif