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