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;
18 extern map<string, string> mapAddressBook;
19 extern CCriticalSection cs_mapAddressBook;
20 extern vector<unsigned char> vchDefaultKey;
22 extern int nBestHeight;
25 extern unsigned int nWalletDBUpdated;
29 extern void DBFlush(bool fShutdown);
30 extern vector<unsigned char> GetKeyFromKeyPool();
31 extern int64 GetOldestKeyPoolTime();
44 explicit CDB(const char* pszFile, const char* pszMode="r+");
50 void operator=(const CDB&);
53 template<typename K, typename T>
54 bool Read(const K& key, T& value)
60 CDataStream ssKey(SER_DISK);
63 Dbt datKey(&ssKey[0], ssKey.size());
67 datValue.set_flags(DB_DBT_MALLOC);
68 int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
69 memset(datKey.get_data(), 0, datKey.get_size());
70 if (datValue.get_data() == NULL)
74 CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
77 // Clear and free memory
78 memset(datValue.get_data(), 0, datValue.get_size());
79 free(datValue.get_data());
83 template<typename K, typename T>
84 bool Write(const K& key, const T& value, bool fOverwrite=true)
89 assert(("Write called on database in read-only mode", false));
92 CDataStream ssKey(SER_DISK);
95 Dbt datKey(&ssKey[0], ssKey.size());
98 CDataStream ssValue(SER_DISK);
99 ssValue.reserve(10000);
101 Dbt datValue(&ssValue[0], ssValue.size());
104 int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
106 // Clear memory in case it was a private key
107 memset(datKey.get_data(), 0, datKey.get_size());
108 memset(datValue.get_data(), 0, datValue.get_size());
113 bool Erase(const K& key)
118 assert(("Erase called on database in read-only mode", false));
121 CDataStream ssKey(SER_DISK);
124 Dbt datKey(&ssKey[0], ssKey.size());
127 int ret = pdb->del(GetTxn(), &datKey, 0);
130 memset(datKey.get_data(), 0, datKey.get_size());
131 return (ret == 0 || ret == DB_NOTFOUND);
135 bool Exists(const K& key)
141 CDataStream ssKey(SER_DISK);
144 Dbt datKey(&ssKey[0], ssKey.size());
147 int ret = pdb->exists(GetTxn(), &datKey, 0);
150 memset(datKey.get_data(), 0, datKey.get_size());
159 int ret = pdb->cursor(NULL, &pcursor, 0);
165 int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
169 if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
171 datKey.set_data(&ssKey[0]);
172 datKey.set_size(ssKey.size());
175 if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
177 datValue.set_data(&ssValue[0]);
178 datValue.set_size(ssValue.size());
180 datKey.set_flags(DB_DBT_MALLOC);
181 datValue.set_flags(DB_DBT_MALLOC);
182 int ret = pcursor->get(&datKey, &datValue, fFlags);
185 else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
188 // Convert to streams
189 ssKey.SetType(SER_DISK);
191 ssKey.write((char*)datKey.get_data(), datKey.get_size());
192 ssValue.SetType(SER_DISK);
194 ssValue.write((char*)datValue.get_data(), datValue.get_size());
196 // Clear and free memory
197 memset(datKey.get_data(), 0, datKey.get_size());
198 memset(datValue.get_data(), 0, datValue.get_size());
199 free(datKey.get_data());
200 free(datValue.get_data());
218 int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
219 if (!ptxn || ret != 0)
221 vTxn.push_back(ptxn);
231 int ret = vTxn.back()->commit(0);
242 int ret = vTxn.back()->abort();
247 bool ReadVersion(int& nVersion)
250 return Read(string("version"), nVersion);
253 bool WriteVersion(int nVersion)
255 return Write(string("version"), nVersion);
266 class CTxDB : public CDB
269 CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { }
272 void operator=(const CTxDB&);
274 bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
275 bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
276 bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
277 bool EraseTxIndex(const CTransaction& tx);
278 bool ContainsTx(uint256 hash);
279 bool ReadOwnerTxes(uint160 hash160, int nHeight, vector<CTransaction>& vtx);
280 bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
281 bool ReadDiskTx(uint256 hash, CTransaction& tx);
282 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
283 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
284 bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
285 bool EraseBlockIndex(uint256 hash);
286 bool ReadHashBestChain(uint256& hashBestChain);
287 bool WriteHashBestChain(uint256 hashBestChain);
288 bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
289 bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
290 bool LoadBlockIndex();
297 class CAddrDB : public CDB
300 CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
302 CAddrDB(const CAddrDB&);
303 void operator=(const CAddrDB&);
305 bool WriteAddress(const CAddress& addr);
306 bool EraseAddress(const CAddress& addr);
307 bool LoadAddresses();
310 bool LoadAddresses();
321 vector<unsigned char> vchPubKey;
328 CKeyPool(const vector<unsigned char>& vchPubKeyIn)
331 vchPubKey = vchPubKeyIn;
336 if (!(nType & SER_GETHASH))
339 READWRITE(vchPubKey);
346 class CWalletDB : public CDB
349 CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode)
353 CWalletDB(const CWalletDB&);
354 void operator=(const CWalletDB&);
356 bool ReadName(const string& strAddress, string& strName)
359 return Read(make_pair(string("name"), strAddress), strName);
362 bool WriteName(const string& strAddress, const string& strName)
364 CRITICAL_BLOCK(cs_mapAddressBook)
365 mapAddressBook[strAddress] = strName;
367 return Write(make_pair(string("name"), strAddress), strName);
370 bool EraseName(const string& strAddress)
372 // This should only be used for sending addresses, never for receiving addresses,
373 // receiving addresses must always have an address book entry if they're not change return.
374 CRITICAL_BLOCK(cs_mapAddressBook)
375 mapAddressBook.erase(strAddress);
377 return Erase(make_pair(string("name"), strAddress));
380 bool ReadTx(uint256 hash, CWalletTx& wtx)
382 return Read(make_pair(string("tx"), hash), wtx);
385 bool WriteTx(uint256 hash, const CWalletTx& wtx)
388 return Write(make_pair(string("tx"), hash), wtx);
391 bool EraseTx(uint256 hash)
394 return Erase(make_pair(string("tx"), hash));
397 bool ReadKey(const vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
400 return Read(make_pair(string("key"), vchPubKey), vchPrivKey);
403 bool WriteKey(const vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
406 return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false);
409 bool WriteBestBlock(const CBlockLocator& locator)
412 return Write(string("bestblock"), locator);
415 bool ReadBestBlock(CBlockLocator& locator)
417 return Read(string("bestblock"), locator);
420 bool ReadDefaultKey(vector<unsigned char>& vchPubKey)
423 return Read(string("defaultkey"), vchPubKey);
426 bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)
428 vchDefaultKey = vchPubKey;
430 return Write(string("defaultkey"), vchPubKey);
434 bool ReadSetting(const string& strKey, T& value)
436 return Read(make_pair(string("setting"), strKey), value);
440 bool WriteSetting(const string& strKey, const T& value)
443 return Write(make_pair(string("setting"), strKey), value);
446 bool ReadAccount(const string& strAccount, CAccount& account);
447 bool WriteAccount(const string& strAccount, const CAccount& account);
448 bool WriteAccountingEntry(const CAccountingEntry& acentry);
449 int64 GetAccountCreditDebit(const string& strAccount);
450 void ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& acentries);
454 void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
455 void KeepKey(int64 nIndex);
456 static void ReturnKey(int64 nIndex);
457 friend class CReserveKey;
458 friend vector<unsigned char> GetKeyFromKeyPool();
459 friend int64 GetOldestKeyPoolTime();
462 bool LoadWallet(bool& fFirstRunRet);
463 void BackupWallet(const string& strDest);
465 inline bool SetAddressBookName(const string& strAddress, const string& strName)
467 return CWalletDB().WriteName(strAddress, strName);
474 vector<unsigned char> vchPubKey;
487 vector<unsigned char> GetReservedKey()
492 CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
493 vchPubKey = keypool.vchPubKey;
495 assert(!vchPubKey.empty());
502 CWalletDB().KeepKey(nIndex);
510 CWalletDB::ReturnKey(nIndex);