-// Copyright (c) 2009-2010 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
-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 CCriticalSection cs_mapAddressBook;\r
-extern bool fClient;\r
-\r
-\r
-extern unsigned int nWalletDBUpdated;\r
-extern DbEnv dbenv;\r
-\r
-\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
- bool fReadOnly;\r
-\r
- explicit CDB(const char* pszFile, const char* pszMode="r+");\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
- if (fReadOnly)\r
- assert(("Write called on database in read-only mode", 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
- if (fReadOnly)\r
- assert(("Erase called on database in read-only mode", 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+") : CDB(!fClient ? "blkindex.dat" : NULL, pszMode) { }\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 CAddrDB : public CDB\r
-{\r
-public:\r
- CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }\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
-\r
-class CWalletDB : public CDB\r
-{\r
-public:\r
- CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode) { }\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
- CRITICAL_BLOCK(cs_mapAddressBook)\r
- mapAddressBook[strAddress] = strName;\r
- nWalletDBUpdated++;\r
- return Write(make_pair(string("name"), strAddress), strName);\r
- }\r
-\r
- bool EraseName(const string& strAddress)\r
- {\r
- // This should only be used for sending addresses, never for receiving addresses,\r
- // receiving addresses must always have an address book entry if they're not change return.\r
- CRITICAL_BLOCK(cs_mapAddressBook)\r
- mapAddressBook.erase(strAddress);\r
- nWalletDBUpdated++;\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
- nWalletDBUpdated++;\r
- return Write(make_pair(string("tx"), hash), wtx);\r
- }\r
-\r
- bool EraseTx(uint256 hash)\r
- {\r
- nWalletDBUpdated++;\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
- nWalletDBUpdated++;\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
- nWalletDBUpdated++;\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
- nWalletDBUpdated++;\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();
+ }
+};