You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

db.h 13KB

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