genesis                 1 
genesis                 2 
genesis                 3 
genesis                 4 
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         
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         
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         
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         
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         
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         
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         
genesis               105         int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
genesis               106 
genesis               107         
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         
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         
genesis               128         int ret = pdb->del(GetTxn(), &datKey, 0);
genesis               129 
genesis               130         
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         
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         
genesis               148         int ret = pdb->exists(GetTxn(), &datKey, 0);
genesis               149 
genesis               150         
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         
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         
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         
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