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