1 // Copyright (c) 2009-2010 Satoshi Nakamoto
\r
2 // Distributed under the MIT/X11 software license, see the accompanying
\r
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
\r
7 class CDiskBlockIndex;
\r
15 extern map<string, string> mapAddressBook;
\r
16 extern CCriticalSection cs_mapAddressBook;
\r
17 extern bool fClient;
\r
20 extern unsigned int nWalletDBUpdated;
\r
24 extern void DBFlush(bool fShutdown);
\r
34 vector<DbTxn*> vTxn;
\r
37 explicit CDB(const char* pszFile, const char* pszMode="r+");
\r
43 void operator=(const CDB&);
\r
46 template<typename K, typename T>
\r
47 bool Read(const K& key, T& value)
\r
53 CDataStream ssKey(SER_DISK);
\r
54 ssKey.reserve(1000);
\r
56 Dbt datKey(&ssKey[0], ssKey.size());
\r
60 datValue.set_flags(DB_DBT_MALLOC);
\r
61 int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
\r
62 memset(datKey.get_data(), 0, datKey.get_size());
\r
63 if (datValue.get_data() == NULL)
\r
66 // Unserialize value
\r
67 CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
\r
70 // Clear and free memory
\r
71 memset(datValue.get_data(), 0, datValue.get_size());
\r
72 free(datValue.get_data());
\r
76 template<typename K, typename T>
\r
77 bool Write(const K& key, const T& value, bool fOverwrite=true)
\r
82 assert(("Write called on database in read-only mode", false));
\r
85 CDataStream ssKey(SER_DISK);
\r
86 ssKey.reserve(1000);
\r
88 Dbt datKey(&ssKey[0], ssKey.size());
\r
91 CDataStream ssValue(SER_DISK);
\r
92 ssValue.reserve(10000);
\r
94 Dbt datValue(&ssValue[0], ssValue.size());
\r
97 int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
\r
99 // Clear memory in case it was a private key
\r
100 memset(datKey.get_data(), 0, datKey.get_size());
\r
101 memset(datValue.get_data(), 0, datValue.get_size());
\r
105 template<typename K>
\r
106 bool Erase(const K& key)
\r
111 assert(("Erase called on database in read-only mode", false));
\r
114 CDataStream ssKey(SER_DISK);
\r
115 ssKey.reserve(1000);
\r
117 Dbt datKey(&ssKey[0], ssKey.size());
\r
120 int ret = pdb->del(GetTxn(), &datKey, 0);
\r
123 memset(datKey.get_data(), 0, datKey.get_size());
\r
124 return (ret == 0 || ret == DB_NOTFOUND);
\r
127 template<typename K>
\r
128 bool Exists(const K& key)
\r
134 CDataStream ssKey(SER_DISK);
\r
135 ssKey.reserve(1000);
\r
137 Dbt datKey(&ssKey[0], ssKey.size());
\r
140 int ret = pdb->exists(GetTxn(), &datKey, 0);
\r
143 memset(datKey.get_data(), 0, datKey.get_size());
\r
151 Dbc* pcursor = NULL;
\r
152 int ret = pdb->cursor(NULL, &pcursor, 0);
\r
158 int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
\r
162 if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
\r
164 datKey.set_data(&ssKey[0]);
\r
165 datKey.set_size(ssKey.size());
\r
168 if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
\r
170 datValue.set_data(&ssValue[0]);
\r
171 datValue.set_size(ssValue.size());
\r
173 datKey.set_flags(DB_DBT_MALLOC);
\r
174 datValue.set_flags(DB_DBT_MALLOC);
\r
175 int ret = pcursor->get(&datKey, &datValue, fFlags);
\r
178 else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
\r
181 // Convert to streams
\r
182 ssKey.SetType(SER_DISK);
\r
184 ssKey.write((char*)datKey.get_data(), datKey.get_size());
\r
185 ssValue.SetType(SER_DISK);
\r
187 ssValue.write((char*)datValue.get_data(), datValue.get_size());
\r
189 // Clear and free memory
\r
190 memset(datKey.get_data(), 0, datKey.get_size());
\r
191 memset(datValue.get_data(), 0, datValue.get_size());
\r
192 free(datKey.get_data());
\r
193 free(datValue.get_data());
\r
200 return vTxn.back();
\r
210 DbTxn* ptxn = NULL;
\r
211 int ret = dbenv.txn_begin(GetTxn(), &ptxn, 0);
\r
212 if (!ptxn || ret != 0)
\r
214 vTxn.push_back(ptxn);
\r
224 int ret = vTxn.back()->commit(0);
\r
235 int ret = vTxn.back()->abort();
\r
240 bool ReadVersion(int& nVersion)
\r
243 return Read(string("version"), nVersion);
\r
246 bool WriteVersion(int nVersion)
\r
248 return Write(string("version"), nVersion);
\r
259 class CTxDB : public CDB
\r
262 CTxDB(const char* pszMode="r+") : CDB(!fClient ? "blkindex.dat" : NULL, pszMode) { }
\r
264 CTxDB(const CTxDB&);
\r
265 void operator=(const CTxDB&);
\r
267 bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
\r
268 bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
\r
269 bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
\r
270 bool EraseTxIndex(const CTransaction& tx);
\r
271 bool ContainsTx(uint256 hash);
\r
272 bool ReadOwnerTxes(uint160 hash160, int nHeight, vector<CTransaction>& vtx);
\r
273 bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
\r
274 bool ReadDiskTx(uint256 hash, CTransaction& tx);
\r
275 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
\r
276 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
\r
277 bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
\r
278 bool EraseBlockIndex(uint256 hash);
\r
279 bool ReadHashBestChain(uint256& hashBestChain);
\r
280 bool WriteHashBestChain(uint256 hashBestChain);
\r
281 bool LoadBlockIndex();
\r
288 class CAddrDB : public CDB
\r
291 CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
\r
293 CAddrDB(const CAddrDB&);
\r
294 void operator=(const CAddrDB&);
\r
296 bool WriteAddress(const CAddress& addr);
\r
297 bool LoadAddresses();
\r
300 bool LoadAddresses();
\r
307 class CWalletDB : public CDB
\r
310 CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode) { }
\r
312 CWalletDB(const CWalletDB&);
\r
313 void operator=(const CWalletDB&);
\r
315 bool ReadName(const string& strAddress, string& strName)
\r
318 return Read(make_pair(string("name"), strAddress), strName);
\r
321 bool WriteName(const string& strAddress, const string& strName)
\r
323 CRITICAL_BLOCK(cs_mapAddressBook)
\r
324 mapAddressBook[strAddress] = strName;
\r
325 nWalletDBUpdated++;
\r
326 return Write(make_pair(string("name"), strAddress), strName);
\r
329 bool EraseName(const string& strAddress)
\r
331 CRITICAL_BLOCK(cs_mapAddressBook)
\r
332 mapAddressBook.erase(strAddress);
\r
333 nWalletDBUpdated++;
\r
334 return Erase(make_pair(string("name"), strAddress));
\r
337 bool ReadTx(uint256 hash, CWalletTx& wtx)
\r
339 return Read(make_pair(string("tx"), hash), wtx);
\r
342 bool WriteTx(uint256 hash, const CWalletTx& wtx)
\r
344 nWalletDBUpdated++;
\r
345 return Write(make_pair(string("tx"), hash), wtx);
\r
348 bool EraseTx(uint256 hash)
\r
350 nWalletDBUpdated++;
\r
351 return Erase(make_pair(string("tx"), hash));
\r
354 bool ReadKey(const vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
\r
356 vchPrivKey.clear();
\r
357 return Read(make_pair(string("key"), vchPubKey), vchPrivKey);
\r
360 bool WriteKey(const vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
\r
362 nWalletDBUpdated++;
\r
363 return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false);
\r
366 bool ReadDefaultKey(vector<unsigned char>& vchPubKey)
\r
369 return Read(string("defaultkey"), vchPubKey);
\r
372 bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)
\r
374 nWalletDBUpdated++;
\r
375 return Write(string("defaultkey"), vchPubKey);
\r
378 template<typename T>
\r
379 bool ReadSetting(const string& strKey, T& value)
\r
381 return Read(make_pair(string("setting"), strKey), value);
\r
384 template<typename T>
\r
385 bool WriteSetting(const string& strKey, const T& value)
\r
387 nWalletDBUpdated++;
\r
388 return Write(make_pair(string("setting"), strKey), value);
\r
391 bool LoadWallet(vector<unsigned char>& vchDefaultKeyRet);
\r
394 bool LoadWallet(bool& fFirstRunRet);
\r
396 inline bool SetAddressBookName(const string& strAddress, const string& strName)
\r
398 return CWalletDB().WriteName(strAddress, strName);
\r