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