Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2021 The Bitcoin developers
3 : // Copyright (c) 2014-2015 The Dash developers
4 : // Copyright (c) 2015-2021 The PIVX Core developers
5 : // Distributed under the MIT/X11 software license, see the accompanying
6 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 :
8 : #include "wallet/walletdb.h"
9 :
10 : #include "fs.h"
11 :
12 : #include "key_io.h"
13 : #include "protocol.h"
14 : #include "reverse_iterate.h"
15 : #include "sapling/key_io_sapling.h"
16 : #include "serialize.h"
17 : #include "sync.h"
18 : #include "util/system.h"
19 : #include "utiltime.h"
20 : #include "wallet/wallet.h"
21 : #include "wallet/walletutil.h"
22 :
23 : #include <atomic>
24 :
25 : #include <boost/thread.hpp>
26 :
27 : namespace DBKeys {
28 : const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"};
29 : const std::string BESTBLOCK{"bestblock"};
30 : const std::string CRYPTED_KEY{"ckey"};
31 : const std::string CSCRIPT{"cscript"};
32 : const std::string DEFAULTKEY{"defaultkey"};
33 : const std::string DESTDATA{"destdata"};
34 : const std::string HDCHAIN{"hdchain"};
35 : const std::string KEYMETA{"keymeta"};
36 : const std::string KEY{"key"};
37 : const std::string MASTER_KEY{"mkey"};
38 : const std::string MINVERSION{"minversion"};
39 : const std::string NAME{"name"};
40 : const std::string ORDERPOSNEXT{"orderposnext"};
41 : const std::string POOL{"pool"};
42 : const std::string PURPOSE{"purpose"};
43 : const std::string TX{"tx"};
44 : const std::string VERSION{"version"};
45 : const std::string WATCHS{"watchs"};
46 :
47 : // Sapling
48 : const std::string SAP_KEYMETA{"sapzkeymeta"};
49 : const std::string SAP_KEY{"sapzkey"};
50 : const std::string SAP_KEY_CRIPTED{"csapzkey"};
51 : const std::string SAP_ADDR{"sapzaddr"};
52 : const std::string SAP_COMMON_OVK{"commonovk"};
53 : const std::string SAP_HDCHAIN{"hdchain_sap"};
54 : const std::string SAP_WITNESS_CACHE_SIZE{"witnesscachesize"};
55 :
56 : // Wallet custom settings
57 : const std::string AUTOCOMBINE{"autocombinesettings"};
58 : const std::string AUTOCOMBINE_V2{"autocombinesettingsV2"};
59 : const std::string STAKE_SPLIT_THRESHOLD{"stakeSplitThreshold"};
60 : const std::string USE_CUSTOM_FEE{"fUseCustomFee"};
61 : const std::string CUSTOM_FEE_VALUE{"nCustomFee"};
62 :
63 : } // namespace DBKeys
64 :
65 :
66 : //
67 : // WalletBatch
68 : //
69 :
70 3768 : bool WalletBatch::WriteName(const std::string& strAddress, const std::string& strName)
71 : {
72 3768 : return WriteIC(std::make_pair(std::string(DBKeys::NAME), strAddress), strName);
73 : }
74 :
75 0 : bool WalletBatch::EraseName(const std::string& strAddress)
76 : {
77 : // This should only be used for sending addresses, never for receiving addresses,
78 : // receiving addresses must always have an address book entry if they're not change return.
79 0 : return EraseIC(std::make_pair(std::string(DBKeys::NAME), strAddress));
80 : }
81 :
82 3750 : bool WalletBatch::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
83 : {
84 3750 : return WriteIC(std::make_pair(std::string(DBKeys::PURPOSE), strAddress), strPurpose);
85 : }
86 :
87 0 : bool WalletBatch::ErasePurpose(const std::string& strPurpose)
88 : {
89 0 : return EraseIC(std::make_pair(std::string(DBKeys::PURPOSE), strPurpose));
90 : }
91 :
92 336677 : bool WalletBatch::WriteTx(const CWalletTx& wtx)
93 : {
94 673354 : return WriteIC(std::make_pair(std::string(DBKeys::TX), wtx.GetHash()), wtx);
95 : }
96 :
97 212 : bool WalletBatch::EraseTx(uint256 hash)
98 : {
99 424 : return EraseIC(std::make_pair(std::string(DBKeys::TX), hash));
100 : }
101 :
102 11864 : bool WalletBatch::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
103 : {
104 23728 : if (!WriteIC(std::make_pair(std::string(DBKeys::KEYMETA), vchPubKey), keyMeta, false)) {
105 : return false;
106 : }
107 :
108 : // hash pubkey/privkey to accelerate wallet load
109 23728 : std::vector<unsigned char> vchKey;
110 11864 : vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
111 11864 : vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
112 11864 : vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
113 :
114 59320 : return WriteIC(std::make_pair(std::string(DBKeys::KEY), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
115 : }
116 :
117 1746 : bool WalletBatch::WriteCryptedKey(const CPubKey& vchPubKey,
118 : const std::vector<unsigned char>& vchCryptedSecret,
119 : const CKeyMetadata& keyMeta)
120 : {
121 1746 : const bool fEraseUnencryptedKey = true;
122 :
123 3492 : if (!WriteIC(std::make_pair(std::string(DBKeys::KEYMETA), vchPubKey), keyMeta)) {
124 : return false;
125 : }
126 :
127 3492 : if (!WriteIC(std::make_pair(std::string(DBKeys::CRYPTED_KEY), vchPubKey), vchCryptedSecret, false)) {
128 : return false;
129 : }
130 1746 : if (fEraseUnencryptedKey) {
131 5238 : EraseIC(std::make_pair(std::string(DBKeys::KEY), vchPubKey));
132 : }
133 :
134 1746 : return true;
135 : }
136 :
137 2262 : bool WalletBatch::WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk,
138 : const libzcash::SaplingExtendedSpendingKey &key,
139 : const CKeyMetadata &keyMeta)
140 : {
141 4524 : if (!WriteIC(std::make_pair(std::string(DBKeys::SAP_KEYMETA), ivk), keyMeta)) {
142 : return false;
143 : }
144 :
145 4524 : return WriteIC(std::make_pair(std::string(DBKeys::SAP_KEY), ivk), key, false);
146 : }
147 :
148 1 : bool WalletBatch::WriteSaplingPaymentAddress(const libzcash::SaplingPaymentAddress &addr,
149 : const libzcash::SaplingIncomingViewingKey &ivk)
150 : {
151 2 : return WriteIC(std::make_pair(std::string(DBKeys::SAP_ADDR), addr), ivk, false);
152 : }
153 :
154 104 : bool WalletBatch::WriteCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
155 : const std::vector<unsigned char>& vchCryptedSecret,
156 : const CKeyMetadata &keyMeta)
157 : {
158 104 : const bool fEraseUnencryptedKey = true;
159 104 : auto ivk = extfvk.fvk.in_viewing_key();
160 :
161 208 : if (!WriteIC(std::make_pair(std::string(DBKeys::SAP_KEYMETA), ivk), keyMeta)) {
162 : return false;
163 : }
164 :
165 312 : if (!WriteIC(std::make_pair(std::string(DBKeys::SAP_KEY_CRIPTED), ivk),
166 208 : std::make_pair(extfvk, vchCryptedSecret), false)) {
167 : return false;
168 : }
169 :
170 104 : if (fEraseUnencryptedKey) {
171 312 : EraseIC(std::make_pair(std::string(DBKeys::SAP_KEY), ivk));
172 : }
173 104 : return true;
174 : }
175 :
176 237 : bool WalletBatch::WriteSaplingCommonOVK(const uint256& ovk)
177 : {
178 237 : return WriteIC(std::string(DBKeys::SAP_COMMON_OVK), ovk);
179 : }
180 :
181 0 : bool WalletBatch::ReadSaplingCommonOVK(uint256& ovkRet)
182 : {
183 0 : return m_batch.Read(std::string(DBKeys::SAP_COMMON_OVK), ovkRet);
184 : }
185 :
186 327 : bool WalletBatch::WriteWitnessCacheSize(int64_t nWitnessCacheSize)
187 : {
188 654 : return WriteIC(std::string(DBKeys::SAP_WITNESS_CACHE_SIZE), nWitnessCacheSize);
189 : }
190 :
191 8 : bool WalletBatch::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
192 : {
193 16 : return WriteIC(std::make_pair(std::string(DBKeys::MASTER_KEY), nID), kMasterKey, true);
194 : }
195 :
196 15 : bool WalletBatch::WriteCScript(const uint160& hash, const CScript& redeemScript)
197 : {
198 30 : return WriteIC(std::make_pair(std::string(DBKeys::CSCRIPT), hash), redeemScript, false);
199 : }
200 :
201 41 : bool WalletBatch::WriteWatchOnly(const CScript& dest)
202 : {
203 82 : return WriteIC(std::make_pair(std::string(DBKeys::WATCHS), dest), '1');
204 : }
205 :
206 1 : bool WalletBatch::EraseWatchOnly(const CScript& dest)
207 : {
208 2 : return EraseIC(std::make_pair(std::string(DBKeys::WATCHS), dest));
209 : }
210 :
211 327 : bool WalletBatch::WriteBestBlock(const CBlockLocator& locator)
212 : {
213 981 : WriteIC(std::string(DBKeys::BESTBLOCK), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
214 654 : return WriteIC(std::string(DBKeys::BESTBLOCK_NOMERKLE), locator);
215 : }
216 :
217 351 : bool WalletBatch::ReadBestBlock(CBlockLocator& locator)
218 : {
219 1053 : if (m_batch.Read(std::string(DBKeys::BESTBLOCK), locator) && !locator.vHave.empty()) {
220 : return true;
221 : }
222 702 : return m_batch.Read(std::string(DBKeys::BESTBLOCK_NOMERKLE), locator);
223 : }
224 :
225 119200 : bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext)
226 : {
227 119200 : return WriteIC(std::string(DBKeys::ORDERPOSNEXT), nOrderPosNext);
228 : }
229 :
230 0 : bool WalletBatch::WriteStakeSplitThreshold(const CAmount& nStakeSplitThreshold)
231 : {
232 0 : return WriteIC(std::string(DBKeys::STAKE_SPLIT_THRESHOLD), nStakeSplitThreshold);
233 : }
234 :
235 0 : bool WalletBatch::WriteUseCustomFee(bool fUse)
236 : {
237 0 : return WriteIC(std::string(DBKeys::USE_CUSTOM_FEE), fUse);
238 : }
239 :
240 0 : bool WalletBatch::WriteCustomFeeValue(const CAmount& nFee)
241 : {
242 0 : return WriteIC(std::string(DBKeys::CUSTOM_FEE_VALUE), nFee);
243 : }
244 :
245 2 : bool WalletBatch::WriteAutoCombineSettings(bool fEnable, CAmount nCombineThreshold, int frequency)
246 : {
247 2 : std::pair<std::pair<bool, CAmount>, int> pSettings;
248 2 : pSettings.first.first = fEnable;
249 2 : pSettings.first.second = nCombineThreshold;
250 2 : pSettings.second = frequency;
251 2 : EraseIC(std::string(DBKeys::AUTOCOMBINE));
252 4 : return WriteIC(std::string(DBKeys::AUTOCOMBINE_V2), pSettings, true);
253 : }
254 :
255 6800 : bool WalletBatch::ReadPool(int64_t nPool, CKeyPool& keypool)
256 : {
257 13600 : return m_batch.Read(std::make_pair(std::string(DBKeys::POOL), nPool), keypool);
258 : }
259 :
260 11507 : bool WalletBatch::WritePool(int64_t nPool, const CKeyPool& keypool)
261 : {
262 23014 : return WriteIC(std::make_pair(std::string(DBKeys::POOL), nPool), keypool);
263 : }
264 :
265 7216 : bool WalletBatch::ErasePool(int64_t nPool)
266 : {
267 14432 : return EraseIC(std::make_pair(std::string(DBKeys::POOL), nPool));
268 : }
269 :
270 238 : bool WalletBatch::WriteMinVersion(int nVersion)
271 : {
272 238 : return WriteIC(std::string(DBKeys::MINVERSION), nVersion);
273 : }
274 :
275 13231 : bool WalletBatch::WriteHDChain(const CHDChain& chain)
276 : {
277 13231 : std::string key = chain.chainType == HDChain::ChainCounterType::Sapling ?
278 13231 : DBKeys::SAP_HDCHAIN : DBKeys::HDCHAIN;
279 13231 : return WriteIC(key, chain);
280 : }
281 :
282 0 : DBErrors WalletBatch::ReorderTransactions(CWallet* pwallet)
283 : {
284 0 : LOCK(pwallet->cs_wallet);
285 : // Old wallets didn't have any defined order for transactions
286 : // Probably a bad idea to change the output of this
287 :
288 : // First: get all CWalletTx into a sorted-by-time multimap.
289 0 : typedef std::multimap<int64_t, CWalletTx*> TxItems;
290 0 : TxItems txByTime;
291 :
292 0 : for (auto it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it) {
293 0 : CWalletTx* wtx = &((*it).second);
294 0 : txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
295 : }
296 :
297 0 : int64_t& nOrderPosNext = pwallet->nOrderPosNext;
298 0 : nOrderPosNext = 0;
299 0 : std::vector<int64_t> nOrderPosOffsets;
300 0 : for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) {
301 0 : CWalletTx *const pwtx = (*it).second;
302 0 : int64_t& nOrderPos = pwtx->nOrderPos;
303 :
304 0 : if (nOrderPos == -1) {
305 0 : nOrderPos = nOrderPosNext++;
306 0 : nOrderPosOffsets.push_back(nOrderPos);
307 :
308 0 : if (!WriteTx(*pwtx)) return DB_LOAD_FAIL;
309 :
310 : } else {
311 0 : int64_t nOrderPosOff = 0;
312 0 : for (const int64_t& nOffsetStart : nOrderPosOffsets) {
313 0 : if (nOrderPos >= nOffsetStart)
314 0 : ++nOrderPosOff;
315 : }
316 0 : nOrderPos += nOrderPosOff;
317 0 : nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
318 :
319 0 : if (!nOrderPosOff) continue;
320 :
321 : // Since we're changing the order, write it back
322 0 : if (!WriteTx(*pwtx)) return DB_LOAD_FAIL;
323 : }
324 : }
325 0 : WriteOrderPosNext(nOrderPosNext);
326 :
327 : return DB_LOAD_OK;
328 : }
329 :
330 0 : class CWalletScanState
331 : {
332 : public:
333 : unsigned int nKeys;
334 : unsigned int nCKeys;
335 : unsigned int nKeyMeta;
336 : unsigned int nZKeys;
337 : unsigned int nZKeyMeta;
338 : unsigned int nSapZAddrs;
339 : bool fIsEncrypted;
340 : bool fAnyUnordered;
341 : int nFileVersion;
342 : std::vector<uint256> vWalletUpgrade;
343 :
344 403 : CWalletScanState()
345 403 : {
346 403 : nKeys = nCKeys = nKeyMeta = nZKeys = nZKeyMeta = nSapZAddrs = 0;
347 403 : fIsEncrypted = false;
348 403 : fAnyUnordered = false;
349 403 : nFileVersion = 0;
350 : }
351 : };
352 :
353 27964 : bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, CWalletScanState& wss, std::string& strType, std::string& strErr)
354 : {
355 27964 : try {
356 : // Unserialize
357 : // Taking advantage of the fact that pair serialization
358 : // is just the two items serialized one after the other
359 27964 : ssKey >> strType;
360 27964 : if (strType == DBKeys::NAME) {
361 520 : std::string strAddress;
362 260 : ssKey >> strAddress;
363 520 : std::string strName;
364 260 : ssValue >> strName;
365 520 : pwallet->LoadAddressBookName(Standard::DecodeDestination(strAddress), strName);
366 27704 : } else if (strType == DBKeys::PURPOSE) {
367 520 : std::string strAddress;
368 260 : ssKey >> strAddress;
369 520 : std::string strPurpose;
370 260 : ssValue >> strPurpose;
371 520 : pwallet->LoadAddressBookPurpose(Standard::DecodeDestination(strAddress), strPurpose);
372 27444 : } else if (strType == DBKeys::TX) {
373 6551 : uint256 hash;
374 6551 : ssKey >> hash;
375 13102 : CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
376 6551 : ssValue >> wtx;
377 6551 : if (wtx.GetHash() != hash)
378 0 : return false;
379 :
380 : // Undo serialize changes in 31600
381 6551 : if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703) {
382 0 : if (!ssValue.empty()) {
383 0 : char fTmp;
384 0 : char fUnused;
385 0 : std::string unused_string;
386 0 : ssValue >> fTmp >> fUnused >> unused_string;
387 0 : strErr = strprintf("LoadWallet() upgrading tx ver=%d %d %s",
388 0 : wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
389 0 : wtx.fTimeReceivedIsTxTime = fTmp;
390 : } else {
391 0 : strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
392 0 : wtx.fTimeReceivedIsTxTime = 0;
393 : }
394 0 : wss.vWalletUpgrade.push_back(hash);
395 : }
396 :
397 6551 : if (wtx.nOrderPos == -1)
398 0 : wss.fAnyUnordered = true;
399 :
400 6551 : pwallet->LoadToWallet(wtx);
401 20893 : } else if (strType == DBKeys::WATCHS) {
402 22 : CScript script;
403 11 : ssKey >> script;
404 11 : char fYes;
405 11 : ssValue >> fYes;
406 11 : if (fYes == '1')
407 11 : pwallet->LoadWatchOnly(script);
408 :
409 : // Watch-only addresses have no birthday information for now,
410 : // so set the wallet birthday to the beginning of time.
411 11 : pwallet->nTimeFirstKey = 1;
412 20882 : } else if (strType == DBKeys::KEY) {
413 7787 : CPubKey vchPubKey;
414 7787 : ssKey >> vchPubKey;
415 7787 : if (!vchPubKey.IsValid()) {
416 0 : strErr = "Error reading wallet database: CPubKey corrupt";
417 0 : return false;
418 : }
419 15574 : CKey key;
420 15574 : CPrivKey pkey;
421 7787 : uint256 hash;
422 7787 : wss.nKeys++;
423 7787 : ssValue >> pkey;
424 :
425 : // Old wallets store keys as "key" [pubkey] => [privkey]
426 : // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
427 : // using EC operations as a checksum.
428 : // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
429 : // remaining backwards-compatible.
430 7787 : try {
431 7787 : ssValue >> hash;
432 0 : } catch (...) {
433 : }
434 :
435 7787 : bool fSkipCheck = false;
436 :
437 15574 : if (!hash.IsNull()) {
438 : // hash pubkey/privkey to accelerate wallet load
439 15574 : std::vector<unsigned char> vchKey;
440 7787 : vchKey.reserve(vchPubKey.size() + pkey.size());
441 7787 : vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
442 7787 : vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
443 :
444 7787 : if (Hash(vchKey.begin(), vchKey.end()) != hash) {
445 0 : strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
446 0 : return false;
447 : }
448 :
449 7787 : fSkipCheck = true;
450 : }
451 :
452 7787 : if (!key.Load(pkey, vchPubKey, fSkipCheck)) {
453 0 : strErr = "Error reading wallet database: CPrivKey corrupt";
454 : return false;
455 : }
456 7787 : if (!pwallet->LoadKey(key, vchPubKey)) {
457 0 : strErr = "Error reading wallet database: LoadKey failed";
458 : return false;
459 : }
460 13095 : } else if (strType == DBKeys::MASTER_KEY) {
461 1 : unsigned int nID;
462 1 : ssKey >> nID;
463 2 : CMasterKey kMasterKey;
464 1 : ssValue >> kMasterKey;
465 1 : if (pwallet->mapMasterKeys.count(nID) != 0) {
466 0 : strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID);
467 0 : return false;
468 : }
469 1 : pwallet->mapMasterKeys[nID] = kMasterKey;
470 1 : if (pwallet->nMasterKeyMaxID < nID)
471 1 : pwallet->nMasterKeyMaxID = nID;
472 13094 : } else if (strType == DBKeys::CRYPTED_KEY) {
473 602 : CPubKey vchPubKey;
474 602 : ssKey >> vchPubKey;
475 1204 : std::vector<unsigned char> vchPrivKey;
476 602 : ssValue >> vchPrivKey;
477 602 : wss.nCKeys++;
478 :
479 602 : if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey)) {
480 0 : strErr = "Error reading wallet database: LoadCryptedKey failed";
481 0 : return false;
482 : }
483 602 : wss.fIsEncrypted = true;
484 12492 : } else if (strType == DBKeys::KEYMETA) {
485 8389 : CPubKey vchPubKey;
486 8389 : ssKey >> vchPubKey;
487 16778 : CKeyMetadata keyMeta;
488 8389 : ssValue >> keyMeta;
489 8389 : wss.nKeyMeta++;
490 :
491 8389 : pwallet->LoadKeyMetadata(vchPubKey, keyMeta);
492 :
493 : // find earliest key creation time, as wallet birthday
494 8389 : if (!pwallet->nTimeFirstKey ||
495 8389 : (keyMeta.nCreateTime < pwallet->nTimeFirstKey))
496 0 : pwallet->nTimeFirstKey = keyMeta.nCreateTime;
497 4103 : } else if (strType == DBKeys::DEFAULTKEY) {
498 : // We don't want or need the default key, but if there is one set,
499 : // we want to make sure that it is valid so that we can detect corruption
500 0 : CPubKey vchPubKey;
501 0 : ssValue >> vchPubKey;
502 0 : if (!vchPubKey.IsValid()) {
503 0 : strErr = "Error reading wallet database: Default Key corrupt";
504 0 : return false;
505 : }
506 4103 : } else if (strType == DBKeys::POOL) {
507 2307 : int64_t nIndex;
508 2307 : ssKey >> nIndex;
509 2307 : CKeyPool keypool;
510 2307 : ssValue >> keypool;
511 2307 : pwallet->GetScriptPubKeyMan()->LoadKeyPool(nIndex, keypool);
512 1796 : } else if (strType == DBKeys::VERSION) {
513 403 : ssValue >> wss.nFileVersion;
514 403 : if (wss.nFileVersion == 10300)
515 0 : wss.nFileVersion = 300;
516 1393 : } else if (strType == DBKeys::CSCRIPT) {
517 2 : uint160 hash;
518 2 : ssKey >> hash;
519 4 : CScript script;
520 2 : ssValue >> script;
521 2 : if (!pwallet->LoadCScript(script)) {
522 0 : strErr = "Error reading wallet database: LoadCScript failed";
523 0 : return false;
524 : }
525 1391 : } else if (strType == DBKeys::ORDERPOSNEXT) {
526 132 : ssValue >> pwallet->nOrderPosNext;
527 1259 : } else if (strType == DBKeys::STAKE_SPLIT_THRESHOLD) {
528 0 : ssValue >> pwallet->nStakeSplitThreshold;
529 : // originally saved as integer
530 0 : if (pwallet->nStakeSplitThreshold < COIN)
531 0 : pwallet->nStakeSplitThreshold *= COIN;
532 1259 : } else if (strType == DBKeys::USE_CUSTOM_FEE) {
533 0 : ssValue >> pwallet->fUseCustomFee;
534 1259 : } else if (strType == DBKeys::CUSTOM_FEE_VALUE) {
535 0 : ssValue >> pwallet->nCustomFee;
536 1259 : } else if (strType == DBKeys::AUTOCOMBINE) {
537 0 : std::pair<bool, CAmount> pSettings;
538 0 : ssValue >> pSettings;
539 0 : pwallet->fCombineDust = pSettings.first;
540 0 : pwallet->nAutoCombineThreshold = pSettings.second;
541 : // Value used for old autocombine
542 0 : pwallet->frequency = 1;
543 : // originally saved as integer
544 0 : if (pwallet->nAutoCombineThreshold < COIN)
545 0 : pwallet->nAutoCombineThreshold *= COIN;
546 1259 : } else if (strType == DBKeys::AUTOCOMBINE_V2) {
547 0 : std::pair<std::pair<bool, CAmount>, int> pSettings;
548 0 : ssValue >> pSettings;
549 0 : pwallet->fCombineDust = pSettings.first.first;
550 0 : pwallet->nAutoCombineThreshold = pSettings.first.second;
551 0 : pwallet->frequency = pSettings.second;
552 1259 : } else if (strType == DBKeys::DESTDATA) {
553 0 : std::string strAddress, strKey, strValue;
554 0 : ssKey >> strAddress;
555 0 : ssKey >> strKey;
556 0 : ssValue >> strValue;
557 0 : if (!pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue)) {
558 0 : strErr = "Error reading wallet database: LoadDestData failed";
559 0 : return false;
560 : }
561 1259 : } else if (strType == DBKeys::HDCHAIN) { // Regular key chain counter
562 159 : CHDChain chain;
563 159 : ssValue >> chain;
564 159 : pwallet->GetScriptPubKeyMan()->SetHDChain(chain, true);
565 1100 : } else if (strType == DBKeys::SAP_HDCHAIN) {
566 159 : CHDChain chain;
567 159 : ssValue >> chain;
568 159 : pwallet->GetSaplingScriptPubKeyMan()->SetHDChain(chain, true);
569 941 : } else if (strType == DBKeys::SAP_KEY) {
570 35 : libzcash::SaplingIncomingViewingKey ivk;
571 35 : ssKey >> ivk;
572 35 : libzcash::SaplingExtendedSpendingKey key;
573 35 : ssValue >> key;
574 35 : if (!pwallet->LoadSaplingZKey(key)) {
575 0 : strErr = "Error reading wallet database: LoadSaplingZKey failed";
576 0 : return false;
577 : }
578 : //add checks for integrity
579 35 : wss.nZKeys++;
580 906 : } else if (strType == DBKeys::SAP_COMMON_OVK) {
581 159 : uint256 ovk;
582 159 : ssValue >> ovk;
583 318 : pwallet->GetSaplingScriptPubKeyMan()->setCommonOVK(ovk);
584 747 : } else if (strType == DBKeys::SAP_KEY_CRIPTED) {
585 2 : libzcash::SaplingIncomingViewingKey ivk;
586 2 : ssKey >> ivk;
587 2 : libzcash::SaplingExtendedFullViewingKey extfvk;
588 2 : ssValue >> extfvk;
589 4 : std::vector<unsigned char> vchCryptedSecret;
590 2 : ssValue >> vchCryptedSecret;
591 2 : wss.nCKeys++;
592 :
593 2 : if (!pwallet->LoadCryptedSaplingZKey(extfvk, vchCryptedSecret)) {
594 0 : strErr = "Error reading wallet database: LoadCryptedSaplingZKey failed";
595 0 : return false;
596 : }
597 2 : wss.fIsEncrypted = true;
598 745 : } else if (strType == DBKeys::SAP_KEYMETA) {
599 37 : libzcash::SaplingIncomingViewingKey ivk;
600 37 : ssKey >> ivk;
601 74 : CKeyMetadata keyMeta;
602 37 : ssValue >> keyMeta;
603 :
604 37 : wss.nZKeyMeta++;
605 :
606 37 : pwallet->LoadSaplingZKeyMetadata(ivk, keyMeta);
607 708 : } else if (strType == DBKeys::SAP_ADDR) {
608 0 : libzcash::SaplingPaymentAddress addr;
609 0 : ssKey >> addr;
610 0 : libzcash::SaplingIncomingViewingKey ivk;
611 0 : ssValue >> ivk;
612 :
613 0 : wss.nSapZAddrs++;
614 :
615 0 : if (!pwallet->LoadSaplingPaymentAddress(addr, ivk)) {
616 0 : strErr = "Error reading wallet database: LoadSaplingPaymentAddress failed";
617 0 : return false;
618 : }
619 708 : } else if (strType == DBKeys::SAP_WITNESS_CACHE_SIZE) {
620 28122 : ssValue >> pwallet->GetSaplingScriptPubKeyMan()->nWitnessCacheSize;
621 : }
622 0 : } catch (...) {
623 0 : return false;
624 : }
625 : return true;
626 : }
627 :
628 0 : bool WalletBatch::IsKeyType(const std::string& strType)
629 : {
630 0 : return (strType == DBKeys::KEY ||
631 0 : strType == DBKeys::MASTER_KEY || strType == DBKeys::CRYPTED_KEY ||
632 0 : strType == DBKeys::SAP_KEY || strType == DBKeys::SAP_KEY_CRIPTED);
633 : }
634 :
635 403 : DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
636 : {
637 806 : CWalletScanState wss;
638 403 : bool fNoncriticalErrors = false;
639 403 : DBErrors result = DB_LOAD_OK;
640 :
641 806 : LOCK(pwallet->cs_wallet);
642 403 : try {
643 403 : int nMinVersion = 0;
644 806 : if (m_batch.Read((std::string) DBKeys::MINVERSION, nMinVersion)) {
645 162 : if (nMinVersion > CLIENT_VERSION) {
646 0 : return DB_TOO_NEW;
647 : }
648 162 : pwallet->LoadMinVersion(nMinVersion);
649 : }
650 :
651 : // Get cursor
652 403 : Dbc* pcursor = m_batch.GetCursor();
653 403 : if (!pcursor) {
654 0 : LogPrintf("Error getting wallet database cursor\n");
655 : return DB_CORRUPT;
656 : }
657 :
658 28367 : while (true) {
659 : // Read next record
660 28367 : CDataStream ssKey(SER_DISK, CLIENT_VERSION);
661 27964 : CDataStream ssValue(SER_DISK, CLIENT_VERSION);
662 28367 : int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue);
663 28367 : if (ret == DB_NOTFOUND) {
664 : break;
665 27964 : } else if (ret != 0) {
666 0 : LogPrintf("Error reading next record from wallet database\n");
667 0 : return DB_CORRUPT;
668 : }
669 :
670 : // Try to be tolerant of single corrupt records:
671 56247 : std::string strType, strErr;
672 27964 : if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr)) {
673 : // losing keys is considered a catastrophic error, anything else
674 : // we assume the user can live with:
675 0 : if (IsKeyType(strType) || strType == DBKeys::DEFAULTKEY) {
676 : result = DB_CORRUPT;
677 : } else {
678 : // Leave other errors alone, if we try to fix them we might make things worse.
679 0 : fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
680 0 : if (strType == DBKeys::TX)
681 : // Rescan if there is a bad transaction record:
682 0 : gArgs.SoftSetBoolArg("-rescan", true);
683 : }
684 : }
685 27964 : if (!strErr.empty())
686 0 : LogPrintf("%s\n", strErr);
687 : }
688 403 : pcursor->close();
689 0 : } catch (const boost::thread_interrupted&) {
690 0 : throw;
691 0 : } catch (...) {
692 0 : result = DB_CORRUPT;
693 : }
694 :
695 403 : if (fNoncriticalErrors && result == DB_LOAD_OK)
696 : result = DB_NONCRITICAL_ERROR;
697 :
698 : // Any wallet corruption at all: skip any rewriting or
699 : // upgrading, we don't want to make it worse.
700 403 : if (result != DB_LOAD_OK)
701 0 : return result;
702 :
703 403 : LogPrintf("nFileVersion = %d\n", wss.nFileVersion);
704 :
705 403 : LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
706 403 : wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys);
707 :
708 403 : LogPrintf("ZKeys: %u plaintext, -- encrypted, %u w/metadata, %u total\n",
709 403 : wss.nZKeys, wss.nZKeyMeta, wss.nZKeys + 0);
710 :
711 : // nTimeFirstKey is only reliable if all keys have metadata
712 403 : if ((wss.nKeys + wss.nCKeys) != wss.nKeyMeta)
713 1 : pwallet->nTimeFirstKey = 1; // 0 would be considered 'no value'
714 :
715 403 : for (const uint256& hash : wss.vWalletUpgrade) {
716 0 : WriteTx(pwallet->mapWallet.at(hash));
717 : }
718 :
719 : // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
720 403 : if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000)) {
721 : return DB_NEED_REWRITE;
722 : }
723 :
724 403 : if (wss.nFileVersion < CLIENT_VERSION) { // Update
725 2 : WriteVersion(CLIENT_VERSION);
726 : }
727 :
728 403 : if (wss.fAnyUnordered) {
729 0 : result = ReorderTransactions(pwallet);
730 : }
731 :
732 : return result;
733 : }
734 :
735 5 : DBErrors WalletBatch::FindWalletTx(CWallet* pwallet, std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx)
736 : {
737 5 : bool fNoncriticalErrors = false;
738 5 : DBErrors result = DB_LOAD_OK;
739 :
740 5 : try {
741 10 : LOCK(pwallet->cs_wallet);
742 5 : int nMinVersion = 0;
743 10 : if (m_batch.Read((std::string) DBKeys::MINVERSION, nMinVersion)) {
744 5 : if (nMinVersion > CLIENT_VERSION) {
745 0 : return DB_TOO_NEW;
746 : }
747 5 : pwallet->LoadMinVersion(nMinVersion);
748 : }
749 :
750 : // Get cursor
751 5 : Dbc* pcursor = m_batch.GetCursor();
752 5 : if (!pcursor) {
753 0 : LogPrintf("Error getting wallet database cursor\n");
754 : return DB_CORRUPT;
755 : }
756 :
757 388 : while (true) {
758 : // Read next record
759 388 : CDataStream ssKey(SER_DISK, CLIENT_VERSION);
760 383 : CDataStream ssValue(SER_DISK, CLIENT_VERSION);
761 388 : int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue);
762 388 : if (ret == DB_NOTFOUND) {
763 : break;
764 383 : } else if (ret != 0) {
765 0 : LogPrintf("Error reading next record from wallet database\n");
766 0 : return DB_CORRUPT;
767 : }
768 :
769 766 : std::string strType;
770 383 : ssKey >> strType;
771 383 : if (strType == DBKeys::TX) {
772 212 : uint256 hash;
773 212 : ssKey >> hash;
774 :
775 424 : CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
776 212 : ssValue >> wtx;
777 :
778 212 : vTxHash.push_back(hash);
779 212 : vWtx.push_back(wtx);
780 : }
781 : }
782 5 : pcursor->close();
783 0 : } catch (const boost::thread_interrupted&) {
784 0 : throw;
785 0 : } catch (...) {
786 0 : result = DB_CORRUPT;
787 : }
788 :
789 5 : if (fNoncriticalErrors && result == DB_LOAD_OK)
790 : result = DB_NONCRITICAL_ERROR;
791 :
792 5 : return result;
793 : }
794 :
795 5 : DBErrors WalletBatch::ZapWalletTx(CWallet* pwallet, std::vector<CWalletTx>& vWtx)
796 : {
797 : // build list of wallet TXs
798 10 : std::vector<uint256> vTxHash;
799 5 : DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx);
800 5 : if (err != DB_LOAD_OK) {
801 : return err;
802 : }
803 :
804 : // erase each wallet TX
805 217 : for (uint256& hash : vTxHash) {
806 212 : if (!EraseTx(hash)) return DB_CORRUPT;
807 : }
808 :
809 5 : return DB_LOAD_OK;
810 : }
811 :
812 38013 : void MaybeCompactWalletDB()
813 : {
814 38013 : static std::atomic<bool> fOneThread;
815 38013 : if (fOneThread.exchange(true)) {
816 : return;
817 : }
818 38013 : if (!gArgs.GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) {
819 : return;
820 : }
821 :
822 76060 : for (CWalletRef pwallet : vpwallets) {
823 38047 : WalletDatabase& dbh = pwallet->GetDBHandle();
824 :
825 38047 : unsigned int nUpdateCounter = dbh.nUpdateCounter;
826 38047 : if (dbh.nLastSeen != nUpdateCounter) {
827 4496 : dbh.nLastSeen = nUpdateCounter;
828 4496 : dbh.nLastWalletUpdate = GetTime();
829 : }
830 :
831 38047 : if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) {
832 19004 : if (BerkeleyBatch::PeriodicFlush(dbh)) {
833 804 : dbh.nLastFlushed = nUpdateCounter;
834 : }
835 : }
836 : }
837 :
838 38013 : fOneThread = false;
839 : }
840 :
841 : typedef std::multimap<std::time_t, fs::path> folder_set_t;
842 287 : static folder_set_t buildBackupsMapSortedByLastWrite(const std::string& strWalletFile, const fs::path& backupsDir)
843 : {
844 287 : folder_set_t folder_set;
845 574 : fs::directory_iterator end_iter;
846 : // Build map of backup files for current(!) wallet sorted by last write time
847 744 : for (fs::directory_iterator dir_iter(backupsDir); dir_iter != end_iter; ++dir_iter) {
848 : // Only check regular files
849 457 : if (fs::is_regular_file(dir_iter->status())) {
850 : // Only add the backups for the current wallet, e.g. wallet.dat.*
851 462 : if(dir_iter->path().stem().string() == strWalletFile) {
852 402 : folder_set.insert(folder_set_t::value_type(fs::last_write_time(dir_iter->path()), *dir_iter));
853 : }
854 : }
855 : }
856 287 : return folder_set;
857 : }
858 :
859 287 : static bool cleanWalletBackups(folder_set_t& folder_set, int nWalletBackups, std::string& strBackupWarning)
860 : {
861 : // Loop backward through backup files and keep the N newest ones (1 <= N <= 10)
862 287 : int counter = 0;
863 689 : for (const std::pair<const std::time_t, fs::path>& file : reverse_iterate(folder_set)) {
864 402 : counter++;
865 402 : if (counter > nWalletBackups) {
866 : // More than nWalletBackups backups: delete oldest one(s)
867 1 : try {
868 1 : fs::remove(file.second);
869 1 : LogPrintf("Old backup deleted: %s\n", file.second);
870 0 : } catch (fs::filesystem_error &error) {
871 0 : strBackupWarning = strprintf(_("Failed to delete backup, error: %s"), error.what());
872 0 : LogPrintf("%s\n", strBackupWarning);
873 0 : return false;
874 : }
875 : }
876 : }
877 287 : return true;
878 : }
879 :
880 361 : bool AutoBackupWallet(CWallet& wallet, std::string& strBackupWarning, std::string& strBackupError)
881 : {
882 361 : strBackupWarning = strBackupError = "";
883 722 : int nWalletBackups = std::max(0, std::min(10, (int)gArgs.GetArg("-createwalletbackups", DEFAULT_CREATEWALLETBACKUPS)));
884 361 : if (nWalletBackups == 0) {
885 0 : LogPrintf("Automatic wallet backups are disabled!\n");
886 0 : return false;
887 : }
888 :
889 722 : fs::path backupsDir = GetDataDir() / "backups";
890 361 : backupsDir.make_preferred();
891 361 : TryCreateDirectories(backupsDir);
892 722 : std::string strWalletFile = wallet.GetUniqueWalletBackupName();
893 1083 : fs::path backupFile = backupsDir / strWalletFile;
894 361 : backupFile.make_preferred();
895 648 : if (fs::exists(backupFile)) {
896 74 : LogPrintf("%s\n", _("Failed to create backup, file already exists! This could happen if you restarted wallet in less than 60 seconds. You can continue if you are ok with this."));
897 74 : return false;
898 : }
899 :
900 : // Try to backup
901 287 : if (!wallet.BackupWallet(backupFile.string())) {
902 0 : strBackupError = "Failed to backup wallet";
903 : return false; // error is logged internally
904 : }
905 :
906 : // Keep only 0 < nWalletBackups <= 10 backups, including the new one of course
907 648 : folder_set_t folder_set = buildBackupsMapSortedByLastWrite(backupFile.stem().string(), backupsDir);
908 287 : return cleanWalletBackups(folder_set, nWalletBackups, strBackupWarning);
909 : }
910 :
911 : //
912 : // Try to (very carefully!) recover wallet file if there is a problem.
913 : //
914 0 : bool WalletBatch::Recover(const fs::path& wallet_path, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename)
915 : {
916 0 : return BerkeleyBatch::Recover(wallet_path, callbackDataIn, recoverKVcallback, out_backup_filename);
917 : }
918 :
919 0 : bool WalletBatch::Recover(const fs::path& wallet_path, std::string& out_backup_filename)
920 : {
921 : // recover without a key filter callback
922 : // results in recovering all record types
923 0 : return WalletBatch::Recover(wallet_path, nullptr, nullptr, out_backup_filename);
924 : }
925 :
926 0 : bool WalletBatch::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
927 : {
928 0 : CWallet *dummyWallet = reinterpret_cast<CWallet*>(callbackData);
929 0 : CWalletScanState dummyWss;
930 0 : std::string strType, strErr;
931 0 : bool fReadOK;
932 0 : {
933 : // Required in LoadKeyMetadata():
934 0 : LOCK(dummyWallet->cs_wallet);
935 0 : fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue,
936 : dummyWss, strType, strErr);
937 : }
938 0 : if (!IsKeyType(strType) && strType != DBKeys::HDCHAIN)
939 : return false;
940 0 : if (!fReadOK)
941 : {
942 0 : LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", strType, strErr);
943 : return false;
944 : }
945 :
946 : return true;
947 : }
948 :
949 377 : bool WalletBatch::VerifyEnvironment(const fs::path& wallet_path, std::string& errorStr)
950 : {
951 377 : return BerkeleyBatch::VerifyEnvironment(wallet_path, errorStr);
952 : }
953 :
954 374 : bool WalletBatch::VerifyDatabaseFile(const fs::path& wallet_path, std::string& warningStr, std::string& errorStr)
955 : {
956 374 : return BerkeleyBatch::VerifyDatabaseFile(wallet_path, warningStr, errorStr, WalletBatch::Recover);
957 : }
958 :
959 0 : bool WalletBatch::WriteDestData(const std::string& address, const std::string& key, const std::string& value)
960 : {
961 0 : return WriteIC(std::make_pair(std::string(DBKeys::DESTDATA), std::make_pair(address, key)), value);
962 : }
963 :
964 0 : bool WalletBatch::EraseDestData(const std::string& address, const std::string& key)
965 : {
966 0 : return EraseIC(std::make_pair(std::string(DBKeys::DESTDATA), std::make_pair(address, key)));
967 : }
968 :
969 334 : bool WalletBatch::TxnBegin()
970 : {
971 334 : return m_batch.TxnBegin();
972 : }
973 :
974 334 : bool WalletBatch::TxnCommit()
975 : {
976 334 : return m_batch.TxnCommit();
977 : }
978 :
979 0 : bool WalletBatch::TxnAbort()
980 : {
981 0 : return m_batch.TxnAbort();
982 : }
983 :
984 0 : bool WalletBatch::ReadVersion(int& nVersion)
985 : {
986 0 : return m_batch.ReadVersion(nVersion);
987 : }
988 :
989 2 : bool WalletBatch::WriteVersion(int nVersion)
990 : {
991 2 : return m_batch.WriteVersion(nVersion);
992 : }
|