1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
15 class CAccountingEntry;
17 extern map<string, string> mapAddressBook;
18 extern CCriticalSection cs_mapAddressBook;
19 extern vector<unsigned char> vchDefaultKey;
21 extern int nBestHeight;
24 extern unsigned int nWalletDBUpdated;
28 extern void DBFlush(bool fShutdown);
29 extern vector<unsigned char> GetKeyFromKeyPool();
30 extern int64 GetOldestKeyPoolTime();
43 explicit CDB(const char* pszFile, const char* pszMode="r+");
49 void operator=(const CDB&);
52 template<typename K, typename T>
53 bool Read(const K& key, T& value)
59 CDataStream ssKey(SER_DISK);
62 Dbt datKey(&ssKey[0], ssKey.size());
66 datValue.set_flags(DB_DBT_MALLOC);
67 int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
68 memset(datKey.get_data(), 0, datKey.get_size());
69 if (datValue.get_data() == NULL)
73 CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
76 // Clear and free memory
77 memset(datValue.get_data(), 0, datValue.get_size());
78 free(datValue.get_data());
82 template<typename K, typename T>
83 bool Write(const K& key, const T& value, bool fOverwrite=true)
88 assert(("Write called on database in read-only mode", false));
91 CDataStream ssKey(SER_DISK);
94 Dbt datKey(&ssKey[0], ssKey.size());
97 CDataStream ssValue(SER_DISK);
98 ssValue.reserve(10000);
100 Dbt datValue(&ssValue[0], ssValue.size());
103 int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
105 // Clear memory in case it was a private key
106 memset(datKey.get_data(), 0, datKey.get_size());
107 memset(datValue.get_data(), 0, datValue.get_size());
112 bool Erase(const K& key)
117 assert(("Erase called on database in read-only mode", false));
120 CDataStream ssKey(SER_DISK);
123 Dbt datKey(&ssKey[0], ssKey.size());
126 int ret = pdb->del(GetTxn(), &datKey, 0);
129 memset(datKey.get_data(), 0, datKey.get_size());
130 return (ret == 0 || ret == DB_NOTFOUND);
134 bool Exists(const K& key)
140 CDataStream ssKey(SER_DISK);
143 Dbt datKey(&ssKey[0], ssKey.size());
146 int ret = pdb->exists(GetTxn(), &datKey, 0);
149 memset(datKey.get_data(), 0, datKey.get_size());
158 int ret = pdb->cursor(NULL, &pcursor, 0);
164 int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
168 if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
170 datKey.set_data(&ssKey[0]);
171 datKey.set_size(ssKey.size());
174 if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
176 datValue.set_data(&ssValue[0]);
177 datValue.set_size(ssValue.size());
179 datKey.set_flags(DB_DBT_MALLOC);
180 datValue.set_flags(DB_DBT_MALLOC);
181 int ret = pcursor->get(&datKey, &datValue, fFlags);
184 else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
187 // Convert to streams
188 ssKey.SetType(SER_DISK);
190 ssKey.write((char*)datKey.get_data(), datKey.get_size());
191 ssValue.SetType(SER_DISK);
193 ssValue.write((char*)datValue.get_data(), datValue.get_size());
195 // Clear and free memory
196 memset(datKey.get_data(), 0, datKey.get_size());
197 memset(datValue.get_data(), 0, datValue.get_size());
198 free(datKey.get_data());
199 free(datValue.get_data());
217 int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
218 if (!ptxn || ret != 0)
220 vTxn.push_back(ptxn);
230 int ret = vTxn.back()->commit(0);
241 int ret = vTxn.back()->abort();
246 bool ReadVersion(int& nVersion)
249 return Read(string("version"), nVersion);
252 bool WriteVersion(int nVersion)
254 return Write(string("version"), nVersion);
265 class CTxDB : public CDB
268 CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { }
271 void operator=(const CTxDB&);
273 bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
274 bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
275 bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
276 bool EraseTxIndex(const CTransaction& tx);
277 bool ContainsTx(uint256 hash);
278 bool ReadOwnerTxes(uint160 hash160, int nHeight, vector<CTransaction>& vtx);
279 bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
280 bool ReadDiskTx(uint256 hash, CTransaction& tx);
281 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
282 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
283 bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
284 bool EraseBlockIndex(uint256 hash);
285 bool ReadHashBestChain(uint256& hashBestChain);
286 bool WriteHashBestChain(uint256 hashBestChain);
287 bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
288 bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
289 bool LoadBlockIndex();
296 class CAddrDB : public CDB
299 CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
301 CAddrDB(const CAddrDB&);
302 void operator=(const CAddrDB&);
304 bool WriteAddress(const CAddress& addr);
305 bool EraseAddress(const CAddress& addr);
306 bool LoadAddresses();
309 bool LoadAddresses();
320 vector<unsigned char> vchPubKey;
327 CKeyPool(const vector<unsigned char>& vchPubKeyIn)
330 vchPubKey = vchPubKeyIn;
335 if (!(nType & SER_GETHASH))
338 READWRITE(vchPubKey);
345 class CWalletDB : public CDB
348 CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode)
352 CWalletDB(const CWalletDB&);
353 void operator=(const CWalletDB&);
355 bool ReadName(const string& strAddress, string& strName)
358 return Read(make_pair(string("name"), strAddress), strName);
361 bool WriteName(const string& strAddress, const string& strName)
363 CRITICAL_BLOCK(cs_mapAddressBook)
364 mapAddressBook[strAddress] = strName;
366 return Write(make_pair(string("name"), strAddress), strName);
369 bool EraseName(const string& strAddress)
371 // This should only be used for sending addresses, never for receiving addresses,
372 // receiving addresses must always have an address book entry if they're not change return.
373 CRITICAL_BLOCK(cs_mapAddressBook)
374 mapAddressBook.erase(strAddress);
376 return Erase(make_pair(string("name"), strAddress));
379 bool ReadTx(uint256 hash, CWalletTx& wtx)
381 return Read(make_pair(string("tx"), hash), wtx);
384 bool WriteTx(uint256 hash, const CWalletTx& wtx)
387 return Write(make_pair(string("tx"), hash), wtx);
390 bool EraseTx(uint256 hash)
393 return Erase(make_pair(string("tx"), hash));
396 bool ReadKey(const vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
399 return Read(make_pair(string("key"), vchPubKey), vchPrivKey);
402 bool WriteKey(const vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
405 return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false);
408 bool ReadDefaultKey(vector<unsigned char>& vchPubKey)
411 return Read(string("defaultkey"), vchPubKey);
414 bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)
416 vchDefaultKey = vchPubKey;
418 return Write(string("defaultkey"), vchPubKey);
422 bool ReadSetting(const string& strKey, T& value)
424 return Read(make_pair(string("setting"), strKey), value);
428 bool WriteSetting(const string& strKey, const T& value)
431 return Write(make_pair(string("setting"), strKey), value);
434 bool ReadAccount(const string& strAccount, CAccount& account);
435 bool WriteAccount(const string& strAccount, const CAccount& account);
436 bool WriteAccountingEntry(const CAccountingEntry& acentry);
437 int64 GetAccountCreditDebit(const string& strAccount);
438 void ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& acentries);
442 void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
443 void KeepKey(int64 nIndex);
444 static void ReturnKey(int64 nIndex);
445 friend class CReserveKey;
446 friend vector<unsigned char> GetKeyFromKeyPool();
447 friend int64 GetOldestKeyPoolTime();
450 bool LoadWallet(bool& fFirstRunRet);
451 void BackupWallet(const string& strDest);
453 inline bool SetAddressBookName(const string& strAddress, const string& strName)
455 return CWalletDB().WriteName(strAddress, strName);
462 vector<unsigned char> vchPubKey;
475 vector<unsigned char> GetReservedKey()
480 CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
481 vchPubKey = keypool.vchPubKey;
483 assert(!vchPubKey.empty());
490 CWalletDB().KeepKey(nIndex);
498 CWalletDB::ReturnKey(nIndex);