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 extern map
<string
, string
> mapAddressBook
;
16 extern CCriticalSection cs_mapAddressBook
;
17 extern vector
<unsigned char> vchDefaultKey
;
19 extern int nBestHeight
;
22 extern unsigned int nWalletDBUpdated
;
26 extern void DBFlush(bool fShutdown
);
39 explicit CDB(const char* pszFile
, const char* pszMode
="r+");
45 void operator=(const CDB
&);
48 template<typename K
, typename T
>
49 bool Read(const K
& key
, T
& value
)
55 CDataStream
ssKey(SER_DISK
);
58 Dbt
datKey(&ssKey
[0], ssKey
.size());
62 datValue
.set_flags(DB_DBT_MALLOC
);
63 int ret
= pdb
->get(GetTxn(), &datKey
, &datValue
, 0);
64 memset(datKey
.get_data(), 0, datKey
.get_size());
65 if (datValue
.get_data() == NULL
)
69 CDataStream
ssValue((char*)datValue
.get_data(), (char*)datValue
.get_data() + datValue
.get_size(), SER_DISK
);
72 // Clear and free memory
73 memset(datValue
.get_data(), 0, datValue
.get_size());
74 free(datValue
.get_data());
78 template<typename K
, typename T
>
79 bool Write(const K
& key
, const T
& value
, bool fOverwrite
=true)
84 assert(("Write called on database in read-only mode", false));
87 CDataStream
ssKey(SER_DISK
);
90 Dbt
datKey(&ssKey
[0], ssKey
.size());
93 CDataStream
ssValue(SER_DISK
);
94 ssValue
.reserve(10000);
96 Dbt
datValue(&ssValue
[0], ssValue
.size());
99 int ret
= pdb
->put(GetTxn(), &datKey
, &datValue
, (fOverwrite
? 0 : DB_NOOVERWRITE
));
101 // Clear memory in case it was a private key
102 memset(datKey
.get_data(), 0, datKey
.get_size());
103 memset(datValue
.get_data(), 0, datValue
.get_size());
108 bool Erase(const K
& key
)
113 assert(("Erase called on database in read-only mode", false));
116 CDataStream
ssKey(SER_DISK
);
119 Dbt
datKey(&ssKey
[0], ssKey
.size());
122 int ret
= pdb
->del(GetTxn(), &datKey
, 0);
125 memset(datKey
.get_data(), 0, datKey
.get_size());
126 return (ret
== 0 || ret
== DB_NOTFOUND
);
130 bool Exists(const K
& key
)
136 CDataStream
ssKey(SER_DISK
);
139 Dbt
datKey(&ssKey
[0], ssKey
.size());
142 int ret
= pdb
->exists(GetTxn(), &datKey
, 0);
145 memset(datKey
.get_data(), 0, datKey
.get_size());
154 int ret
= pdb
->cursor(NULL
, &pcursor
, 0);
160 int ReadAtCursor(Dbc
* pcursor
, CDataStream
& ssKey
, CDataStream
& ssValue
, unsigned int fFlags
=DB_NEXT
)
164 if (fFlags
== DB_SET
|| fFlags
== DB_SET_RANGE
|| fFlags
== DB_GET_BOTH
|| fFlags
== DB_GET_BOTH_RANGE
)
166 datKey
.set_data(&ssKey
[0]);
167 datKey
.set_size(ssKey
.size());
170 if (fFlags
== DB_GET_BOTH
|| fFlags
== DB_GET_BOTH_RANGE
)
172 datValue
.set_data(&ssValue
[0]);
173 datValue
.set_size(ssValue
.size());
175 datKey
.set_flags(DB_DBT_MALLOC
);
176 datValue
.set_flags(DB_DBT_MALLOC
);
177 int ret
= pcursor
->get(&datKey
, &datValue
, fFlags
);
180 else if (datKey
.get_data() == NULL
|| datValue
.get_data() == NULL
)
183 // Convert to streams
184 ssKey
.SetType(SER_DISK
);
186 ssKey
.write((char*)datKey
.get_data(), datKey
.get_size());
187 ssValue
.SetType(SER_DISK
);
189 ssValue
.write((char*)datValue
.get_data(), datValue
.get_size());
191 // Clear and free memory
192 memset(datKey
.get_data(), 0, datKey
.get_size());
193 memset(datValue
.get_data(), 0, datValue
.get_size());
194 free(datKey
.get_data());
195 free(datValue
.get_data());
213 int ret
= dbenv
.txn_begin(GetTxn(), &ptxn
, DB_TXN_NOSYNC
);
214 if (!ptxn
|| ret
!= 0)
216 vTxn
.push_back(ptxn
);
226 int ret
= vTxn
.back()->commit(0);
237 int ret
= vTxn
.back()->abort();
242 bool ReadVersion(int& nVersion
)
245 return Read(string("version"), nVersion
);
248 bool WriteVersion(int nVersion
)
250 return Write(string("version"), nVersion
);
261 class CTxDB
: public CDB
264 CTxDB(const char* pszMode
="r+") : CDB(!fClient
? "blkindex.dat" : NULL
, pszMode
) { }
267 void operator=(const CTxDB
&);
269 bool ReadTxIndex(uint256 hash
, CTxIndex
& txindex
);
270 bool UpdateTxIndex(uint256 hash
, const CTxIndex
& txindex
);
271 bool AddTxIndex(const CTransaction
& tx
, const CDiskTxPos
& pos
, int nHeight
);
272 bool EraseTxIndex(const CTransaction
& tx
);
273 bool ContainsTx(uint256 hash
);
274 bool ReadOwnerTxes(uint160 hash160
, int nHeight
, vector
<CTransaction
>& vtx
);
275 bool ReadDiskTx(uint256 hash
, CTransaction
& tx
, CTxIndex
& txindex
);
276 bool ReadDiskTx(uint256 hash
, CTransaction
& tx
);
277 bool ReadDiskTx(COutPoint outpoint
, CTransaction
& tx
, CTxIndex
& txindex
);
278 bool ReadDiskTx(COutPoint outpoint
, CTransaction
& tx
);
279 bool WriteBlockIndex(const CDiskBlockIndex
& blockindex
);
280 bool EraseBlockIndex(uint256 hash
);
281 bool ReadHashBestChain(uint256
& hashBestChain
);
282 bool WriteHashBestChain(uint256 hashBestChain
);
283 bool ReadBestInvalidWork(CBigNum
& bnBestInvalidWork
);
284 bool WriteBestInvalidWork(CBigNum bnBestInvalidWork
);
285 bool LoadBlockIndex();
292 class CAddrDB
: public CDB
295 CAddrDB(const char* pszMode
="r+") : CDB("addr.dat", pszMode
) { }
297 CAddrDB(const CAddrDB
&);
298 void operator=(const CAddrDB
&);
300 bool WriteAddress(const CAddress
& addr
);
301 bool LoadAddresses();
304 bool LoadAddresses();
311 class CWalletDB
: public CDB
314 CWalletDB(const char* pszMode
="r+") : CDB("wallet.dat", pszMode
) { }
316 CWalletDB(const CWalletDB
&);
317 void operator=(const CWalletDB
&);
319 bool ReadName(const string
& strAddress
, string
& strName
)
322 return Read(make_pair(string("name"), strAddress
), strName
);
325 bool WriteName(const string
& strAddress
, const string
& strName
)
327 CRITICAL_BLOCK(cs_mapAddressBook
)
328 mapAddressBook
[strAddress
] = strName
;
330 return Write(make_pair(string("name"), strAddress
), strName
);
333 bool EraseName(const string
& strAddress
)
335 // This should only be used for sending addresses, never for receiving addresses,
336 // receiving addresses must always have an address book entry if they're not change return.
337 CRITICAL_BLOCK(cs_mapAddressBook
)
338 mapAddressBook
.erase(strAddress
);
340 return Erase(make_pair(string("name"), strAddress
));
343 bool ReadTx(uint256 hash
, CWalletTx
& wtx
)
345 return Read(make_pair(string("tx"), hash
), wtx
);
348 bool WriteTx(uint256 hash
, const CWalletTx
& wtx
)
351 return Write(make_pair(string("tx"), hash
), wtx
);
354 bool EraseTx(uint256 hash
)
357 return Erase(make_pair(string("tx"), hash
));
360 bool ReadKey(const vector
<unsigned char>& vchPubKey
, CPrivKey
& vchPrivKey
)
363 return Read(make_pair(string("key"), vchPubKey
), vchPrivKey
);
366 bool WriteKey(const vector
<unsigned char>& vchPubKey
, const CPrivKey
& vchPrivKey
)
369 return Write(make_pair(string("key"), vchPubKey
), vchPrivKey
, false);
372 bool ReadDefaultKey(vector
<unsigned char>& vchPubKey
)
375 return Read(string("defaultkey"), vchPubKey
);
378 bool WriteDefaultKey(const vector
<unsigned char>& vchPubKey
)
380 vchDefaultKey
= vchPubKey
;
382 return Write(string("defaultkey"), vchPubKey
);
386 bool ReadSetting(const string
& strKey
, T
& value
)
388 return Read(make_pair(string("setting"), strKey
), value
);
392 bool WriteSetting(const string
& strKey
, const T
& value
)
395 return Write(make_pair(string("setting"), strKey
), value
);
401 bool LoadWallet(bool& fFirstRunRet
);
402 void BackupWallet(const string
& strDest
);
404 inline bool SetAddressBookName(const string
& strAddress
, const string
& strName
)
406 return CWalletDB().WriteName(strAddress
, strName
);