Better wording for transaction fee notification messages
[novacoin.git] / db.h
diff --git a/db.h b/db.h
index 4961468..290981c 100644 (file)
--- a/db.h
+++ b/db.h
-// Copyright (c) 2009 Satoshi Nakamoto\r
-// Distributed under the MIT/X11 software license, see the accompanying\r
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
-\r
-#include <db_cxx.h>\r
-class CTransaction;\r
-class CTxIndex;\r
-class CDiskBlockIndex;\r
-class CDiskTxPos;\r
-class COutPoint;\r
-class CUser;\r
-class CReview;\r
-class CAddress;\r
-class CWalletTx;\r
-\r
-extern map<string, string> mapAddressBook;\r
-extern bool fClient;\r
-\r
-\r
-extern DbEnv dbenv;\r
-extern void DBFlush(bool fShutdown);\r
-\r
-\r
-\r
-\r
-class CDB\r
-{\r
-protected:\r
-    Db* pdb;\r
-    string strFile;\r
-    vector<DbTxn*> vTxn;\r
-\r
-    explicit CDB(const char* pszFile, const char* pszMode="r+", bool fTxn=false);\r
-    ~CDB() { Close(); }\r
-public:\r
-    void Close();\r
-private:\r
-    CDB(const CDB&);\r
-    void operator=(const CDB&);\r
-\r
-protected:\r
-    template<typename K, typename T>\r
-    bool Read(const K& key, T& value)\r
-    {\r
-        if (!pdb)\r
-            return false;\r
-\r
-        // Key\r
-        CDataStream ssKey(SER_DISK);\r
-        ssKey.reserve(1000);\r
-        ssKey << key;\r
-        Dbt datKey(&ssKey[0], ssKey.size());\r
-\r
-        // Read\r
-        Dbt datValue;\r
-        datValue.set_flags(DB_DBT_MALLOC);\r
-        int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);\r
-        memset(datKey.get_data(), 0, datKey.get_size());\r
-        if (datValue.get_data() == NULL)\r
-            return false;\r
-\r
-        // Unserialize value\r
-        CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);\r
-        ssValue >> value;\r
-\r
-        // Clear and free memory\r
-        memset(datValue.get_data(), 0, datValue.get_size());\r
-        free(datValue.get_data());\r
-        return (ret == 0);\r
-    }\r
-\r
-    template<typename K, typename T>\r
-    bool Write(const K& key, const T& value, bool fOverwrite=true)\r
-    {\r
-        if (!pdb)\r
-            return false;\r
-\r
-        // Key\r
-        CDataStream ssKey(SER_DISK);\r
-        ssKey.reserve(1000);\r
-        ssKey << key;\r
-        Dbt datKey(&ssKey[0], ssKey.size());\r
-\r
-        // Value\r
-        CDataStream ssValue(SER_DISK);\r
-        ssValue.reserve(10000);\r
-        ssValue << value;\r
-        Dbt datValue(&ssValue[0], ssValue.size());\r
-\r
-        // Write\r
-        int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));\r
-\r
-        // Clear memory in case it was a private key\r
-        memset(datKey.get_data(), 0, datKey.get_size());\r
-        memset(datValue.get_data(), 0, datValue.get_size());\r
-        return (ret == 0);\r
-    }\r
-\r
-    template<typename K>\r
-    bool Erase(const K& key)\r
-    {\r
-        if (!pdb)\r
-            return false;\r
-\r
-        // Key\r
-        CDataStream ssKey(SER_DISK);\r
-        ssKey.reserve(1000);\r
-        ssKey << key;\r
-        Dbt datKey(&ssKey[0], ssKey.size());\r
-\r
-        // Erase\r
-        int ret = pdb->del(GetTxn(), &datKey, 0);\r
-\r
-        // Clear memory\r
-        memset(datKey.get_data(), 0, datKey.get_size());\r
-        return (ret == 0 || ret == DB_NOTFOUND);\r
-    }\r
-\r
-    template<typename K>\r
-    bool Exists(const K& key)\r
-    {\r
-        if (!pdb)\r
-            return false;\r
-\r
-        // Key\r
-        CDataStream ssKey(SER_DISK);\r
-        ssKey.reserve(1000);\r
-        ssKey << key;\r
-        Dbt datKey(&ssKey[0], ssKey.size());\r
-\r
-        // Exists\r
-        int ret = pdb->exists(GetTxn(), &datKey, 0);\r
-\r
-        // Clear memory\r
-        memset(datKey.get_data(), 0, datKey.get_size());\r
-        return (ret == 0);\r
-    }\r
-\r
-    Dbc* GetCursor()\r
-    {\r
-        if (!pdb)\r
-            return NULL;\r
-        Dbc* pcursor = NULL;\r
-        int ret = pdb->cursor(NULL, &pcursor, 0);\r
-        if (ret != 0)\r
-            return NULL;\r
-        return pcursor;\r
-    }\r
-\r
-    int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)\r
-    {\r
-        // Read at cursor\r
-        Dbt datKey;\r
-        if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)\r
-        {\r
-            datKey.set_data(&ssKey[0]);\r
-            datKey.set_size(ssKey.size());\r
-        }\r
-        Dbt datValue;\r
-        if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)\r
-        {\r
-            datValue.set_data(&ssValue[0]);\r
-            datValue.set_size(ssValue.size());\r
-        }\r
-        datKey.set_flags(DB_DBT_MALLOC);\r
-        datValue.set_flags(DB_DBT_MALLOC);\r
-        int ret = pcursor->get(&datKey, &datValue, fFlags);\r
-        if (ret != 0)\r
-            return ret;\r
-        else if (datKey.get_data() == NULL || datValue.get_data() == NULL)\r
-            return 99999;\r
-\r
-        // Convert to streams\r
-        ssKey.SetType(SER_DISK);\r
-        ssKey.clear();\r
-        ssKey.write((char*)datKey.get_data(), datKey.get_size());\r
-        ssValue.SetType(SER_DISK);\r
-        ssValue.clear();\r
-        ssValue.write((char*)datValue.get_data(), datValue.get_size());\r
-\r
-        // Clear and free memory\r
-        memset(datKey.get_data(), 0, datKey.get_size());\r
-        memset(datValue.get_data(), 0, datValue.get_size());\r
-        free(datKey.get_data());\r
-        free(datValue.get_data());\r
-        return 0;\r
-    }\r
-\r
-    DbTxn* GetTxn()\r
-    {\r
-        if (!vTxn.empty())\r
-            return vTxn.back();\r
-        else\r
-            return NULL;\r
-    }\r
-\r
-public:\r
-    bool TxnBegin()\r
-    {\r
-        if (!pdb)\r
-            return false;\r
-        DbTxn* ptxn = NULL;\r
-        int ret = dbenv.txn_begin(GetTxn(), &ptxn, 0);\r
-        if (!ptxn || ret != 0)\r
-            return false;\r
-        vTxn.push_back(ptxn);\r
-        return true;\r
-    }\r
-\r
-    bool TxnCommit()\r
-    {\r
-        if (!pdb)\r
-            return false;\r
-        if (vTxn.empty())\r
-            return false;\r
-        int ret = vTxn.back()->commit(0);\r
-        vTxn.pop_back();\r
-        return (ret == 0);\r
-    }\r
-\r
-    bool TxnAbort()\r
-    {\r
-        if (!pdb)\r
-            return false;\r
-        if (vTxn.empty())\r
-            return false;\r
-        int ret = vTxn.back()->abort();\r
-        vTxn.pop_back();\r
-        return (ret == 0);\r
-    }\r
-\r
-    bool ReadVersion(int& nVersion)\r
-    {\r
-        nVersion = 0;\r
-        return Read(string("version"), nVersion);\r
-    }\r
-\r
-    bool WriteVersion(int nVersion)\r
-    {\r
-        return Write(string("version"), nVersion);\r
-    }\r
-};\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-class CTxDB : public CDB\r
-{\r
-public:\r
-    CTxDB(const char* pszMode="r+", bool fTxn=false) : CDB(!fClient ? "blkindex.dat" : NULL, pszMode, fTxn) { }\r
-private:\r
-    CTxDB(const CTxDB&);\r
-    void operator=(const CTxDB&);\r
-public:\r
-    bool ReadTxIndex(uint256 hash, CTxIndex& txindex);\r
-    bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);\r
-    bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);\r
-    bool EraseTxIndex(const CTransaction& tx);\r
-    bool ContainsTx(uint256 hash);\r
-    bool ReadOwnerTxes(uint160 hash160, int nHeight, vector<CTransaction>& vtx);\r
-    bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);\r
-    bool ReadDiskTx(uint256 hash, CTransaction& tx);\r
-    bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);\r
-    bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);\r
-    bool WriteBlockIndex(const CDiskBlockIndex& blockindex);\r
-    bool EraseBlockIndex(uint256 hash);\r
-    bool ReadHashBestChain(uint256& hashBestChain);\r
-    bool WriteHashBestChain(uint256 hashBestChain);\r
-    bool LoadBlockIndex();\r
-};\r
-\r
-\r
-\r
-\r
-\r
-class CReviewDB : public CDB\r
-{\r
-public:\r
-    CReviewDB(const char* pszMode="r+", bool fTxn=false) : CDB("reviews.dat", pszMode, fTxn) { }\r
-private:\r
-    CReviewDB(const CReviewDB&);\r
-    void operator=(const CReviewDB&);\r
-public:\r
-    bool ReadUser(uint256 hash, CUser& user)\r
-    {\r
-        return Read(make_pair(string("user"), hash), user);\r
-    }\r
-\r
-    bool WriteUser(uint256 hash, const CUser& user)\r
-    {\r
-        return Write(make_pair(string("user"), hash), user);\r
-    }\r
-\r
-    bool ReadReviews(uint256 hash, vector<CReview>& vReviews);\r
-    bool WriteReviews(uint256 hash, const vector<CReview>& vReviews);\r
-};\r
-\r
-\r
-\r
-\r
-\r
-class CMarketDB : public CDB\r
-{\r
-public:\r
-    CMarketDB(const char* pszMode="r+", bool fTxn=false) : CDB("market.dat", pszMode, fTxn) { }\r
-private:\r
-    CMarketDB(const CMarketDB&);\r
-    void operator=(const CMarketDB&);\r
-};\r
-\r
-\r
-\r
-\r
-\r
-class CAddrDB : public CDB\r
-{\r
-public:\r
-    CAddrDB(const char* pszMode="r+", bool fTxn=false) : CDB("addr.dat", pszMode, fTxn) { }\r
-private:\r
-    CAddrDB(const CAddrDB&);\r
-    void operator=(const CAddrDB&);\r
-public:\r
-    bool WriteAddress(const CAddress& addr);\r
-    bool LoadAddresses();\r
-};\r
-\r
-bool LoadAddresses();\r
-\r
-\r
-\r
-\r
-\r
-class CWalletDB : public CDB\r
-{\r
-public:\r
-    CWalletDB(const char* pszMode="r+", bool fTxn=false) : CDB("wallet.dat", pszMode, fTxn) { }\r
-    ~CWalletDB();\r
-private:\r
-    CWalletDB(const CWalletDB&);\r
-    void operator=(const CWalletDB&);\r
-public:\r
-    bool ReadName(const string& strAddress, string& strName)\r
-    {\r
-        strName = "";\r
-        return Read(make_pair(string("name"), strAddress), strName);\r
-    }\r
-\r
-    bool WriteName(const string& strAddress, const string& strName)\r
-    {\r
-        mapAddressBook[strAddress] = strName;\r
-        return Write(make_pair(string("name"), strAddress), strName);\r
-    }\r
-\r
-    bool EraseName(const string& strAddress)\r
-    {\r
-        mapAddressBook.erase(strAddress);\r
-        return Erase(make_pair(string("name"), strAddress));\r
-    }\r
-\r
-    bool ReadTx(uint256 hash, CWalletTx& wtx)\r
-    {\r
-        return Read(make_pair(string("tx"), hash), wtx);\r
-    }\r
-\r
-    bool WriteTx(uint256 hash, const CWalletTx& wtx)\r
-    {\r
-        return Write(make_pair(string("tx"), hash), wtx);\r
-    }\r
-\r
-    bool EraseTx(uint256 hash)\r
-    {\r
-        return Erase(make_pair(string("tx"), hash));\r
-    }\r
-\r
-    bool ReadKey(const vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)\r
-    {\r
-        vchPrivKey.clear();\r
-        return Read(make_pair(string("key"), vchPubKey), vchPrivKey);\r
-    }\r
-\r
-    bool WriteKey(const vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)\r
-    {\r
-        return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false);\r
-    }\r
-\r
-    bool ReadDefaultKey(vector<unsigned char>& vchPubKey)\r
-    {\r
-        vchPubKey.clear();\r
-        return Read(string("defaultkey"), vchPubKey);\r
-    }\r
-\r
-    bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)\r
-    {\r
-        return Write(string("defaultkey"), vchPubKey);\r
-    }\r
-\r
-    template<typename T>\r
-    bool ReadSetting(const string& strKey, T& value)\r
-    {\r
-        return Read(make_pair(string("setting"), strKey), value);\r
-    }\r
-\r
-    template<typename T>\r
-    bool WriteSetting(const string& strKey, const T& value)\r
-    {\r
-        return Write(make_pair(string("setting"), strKey), value);\r
-    }\r
-\r
-    bool LoadWallet(vector<unsigned char>& vchDefaultKeyRet);\r
-};\r
-\r
-bool LoadWallet(bool& fFirstRunRet);\r
-\r
-inline bool SetAddressBookName(const string& strAddress, const string& strName)\r
-{\r
-    return CWalletDB().WriteName(strAddress, strName);\r
-}\r
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
+class CTransaction;
+class CTxIndex;
+class CDiskBlockIndex;
+class CDiskTxPos;
+class COutPoint;
+class CUser;
+class CReview;
+class CAddress;
+class CWalletTx;
+class CAccount;
+class CAccountingEntry;
+class CBlockLocator;
+
+extern map<string, string> mapAddressBook;
+extern CCriticalSection cs_mapAddressBook;
+extern vector<unsigned char> vchDefaultKey;
+extern bool fClient;
+extern int nBestHeight;
+
+
+extern unsigned int nWalletDBUpdated;
+extern DbEnv dbenv;
+
+
+extern void DBFlush(bool fShutdown);
+extern vector<unsigned char> GetKeyFromKeyPool();
+extern int64 GetOldestKeyPoolTime();
+
+
+
+
+class CDB
+{
+protected:
+    Db* pdb;
+    string strFile;
+    vector<DbTxn*> vTxn;
+    bool fReadOnly;
+
+    explicit CDB(const char* pszFile, const char* pszMode="r+");
+    ~CDB() { Close(); }
+public:
+    void Close();
+private:
+    CDB(const CDB&);
+    void operator=(const CDB&);
+
+protected:
+    template<typename K, typename T>
+    bool Read(const K& key, T& value)
+    {
+        if (!pdb)
+            return false;
+
+        // Key
+        CDataStream ssKey(SER_DISK);
+        ssKey.reserve(1000);
+        ssKey << key;
+        Dbt datKey(&ssKey[0], ssKey.size());
+
+        // Read
+        Dbt datValue;
+        datValue.set_flags(DB_DBT_MALLOC);
+        int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
+        memset(datKey.get_data(), 0, datKey.get_size());
+        if (datValue.get_data() == NULL)
+            return false;
+
+        // Unserialize value
+        CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
+        ssValue >> value;
+
+        // Clear and free memory
+        memset(datValue.get_data(), 0, datValue.get_size());
+        free(datValue.get_data());
+        return (ret == 0);
+    }
+
+    template<typename K, typename T>
+    bool Write(const K& key, const T& value, bool fOverwrite=true)
+    {
+        if (!pdb)
+            return false;
+        if (fReadOnly)
+            assert(("Write called on database in read-only mode", false));
+
+        // Key
+        CDataStream ssKey(SER_DISK);
+        ssKey.reserve(1000);
+        ssKey << key;
+        Dbt datKey(&ssKey[0], ssKey.size());
+
+        // Value
+        CDataStream ssValue(SER_DISK);
+        ssValue.reserve(10000);
+        ssValue << value;
+        Dbt datValue(&ssValue[0], ssValue.size());
+
+        // Write
+        int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
+
+        // Clear memory in case it was a private key
+        memset(datKey.get_data(), 0, datKey.get_size());
+        memset(datValue.get_data(), 0, datValue.get_size());
+        return (ret == 0);
+    }
+
+    template<typename K>
+    bool Erase(const K& key)
+    {
+        if (!pdb)
+            return false;
+        if (fReadOnly)
+            assert(("Erase called on database in read-only mode", false));
+
+        // Key
+        CDataStream ssKey(SER_DISK);
+        ssKey.reserve(1000);
+        ssKey << key;
+        Dbt datKey(&ssKey[0], ssKey.size());
+
+        // Erase
+        int ret = pdb->del(GetTxn(), &datKey, 0);
+
+        // Clear memory
+        memset(datKey.get_data(), 0, datKey.get_size());
+        return (ret == 0 || ret == DB_NOTFOUND);
+    }
+
+    template<typename K>
+    bool Exists(const K& key)
+    {
+        if (!pdb)
+            return false;
+
+        // Key
+        CDataStream ssKey(SER_DISK);
+        ssKey.reserve(1000);
+        ssKey << key;
+        Dbt datKey(&ssKey[0], ssKey.size());
+
+        // Exists
+        int ret = pdb->exists(GetTxn(), &datKey, 0);
+
+        // Clear memory
+        memset(datKey.get_data(), 0, datKey.get_size());
+        return (ret == 0);
+    }
+
+    Dbc* GetCursor()
+    {
+        if (!pdb)
+            return NULL;
+        Dbc* pcursor = NULL;
+        int ret = pdb->cursor(NULL, &pcursor, 0);
+        if (ret != 0)
+            return NULL;
+        return pcursor;
+    }
+
+    int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
+    {
+        // Read at cursor
+        Dbt datKey;
+        if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
+        {
+            datKey.set_data(&ssKey[0]);
+            datKey.set_size(ssKey.size());
+        }
+        Dbt datValue;
+        if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
+        {
+            datValue.set_data(&ssValue[0]);
+            datValue.set_size(ssValue.size());
+        }
+        datKey.set_flags(DB_DBT_MALLOC);
+        datValue.set_flags(DB_DBT_MALLOC);
+        int ret = pcursor->get(&datKey, &datValue, fFlags);
+        if (ret != 0)
+            return ret;
+        else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
+            return 99999;
+
+        // Convert to streams
+        ssKey.SetType(SER_DISK);
+        ssKey.clear();
+        ssKey.write((char*)datKey.get_data(), datKey.get_size());
+        ssValue.SetType(SER_DISK);
+        ssValue.clear();
+        ssValue.write((char*)datValue.get_data(), datValue.get_size());
+
+        // Clear and free memory
+        memset(datKey.get_data(), 0, datKey.get_size());
+        memset(datValue.get_data(), 0, datValue.get_size());
+        free(datKey.get_data());
+        free(datValue.get_data());
+        return 0;
+    }
+
+    DbTxn* GetTxn()
+    {
+        if (!vTxn.empty())
+            return vTxn.back();
+        else
+            return NULL;
+    }
+
+public:
+    bool TxnBegin()
+    {
+        if (!pdb)
+            return false;
+        DbTxn* ptxn = NULL;
+        int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
+        if (!ptxn || ret != 0)
+            return false;
+        vTxn.push_back(ptxn);
+        return true;
+    }
+
+    bool TxnCommit()
+    {
+        if (!pdb)
+            return false;
+        if (vTxn.empty())
+            return false;
+        int ret = vTxn.back()->commit(0);
+        vTxn.pop_back();
+        return (ret == 0);
+    }
+
+    bool TxnAbort()
+    {
+        if (!pdb)
+            return false;
+        if (vTxn.empty())
+            return false;
+        int ret = vTxn.back()->abort();
+        vTxn.pop_back();
+        return (ret == 0);
+    }
+
+    bool ReadVersion(int& nVersion)
+    {
+        nVersion = 0;
+        return Read(string("version"), nVersion);
+    }
+
+    bool WriteVersion(int nVersion)
+    {
+        return Write(string("version"), nVersion);
+    }
+};
+
+
+
+
+
+
+
+
+class CTxDB : public CDB
+{
+public:
+    CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { }
+private:
+    CTxDB(const CTxDB&);
+    void operator=(const CTxDB&);
+public:
+    bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
+    bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
+    bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
+    bool EraseTxIndex(const CTransaction& tx);
+    bool ContainsTx(uint256 hash);
+    bool ReadOwnerTxes(uint160 hash160, int nHeight, vector<CTransaction>& vtx);
+    bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
+    bool ReadDiskTx(uint256 hash, CTransaction& tx);
+    bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
+    bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
+    bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
+    bool EraseBlockIndex(uint256 hash);
+    bool ReadHashBestChain(uint256& hashBestChain);
+    bool WriteHashBestChain(uint256 hashBestChain);
+    bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
+    bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
+    bool LoadBlockIndex();
+};
+
+
+
+
+
+class CAddrDB : public CDB
+{
+public:
+    CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
+private:
+    CAddrDB(const CAddrDB&);
+    void operator=(const CAddrDB&);
+public:
+    bool WriteAddress(const CAddress& addr);
+    bool EraseAddress(const CAddress& addr);
+    bool LoadAddresses();
+};
+
+bool LoadAddresses();
+
+
+
+
+
+
+class CKeyPool
+{
+public:
+    int64 nTime;
+    vector<unsigned char> vchPubKey;
+
+    CKeyPool()
+    {
+        nTime = GetTime();
+    }
+
+    CKeyPool(const vector<unsigned char>& vchPubKeyIn)
+    {
+        nTime = GetTime();
+        vchPubKey = vchPubKeyIn;
+    }
+
+    IMPLEMENT_SERIALIZE
+    (
+        if (!(nType & SER_GETHASH))
+            READWRITE(nVersion);
+        READWRITE(nTime);
+        READWRITE(vchPubKey);
+    )
+};
+
+
+
+
+class CWalletDB : public CDB
+{
+public:
+    CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode)
+    {
+    }
+private:
+    CWalletDB(const CWalletDB&);
+    void operator=(const CWalletDB&);
+public:
+    bool ReadName(const string& strAddress, string& strName)
+    {
+        strName = "";
+        return Read(make_pair(string("name"), strAddress), strName);
+    }
+
+    bool WriteName(const string& strAddress, const string& strName)
+    {
+        CRITICAL_BLOCK(cs_mapAddressBook)
+            mapAddressBook[strAddress] = strName;
+        nWalletDBUpdated++;
+        return Write(make_pair(string("name"), strAddress), strName);
+    }
+
+    bool EraseName(const string& strAddress)
+    {
+        // This should only be used for sending addresses, never for receiving addresses,
+        // receiving addresses must always have an address book entry if they're not change return.
+        CRITICAL_BLOCK(cs_mapAddressBook)
+            mapAddressBook.erase(strAddress);
+        nWalletDBUpdated++;
+        return Erase(make_pair(string("name"), strAddress));
+    }
+
+    bool ReadTx(uint256 hash, CWalletTx& wtx)
+    {
+        return Read(make_pair(string("tx"), hash), wtx);
+    }
+
+    bool WriteTx(uint256 hash, const CWalletTx& wtx)
+    {
+        nWalletDBUpdated++;
+        return Write(make_pair(string("tx"), hash), wtx);
+    }
+
+    bool EraseTx(uint256 hash)
+    {
+        nWalletDBUpdated++;
+        return Erase(make_pair(string("tx"), hash));
+    }
+
+    bool ReadKey(const vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
+    {
+        vchPrivKey.clear();
+        return Read(make_pair(string("key"), vchPubKey), vchPrivKey);
+    }
+
+    bool WriteKey(const vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
+    {
+        nWalletDBUpdated++;
+        return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false);
+    }
+
+    bool WriteBestBlock(const CBlockLocator& locator)
+    {
+        nWalletDBUpdated++;
+        return Write(string("bestblock"), locator);
+    }
+
+    bool ReadBestBlock(CBlockLocator& locator)
+    {
+        return Read(string("bestblock"), locator);
+    }
+
+    bool ReadDefaultKey(vector<unsigned char>& vchPubKey)
+    {
+        vchPubKey.clear();
+        return Read(string("defaultkey"), vchPubKey);
+    }
+
+    bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)
+    {
+        vchDefaultKey = vchPubKey;
+        nWalletDBUpdated++;
+        return Write(string("defaultkey"), vchPubKey);
+    }
+
+    template<typename T>
+    bool ReadSetting(const string& strKey, T& value)
+    {
+        return Read(make_pair(string("setting"), strKey), value);
+    }
+
+    template<typename T>
+    bool WriteSetting(const string& strKey, const T& value)
+    {
+        nWalletDBUpdated++;
+        return Write(make_pair(string("setting"), strKey), value);
+    }
+
+    bool ReadAccount(const string& strAccount, CAccount& account);
+    bool WriteAccount(const string& strAccount, const CAccount& account);
+    bool WriteAccountingEntry(const CAccountingEntry& acentry);
+    int64 GetAccountCreditDebit(const string& strAccount);
+    void ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& acentries);
+
+    bool LoadWallet();
+protected:
+    void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
+    void KeepKey(int64 nIndex);
+    static void ReturnKey(int64 nIndex);
+    friend class CReserveKey;
+    friend vector<unsigned char> GetKeyFromKeyPool();
+    friend int64 GetOldestKeyPoolTime();
+};
+
+bool LoadWallet(bool& fFirstRunRet);
+void BackupWallet(const string& strDest);
+
+inline bool SetAddressBookName(const string& strAddress, const string& strName)
+{
+    return CWalletDB().WriteName(strAddress, strName);
+}
+
+class CReserveKey
+{
+protected:
+    int64 nIndex;
+    vector<unsigned char> vchPubKey;
+public:
+    CReserveKey()
+    {
+        nIndex = -1;
+    }
+
+    ~CReserveKey()
+    {
+        if (!fShutdown)
+            ReturnKey();
+    }
+
+    vector<unsigned char> GetReservedKey()
+    {
+        if (nIndex == -1)
+        {
+            CKeyPool keypool;
+            CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
+            vchPubKey = keypool.vchPubKey;
+        }
+        assert(!vchPubKey.empty());
+        return vchPubKey;
+    }
+
+    void KeepKey()
+    {
+        if (nIndex != -1)
+            CWalletDB().KeepKey(nIndex);
+        nIndex = -1;
+        vchPubKey.clear();
+    }
+
+    void ReturnKey()
+    {
+        if (nIndex != -1)
+            CWalletDB::ReturnKey(nIndex);
+        nIndex = -1;
+        vchPubKey.clear();
+    }
+};