File indexing completed on 2020-06-25 15:44:20
0001
0002
0003
0004
0005 #ifndef BITCOIN_DB_H
0006 #define BITCOIN_DB_H
0007
0008 #include "key.h"
0009
0010 #include <map>
0011 #include <string>
0012 #include <vector>
0013
0014 #include <db_cxx.h>
0015
0016 class CTxIndex;
0017 class CDiskBlockIndex;
0018 class CDiskTxPos;
0019 class COutPoint;
0020 class CAddress;
0021 class CWalletTx;
0022 class CWallet;
0023 class CAccount;
0024 class CAccountingEntry;
0025 class CBlockLocator;
0026
0027
0028 extern unsigned int nWalletDBUpdated;
0029 extern DbEnv dbenv;
0030
0031 extern void DBFlush(bool fShutdown);
0032 void ThreadFlushWalletDB(void* parg);
0033 bool BackupWallet(const CWallet& wallet, const std::string& strDest);
0034
0035
0036
0037 class CDB
0038 {
0039 protected:
0040 Db* pdb;
0041 std::string strFile;
0042 std::vector<DbTxn*> vTxn;
0043 bool fReadOnly;
0044
0045 explicit CDB(const char* pszFile, const char* pszMode="r+");
0046 ~CDB() { Close(); }
0047 public:
0048 void Close();
0049 private:
0050 CDB(const CDB&);
0051 void operator=(const CDB&);
0052
0053 protected:
0054 template<typename K, typename T>
0055 bool Read(const K& key, T& value)
0056 {
0057 if (!pdb)
0058 return false;
0059
0060
0061 CDataStream ssKey(SER_DISK);
0062 ssKey.reserve(1000);
0063 ssKey << key;
0064 Dbt datKey(&ssKey[0], ssKey.size());
0065
0066
0067 Dbt datValue;
0068 datValue.set_flags(DB_DBT_MALLOC);
0069 int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
0070 memset(datKey.get_data(), 0, datKey.get_size());
0071 if (datValue.get_data() == NULL)
0072 return false;
0073
0074
0075 CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
0076 ssValue >> value;
0077
0078
0079 memset(datValue.get_data(), 0, datValue.get_size());
0080 free(datValue.get_data());
0081 return (ret == 0);
0082 }
0083
0084 template<typename K, typename T>
0085 bool Write(const K& key, const T& value, bool fOverwrite=true)
0086 {
0087 if (!pdb)
0088 return false;
0089 if (fReadOnly)
0090 assert(!"Write called on database in read-only mode");
0091
0092
0093 CDataStream ssKey(SER_DISK);
0094 ssKey.reserve(1000);
0095 ssKey << key;
0096 Dbt datKey(&ssKey[0], ssKey.size());
0097
0098
0099 CDataStream ssValue(SER_DISK);
0100 ssValue.reserve(10000);
0101 ssValue << value;
0102 Dbt datValue(&ssValue[0], ssValue.size());
0103
0104
0105 int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
0106
0107
0108 memset(datKey.get_data(), 0, datKey.get_size());
0109 memset(datValue.get_data(), 0, datValue.get_size());
0110 return (ret == 0);
0111 }
0112
0113 template<typename K>
0114 bool Erase(const K& key)
0115 {
0116 if (!pdb)
0117 return false;
0118 if (fReadOnly)
0119 assert(!"Erase called on database in read-only mode");
0120
0121
0122 CDataStream ssKey(SER_DISK);
0123 ssKey.reserve(1000);
0124 ssKey << key;
0125 Dbt datKey(&ssKey[0], ssKey.size());
0126
0127
0128 int ret = pdb->del(GetTxn(), &datKey, 0);
0129
0130
0131 memset(datKey.get_data(), 0, datKey.get_size());
0132 return (ret == 0 || ret == DB_NOTFOUND);
0133 }
0134
0135 template<typename K>
0136 bool Exists(const K& key)
0137 {
0138 if (!pdb)
0139 return false;
0140
0141
0142 CDataStream ssKey(SER_DISK);
0143 ssKey.reserve(1000);
0144 ssKey << key;
0145 Dbt datKey(&ssKey[0], ssKey.size());
0146
0147
0148 int ret = pdb->exists(GetTxn(), &datKey, 0);
0149
0150
0151 memset(datKey.get_data(), 0, datKey.get_size());
0152 return (ret == 0);
0153 }
0154
0155 Dbc* GetCursor()
0156 {
0157 if (!pdb)
0158 return NULL;
0159 Dbc* pcursor = NULL;
0160 int ret = pdb->cursor(NULL, &pcursor, 0);
0161 if (ret != 0)
0162 return NULL;
0163 return pcursor;
0164 }
0165
0166 int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
0167 {
0168
0169 Dbt datKey;
0170 if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
0171 {
0172 datKey.set_data(&ssKey[0]);
0173 datKey.set_size(ssKey.size());
0174 }
0175 Dbt datValue;
0176 if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
0177 {
0178 datValue.set_data(&ssValue[0]);
0179 datValue.set_size(ssValue.size());
0180 }
0181 datKey.set_flags(DB_DBT_MALLOC);
0182 datValue.set_flags(DB_DBT_MALLOC);
0183 int ret = pcursor->get(&datKey, &datValue, fFlags);
0184 if (ret != 0)
0185 return ret;
0186 else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
0187 return 99999;
0188
0189
0190 ssKey.SetType(SER_DISK);
0191 ssKey.clear();
0192 ssKey.write((char*)datKey.get_data(), datKey.get_size());
0193 ssValue.SetType(SER_DISK);
0194 ssValue.clear();
0195 ssValue.write((char*)datValue.get_data(), datValue.get_size());
0196
0197
0198 memset(datKey.get_data(), 0, datKey.get_size());
0199 memset(datValue.get_data(), 0, datValue.get_size());
0200 free(datKey.get_data());
0201 free(datValue.get_data());
0202 return 0;
0203 }
0204
0205 DbTxn* GetTxn()
0206 {
0207 if (!vTxn.empty())
0208 return vTxn.back();
0209 else
0210 return NULL;
0211 }
0212
0213 public:
0214 bool TxnBegin()
0215 {
0216 if (!pdb)
0217 return false;
0218 DbTxn* ptxn = NULL;
0219 int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
0220 if (!ptxn || ret != 0)
0221 return false;
0222 vTxn.push_back(ptxn);
0223 return true;
0224 }
0225
0226 bool TxnCommit()
0227 {
0228 if (!pdb)
0229 return false;
0230 if (vTxn.empty())
0231 return false;
0232 int ret = vTxn.back()->commit(0);
0233 vTxn.pop_back();
0234 return (ret == 0);
0235 }
0236
0237 bool TxnAbort()
0238 {
0239 if (!pdb)
0240 return false;
0241 if (vTxn.empty())
0242 return false;
0243 int ret = vTxn.back()->abort();
0244 vTxn.pop_back();
0245 return (ret == 0);
0246 }
0247
0248 bool ReadVersion(int& nVersion)
0249 {
0250 nVersion = 0;
0251 return Read(std::string("version"), nVersion);
0252 }
0253
0254 bool WriteVersion(int nVersion)
0255 {
0256 return Write(std::string("version"), nVersion);
0257 }
0258
0259 bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
0260 };
0261
0262
0263
0264
0265
0266
0267
0268
0269 class CTxDB : public CDB
0270 {
0271 public:
0272 CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { }
0273 private:
0274 CTxDB(const CTxDB&);
0275 void operator=(const CTxDB&);
0276 public:
0277 bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
0278 bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
0279 bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
0280 bool EraseTxIndex(const CTransaction& tx);
0281 bool ContainsTx(uint256 hash);
0282 bool ReadOwnerTxes(uint160 hash160, int nHeight, std::vector<CTransaction>& vtx);
0283 bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
0284 bool ReadDiskTx(uint256 hash, CTransaction& tx);
0285 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
0286 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
0287 bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
0288 bool EraseBlockIndex(uint256 hash);
0289 bool ReadHashBestChain(uint256& hashBestChain);
0290 bool WriteHashBestChain(uint256 hashBestChain);
0291 bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
0292 bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
0293 bool LoadBlockIndex();
0294 };
0295
0296
0297
0298
0299
0300 class CAddrDB : public CDB
0301 {
0302 public:
0303 CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
0304 private:
0305 CAddrDB(const CAddrDB&);
0306 void operator=(const CAddrDB&);
0307 public:
0308 bool WriteAddress(const CAddress& addr);
0309 bool EraseAddress(const CAddress& addr);
0310 bool LoadAddresses();
0311 };
0312
0313 bool LoadAddresses();
0314
0315
0316
0317 class CKeyPool
0318 {
0319 public:
0320 int64 nTime;
0321 std::vector<unsigned char> vchPubKey;
0322
0323 CKeyPool()
0324 {
0325 nTime = GetTime();
0326 }
0327
0328 CKeyPool(const std::vector<unsigned char>& vchPubKeyIn)
0329 {
0330 nTime = GetTime();
0331 vchPubKey = vchPubKeyIn;
0332 }
0333
0334 IMPLEMENT_SERIALIZE
0335 (
0336 if (!(nType & SER_GETHASH))
0337 READWRITE(nVersion);
0338 READWRITE(nTime);
0339 READWRITE(vchPubKey);
0340 )
0341 };
0342
0343
0344
0345
0346 enum DBErrors
0347 {
0348 DB_LOAD_OK,
0349 DB_CORRUPT,
0350 DB_TOO_NEW,
0351 DB_LOAD_FAIL,
0352 DB_NEED_REWRITE
0353 };
0354
0355 class CWalletDB : public CDB
0356 {
0357 public:
0358 CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode)
0359 {
0360 }
0361 private:
0362 CWalletDB(const CWalletDB&);
0363 void operator=(const CWalletDB&);
0364 public:
0365 bool ReadName(const std::string& strAddress, std::string& strName)
0366 {
0367 strName = "";
0368 return Read(std::make_pair(std::string("name"), strAddress), strName);
0369 }
0370
0371 bool WriteName(const std::string& strAddress, const std::string& strName);
0372
0373 bool EraseName(const std::string& strAddress);
0374
0375 bool ReadTx(uint256 hash, CWalletTx& wtx)
0376 {
0377 return Read(std::make_pair(std::string("tx"), hash), wtx);
0378 }
0379
0380 bool WriteTx(uint256 hash, const CWalletTx& wtx)
0381 {
0382 nWalletDBUpdated++;
0383 return Write(std::make_pair(std::string("tx"), hash), wtx);
0384 }
0385
0386 bool EraseTx(uint256 hash)
0387 {
0388 nWalletDBUpdated++;
0389 return Erase(std::make_pair(std::string("tx"), hash));
0390 }
0391
0392 bool ReadKey(const std::vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
0393 {
0394 vchPrivKey.clear();
0395 return Read(std::make_pair(std::string("key"), vchPubKey), vchPrivKey);
0396 }
0397
0398 bool WriteKey(const std::vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
0399 {
0400 nWalletDBUpdated++;
0401 return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
0402 }
0403
0404 bool WriteCryptedKey(const std::vector<unsigned char>& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, bool fEraseUnencryptedKey = true)
0405 {
0406 nWalletDBUpdated++;
0407 if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
0408 return false;
0409 if (fEraseUnencryptedKey)
0410 {
0411 Erase(std::make_pair(std::string("key"), vchPubKey));
0412 Erase(std::make_pair(std::string("wkey"), vchPubKey));
0413 }
0414 return true;
0415 }
0416
0417 bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
0418 {
0419 nWalletDBUpdated++;
0420 return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
0421 }
0422
0423 bool WriteBestBlock(const CBlockLocator& locator)
0424 {
0425 nWalletDBUpdated++;
0426 return Write(std::string("bestblock"), locator);
0427 }
0428
0429 bool ReadBestBlock(CBlockLocator& locator)
0430 {
0431 return Read(std::string("bestblock"), locator);
0432 }
0433
0434 bool ReadDefaultKey(std::vector<unsigned char>& vchPubKey)
0435 {
0436 vchPubKey.clear();
0437 return Read(std::string("defaultkey"), vchPubKey);
0438 }
0439
0440 bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
0441 {
0442 nWalletDBUpdated++;
0443 return Write(std::string("defaultkey"), vchPubKey);
0444 }
0445
0446 bool ReadPool(int64 nPool, CKeyPool& keypool)
0447 {
0448 return Read(std::make_pair(std::string("pool"), nPool), keypool);
0449 }
0450
0451 bool WritePool(int64 nPool, const CKeyPool& keypool)
0452 {
0453 nWalletDBUpdated++;
0454 return Write(std::make_pair(std::string("pool"), nPool), keypool);
0455 }
0456
0457 bool ErasePool(int64 nPool)
0458 {
0459 nWalletDBUpdated++;
0460 return Erase(std::make_pair(std::string("pool"), nPool));
0461 }
0462
0463 template<typename T>
0464 bool ReadSetting(const std::string& strKey, T& value)
0465 {
0466 return Read(std::make_pair(std::string("setting"), strKey), value);
0467 }
0468
0469 template<typename T>
0470 bool WriteSetting(const std::string& strKey, const T& value)
0471 {
0472 nWalletDBUpdated++;
0473 return Write(std::make_pair(std::string("setting"), strKey), value);
0474 }
0475
0476 bool ReadAccount(const std::string& strAccount, CAccount& account);
0477 bool WriteAccount(const std::string& strAccount, const CAccount& account);
0478 bool WriteAccountingEntry(const CAccountingEntry& acentry);
0479 int64 GetAccountCreditDebit(const std::string& strAccount);
0480 void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
0481
0482 int LoadWallet(CWallet* pwallet);
0483 };
0484
0485 #endif