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 extern map<string, string> mapAddressBook;
16 extern CCriticalSection cs_mapAddressBook;
17 extern vector<unsigned char> vchDefaultKey;
19 extern int nBestHeight;
22 extern unsigned int nWalletDBUpdated;
26 extern void DBFlush(bool fShutdown);
39 explicit CDB(const char* pszFile, const char* pszMode="r+");
45 void operator=(const CDB&);
48 template<typename K, typename T>
49 bool Read(const K& key, T& value)
55 CDataStream ssKey(SER_DISK);
58 Dbt datKey(&ssKey[0], ssKey.size());
62 datValue.set_flags(DB_DBT_MALLOC);
63 int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
64 memset(datKey.get_data(), 0, datKey.get_size());
65 if (datValue.get_data() == NULL)
69 CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
72 // Clear and free memory
73 memset(datValue.get_data(), 0, datValue.get_size());
74 free(datValue.get_data());
78 template<typename K, typename T>
79 bool Write(const K& key, const T& value, bool fOverwrite=true)
84 assert(("Write called on database in read-only mode", false));
87 CDataStream ssKey(SER_DISK);
90 Dbt datKey(&ssKey[0], ssKey.size());
93 CDataStream ssValue(SER_DISK);
94 ssValue.reserve(10000);
96 Dbt datValue(&ssValue[0], ssValue.size());
99 int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
101 // Clear memory in case it was a private key
102 memset(datKey.get_data(), 0, datKey.get_size());
103 memset(datValue.get_data(), 0, datValue.get_size());
108 bool Erase(const K& key)
113 assert(("Erase called on database in read-only mode", false));
116 CDataStream ssKey(SER_DISK);
119 Dbt datKey(&ssKey[0], ssKey.size());
122 int ret = pdb->del(GetTxn(), &datKey, 0);
125 memset(datKey.get_data(), 0, datKey.get_size());
126 return (ret == 0 || ret == DB_NOTFOUND);
130 bool Exists(const K& key)
136 CDataStream ssKey(SER_DISK);
139 Dbt datKey(&ssKey[0], ssKey.size());
142 int ret = pdb->exists(GetTxn(), &datKey, 0);
145 memset(datKey.get_data(), 0, datKey.get_size());
154 int ret = pdb->cursor(NULL, &pcursor, 0);
160 int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
164 if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
166 datKey.set_data(&ssKey[0]);
167 datKey.set_size(ssKey.size());
170 if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
172 datValue.set_data(&ssValue[0]);
173 datValue.set_size(ssValue.size());
175 datKey.set_flags(DB_DBT_MALLOC);
176 datValue.set_flags(DB_DBT_MALLOC);
177 int ret = pcursor->get(&datKey, &datValue, fFlags);
180 else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
183 // Convert to streams
184 ssKey.SetType(SER_DISK);
186 ssKey.write((char*)datKey.get_data(), datKey.get_size());
187 ssValue.SetType(SER_DISK);
189 ssValue.write((char*)datValue.get_data(), datValue.get_size());
191 // Clear and free memory
192 memset(datKey.get_data(), 0, datKey.get_size());
193 memset(datValue.get_data(), 0, datValue.get_size());
194 free(datKey.get_data());
195 free(datValue.get_data());
213 int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
214 if (!ptxn || ret != 0)
216 vTxn.push_back(ptxn);
226 int ret = vTxn.back()->commit(0);
237 int ret = vTxn.back()->abort();
242 bool ReadVersion(int& nVersion)
245 return Read(string("version"), nVersion);
248 bool WriteVersion(int nVersion)
250 return Write(string("version"), nVersion);
261 class CTxDB : public CDB
264 CTxDB(const char* pszMode="r+") : CDB(!fClient ? "blkindex.dat" : NULL, pszMode) { }
267 void operator=(const CTxDB&);
269 bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
270 bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
271 bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
272 bool EraseTxIndex(const CTransaction& tx);
273 bool ContainsTx(uint256 hash);
274 bool ReadOwnerTxes(uint160 hash160, int nHeight, vector<CTransaction>& vtx);
275 bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
276 bool ReadDiskTx(uint256 hash, CTransaction& tx);
277 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
278 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
279 bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
280 bool EraseBlockIndex(uint256 hash);
281 bool ReadHashBestChain(uint256& hashBestChain);
282 bool WriteHashBestChain(uint256 hashBestChain);
283 bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
284 bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
285 bool LoadBlockIndex();
292 class CAddrDB : public CDB
295 CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
297 CAddrDB(const CAddrDB&);
298 void operator=(const CAddrDB&);
300 bool WriteAddress(const CAddress& addr);
301 bool LoadAddresses();
304 bool LoadAddresses();
315 vector<unsigned char> vchPubKey;
322 CKeyPool(const vector<unsigned char>& vchPubKeyIn)
325 vchPubKey = vchPubKeyIn;
330 if (!(nType & SER_GETHASH))
333 READWRITE(vchPubKey);
340 class CWalletDB : public CDB
343 CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode) { }
345 CWalletDB(const CWalletDB&);
346 void operator=(const CWalletDB&);
348 bool ReadName(const string& strAddress, string& strName)
351 return Read(make_pair(string("name"), strAddress), strName);
354 bool WriteName(const string& strAddress, const string& strName)
356 CRITICAL_BLOCK(cs_mapAddressBook)
357 mapAddressBook[strAddress] = strName;
359 return Write(make_pair(string("name"), strAddress), strName);
362 bool EraseName(const string& strAddress)
364 // This should only be used for sending addresses, never for receiving addresses,
365 // receiving addresses must always have an address book entry if they're not change return.
366 CRITICAL_BLOCK(cs_mapAddressBook)
367 mapAddressBook.erase(strAddress);
369 return Erase(make_pair(string("name"), strAddress));
372 bool ReadTx(uint256 hash, CWalletTx& wtx)
374 return Read(make_pair(string("tx"), hash), wtx);
377 bool WriteTx(uint256 hash, const CWalletTx& wtx)
380 return Write(make_pair(string("tx"), hash), wtx);
383 bool EraseTx(uint256 hash)
386 return Erase(make_pair(string("tx"), hash));
389 bool ReadKey(const vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
392 return Read(make_pair(string("key"), vchPubKey), vchPrivKey);
395 bool WriteKey(const vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
398 return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false);
401 bool ReadDefaultKey(vector<unsigned char>& vchPubKey)
404 return Read(string("defaultkey"), vchPubKey);
407 bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)
409 vchDefaultKey = vchPubKey;
411 return Write(string("defaultkey"), vchPubKey);
415 bool ReadSetting(const string& strKey, T& value)
417 return Read(make_pair(string("setting"), strKey), value);
421 bool WriteSetting(const string& strKey, const T& value)
424 return Write(make_pair(string("setting"), strKey), value);
429 void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
430 void KeepKey(int64 nIndex);
431 static void ReturnKey(int64 nIndex);
432 friend class CReserveKey;
434 vector<unsigned char> GetKeyFromKeyPool();
437 bool LoadWallet(bool& fFirstRunRet);
438 void BackupWallet(const string& strDest);
440 inline bool SetAddressBookName(const string& strAddress, const string& strName)
442 return CWalletDB().WriteName(strAddress, strName);
449 vector<unsigned char> vchPubKey;
462 vector<unsigned char> GetReservedKey()
467 CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
468 vchPubKey = keypool.vchPubKey;
470 assert(!vchPubKey.empty());
477 CWalletDB().KeepKey(nIndex);
485 CWalletDB::ReturnKey(nIndex);