Back to home page

Bitcoin sources

 
 

    


0001 // Copyright (c) 2009-2010 Satoshi Nakamoto
0002 // Copyright (c) 2011 The Bitcoin developers
0003 // Distributed under the MIT/X11 software license, see the accompanying
0004 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
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         // Key
0061         CDataStream ssKey(SER_DISK);
0062         ssKey.reserve(1000);
0063         ssKey << key;
0064         Dbt datKey(&ssKey[0], ssKey.size());
0065 
0066         // Read
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         // Unserialize value
0075         CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
0076         ssValue >> value;
0077 
0078         // Clear and free memory
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         // Key
0093         CDataStream ssKey(SER_DISK);
0094         ssKey.reserve(1000);
0095         ssKey << key;
0096         Dbt datKey(&ssKey[0], ssKey.size());
0097 
0098         // Value
0099         CDataStream ssValue(SER_DISK);
0100         ssValue.reserve(10000);
0101         ssValue << value;
0102         Dbt datValue(&ssValue[0], ssValue.size());
0103 
0104         // Write
0105         int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
0106 
0107         // Clear memory in case it was a private key
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         // Key
0122         CDataStream ssKey(SER_DISK);
0123         ssKey.reserve(1000);
0124         ssKey << key;
0125         Dbt datKey(&ssKey[0], ssKey.size());
0126 
0127         // Erase
0128         int ret = pdb->del(GetTxn(), &datKey, 0);
0129 
0130         // Clear memory
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         // Key
0142         CDataStream ssKey(SER_DISK);
0143         ssKey.reserve(1000);
0144         ssKey << key;
0145         Dbt datKey(&ssKey[0], ssKey.size());
0146 
0147         // Exists
0148         int ret = pdb->exists(GetTxn(), &datKey, 0);
0149 
0150         // Clear memory
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         // Read at cursor
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         // Convert to streams
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         // Clear and free memory
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