Projects : bitcoin : bitcoin_tx_fee_cleanup

bitcoin/src/db.h

Dir - Raw

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
16class CTxIndex;
17class CDiskBlockIndex;
18class CDiskTxPos;
19class COutPoint;
20class CAddress;
21class CWalletTx;
22class CWallet;
23class CAccount;
24class CAccountingEntry;
25class CBlockLocator;
26
27
28extern unsigned int nWalletDBUpdated;
29extern DbEnv dbenv;
30
31extern void DBFlush(bool fShutdown);
32void ThreadFlushWalletDB(void* parg);
33bool BackupWallet(const CWallet& wallet, const std::string& strDest);
34
35
36
37class CDB
38{
39protected:
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(); }
47public:
48 void Close();
49private:
50 CDB(const CDB&);
51 void operator=(const CDB&);
52
53protected:
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
213public:
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
269class CTxDB : public CDB
270{
271public:
272 CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { }
273private:
274 CTxDB(const CTxDB&);
275 void operator=(const CTxDB&);
276public:
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
300class CAddrDB : public CDB
301{
302public:
303 CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
304private:
305 CAddrDB(const CAddrDB&);
306 void operator=(const CAddrDB&);
307public:
308 bool WriteAddress(const CAddress& addr);
309 bool EraseAddress(const CAddress& addr);
310 bool LoadAddresses();
311};
312
313bool LoadAddresses();
314
315
316
317class CKeyPool
318{
319public:
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
346enum DBErrors
347{
348 DB_LOAD_OK,
349 DB_CORRUPT,
350 DB_TOO_NEW,
351 DB_LOAD_FAIL,
352 DB_NEED_REWRITE
353};
354
355class CWalletDB : public CDB
356{
357public:
358 CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode)
359 {
360 }
361private:
362 CWalletDB(const CWalletDB&);
363 void operator=(const CWalletDB&);
364public:
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 WriteBestBlock(const CBlockLocator& locator)
424 {
425 nWalletDBUpdated++;
426 return Write(std::string("bestblock"), locator);
427 }
428
429 bool ReadBestBlock(CBlockLocator& locator)
430 {
431 return Read(std::string("bestblock"), locator);
432 }
433
434 bool ReadDefaultKey(std::vector<unsigned char>& vchPubKey)
435 {
436 vchPubKey.clear();
437 return Read(std::string("defaultkey"), vchPubKey);
438 }
439
440 bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
441 {
442 nWalletDBUpdated++;
443 return Write(std::string("defaultkey"), vchPubKey);
444 }
445
446 bool ReadPool(int64 nPool, CKeyPool& keypool)
447 {
448 return Read(std::make_pair(std::string("pool"), nPool), keypool);
449 }
450
451 bool WritePool(int64 nPool, const CKeyPool& keypool)
452 {
453 nWalletDBUpdated++;
454 return Write(std::make_pair(std::string("pool"), nPool), keypool);
455 }
456
457 bool ErasePool(int64 nPool)
458 {
459 nWalletDBUpdated++;
460 return Erase(std::make_pair(std::string("pool"), nPool));
461 }
462
463 template<typename T>
464 bool ReadSetting(const std::string& strKey, T& value)
465 {
466 return Read(std::make_pair(std::string("setting"), strKey), value);
467 }
468
469 template<typename T>
470 bool WriteSetting(const std::string& strKey, const T& value)
471 {
472 nWalletDBUpdated++;
473 return Write(std::make_pair(std::string("setting"), strKey), value);
474 }
475
476 bool ReadAccount(const std::string& strAccount, CAccount& account);
477 bool WriteAccount(const std::string& strAccount, const CAccount& account);
478 bool WriteAccountingEntry(const CAccountingEntry& acentry);
479 int64 GetAccountCreditDebit(const std::string& strAccount);
480 void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
481
482 int LoadWallet(CWallet* pwallet);
483};
484
485#endif