Remove headers.h
[novacoin.git] / src / db.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
5 #ifndef BITCOIN_DB_H
6 #define BITCOIN_DB_H
7
8 #include "key.h"
9 #include "main.h"
10 #include "wallet.h"
11
12 #include <map>
13 #include <string>
14 #include <vector>
15
16 #include <db_cxx.h>
17
18 class CAccount;
19 class CAccountingEntry;
20 class CAddress;
21 class CAddrMan;
22 class CBlockLocator;
23 class CDiskBlockIndex;
24 class CDiskTxPos;
25 class CMasterKey;
26 class COutPoint;
27 class CTxIndex;
28 class CWallet;
29 class CWalletTx;
30
31 extern unsigned int nWalletDBUpdated;
32 extern DbEnv dbenv;
33
34 extern void DBFlush(bool fShutdown);
35 void ThreadFlushWalletDB(void* parg);
36 bool BackupWallet(const CWallet& wallet, const std::string& strDest);
37
38
39 /** RAII class that provides access to a Berkeley database */
40 class CDB
41 {
42 protected:
43     Db* pdb;
44     std::string strFile;
45     std::vector<DbTxn*> vTxn;
46     bool fReadOnly;
47
48     explicit CDB(const char* pszFile, const char* pszMode="r+");
49     ~CDB() { Close(); }
50 public:
51     void Close();
52 private:
53     CDB(const CDB&);
54     void operator=(const CDB&);
55
56 protected:
57     template<typename K, typename T>
58     bool Read(const K& key, T& value)
59     {
60         if (!pdb)
61             return false;
62
63         // Key
64         CDataStream ssKey(SER_DISK);
65         ssKey.reserve(1000);
66         ssKey << key;
67         Dbt datKey(&ssKey[0], ssKey.size());
68
69         // Read
70         Dbt datValue;
71         datValue.set_flags(DB_DBT_MALLOC);
72         int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
73         memset(datKey.get_data(), 0, datKey.get_size());
74         if (datValue.get_data() == NULL)
75             return false;
76
77         // Unserialize value
78         CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
79         ssValue >> value;
80
81         // Clear and free memory
82         memset(datValue.get_data(), 0, datValue.get_size());
83         free(datValue.get_data());
84         return (ret == 0);
85     }
86
87     template<typename K, typename T>
88     bool Write(const K& key, const T& value, bool fOverwrite=true)
89     {
90         if (!pdb)
91             return false;
92         if (fReadOnly)
93             assert(!"Write called on database in read-only mode");
94
95         // Key
96         CDataStream ssKey(SER_DISK);
97         ssKey.reserve(1000);
98         ssKey << key;
99         Dbt datKey(&ssKey[0], ssKey.size());
100
101         // Value
102         CDataStream ssValue(SER_DISK);
103         ssValue.reserve(10000);
104         ssValue << value;
105         Dbt datValue(&ssValue[0], ssValue.size());
106
107         // Write
108         int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
109
110         // Clear memory in case it was a private key
111         memset(datKey.get_data(), 0, datKey.get_size());
112         memset(datValue.get_data(), 0, datValue.get_size());
113         return (ret == 0);
114     }
115
116     template<typename K>
117     bool Erase(const K& key)
118     {
119         if (!pdb)
120             return false;
121         if (fReadOnly)
122             assert(!"Erase called on database in read-only mode");
123
124         // Key
125         CDataStream ssKey(SER_DISK);
126         ssKey.reserve(1000);
127         ssKey << key;
128         Dbt datKey(&ssKey[0], ssKey.size());
129
130         // Erase
131         int ret = pdb->del(GetTxn(), &datKey, 0);
132
133         // Clear memory
134         memset(datKey.get_data(), 0, datKey.get_size());
135         return (ret == 0 || ret == DB_NOTFOUND);
136     }
137
138     template<typename K>
139     bool Exists(const K& key)
140     {
141         if (!pdb)
142             return false;
143
144         // Key
145         CDataStream ssKey(SER_DISK);
146         ssKey.reserve(1000);
147         ssKey << key;
148         Dbt datKey(&ssKey[0], ssKey.size());
149
150         // Exists
151         int ret = pdb->exists(GetTxn(), &datKey, 0);
152
153         // Clear memory
154         memset(datKey.get_data(), 0, datKey.get_size());
155         return (ret == 0);
156     }
157
158     Dbc* GetCursor()
159     {
160         if (!pdb)
161             return NULL;
162         Dbc* pcursor = NULL;
163         int ret = pdb->cursor(NULL, &pcursor, 0);
164         if (ret != 0)
165             return NULL;
166         return pcursor;
167     }
168
169     int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
170     {
171         // Read at cursor
172         Dbt datKey;
173         if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
174         {
175             datKey.set_data(&ssKey[0]);
176             datKey.set_size(ssKey.size());
177         }
178         Dbt datValue;
179         if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
180         {
181             datValue.set_data(&ssValue[0]);
182             datValue.set_size(ssValue.size());
183         }
184         datKey.set_flags(DB_DBT_MALLOC);
185         datValue.set_flags(DB_DBT_MALLOC);
186         int ret = pcursor->get(&datKey, &datValue, fFlags);
187         if (ret != 0)
188             return ret;
189         else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
190             return 99999;
191
192         // Convert to streams
193         ssKey.SetType(SER_DISK);
194         ssKey.clear();
195         ssKey.write((char*)datKey.get_data(), datKey.get_size());
196         ssValue.SetType(SER_DISK);
197         ssValue.clear();
198         ssValue.write((char*)datValue.get_data(), datValue.get_size());
199
200         // Clear and free memory
201         memset(datKey.get_data(), 0, datKey.get_size());
202         memset(datValue.get_data(), 0, datValue.get_size());
203         free(datKey.get_data());
204         free(datValue.get_data());
205         return 0;
206     }
207
208     DbTxn* GetTxn()
209     {
210         if (!vTxn.empty())
211             return vTxn.back();
212         else
213             return NULL;
214     }
215
216 public:
217     bool TxnBegin()
218     {
219         if (!pdb)
220             return false;
221         DbTxn* ptxn = NULL;
222         int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
223         if (!ptxn || ret != 0)
224             return false;
225         vTxn.push_back(ptxn);
226         return true;
227     }
228
229     bool TxnCommit()
230     {
231         if (!pdb)
232             return false;
233         if (vTxn.empty())
234             return false;
235         int ret = vTxn.back()->commit(0);
236         vTxn.pop_back();
237         return (ret == 0);
238     }
239
240     bool TxnAbort()
241     {
242         if (!pdb)
243             return false;
244         if (vTxn.empty())
245             return false;
246         int ret = vTxn.back()->abort();
247         vTxn.pop_back();
248         return (ret == 0);
249     }
250
251     bool ReadVersion(int& nVersion)
252     {
253         nVersion = 0;
254         return Read(std::string("version"), nVersion);
255     }
256
257     bool WriteVersion(int nVersion)
258     {
259         return Write(std::string("version"), nVersion);
260     }
261
262     bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
263 };
264
265
266
267
268
269
270
271 /** Access to the transaction database (blkindex.dat) */
272 class CTxDB : public CDB
273 {
274 public:
275     CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { }
276 private:
277     CTxDB(const CTxDB&);
278     void operator=(const CTxDB&);
279 public:
280     bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
281     bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
282     bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
283     bool EraseTxIndex(const CTransaction& tx);
284     bool ContainsTx(uint256 hash);
285     bool ReadOwnerTxes(uint160 hash160, int nHeight, std::vector<CTransaction>& vtx);
286     bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
287     bool ReadDiskTx(uint256 hash, CTransaction& tx);
288     bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
289     bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
290     bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
291     bool EraseBlockIndex(uint256 hash);
292     bool ReadHashBestChain(uint256& hashBestChain);
293     bool WriteHashBestChain(uint256 hashBestChain);
294     bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
295     bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
296     bool LoadBlockIndex();
297 };
298
299
300
301
302 /** Access to the (IP) address database (addr.dat) */
303 class CAddrDB : public CDB
304 {
305 public:
306     CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
307 private:
308     CAddrDB(const CAddrDB&);
309     void operator=(const CAddrDB&);
310 public:
311     bool WriteAddrman(const CAddrMan& addr);
312     bool LoadAddresses();
313 };
314
315 bool LoadAddresses();
316
317
318
319 /** Error statuses for the wallet database */
320 enum DBErrors
321 {
322     DB_LOAD_OK,
323     DB_CORRUPT,
324     DB_TOO_NEW,
325     DB_LOAD_FAIL,
326     DB_NEED_REWRITE
327 };
328
329 /** Access to the wallet database (wallet.dat) */
330 class CWalletDB : public CDB
331 {
332 public:
333     CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode)
334     {
335     }
336 private:
337     CWalletDB(const CWalletDB&);
338     void operator=(const CWalletDB&);
339 public:
340     bool ReadName(const std::string& strAddress, std::string& strName)
341     {
342         strName = "";
343         return Read(std::make_pair(std::string("name"), strAddress), strName);
344     }
345
346     bool WriteName(const std::string& strAddress, const std::string& strName);
347
348     bool EraseName(const std::string& strAddress);
349
350     bool ReadTx(uint256 hash, CWalletTx& wtx)
351     {
352         return Read(std::make_pair(std::string("tx"), hash), wtx);
353     }
354
355     bool WriteTx(uint256 hash, const CWalletTx& wtx)
356     {
357         nWalletDBUpdated++;
358         return Write(std::make_pair(std::string("tx"), hash), wtx);
359     }
360
361     bool EraseTx(uint256 hash)
362     {
363         nWalletDBUpdated++;
364         return Erase(std::make_pair(std::string("tx"), hash));
365     }
366
367     bool ReadKey(const std::vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
368     {
369         vchPrivKey.clear();
370         return Read(std::make_pair(std::string("key"), vchPubKey), vchPrivKey);
371     }
372
373     bool WriteKey(const std::vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
374     {
375         nWalletDBUpdated++;
376         return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
377     }
378
379     bool WriteCryptedKey(const std::vector<unsigned char>& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, bool fEraseUnencryptedKey = true)
380     {
381         nWalletDBUpdated++;
382         if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
383             return false;
384         if (fEraseUnencryptedKey)
385         {
386             Erase(std::make_pair(std::string("key"), vchPubKey));
387             Erase(std::make_pair(std::string("wkey"), vchPubKey));
388         }
389         return true;
390     }
391
392     bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
393     {
394         nWalletDBUpdated++;
395         return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
396     }
397
398     // Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013
399     bool ReadCScript(const uint160 &hash, CScript& redeemScript)
400     {
401         redeemScript.clear();
402         return Read(std::make_pair(std::string("cscript"), hash), redeemScript);
403     }
404
405     bool WriteCScript(const uint160& hash, const CScript& redeemScript)
406     {
407         nWalletDBUpdated++;
408         return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false);
409     }
410
411     bool WriteBestBlock(const CBlockLocator& locator)
412     {
413         nWalletDBUpdated++;
414         return Write(std::string("bestblock"), locator);
415     }
416
417     bool ReadBestBlock(CBlockLocator& locator)
418     {
419         return Read(std::string("bestblock"), locator);
420     }
421
422     bool ReadDefaultKey(std::vector<unsigned char>& vchPubKey)
423     {
424         vchPubKey.clear();
425         return Read(std::string("defaultkey"), vchPubKey);
426     }
427
428     bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
429     {
430         nWalletDBUpdated++;
431         return Write(std::string("defaultkey"), vchPubKey);
432     }
433
434     bool ReadPool(int64 nPool, CKeyPool& keypool)
435     {
436         return Read(std::make_pair(std::string("pool"), nPool), keypool);
437     }
438
439     bool WritePool(int64 nPool, const CKeyPool& keypool)
440     {
441         nWalletDBUpdated++;
442         return Write(std::make_pair(std::string("pool"), nPool), keypool);
443     }
444
445     bool ErasePool(int64 nPool)
446     {
447         nWalletDBUpdated++;
448         return Erase(std::make_pair(std::string("pool"), nPool));
449     }
450
451     // Settings are no longer stored in wallet.dat; these are
452     // used only for backwards compatibility:
453     template<typename T>
454     bool ReadSetting(const std::string& strKey, T& value)
455     {
456         return Read(std::make_pair(std::string("setting"), strKey), value);
457     }
458     template<typename T>
459     bool WriteSetting(const std::string& strKey, const T& value)
460     {
461         nWalletDBUpdated++;
462         return Write(std::make_pair(std::string("setting"), strKey), value);
463     }
464     bool EraseSetting(const std::string& strKey)
465     {
466         nWalletDBUpdated++;
467         return Erase(std::make_pair(std::string("setting"), strKey));
468     }
469
470     bool WriteMinVersion(int nVersion)
471     {
472         return Write(std::string("minversion"), nVersion);
473     }
474
475     bool ReadAccount(const std::string& strAccount, CAccount& account);
476     bool WriteAccount(const std::string& strAccount, const CAccount& account);
477     bool WriteAccountingEntry(const CAccountingEntry& acentry);
478     int64 GetAccountCreditDebit(const std::string& strAccount);
479     void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
480
481     int LoadWallet(CWallet* pwallet);
482 };
483
484 #endif