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.
15 class CAccountingEntry
;
17 extern map
<string
, string
> mapAddressBook
;
18 extern CCriticalSection cs_mapAddressBook
;
19 extern vector
<unsigned char> vchDefaultKey
;
21 extern int nBestHeight
;
24 extern unsigned int nWalletDBUpdated
;
28 extern void DBFlush(bool fShutdown
);
29 extern vector
<unsigned char> GetKeyFromKeyPool();
30 extern int64
GetOldestKeyPoolTime();
43 explicit CDB(const char* pszFile
, const char* pszMode
="r+");
49 void operator=(const CDB
&);
52 template<typename K
, typename T
>
53 bool Read(const K
& key
, T
& value
)
59 CDataStream
ssKey(SER_DISK
);
62 Dbt
datKey(&ssKey
[0], ssKey
.size());
66 datValue
.set_flags(DB_DBT_MALLOC
);
67 int ret
= pdb
->get(GetTxn(), &datKey
, &datValue
, 0);
68 memset(datKey
.get_data(), 0, datKey
.get_size());
69 if (datValue
.get_data() == NULL
)
73 CDataStream
ssValue((char*)datValue
.get_data(), (char*)datValue
.get_data() + datValue
.get_size(), SER_DISK
);
76 // Clear and free memory
77 memset(datValue
.get_data(), 0, datValue
.get_size());
78 free(datValue
.get_data());
82 template<typename K
, typename T
>
83 bool Write(const K
& key
, const T
& value
, bool fOverwrite
=true)
88 assert(("Write called on database in read-only mode", false));
91 CDataStream
ssKey(SER_DISK
);
94 Dbt
datKey(&ssKey
[0], ssKey
.size());
97 CDataStream
ssValue(SER_DISK
);
98 ssValue
.reserve(10000);
100 Dbt
datValue(&ssValue
[0], ssValue
.size());
103 int ret
= pdb
->put(GetTxn(), &datKey
, &datValue
, (fOverwrite
? 0 : DB_NOOVERWRITE
));
105 // Clear memory in case it was a private key
106 memset(datKey
.get_data(), 0, datKey
.get_size());
107 memset(datValue
.get_data(), 0, datValue
.get_size());
112 bool Erase(const K
& key
)
117 assert(("Erase called on database in read-only mode", false));
120 CDataStream
ssKey(SER_DISK
);
123 Dbt
datKey(&ssKey
[0], ssKey
.size());
126 int ret
= pdb
->del(GetTxn(), &datKey
, 0);
129 memset(datKey
.get_data(), 0, datKey
.get_size());
130 return (ret
== 0 || ret
== DB_NOTFOUND
);
134 bool Exists(const K
& key
)
140 CDataStream
ssKey(SER_DISK
);
143 Dbt
datKey(&ssKey
[0], ssKey
.size());
146 int ret
= pdb
->exists(GetTxn(), &datKey
, 0);
149 memset(datKey
.get_data(), 0, datKey
.get_size());
158 int ret
= pdb
->cursor(NULL
, &pcursor
, 0);
164 int ReadAtCursor(Dbc
* pcursor
, CDataStream
& ssKey
, CDataStream
& ssValue
, unsigned int fFlags
=DB_NEXT
)
168 if (fFlags
== DB_SET
|| fFlags
== DB_SET_RANGE
|| fFlags
== DB_GET_BOTH
|| fFlags
== DB_GET_BOTH_RANGE
)
170 datKey
.set_data(&ssKey
[0]);
171 datKey
.set_size(ssKey
.size());
174 if (fFlags
== DB_GET_BOTH
|| fFlags
== DB_GET_BOTH_RANGE
)
176 datValue
.set_data(&ssValue
[0]);
177 datValue
.set_size(ssValue
.size());
179 datKey
.set_flags(DB_DBT_MALLOC
);
180 datValue
.set_flags(DB_DBT_MALLOC
);
181 int ret
= pcursor
->get(&datKey
, &datValue
, fFlags
);
184 else if (datKey
.get_data() == NULL
|| datValue
.get_data() == NULL
)
187 // Convert to streams
188 ssKey
.SetType(SER_DISK
);
190 ssKey
.write((char*)datKey
.get_data(), datKey
.get_size());
191 ssValue
.SetType(SER_DISK
);
193 ssValue
.write((char*)datValue
.get_data(), datValue
.get_size());
195 // Clear and free memory
196 memset(datKey
.get_data(), 0, datKey
.get_size());
197 memset(datValue
.get_data(), 0, datValue
.get_size());
198 free(datKey
.get_data());
199 free(datValue
.get_data());
217 int ret
= dbenv
.txn_begin(GetTxn(), &ptxn
, DB_TXN_NOSYNC
);
218 if (!ptxn
|| ret
!= 0)
220 vTxn
.push_back(ptxn
);
230 int ret
= vTxn
.back()->commit(0);
241 int ret
= vTxn
.back()->abort();
246 bool ReadVersion(int& nVersion
)
249 return Read(string("version"), nVersion
);
252 bool WriteVersion(int nVersion
)
254 return Write(string("version"), nVersion
);
265 class CTxDB
: public CDB
268 CTxDB(const char* pszMode
="r+") : CDB("blkindex.dat", pszMode
) { }
271 void operator=(const CTxDB
&);
273 bool ReadTxIndex(uint256 hash
, CTxIndex
& txindex
);
274 bool UpdateTxIndex(uint256 hash
, const CTxIndex
& txindex
);
275 bool AddTxIndex(const CTransaction
& tx
, const CDiskTxPos
& pos
, int nHeight
);
276 bool EraseTxIndex(const CTransaction
& tx
);
277 bool ContainsTx(uint256 hash
);
278 bool ReadOwnerTxes(uint160 hash160
, int nHeight
, vector
<CTransaction
>& vtx
);
279 bool ReadDiskTx(uint256 hash
, CTransaction
& tx
, CTxIndex
& txindex
);
280 bool ReadDiskTx(uint256 hash
, CTransaction
& tx
);
281 bool ReadDiskTx(COutPoint outpoint
, CTransaction
& tx
, CTxIndex
& txindex
);
282 bool ReadDiskTx(COutPoint outpoint
, CTransaction
& tx
);
283 bool WriteBlockIndex(const CDiskBlockIndex
& blockindex
);
284 bool EraseBlockIndex(uint256 hash
);
285 bool ReadHashBestChain(uint256
& hashBestChain
);
286 bool WriteHashBestChain(uint256 hashBestChain
);
287 bool ReadBestInvalidWork(CBigNum
& bnBestInvalidWork
);
288 bool WriteBestInvalidWork(CBigNum bnBestInvalidWork
);
289 bool LoadBlockIndex();
296 class CAddrDB
: public CDB
299 CAddrDB(const char* pszMode
="r+") : CDB("addr.dat", pszMode
) { }
301 CAddrDB(const CAddrDB
&);
302 void operator=(const CAddrDB
&);
304 bool WriteAddress(const CAddress
& addr
);
305 bool EraseAddress(const CAddress
& addr
);
306 bool LoadAddresses();
309 bool LoadAddresses();
320 vector
<unsigned char> vchPubKey
;
327 CKeyPool(const vector
<unsigned char>& vchPubKeyIn
)
330 vchPubKey
= vchPubKeyIn
;
335 if (!(nType
& SER_GETHASH
))
338 READWRITE(vchPubKey
);
345 class CWalletDB
: public CDB
348 CWalletDB(const char* pszMode
="r+") : CDB("wallet.dat", pszMode
)
352 CWalletDB(const CWalletDB
&);
353 void operator=(const CWalletDB
&);
355 bool ReadName(const string
& strAddress
, string
& strName
)
358 return Read(make_pair(string("name"), strAddress
), strName
);
361 bool WriteName(const string
& strAddress
, const string
& strName
)
363 CRITICAL_BLOCK(cs_mapAddressBook
)
364 mapAddressBook
[strAddress
] = strName
;
366 return Write(make_pair(string("name"), strAddress
), strName
);
369 bool EraseName(const string
& strAddress
)
371 // This should only be used for sending addresses, never for receiving addresses,
372 // receiving addresses must always have an address book entry if they're not change return.
373 CRITICAL_BLOCK(cs_mapAddressBook
)
374 mapAddressBook
.erase(strAddress
);
376 return Erase(make_pair(string("name"), strAddress
));
379 bool ReadTx(uint256 hash
, CWalletTx
& wtx
)
381 return Read(make_pair(string("tx"), hash
), wtx
);
384 bool WriteTx(uint256 hash
, const CWalletTx
& wtx
)
387 return Write(make_pair(string("tx"), hash
), wtx
);
390 bool EraseTx(uint256 hash
)
393 return Erase(make_pair(string("tx"), hash
));
396 bool ReadKey(const vector
<unsigned char>& vchPubKey
, CPrivKey
& vchPrivKey
)
399 return Read(make_pair(string("key"), vchPubKey
), vchPrivKey
);
402 bool WriteKey(const vector
<unsigned char>& vchPubKey
, const CPrivKey
& vchPrivKey
)
405 return Write(make_pair(string("key"), vchPubKey
), vchPrivKey
, false);
408 bool ReadDefaultKey(vector
<unsigned char>& vchPubKey
)
411 return Read(string("defaultkey"), vchPubKey
);
414 bool WriteDefaultKey(const vector
<unsigned char>& vchPubKey
)
416 vchDefaultKey
= vchPubKey
;
418 return Write(string("defaultkey"), vchPubKey
);
422 bool ReadSetting(const string
& strKey
, T
& value
)
424 return Read(make_pair(string("setting"), strKey
), value
);
428 bool WriteSetting(const string
& strKey
, const T
& value
)
431 return Write(make_pair(string("setting"), strKey
), value
);
434 bool ReadAccount(const string
& strAccount
, CAccount
& account
);
435 bool WriteAccount(const string
& strAccount
, const CAccount
& account
);
436 bool WriteAccountingEntry(const string
& strAccount
, const CAccountingEntry
& acentry
);
437 int64
GetAccountCreditDebit(const string
& strAccount
);
438 void ListAccountCreditDebit(const string
& strAccount
, list
<CAccountingEntry
>& acentries
);
442 void ReserveKeyFromKeyPool(int64
& nIndex
, CKeyPool
& keypool
);
443 void KeepKey(int64 nIndex
);
444 static void ReturnKey(int64 nIndex
);
445 friend class CReserveKey
;
446 friend vector
<unsigned char> GetKeyFromKeyPool();
447 friend int64
GetOldestKeyPoolTime();
450 bool LoadWallet(bool& fFirstRunRet
);
451 void BackupWallet(const string
& strDest
);
453 inline bool SetAddressBookName(const string
& strAddress
, const string
& strName
)
455 return CWalletDB().WriteName(strAddress
, strName
);
462 vector
<unsigned char> vchPubKey
;
475 vector
<unsigned char> GetReservedKey()
480 CWalletDB().ReserveKeyFromKeyPool(nIndex
, keypool
);
481 vchPubKey
= keypool
.vchPubKey
;
483 assert(!vchPubKey
.empty());
490 CWalletDB().KeepKey(nIndex
);
498 CWalletDB::ReturnKey(nIndex
);