1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include <wallet/wallet.h>
7
8 #include <chain.h>
9 #include <consensus/consensus.h>
10 #include <consensus/validation.h>
11 #include <external_signer.h>
12 #include <fs.h>
13 #include <interfaces/chain.h>
14 #include <interfaces/wallet.h>
15 #include <key.h>
16 #include <key_io.h>
17 #include <outputtype.h>
18 #include <policy/fees.h>
19 #include <policy/policy.h>
20 #include <primitives/block.h>
21 #include <primitives/transaction.h>
22 #include <psbt.h>
23 #include <script/descriptor.h>
24 #include <script/script.h>
25 #include <script/signingprovider.h>
26 #include <txmempool.h>
27 #include <util/bip32.h>
28 #include <util/check.h>
29 #include <util/error.h>
30 #include <util/fees.h>
31 #include <util/moneystr.h>
32 #include <util/rbf.h>
33 #include <util/string.h>
34 #include <util/translation.h>
35 #include <wallet/coincontrol.h>
36 #include <wallet/fees.h>
37 #include <wallet/external_signer_scriptpubkeyman.h>
38
39 #include <univalue.h>
40
41 #include <algorithm>
42 #include <assert.h>
43 #include <optional>
44
45 #include <boost/algorithm/string/replace.hpp>
46
47 using interfaces::FoundBlock;
48
49 const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS{
50 {WALLET_FLAG_AVOID_REUSE,
51 "You need to rescan the blockchain in order to correctly mark used "
52 "destinations in the past. Until this is done, some destinations may "
53 "be considered unused, even if the opposite is the case."
54 },
55 };
56
57 RecursiveMutex cs_wallets;
58 static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
59 static std::list<LoadWalletFn> g_load_wallet_fns GUARDED_BY(cs_wallets);
60
AddWalletSetting(interfaces::Chain & chain,const std::string & wallet_name)61 bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
62 {
63 util::SettingsValue setting_value = chain.getRwSetting("wallet");
64 if (!setting_value.isArray()) setting_value.setArray();
65 for (const util::SettingsValue& value : setting_value.getValues()) {
66 if (value.isStr() && value.get_str() == wallet_name) return true;
67 }
68 setting_value.push_back(wallet_name);
69 return chain.updateRwSetting("wallet", setting_value);
70 }
71
RemoveWalletSetting(interfaces::Chain & chain,const std::string & wallet_name)72 bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
73 {
74 util::SettingsValue setting_value = chain.getRwSetting("wallet");
75 if (!setting_value.isArray()) return true;
76 util::SettingsValue new_value(util::SettingsValue::VARR);
77 for (const util::SettingsValue& value : setting_value.getValues()) {
78 if (!value.isStr() || value.get_str() != wallet_name) new_value.push_back(value);
79 }
80 if (new_value.size() == setting_value.size()) return true;
81 return chain.updateRwSetting("wallet", new_value);
82 }
83
UpdateWalletSetting(interfaces::Chain & chain,const std::string & wallet_name,std::optional<bool> load_on_startup,std::vector<bilingual_str> & warnings)84 static void UpdateWalletSetting(interfaces::Chain& chain,
85 const std::string& wallet_name,
86 std::optional<bool> load_on_startup,
87 std::vector<bilingual_str>& warnings)
88 {
89 if (!load_on_startup) return;
90 if (load_on_startup.value() && !AddWalletSetting(chain, wallet_name)) {
91 warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
92 } else if (!load_on_startup.value() && !RemoveWalletSetting(chain, wallet_name)) {
93 warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
94 }
95 }
96
AddWallet(const std::shared_ptr<CWallet> & wallet)97 bool AddWallet(const std::shared_ptr<CWallet>& wallet)
98 {
99 LOCK(cs_wallets);
100 assert(wallet);
101 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
102 if (i != vpwallets.end()) return false;
103 vpwallets.push_back(wallet);
104 wallet->ConnectScriptPubKeyManNotifiers();
105 wallet->NotifyCanGetAddressesChanged();
106 return true;
107 }
108
RemoveWallet(const std::shared_ptr<CWallet> & wallet,std::optional<bool> load_on_start,std::vector<bilingual_str> & warnings)109 bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
110 {
111 assert(wallet);
112
113 interfaces::Chain& chain = wallet->chain();
114 std::string name = wallet->GetName();
115
116 // Unregister with the validation interface which also drops shared ponters.
117 wallet->m_chain_notifications_handler.reset();
118 LOCK(cs_wallets);
119 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
120 if (i == vpwallets.end()) return false;
121 vpwallets.erase(i);
122
123 // Write the wallet setting
124 UpdateWalletSetting(chain, name, load_on_start, warnings);
125
126 return true;
127 }
128
RemoveWallet(const std::shared_ptr<CWallet> & wallet,std::optional<bool> load_on_start)129 bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start)
130 {
131 std::vector<bilingual_str> warnings;
132 return RemoveWallet(wallet, load_on_start, warnings);
133 }
134
GetWallets()135 std::vector<std::shared_ptr<CWallet>> GetWallets()
136 {
137 LOCK(cs_wallets);
138 return vpwallets;
139 }
140
GetWallet(const std::string & name)141 std::shared_ptr<CWallet> GetWallet(const std::string& name)
142 {
143 LOCK(cs_wallets);
144 for (const std::shared_ptr<CWallet>& wallet : vpwallets) {
145 if (wallet->GetName() == name) return wallet;
146 }
147 return nullptr;
148 }
149
HandleLoadWallet(LoadWalletFn load_wallet)150 std::unique_ptr<interfaces::Handler> HandleLoadWallet(LoadWalletFn load_wallet)
151 {
152 LOCK(cs_wallets);
153 auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(), std::move(load_wallet));
154 return interfaces::MakeHandler([it] { LOCK(cs_wallets); g_load_wallet_fns.erase(it); });
155 }
156
157 static Mutex g_loading_wallet_mutex;
158 static Mutex g_wallet_release_mutex;
159 static std::condition_variable g_wallet_release_cv;
160 static std::set<std::string> g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex);
161 static std::set<std::string> g_unloading_wallet_set GUARDED_BY(g_wallet_release_mutex);
162
163 // Custom deleter for shared_ptr<CWallet>.
ReleaseWallet(CWallet * wallet)164 static void ReleaseWallet(CWallet* wallet)
165 {
166 const std::string name = wallet->GetName();
167 wallet->WalletLogPrintf("Releasing wallet\n");
168 wallet->Flush();
169 delete wallet;
170 // Wallet is now released, notify UnloadWallet, if any.
171 {
172 LOCK(g_wallet_release_mutex);
173 if (g_unloading_wallet_set.erase(name) == 0) {
174 // UnloadWallet was not called for this wallet, all done.
175 return;
176 }
177 }
178 g_wallet_release_cv.notify_all();
179 }
180
UnloadWallet(std::shared_ptr<CWallet> && wallet)181 void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
182 {
183 // Mark wallet for unloading.
184 const std::string name = wallet->GetName();
185 {
186 LOCK(g_wallet_release_mutex);
187 auto it = g_unloading_wallet_set.insert(name);
188 assert(it.second);
189 }
190 // The wallet can be in use so it's not possible to explicitly unload here.
191 // Notify the unload intent so that all remaining shared pointers are
192 // released.
193 wallet->NotifyUnload();
194
195 // Time to ditch our shared_ptr and wait for ReleaseWallet call.
196 wallet.reset();
197 {
198 WAIT_LOCK(g_wallet_release_mutex, lock);
199 while (g_unloading_wallet_set.count(name) == 1) {
200 g_wallet_release_cv.wait(lock);
201 }
202 }
203 }
204
205 namespace {
LoadWalletInternal(interfaces::Chain & chain,const std::string & name,std::optional<bool> load_on_start,const DatabaseOptions & options,DatabaseStatus & status,bilingual_str & error,std::vector<bilingual_str> & warnings)206 std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
207 {
208 try {
209 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
210 if (!database) {
211 error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
212 return nullptr;
213 }
214
215 chain.initMessage(_("Loading wallet…").translated);
216 std::shared_ptr<CWallet> wallet = CWallet::Create(&chain, name, std::move(database), options.create_flags, error, warnings);
217 if (!wallet) {
218 error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error;
219 status = DatabaseStatus::FAILED_LOAD;
220 return nullptr;
221 }
222 AddWallet(wallet);
223 wallet->postInitProcess();
224
225 // Write the wallet setting
226 UpdateWalletSetting(chain, name, load_on_start, warnings);
227
228 return wallet;
229 } catch (const std::runtime_error& e) {
230 error = Untranslated(e.what());
231 status = DatabaseStatus::FAILED_LOAD;
232 return nullptr;
233 }
234 }
235 } // namespace
236
LoadWallet(interfaces::Chain & chain,const std::string & name,std::optional<bool> load_on_start,const DatabaseOptions & options,DatabaseStatus & status,bilingual_str & error,std::vector<bilingual_str> & warnings)237 std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
238 {
239 auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(name));
240 if (!result.second) {
241 error = Untranslated("Wallet already loading.");
242 status = DatabaseStatus::FAILED_LOAD;
243 return nullptr;
244 }
245 auto wallet = LoadWalletInternal(chain, name, load_on_start, options, status, error, warnings);
246 WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
247 return wallet;
248 }
249
CreateWallet(interfaces::Chain & chain,const std::string & name,std::optional<bool> load_on_start,DatabaseOptions & options,DatabaseStatus & status,bilingual_str & error,std::vector<bilingual_str> & warnings)250 std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
251 {
252 uint64_t wallet_creation_flags = options.create_flags;
253 const SecureString& passphrase = options.create_passphrase;
254
255 if (wallet_creation_flags & WALLET_FLAG_DESCRIPTORS) options.require_format = DatabaseFormat::SQLITE;
256
257 // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
258 bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
259
260 // Born encrypted wallets need to be created blank first.
261 if (!passphrase.empty()) {
262 wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
263 }
264
265 // Private keys must be disabled for an external signer wallet
266 if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
267 error = Untranslated("Private keys must be disabled when using an external signer");
268 status = DatabaseStatus::FAILED_CREATE;
269 return nullptr;
270 }
271
272 // Descriptor support must be enabled for an external signer wallet
273 if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DESCRIPTORS)) {
274 error = Untranslated("Descriptor support must be enabled when using an external signer");
275 status = DatabaseStatus::FAILED_CREATE;
276 return nullptr;
277 }
278
279 // Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
280 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
281 if (!database) {
282 error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
283 status = DatabaseStatus::FAILED_VERIFY;
284 return nullptr;
285 }
286
287 // Do not allow a passphrase when private keys are disabled
288 if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
289 error = Untranslated("Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
290 status = DatabaseStatus::FAILED_CREATE;
291 return nullptr;
292 }
293
294 // Make the wallet
295 chain.initMessage(_("Loading wallet…").translated);
296 std::shared_ptr<CWallet> wallet = CWallet::Create(&chain, name, std::move(database), wallet_creation_flags, error, warnings);
297 if (!wallet) {
298 error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error;
299 status = DatabaseStatus::FAILED_CREATE;
300 return nullptr;
301 }
302
303 // Encrypt the wallet
304 if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
305 if (!wallet->EncryptWallet(passphrase)) {
306 error = Untranslated("Error: Wallet created but failed to encrypt.");
307 status = DatabaseStatus::FAILED_ENCRYPT;
308 return nullptr;
309 }
310 if (!create_blank) {
311 // Unlock the wallet
312 if (!wallet->Unlock(passphrase)) {
313 error = Untranslated("Error: Wallet was encrypted but could not be unlocked");
314 status = DatabaseStatus::FAILED_ENCRYPT;
315 return nullptr;
316 }
317
318 // Set a seed for the wallet
319 {
320 LOCK(wallet->cs_wallet);
321 if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
322 wallet->SetupDescriptorScriptPubKeyMans();
323 } else {
324 for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
325 if (!spk_man->SetupGeneration()) {
326 error = Untranslated("Unable to generate initial keys");
327 status = DatabaseStatus::FAILED_CREATE;
328 return nullptr;
329 }
330 }
331 }
332 }
333
334 // Relock the wallet
335 wallet->Lock();
336 }
337 }
338 AddWallet(wallet);
339 wallet->postInitProcess();
340
341 // Write the wallet settings
342 UpdateWalletSetting(chain, name, load_on_start, warnings);
343
344 status = DatabaseStatus::SUCCESS;
345 return wallet;
346 }
347
348 /** @defgroup mapWallet
349 *
350 * @{
351 */
352
GetWalletTx(const uint256 & hash) const353 const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
354 {
355 AssertLockHeld(cs_wallet);
356 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
357 if (it == mapWallet.end())
358 return nullptr;
359 return &(it->second);
360 }
361
UpgradeKeyMetadata()362 void CWallet::UpgradeKeyMetadata()
363 {
364 if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
365 return;
366 }
367
368 auto spk_man = GetLegacyScriptPubKeyMan();
369 if (!spk_man) {
370 return;
371 }
372
373 spk_man->UpgradeKeyMetadata();
374 SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
375 }
376
UpgradeDescriptorCache()377 void CWallet::UpgradeDescriptorCache()
378 {
379 if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) || IsLocked() || IsWalletFlagSet(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED)) {
380 return;
381 }
382
383 for (ScriptPubKeyMan* spkm : GetAllScriptPubKeyMans()) {
384 DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
385 desc_spkm->UpgradeDescriptorCache();
386 }
387 SetWalletFlag(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED);
388 }
389
Unlock(const SecureString & strWalletPassphrase,bool accept_no_keys)390 bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys)
391 {
392 CCrypter crypter;
393 CKeyingMaterial _vMasterKey;
394
395 {
396 LOCK(cs_wallet);
397 for (const MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
398 {
399 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
400 return false;
401 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
402 continue; // try another master key
403 if (Unlock(_vMasterKey, accept_no_keys)) {
404 // Now that we've unlocked, upgrade the key metadata
405 UpgradeKeyMetadata();
406 // Now that we've unlocked, upgrade the descriptor cache
407 UpgradeDescriptorCache();
408 return true;
409 }
410 }
411 }
412 return false;
413 }
414
ChangeWalletPassphrase(const SecureString & strOldWalletPassphrase,const SecureString & strNewWalletPassphrase)415 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
416 {
417 bool fWasLocked = IsLocked();
418
419 {
420 LOCK(cs_wallet);
421 Lock();
422
423 CCrypter crypter;
424 CKeyingMaterial _vMasterKey;
425 for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
426 {
427 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
428 return false;
429 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
430 return false;
431 if (Unlock(_vMasterKey))
432 {
433 int64_t nStartTime = GetTimeMillis();
434 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
435 pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))));
436
437 nStartTime = GetTimeMillis();
438 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
439 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
440
441 if (pMasterKey.second.nDeriveIterations < 25000)
442 pMasterKey.second.nDeriveIterations = 25000;
443
444 WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
445
446 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
447 return false;
448 if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
449 return false;
450 WalletBatch(GetDatabase()).WriteMasterKey(pMasterKey.first, pMasterKey.second);
451 if (fWasLocked)
452 Lock();
453 return true;
454 }
455 }
456 }
457
458 return false;
459 }
460
chainStateFlushed(const CBlockLocator & loc)461 void CWallet::chainStateFlushed(const CBlockLocator& loc)
462 {
463 WalletBatch batch(GetDatabase());
464 batch.WriteBestBlock(loc);
465 }
466
SetMinVersion(enum WalletFeature nVersion,WalletBatch * batch_in)467 void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in)
468 {
469 LOCK(cs_wallet);
470 if (nWalletVersion >= nVersion)
471 return;
472 nWalletVersion = nVersion;
473
474 {
475 WalletBatch* batch = batch_in ? batch_in : new WalletBatch(GetDatabase());
476 if (nWalletVersion > 40000)
477 batch->WriteMinVersion(nWalletVersion);
478 if (!batch_in)
479 delete batch;
480 }
481 }
482
GetConflicts(const uint256 & txid) const483 std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
484 {
485 std::set<uint256> result;
486 AssertLockHeld(cs_wallet);
487
488 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
489 if (it == mapWallet.end())
490 return result;
491 const CWalletTx& wtx = it->second;
492
493 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
494
495 for (const CTxIn& txin : wtx.tx->vin)
496 {
497 if (mapTxSpends.count(txin.prevout) <= 1)
498 continue; // No conflict if zero or one spends
499 range = mapTxSpends.equal_range(txin.prevout);
500 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
501 result.insert(_it->second);
502 }
503 return result;
504 }
505
HasWalletSpend(const uint256 & txid) const506 bool CWallet::HasWalletSpend(const uint256& txid) const
507 {
508 AssertLockHeld(cs_wallet);
509 auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
510 return (iter != mapTxSpends.end() && iter->first.hash == txid);
511 }
512
Flush()513 void CWallet::Flush()
514 {
515 GetDatabase().Flush();
516 }
517
Close()518 void CWallet::Close()
519 {
520 GetDatabase().Close();
521 }
522
SyncMetaData(std::pair<TxSpends::iterator,TxSpends::iterator> range)523 void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> range)
524 {
525 // We want all the wallet transactions in range to have the same metadata as
526 // the oldest (smallest nOrderPos).
527 // So: find smallest nOrderPos:
528
529 int nMinOrderPos = std::numeric_limits<int>::max();
530 const CWalletTx* copyFrom = nullptr;
531 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
532 const CWalletTx* wtx = &mapWallet.at(it->second);
533 if (wtx->nOrderPos < nMinOrderPos) {
534 nMinOrderPos = wtx->nOrderPos;
535 copyFrom = wtx;
536 }
537 }
538
539 if (!copyFrom) {
540 return;
541 }
542
543 // Now copy data from copyFrom to rest:
544 for (TxSpends::iterator it = range.first; it != range.second; ++it)
545 {
546 const uint256& hash = it->second;
547 CWalletTx* copyTo = &mapWallet.at(hash);
548 if (copyFrom == copyTo) continue;
549 assert(copyFrom && "Oldest wallet transaction in range assumed to have been found.");
550 if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
551 copyTo->mapValue = copyFrom->mapValue;
552 copyTo->vOrderForm = copyFrom->vOrderForm;
553 // fTimeReceivedIsTxTime not copied on purpose
554 // nTimeReceived not copied on purpose
555 copyTo->nTimeSmart = copyFrom->nTimeSmart;
556 copyTo->fFromMe = copyFrom->fFromMe;
557 // nOrderPos not copied on purpose
558 // cached members not copied on purpose
559 }
560 }
561
562 /**
563 * Outpoint is spent if any non-conflicted transaction
564 * spends it:
565 */
IsSpent(const uint256 & hash,unsigned int n) const566 bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
567 {
568 const COutPoint outpoint(hash, n);
569 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
570 range = mapTxSpends.equal_range(outpoint);
571
572 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
573 {
574 const uint256& wtxid = it->second;
575 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
576 if (mit != mapWallet.end()) {
577 int depth = mit->second.GetDepthInMainChain();
578 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
579 return true; // Spent
580 }
581 }
582 return false;
583 }
584
AddToSpends(const COutPoint & outpoint,const uint256 & wtxid)585 void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
586 {
587 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
588
589 setLockedCoins.erase(outpoint);
590
591 std::pair<TxSpends::iterator, TxSpends::iterator> range;
592 range = mapTxSpends.equal_range(outpoint);
593 SyncMetaData(range);
594 }
595
596
AddToSpends(const uint256 & wtxid)597 void CWallet::AddToSpends(const uint256& wtxid)
598 {
599 auto it = mapWallet.find(wtxid);
600 assert(it != mapWallet.end());
601 const CWalletTx& thisTx = it->second;
602 if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
603 return;
604
605 for (const CTxIn& txin : thisTx.tx->vin)
606 AddToSpends(txin.prevout, wtxid);
607 }
608
EncryptWallet(const SecureString & strWalletPassphrase)609 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
610 {
611 if (IsCrypted())
612 return false;
613
614 CKeyingMaterial _vMasterKey;
615
616 _vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
617 GetStrongRandBytes(_vMasterKey.data(), WALLET_CRYPTO_KEY_SIZE);
618
619 CMasterKey kMasterKey;
620
621 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
622 GetStrongRandBytes(kMasterKey.vchSalt.data(), WALLET_CRYPTO_SALT_SIZE);
623
624 CCrypter crypter;
625 int64_t nStartTime = GetTimeMillis();
626 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
627 kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(GetTimeMillis() - nStartTime)));
628
629 nStartTime = GetTimeMillis();
630 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
631 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
632
633 if (kMasterKey.nDeriveIterations < 25000)
634 kMasterKey.nDeriveIterations = 25000;
635
636 WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
637
638 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
639 return false;
640 if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey))
641 return false;
642
643 {
644 LOCK(cs_wallet);
645 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
646 WalletBatch* encrypted_batch = new WalletBatch(GetDatabase());
647 if (!encrypted_batch->TxnBegin()) {
648 delete encrypted_batch;
649 encrypted_batch = nullptr;
650 return false;
651 }
652 encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
653
654 for (const auto& spk_man_pair : m_spk_managers) {
655 auto spk_man = spk_man_pair.second.get();
656 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
657 encrypted_batch->TxnAbort();
658 delete encrypted_batch;
659 encrypted_batch = nullptr;
660 // We now probably have half of our keys encrypted in memory, and half not...
661 // die and let the user reload the unencrypted wallet.
662 assert(false);
663 }
664 }
665
666 // Encryption was introduced in version 0.4.0
667 SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch);
668
669 if (!encrypted_batch->TxnCommit()) {
670 delete encrypted_batch;
671 encrypted_batch = nullptr;
672 // We now have keys encrypted in memory, but not on disk...
673 // die to avoid confusion and let the user reload the unencrypted wallet.
674 assert(false);
675 }
676
677 delete encrypted_batch;
678 encrypted_batch = nullptr;
679
680 Lock();
681 Unlock(strWalletPassphrase);
682
683 // If we are using descriptors, make new descriptors with a new seed
684 if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)) {
685 SetupDescriptorScriptPubKeyMans();
686 } else if (auto spk_man = GetLegacyScriptPubKeyMan()) {
687 // if we are using HD, replace the HD seed with a new one
688 if (spk_man->IsHDEnabled()) {
689 if (!spk_man->SetupGeneration(true)) {
690 return false;
691 }
692 }
693 }
694 Lock();
695
696 // Need to completely rewrite the wallet file; if we don't, bdb might keep
697 // bits of the unencrypted private key in slack space in the database file.
698 GetDatabase().Rewrite();
699
700 // BDB seems to have a bad habit of writing old data into
701 // slack space in .dat files; that is bad if the old data is
702 // unencrypted private keys. So:
703 GetDatabase().ReloadDbEnv();
704
705 }
706 NotifyStatusChanged(this);
707
708 return true;
709 }
710
ReorderTransactions()711 DBErrors CWallet::ReorderTransactions()
712 {
713 LOCK(cs_wallet);
714 WalletBatch batch(GetDatabase());
715
716 // Old wallets didn't have any defined order for transactions
717 // Probably a bad idea to change the output of this
718
719 // First: get all CWalletTx into a sorted-by-time multimap.
720 typedef std::multimap<int64_t, CWalletTx*> TxItems;
721 TxItems txByTime;
722
723 for (auto& entry : mapWallet)
724 {
725 CWalletTx* wtx = &entry.second;
726 txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
727 }
728
729 nOrderPosNext = 0;
730 std::vector<int64_t> nOrderPosOffsets;
731 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
732 {
733 CWalletTx *const pwtx = (*it).second;
734 int64_t& nOrderPos = pwtx->nOrderPos;
735
736 if (nOrderPos == -1)
737 {
738 nOrderPos = nOrderPosNext++;
739 nOrderPosOffsets.push_back(nOrderPos);
740
741 if (!batch.WriteTx(*pwtx))
742 return DBErrors::LOAD_FAIL;
743 }
744 else
745 {
746 int64_t nOrderPosOff = 0;
747 for (const int64_t& nOffsetStart : nOrderPosOffsets)
748 {
749 if (nOrderPos >= nOffsetStart)
750 ++nOrderPosOff;
751 }
752 nOrderPos += nOrderPosOff;
753 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
754
755 if (!nOrderPosOff)
756 continue;
757
758 // Since we're changing the order, write it back
759 if (!batch.WriteTx(*pwtx))
760 return DBErrors::LOAD_FAIL;
761 }
762 }
763 batch.WriteOrderPosNext(nOrderPosNext);
764
765 return DBErrors::LOAD_OK;
766 }
767
IncOrderPosNext(WalletBatch * batch)768 int64_t CWallet::IncOrderPosNext(WalletBatch* batch)
769 {
770 AssertLockHeld(cs_wallet);
771 int64_t nRet = nOrderPosNext++;
772 if (batch) {
773 batch->WriteOrderPosNext(nOrderPosNext);
774 } else {
775 WalletBatch(GetDatabase()).WriteOrderPosNext(nOrderPosNext);
776 }
777 return nRet;
778 }
779
MarkDirty()780 void CWallet::MarkDirty()
781 {
782 {
783 LOCK(cs_wallet);
784 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
785 item.second.MarkDirty();
786 }
787 }
788
MarkReplaced(const uint256 & originalHash,const uint256 & newHash)789 bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
790 {
791 LOCK(cs_wallet);
792
793 auto mi = mapWallet.find(originalHash);
794
795 // There is a bug if MarkReplaced is not called on an existing wallet transaction.
796 assert(mi != mapWallet.end());
797
798 CWalletTx& wtx = (*mi).second;
799
800 // Ensure for now that we're not overwriting data
801 assert(wtx.mapValue.count("replaced_by_txid") == 0);
802
803 wtx.mapValue["replaced_by_txid"] = newHash.ToString();
804
805 // Refresh mempool status without waiting for transactionRemovedFromMempool
806 // notification so the wallet is in an internally consistent state and
807 // immediately knows the old transaction should not be considered trusted
808 // and is eligible to be abandoned
809 wtx.fInMempool = chain().isInMempool(originalHash);
810
811 WalletBatch batch(GetDatabase());
812
813 bool success = true;
814 if (!batch.WriteTx(wtx)) {
815 WalletLogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
816 success = false;
817 }
818
819 NotifyTransactionChanged(originalHash, CT_UPDATED);
820
821 return success;
822 }
823
SetSpentKeyState(WalletBatch & batch,const uint256 & hash,unsigned int n,bool used,std::set<CTxDestination> & tx_destinations)824 void CWallet::SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations)
825 {
826 AssertLockHeld(cs_wallet);
827 const CWalletTx* srctx = GetWalletTx(hash);
828 if (!srctx) return;
829
830 CTxDestination dst;
831 if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
832 if (IsMine(dst)) {
833 if (used != IsAddressUsed(dst)) {
834 if (used) {
835 tx_destinations.insert(dst);
836 }
837 SetAddressUsed(batch, dst, used);
838 }
839 }
840 }
841 }
842
IsSpentKey(const uint256 & hash,unsigned int n) const843 bool CWallet::IsSpentKey(const uint256& hash, unsigned int n) const
844 {
845 AssertLockHeld(cs_wallet);
846 const CWalletTx* srctx = GetWalletTx(hash);
847 if (srctx) {
848 assert(srctx->tx->vout.size() > n);
849 CTxDestination dest;
850 if (!ExtractDestination(srctx->tx->vout[n].scriptPubKey, dest)) {
851 return false;
852 }
853 if (IsAddressUsed(dest)) {
854 return true;
855 }
856 if (IsLegacy()) {
857 LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
858 assert(spk_man != nullptr);
859 for (const auto& keyid : GetAffectedKeys(srctx->tx->vout[n].scriptPubKey, *spk_man)) {
860 WitnessV0KeyHash wpkh_dest(keyid);
861 if (IsAddressUsed(wpkh_dest)) {
862 return true;
863 }
864 ScriptHash sh_wpkh_dest(GetScriptForDestination(wpkh_dest));
865 if (IsAddressUsed(sh_wpkh_dest)) {
866 return true;
867 }
868 PKHash pkh_dest(keyid);
869 if (IsAddressUsed(pkh_dest)) {
870 return true;
871 }
872 }
873 }
874 }
875 return false;
876 }
877
AddToWallet(CTransactionRef tx,const CWalletTx::Confirmation & confirm,const UpdateWalletTxFn & update_wtx,bool fFlushOnClose)878 CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx, bool fFlushOnClose)
879 {
880 LOCK(cs_wallet);
881
882 WalletBatch batch(GetDatabase(), fFlushOnClose);
883
884 uint256 hash = tx->GetHash();
885
886 if (IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
887 // Mark used destinations
888 std::set<CTxDestination> tx_destinations;
889
890 for (const CTxIn& txin : tx->vin) {
891 const COutPoint& op = txin.prevout;
892 SetSpentKeyState(batch, op.hash, op.n, true, tx_destinations);
893 }
894
895 MarkDestinationsDirty(tx_destinations);
896 }
897
898 // Inserts only if not already there, returns tx inserted or tx found
899 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(this, tx));
900 CWalletTx& wtx = (*ret.first).second;
901 bool fInsertedNew = ret.second;
902 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
903 if (fInsertedNew) {
904 wtx.m_confirm = confirm;
905 wtx.nTimeReceived = chain().getAdjustedTime();
906 wtx.nOrderPos = IncOrderPosNext(&batch);
907 wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
908 wtx.nTimeSmart = ComputeTimeSmart(wtx);
909 AddToSpends(hash);
910 }
911
912 if (!fInsertedNew)
913 {
914 if (confirm.status != wtx.m_confirm.status) {
915 wtx.m_confirm.status = confirm.status;
916 wtx.m_confirm.nIndex = confirm.nIndex;
917 wtx.m_confirm.hashBlock = confirm.hashBlock;
918 wtx.m_confirm.block_height = confirm.block_height;
919 fUpdated = true;
920 } else {
921 assert(wtx.m_confirm.nIndex == confirm.nIndex);
922 assert(wtx.m_confirm.hashBlock == confirm.hashBlock);
923 assert(wtx.m_confirm.block_height == confirm.block_height);
924 }
925 // If we have a witness-stripped version of this transaction, and we
926 // see a new version with a witness, then we must be upgrading a pre-segwit
927 // wallet. Store the new version of the transaction with the witness,
928 // as the stripped-version must be invalid.
929 // TODO: Store all versions of the transaction, instead of just one.
930 if (tx->HasWitness() && !wtx.tx->HasWitness()) {
931 wtx.SetTx(tx);
932 fUpdated = true;
933 }
934 }
935
936 //// debug print
937 WalletLogPrintf("AddToWallet %s %s%s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
938
939 // Write to disk
940 if (fInsertedNew || fUpdated)
941 if (!batch.WriteTx(wtx))
942 return nullptr;
943
944 // Break debit/credit balance caches:
945 wtx.MarkDirty();
946
947 // Notify UI of new or updated transaction
948 NotifyTransactionChanged(hash, fInsertedNew ? CT_NEW : CT_UPDATED);
949
950 #if HAVE_SYSTEM
951 // notify an external script when a wallet transaction comes in or is updated
952 std::string strCmd = gArgs.GetArg("-walletnotify", "");
953
954 if (!strCmd.empty())
955 {
956 boost::replace_all(strCmd, "%s", hash.GetHex());
957 if (confirm.status == CWalletTx::Status::CONFIRMED)
958 {
959 boost::replace_all(strCmd, "%b", confirm.hashBlock.GetHex());
960 boost::replace_all(strCmd, "%h", ToString(confirm.block_height));
961 } else {
962 boost::replace_all(strCmd, "%b", "unconfirmed");
963 boost::replace_all(strCmd, "%h", "-1");
964 }
965 #ifndef WIN32
966 // Substituting the wallet name isn't currently supported on windows
967 // because windows shell escaping has not been implemented yet:
968 // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-537384875
969 // A few ways it could be implemented in the future are described in:
970 // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-461288094
971 boost::replace_all(strCmd, "%w", ShellEscape(GetName()));
972 #endif
973 std::thread t(runCommand, strCmd);
974 t.detach(); // thread runs free
975 }
976 #endif
977
978 return &wtx;
979 }
980
LoadToWallet(const uint256 & hash,const UpdateWalletTxFn & fill_wtx)981 bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx)
982 {
983 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(this, nullptr));
984 CWalletTx& wtx = ins.first->second;
985 if (!fill_wtx(wtx, ins.second)) {
986 return false;
987 }
988 // If wallet doesn't have a chain (e.g wallet-tool), don't bother to update txn.
989 if (HaveChain()) {
990 bool active;
991 int height;
992 if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) {
993 // Update cached block height variable since it not stored in the
994 // serialized transaction.
995 wtx.m_confirm.block_height = height;
996 } else if (wtx.isConflicted() || wtx.isConfirmed()) {
997 // If tx block (or conflicting block) was reorged out of chain
998 // while the wallet was shutdown, change tx status to UNCONFIRMED
999 // and reset block height, hash, and index. ABANDONED tx don't have
1000 // associated blocks and don't need to be updated. The case where a
1001 // transaction was reorged out while online and then reconfirmed
1002 // while offline is covered by the rescan logic.
1003 wtx.setUnconfirmed();
1004 wtx.m_confirm.hashBlock = uint256();
1005 wtx.m_confirm.block_height = 0;
1006 wtx.m_confirm.nIndex = 0;
1007 }
1008 }
1009 if (/* insertion took place */ ins.second) {
1010 wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1011 }
1012 AddToSpends(hash);
1013 for (const CTxIn& txin : wtx.tx->vin) {
1014 auto it = mapWallet.find(txin.prevout.hash);
1015 if (it != mapWallet.end()) {
1016 CWalletTx& prevtx = it->second;
1017 if (prevtx.isConflicted()) {
1018 MarkConflicted(prevtx.m_confirm.hashBlock, prevtx.m_confirm.block_height, wtx.GetHash());
1019 }
1020 }
1021 }
1022 return true;
1023 }
1024
AddToWalletIfInvolvingMe(const CTransactionRef & ptx,CWalletTx::Confirmation confirm,bool fUpdate)1025 bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool fUpdate)
1026 {
1027 const CTransaction& tx = *ptx;
1028 {
1029 AssertLockHeld(cs_wallet);
1030
1031 if (!confirm.hashBlock.IsNull()) {
1032 for (const CTxIn& txin : tx.vin) {
1033 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
1034 while (range.first != range.second) {
1035 if (range.first->second != tx.GetHash()) {
1036 WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), confirm.hashBlock.ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
1037 MarkConflicted(confirm.hashBlock, confirm.block_height, range.first->second);
1038 }
1039 range.first++;
1040 }
1041 }
1042 }
1043
1044 bool fExisted = mapWallet.count(tx.GetHash()) != 0;
1045 if (fExisted && !fUpdate) return false;
1046 if (fExisted || IsMine(tx) || IsFromMe(tx))
1047 {
1048 /* Check if any keys in the wallet keypool that were supposed to be unused
1049 * have appeared in a new transaction. If so, remove those keys from the keypool.
1050 * This can happen when restoring an old wallet backup that does not contain
1051 * the mostly recently created transactions from newer versions of the wallet.
1052 */
1053
1054 // loop though all outputs
1055 for (const CTxOut& txout: tx.vout) {
1056 for (const auto& spk_man_pair : m_spk_managers) {
1057 spk_man_pair.second->MarkUnusedAddresses(txout.scriptPubKey);
1058 }
1059 }
1060
1061 // Block disconnection override an abandoned tx as unconfirmed
1062 // which means user may have to call abandontransaction again
1063 return AddToWallet(MakeTransactionRef(tx), confirm, /* update_wtx= */ nullptr, /* fFlushOnClose= */ false);
1064 }
1065 }
1066 return false;
1067 }
1068
TransactionCanBeAbandoned(const uint256 & hashTx) const1069 bool CWallet::TransactionCanBeAbandoned(const uint256& hashTx) const
1070 {
1071 LOCK(cs_wallet);
1072 const CWalletTx* wtx = GetWalletTx(hashTx);
1073 return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain() == 0 && !wtx->InMempool();
1074 }
1075
MarkInputsDirty(const CTransactionRef & tx)1076 void CWallet::MarkInputsDirty(const CTransactionRef& tx)
1077 {
1078 for (const CTxIn& txin : tx->vin) {
1079 auto it = mapWallet.find(txin.prevout.hash);
1080 if (it != mapWallet.end()) {
1081 it->second.MarkDirty();
1082 }
1083 }
1084 }
1085
AbandonTransaction(const uint256 & hashTx)1086 bool CWallet::AbandonTransaction(const uint256& hashTx)
1087 {
1088 LOCK(cs_wallet);
1089
1090 WalletBatch batch(GetDatabase());
1091
1092 std::set<uint256> todo;
1093 std::set<uint256> done;
1094
1095 // Can't mark abandoned if confirmed or in mempool
1096 auto it = mapWallet.find(hashTx);
1097 assert(it != mapWallet.end());
1098 const CWalletTx& origtx = it->second;
1099 if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
1100 return false;
1101 }
1102
1103 todo.insert(hashTx);
1104
1105 while (!todo.empty()) {
1106 uint256 now = *todo.begin();
1107 todo.erase(now);
1108 done.insert(now);
1109 auto it = mapWallet.find(now);
1110 assert(it != mapWallet.end());
1111 CWalletTx& wtx = it->second;
1112 int currentconfirm = wtx.GetDepthInMainChain();
1113 // If the orig tx was not in block, none of its spends can be
1114 assert(currentconfirm <= 0);
1115 // if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon}
1116 if (currentconfirm == 0 && !wtx.isAbandoned()) {
1117 // If the orig tx was not in block/mempool, none of its spends can be in mempool
1118 assert(!wtx.InMempool());
1119 wtx.setAbandoned();
1120 wtx.MarkDirty();
1121 batch.WriteTx(wtx);
1122 NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
1123 // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
1124 TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
1125 while (iter != mapTxSpends.end() && iter->first.hash == now) {
1126 if (!done.count(iter->second)) {
1127 todo.insert(iter->second);
1128 }
1129 iter++;
1130 }
1131 // If a transaction changes 'conflicted' state, that changes the balance
1132 // available of the outputs it spends. So force those to be recomputed
1133 MarkInputsDirty(wtx.tx);
1134 }
1135 }
1136
1137 return true;
1138 }
1139
MarkConflicted(const uint256 & hashBlock,int conflicting_height,const uint256 & hashTx)1140 void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
1141 {
1142 LOCK(cs_wallet);
1143
1144 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1145 // If number of conflict confirms cannot be determined, this means
1146 // that the block is still unknown or not yet part of the main chain,
1147 // for example when loading the wallet during a reindex. Do nothing in that
1148 // case.
1149 if (conflictconfirms >= 0)
1150 return;
1151
1152 // Do not flush the wallet here for performance reasons
1153 WalletBatch batch(GetDatabase(), false);
1154
1155 std::set<uint256> todo;
1156 std::set<uint256> done;
1157
1158 todo.insert(hashTx);
1159
1160 while (!todo.empty()) {
1161 uint256 now = *todo.begin();
1162 todo.erase(now);
1163 done.insert(now);
1164 auto it = mapWallet.find(now);
1165 assert(it != mapWallet.end());
1166 CWalletTx& wtx = it->second;
1167 int currentconfirm = wtx.GetDepthInMainChain();
1168 if (conflictconfirms < currentconfirm) {
1169 // Block is 'more conflicted' than current confirm; update.
1170 // Mark transaction as conflicted with this block.
1171 wtx.m_confirm.nIndex = 0;
1172 wtx.m_confirm.hashBlock = hashBlock;
1173 wtx.m_confirm.block_height = conflicting_height;
1174 wtx.setConflicted();
1175 wtx.MarkDirty();
1176 batch.WriteTx(wtx);
1177 // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
1178 TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
1179 while (iter != mapTxSpends.end() && iter->first.hash == now) {
1180 if (!done.count(iter->second)) {
1181 todo.insert(iter->second);
1182 }
1183 iter++;
1184 }
1185 // If a transaction changes 'conflicted' state, that changes the balance
1186 // available of the outputs it spends. So force those to be recomputed
1187 MarkInputsDirty(wtx.tx);
1188 }
1189 }
1190 }
1191
SyncTransaction(const CTransactionRef & ptx,CWalletTx::Confirmation confirm,bool update_tx)1192 void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool update_tx)
1193 {
1194 if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx))
1195 return; // Not one of ours
1196
1197 // If a transaction changes 'conflicted' state, that changes the balance
1198 // available of the outputs it spends. So force those to be
1199 // recomputed, also:
1200 MarkInputsDirty(ptx);
1201 }
1202
transactionAddedToMempool(const CTransactionRef & tx,uint64_t mempool_sequence)1203 void CWallet::transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) {
1204 LOCK(cs_wallet);
1205 SyncTransaction(tx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, /* index */ 0});
1206
1207 auto it = mapWallet.find(tx->GetHash());
1208 if (it != mapWallet.end()) {
1209 it->second.fInMempool = true;
1210 }
1211 }
1212
transactionRemovedFromMempool(const CTransactionRef & tx,MemPoolRemovalReason reason,uint64_t mempool_sequence)1213 void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {
1214 LOCK(cs_wallet);
1215 auto it = mapWallet.find(tx->GetHash());
1216 if (it != mapWallet.end()) {
1217 it->second.fInMempool = false;
1218 }
1219 // Handle transactions that were removed from the mempool because they
1220 // conflict with transactions in a newly connected block.
1221 if (reason == MemPoolRemovalReason::CONFLICT) {
1222 // Trigger external -walletnotify notifications for these transactions.
1223 // Set Status::UNCONFIRMED instead of Status::CONFLICTED for a few reasons:
1224 //
1225 // 1. The transactionRemovedFromMempool callback does not currently
1226 // provide the conflicting block's hash and height, and for backwards
1227 // compatibility reasons it may not be not safe to store conflicted
1228 // wallet transactions with a null block hash. See
1229 // https://github.com/bitcoin/bitcoin/pull/18600#discussion_r420195993.
1230 // 2. For most of these transactions, the wallet's internal conflict
1231 // detection in the blockConnected handler will subsequently call
1232 // MarkConflicted and update them with CONFLICTED status anyway. This
1233 // applies to any wallet transaction that has inputs spent in the
1234 // block, or that has ancestors in the wallet with inputs spent by
1235 // the block.
1236 // 3. Longstanding behavior since the sync implementation in
1237 // https://github.com/bitcoin/bitcoin/pull/9371 and the prior sync
1238 // implementation before that was to mark these transactions
1239 // unconfirmed rather than conflicted.
1240 //
1241 // Nothing described above should be seen as an unchangeable requirement
1242 // when improving this code in the future. The wallet's heuristics for
1243 // distinguishing between conflicted and unconfirmed transactions are
1244 // imperfect, and could be improved in general, see
1245 // https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
1246 SyncTransaction(tx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, /* index */ 0});
1247 }
1248 }
1249
blockConnected(const CBlock & block,int height)1250 void CWallet::blockConnected(const CBlock& block, int height)
1251 {
1252 const uint256& block_hash = block.GetHash();
1253 LOCK(cs_wallet);
1254
1255 m_last_block_processed_height = height;
1256 m_last_block_processed = block_hash;
1257 for (size_t index = 0; index < block.vtx.size(); index++) {
1258 SyncTransaction(block.vtx[index], {CWalletTx::Status::CONFIRMED, height, block_hash, (int)index});
1259 transactionRemovedFromMempool(block.vtx[index], MemPoolRemovalReason::BLOCK, 0 /* mempool_sequence */);
1260 }
1261 }
1262
blockDisconnected(const CBlock & block,int height)1263 void CWallet::blockDisconnected(const CBlock& block, int height)
1264 {
1265 LOCK(cs_wallet);
1266
1267 // At block disconnection, this will change an abandoned transaction to
1268 // be unconfirmed, whether or not the transaction is added back to the mempool.
1269 // User may have to call abandontransaction again. It may be addressed in the
1270 // future with a stickier abandoned state or even removing abandontransaction call.
1271 m_last_block_processed_height = height - 1;
1272 m_last_block_processed = block.hashPrevBlock;
1273 for (const CTransactionRef& ptx : block.vtx) {
1274 SyncTransaction(ptx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, /* index */ 0});
1275 }
1276 }
1277
updatedBlockTip()1278 void CWallet::updatedBlockTip()
1279 {
1280 m_best_block_time = GetTime();
1281 }
1282
1283
BlockUntilSyncedToCurrentChain() const1284 void CWallet::BlockUntilSyncedToCurrentChain() const {
1285 AssertLockNotHeld(cs_wallet);
1286 // Skip the queue-draining stuff if we know we're caught up with
1287 // ::ChainActive().Tip(), otherwise put a callback in the validation interface queue and wait
1288 // for the queue to drain enough to execute it (indicating we are caught up
1289 // at least with the time we entered this function).
1290 uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed);
1291 chain().waitForNotificationsIfTipChanged(last_block_hash);
1292 }
1293
1294 // Note that this function doesn't distinguish between a 0-valued input,
1295 // and a not-"is mine" (according to the filter) input.
GetDebit(const CTxIn & txin,const isminefilter & filter) const1296 CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
1297 {
1298 {
1299 LOCK(cs_wallet);
1300 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
1301 if (mi != mapWallet.end())
1302 {
1303 const CWalletTx& prev = (*mi).second;
1304 if (txin.prevout.n < prev.tx->vout.size())
1305 if (IsMine(prev.tx->vout[txin.prevout.n]) & filter)
1306 return prev.tx->vout[txin.prevout.n].nValue;
1307 }
1308 }
1309 return 0;
1310 }
1311
IsMine(const CTxOut & txout) const1312 isminetype CWallet::IsMine(const CTxOut& txout) const
1313 {
1314 AssertLockHeld(cs_wallet);
1315 return IsMine(txout.scriptPubKey);
1316 }
1317
IsMine(const CTxDestination & dest) const1318 isminetype CWallet::IsMine(const CTxDestination& dest) const
1319 {
1320 AssertLockHeld(cs_wallet);
1321 return IsMine(GetScriptForDestination(dest));
1322 }
1323
IsMine(const CScript & script) const1324 isminetype CWallet::IsMine(const CScript& script) const
1325 {
1326 AssertLockHeld(cs_wallet);
1327 isminetype result = ISMINE_NO;
1328 for (const auto& spk_man_pair : m_spk_managers) {
1329 result = std::max(result, spk_man_pair.second->IsMine(script));
1330 }
1331 return result;
1332 }
1333
IsMine(const CTransaction & tx) const1334 bool CWallet::IsMine(const CTransaction& tx) const
1335 {
1336 AssertLockHeld(cs_wallet);
1337 for (const CTxOut& txout : tx.vout)
1338 if (IsMine(txout))
1339 return true;
1340 return false;
1341 }
1342
IsFromMe(const CTransaction & tx) const1343 bool CWallet::IsFromMe(const CTransaction& tx) const
1344 {
1345 return (GetDebit(tx, ISMINE_ALL) > 0);
1346 }
1347
GetDebit(const CTransaction & tx,const isminefilter & filter) const1348 CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
1349 {
1350 CAmount nDebit = 0;
1351 for (const CTxIn& txin : tx.vin)
1352 {
1353 nDebit += GetDebit(txin, filter);
1354 if (!MoneyRange(nDebit))
1355 throw std::runtime_error(std::string(__func__) + ": value out of range");
1356 }
1357 return nDebit;
1358 }
1359
IsHDEnabled() const1360 bool CWallet::IsHDEnabled() const
1361 {
1362 // All Active ScriptPubKeyMans must be HD for this to be true
1363 bool result = true;
1364 for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
1365 result &= spk_man->IsHDEnabled();
1366 }
1367 return result;
1368 }
1369
CanGetAddresses(bool internal) const1370 bool CWallet::CanGetAddresses(bool internal) const
1371 {
1372 LOCK(cs_wallet);
1373 if (m_spk_managers.empty()) return false;
1374 for (OutputType t : OUTPUT_TYPES) {
1375 auto spk_man = GetScriptPubKeyMan(t, internal);
1376 if (spk_man && spk_man->CanGetAddresses(internal)) {
1377 return true;
1378 }
1379 }
1380 return false;
1381 }
1382
SetWalletFlag(uint64_t flags)1383 void CWallet::SetWalletFlag(uint64_t flags)
1384 {
1385 LOCK(cs_wallet);
1386 m_wallet_flags |= flags;
1387 if (!WalletBatch(GetDatabase()).WriteWalletFlags(m_wallet_flags))
1388 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1389 }
1390
UnsetWalletFlag(uint64_t flag)1391 void CWallet::UnsetWalletFlag(uint64_t flag)
1392 {
1393 WalletBatch batch(GetDatabase());
1394 UnsetWalletFlagWithDB(batch, flag);
1395 }
1396
UnsetWalletFlagWithDB(WalletBatch & batch,uint64_t flag)1397 void CWallet::UnsetWalletFlagWithDB(WalletBatch& batch, uint64_t flag)
1398 {
1399 LOCK(cs_wallet);
1400 m_wallet_flags &= ~flag;
1401 if (!batch.WriteWalletFlags(m_wallet_flags))
1402 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1403 }
1404
UnsetBlankWalletFlag(WalletBatch & batch)1405 void CWallet::UnsetBlankWalletFlag(WalletBatch& batch)
1406 {
1407 UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
1408 }
1409
IsWalletFlagSet(uint64_t flag) const1410 bool CWallet::IsWalletFlagSet(uint64_t flag) const
1411 {
1412 return (m_wallet_flags & flag);
1413 }
1414
LoadWalletFlags(uint64_t flags)1415 bool CWallet::LoadWalletFlags(uint64_t flags)
1416 {
1417 LOCK(cs_wallet);
1418 if (((flags & KNOWN_WALLET_FLAGS) >> 32) ^ (flags >> 32)) {
1419 // contains unknown non-tolerable wallet flags
1420 return false;
1421 }
1422 m_wallet_flags = flags;
1423
1424 return true;
1425 }
1426
AddWalletFlags(uint64_t flags)1427 bool CWallet::AddWalletFlags(uint64_t flags)
1428 {
1429 LOCK(cs_wallet);
1430 // We should never be writing unknown non-tolerable wallet flags
1431 assert(((flags & KNOWN_WALLET_FLAGS) >> 32) == (flags >> 32));
1432 if (!WalletBatch(GetDatabase()).WriteWalletFlags(flags)) {
1433 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1434 }
1435
1436 return LoadWalletFlags(flags);
1437 }
1438
1439 // Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
1440 // or a max-sized low-S signature (e.g. 72 bytes) if use_max_sig is true
DummySignInput(CTxIn & tx_in,const CTxOut & txout,bool use_max_sig) const1441 bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig) const
1442 {
1443 // Fill in dummy signatures for fee calculation.
1444 const CScript& scriptPubKey = txout.scriptPubKey;
1445 SignatureData sigdata;
1446
1447 std::unique_ptr<SigningProvider> provider = GetSolvingProvider(scriptPubKey);
1448 if (!provider) {
1449 // We don't know about this scriptpbuKey;
1450 return false;
1451 }
1452
1453 if (!ProduceSignature(*provider, use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) {
1454 return false;
1455 }
1456 UpdateInput(tx_in, sigdata);
1457 return true;
1458 }
1459
1460 // Helper for producing a bunch of max-sized low-S low-R signatures (eg 71 bytes)
DummySignTx(CMutableTransaction & txNew,const std::vector<CTxOut> & txouts,bool use_max_sig) const1461 bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig) const
1462 {
1463 // Fill in dummy signatures for fee calculation.
1464 int nIn = 0;
1465 for (const auto& txout : txouts)
1466 {
1467 if (!DummySignInput(txNew.vin[nIn], txout, use_max_sig)) {
1468 return false;
1469 }
1470
1471 nIn++;
1472 }
1473 return true;
1474 }
1475
ImportScripts(const std::set<CScript> scripts,int64_t timestamp)1476 bool CWallet::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
1477 {
1478 auto spk_man = GetLegacyScriptPubKeyMan();
1479 if (!spk_man) {
1480 return false;
1481 }
1482 LOCK(spk_man->cs_KeyStore);
1483 return spk_man->ImportScripts(scripts, timestamp);
1484 }
1485
ImportPrivKeys(const std::map<CKeyID,CKey> & privkey_map,const int64_t timestamp)1486 bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp)
1487 {
1488 auto spk_man = GetLegacyScriptPubKeyMan();
1489 if (!spk_man) {
1490 return false;
1491 }
1492 LOCK(spk_man->cs_KeyStore);
1493 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1494 }
1495
ImportPubKeys(const std::vector<CKeyID> & ordered_pubkeys,const std::map<CKeyID,CPubKey> & pubkey_map,const std::map<CKeyID,std::pair<CPubKey,KeyOriginInfo>> & key_origins,const bool add_keypool,const bool internal,const int64_t timestamp)1496 bool CWallet::ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, const int64_t timestamp)
1497 {
1498 auto spk_man = GetLegacyScriptPubKeyMan();
1499 if (!spk_man) {
1500 return false;
1501 }
1502 LOCK(spk_man->cs_KeyStore);
1503 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, internal, timestamp);
1504 }
1505
ImportScriptPubKeys(const std::string & label,const std::set<CScript> & script_pub_keys,const bool have_solving_data,const bool apply_label,const int64_t timestamp)1506 bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp)
1507 {
1508 auto spk_man = GetLegacyScriptPubKeyMan();
1509 if (!spk_man) {
1510 return false;
1511 }
1512 LOCK(spk_man->cs_KeyStore);
1513 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1514 return false;
1515 }
1516 if (apply_label) {
1517 WalletBatch batch(GetDatabase());
1518 for (const CScript& script : script_pub_keys) {
1519 CTxDestination dest;
1520 ExtractDestination(script, dest);
1521 if (IsValidDestination(dest)) {
1522 SetAddressBookWithDB(batch, dest, label, "receive");
1523 }
1524 }
1525 }
1526 return true;
1527 }
1528
1529 /**
1530 * Scan active chain for relevant transactions after importing keys. This should
1531 * be called whenever new keys are added to the wallet, with the oldest key
1532 * creation time.
1533 *
1534 * @return Earliest timestamp that could be successfully scanned from. Timestamp
1535 * returned will be higher than startTime if relevant blocks could not be read.
1536 */
RescanFromTime(int64_t startTime,const WalletRescanReserver & reserver,bool update)1537 int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
1538 {
1539 // Find starting block. May be null if nCreateTime is greater than the
1540 // highest blockchain timestamp, in which case there is nothing that needs
1541 // to be scanned.
1542 int start_height = 0;
1543 uint256 start_block;
1544 bool start = chain().findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, FoundBlock().hash(start_block).height(start_height));
1545 WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) - start_height + 1 : 0);
1546
1547 if (start) {
1548 // TODO: this should take into account failure by ScanResult::USER_ABORT
1549 ScanResult result = ScanForWalletTransactions(start_block, start_height, {} /* max_height */, reserver, update);
1550 if (result.status == ScanResult::FAILURE) {
1551 int64_t time_max;
1552 CHECK_NONFATAL(chain().findBlock(result.last_failed_block, FoundBlock().maxTime(time_max)));
1553 return time_max + TIMESTAMP_WINDOW + 1;
1554 }
1555 }
1556 return startTime;
1557 }
1558
1559 /**
1560 * Scan the block chain (starting in start_block) for transactions
1561 * from or to us. If fUpdate is true, found transactions that already
1562 * exist in the wallet will be updated.
1563 *
1564 * @param[in] start_block Scan starting block. If block is not on the active
1565 * chain, the scan will return SUCCESS immediately.
1566 * @param[in] start_height Height of start_block
1567 * @param[in] max_height Optional max scanning height. If unset there is
1568 * no maximum and scanning can continue to the tip
1569 *
1570 * @return ScanResult returning scan information and indicating success or
1571 * failure. Return status will be set to SUCCESS if scan was
1572 * successful. FAILURE if a complete rescan was not possible (due to
1573 * pruning or corruption). USER_ABORT if the rescan was aborted before
1574 * it could complete.
1575 *
1576 * @pre Caller needs to make sure start_block (and the optional stop_block) are on
1577 * the main chain after to the addition of any new keys you want to detect
1578 * transactions for.
1579 */
ScanForWalletTransactions(const uint256 & start_block,int start_height,std::optional<int> max_height,const WalletRescanReserver & reserver,bool fUpdate)1580 CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate)
1581 {
1582 int64_t nNow = GetTime();
1583 int64_t start_time = GetTimeMillis();
1584
1585 assert(reserver.isReserved());
1586
1587 uint256 block_hash = start_block;
1588 ScanResult result;
1589
1590 WalletLogPrintf("Rescan started from block %s...\n", start_block.ToString());
1591
1592 fAbortRescan = false;
1593 ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
1594 uint256 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1595 uint256 end_hash = tip_hash;
1596 if (max_height) chain().findAncestorByHeight(tip_hash, *max_height, FoundBlock().hash(end_hash));
1597 double progress_begin = chain().guessVerificationProgress(block_hash);
1598 double progress_end = chain().guessVerificationProgress(end_hash);
1599 double progress_current = progress_begin;
1600 int block_height = start_height;
1601 while (!fAbortRescan && !chain().shutdownRequested()) {
1602 if (progress_end - progress_begin > 0.0) {
1603 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1604 } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal)
1605 m_scanning_progress = 0;
1606 }
1607 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1608 ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
1609 }
1610 if (GetTime() >= nNow + 60) {
1611 nNow = GetTime();
1612 WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1613 }
1614
1615 // Read block data
1616 CBlock block;
1617 chain().findBlock(block_hash, FoundBlock().data(block));
1618
1619 // Find next block separately from reading data above, because reading
1620 // is slow and there might be a reorg while it is read.
1621 bool block_still_active = false;
1622 bool next_block = false;
1623 uint256 next_block_hash;
1624 chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
1625
1626 if (!block.IsNull()) {
1627 LOCK(cs_wallet);
1628 if (!block_still_active) {
1629 // Abort scan if current block is no longer active, to prevent
1630 // marking transactions as coming from the wrong block.
1631 result.last_failed_block = block_hash;
1632 result.status = ScanResult::FAILURE;
1633 break;
1634 }
1635 for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
1636 SyncTransaction(block.vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate);
1637 }
1638 // scan succeeded, record block as most recent successfully scanned
1639 result.last_scanned_block = block_hash;
1640 result.last_scanned_height = block_height;
1641 } else {
1642 // could not scan block, keep scanning but record this block as the most recent failure
1643 result.last_failed_block = block_hash;
1644 result.status = ScanResult::FAILURE;
1645 }
1646 if (max_height && block_height >= *max_height) {
1647 break;
1648 }
1649 {
1650 if (!next_block) {
1651 // break successfully when rescan has reached the tip, or
1652 // previous block is no longer on the chain due to a reorg
1653 break;
1654 }
1655
1656 // increment block and verification progress
1657 block_hash = next_block_hash;
1658 ++block_height;
1659 progress_current = chain().guessVerificationProgress(block_hash);
1660
1661 // handle updated tip hash
1662 const uint256 prev_tip_hash = tip_hash;
1663 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1664 if (!max_height && prev_tip_hash != tip_hash) {
1665 // in case the tip has changed, update progress max
1666 progress_end = chain().guessVerificationProgress(tip_hash);
1667 }
1668 }
1669 }
1670 ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), 100); // hide progress dialog in GUI
1671 if (block_height && fAbortRescan) {
1672 WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1673 result.status = ScanResult::USER_ABORT;
1674 } else if (block_height && chain().shutdownRequested()) {
1675 WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1676 result.status = ScanResult::USER_ABORT;
1677 } else {
1678 WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - start_time);
1679 }
1680 return result;
1681 }
1682
ReacceptWalletTransactions()1683 void CWallet::ReacceptWalletTransactions()
1684 {
1685 // If transactions aren't being broadcasted, don't let them into local mempool either
1686 if (!fBroadcastTransactions)
1687 return;
1688 std::map<int64_t, CWalletTx*> mapSorted;
1689
1690 // Sort pending wallet transactions based on their initial wallet insertion order
1691 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1692 const uint256& wtxid = item.first;
1693 CWalletTx& wtx = item.second;
1694 assert(wtx.GetHash() == wtxid);
1695
1696 int nDepth = wtx.GetDepthInMainChain();
1697
1698 if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) {
1699 mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
1700 }
1701 }
1702
1703 // Try to add wallet transactions to memory pool
1704 for (const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
1705 CWalletTx& wtx = *(item.second);
1706 std::string unused_err_string;
1707 wtx.SubmitMemoryPoolAndRelay(unused_err_string, false);
1708 }
1709 }
1710
SubmitMemoryPoolAndRelay(std::string & err_string,bool relay)1711 bool CWalletTx::SubmitMemoryPoolAndRelay(std::string& err_string, bool relay)
1712 {
1713 // Can't relay if wallet is not broadcasting
1714 if (!pwallet->GetBroadcastTransactions()) return false;
1715 // Don't relay abandoned transactions
1716 if (isAbandoned()) return false;
1717 // Don't try to submit coinbase transactions. These would fail anyway but would
1718 // cause log spam.
1719 if (IsCoinBase()) return false;
1720 // Don't try to submit conflicted or confirmed transactions.
1721 if (GetDepthInMainChain() != 0) return false;
1722
1723 // Submit transaction to mempool for relay
1724 pwallet->WalletLogPrintf("Submitting wtx %s to mempool for relay\n", GetHash().ToString());
1725 // We must set fInMempool here - while it will be re-set to true by the
1726 // entered-mempool callback, if we did not there would be a race where a
1727 // user could call sendmoney in a loop and hit spurious out of funds errors
1728 // because we think that this newly generated transaction's change is
1729 // unavailable as we're not yet aware that it is in the mempool.
1730 //
1731 // Irrespective of the failure reason, un-marking fInMempool
1732 // out-of-order is incorrect - it should be unmarked when
1733 // TransactionRemovedFromMempool fires.
1734 bool ret = pwallet->chain().broadcastTransaction(tx, pwallet->m_default_max_tx_fee, relay, err_string);
1735 fInMempool |= ret;
1736 return ret;
1737 }
1738
GetConflicts() const1739 std::set<uint256> CWalletTx::GetConflicts() const
1740 {
1741 std::set<uint256> result;
1742 if (pwallet != nullptr)
1743 {
1744 uint256 myHash = GetHash();
1745 result = pwallet->GetConflicts(myHash);
1746 result.erase(myHash);
1747 }
1748 return result;
1749 }
1750
1751 // Rebroadcast transactions from the wallet. We do this on a random timer
1752 // to slightly obfuscate which transactions come from our wallet.
1753 //
1754 // Ideally, we'd only resend transactions that we think should have been
1755 // mined in the most recent block. Any transaction that wasn't in the top
1756 // blockweight of transactions in the mempool shouldn't have been mined,
1757 // and so is probably just sitting in the mempool waiting to be confirmed.
1758 // Rebroadcasting does nothing to speed up confirmation and only damages
1759 // privacy.
ResendWalletTransactions()1760 void CWallet::ResendWalletTransactions()
1761 {
1762 // During reindex, importing and IBD, old wallet transactions become
1763 // unconfirmed. Don't resend them as that would spam other nodes.
1764 if (!chain().isReadyToBroadcast()) return;
1765
1766 // Do this infrequently and randomly to avoid giving away
1767 // that these are our transactions.
1768 if (GetTime() < nNextResend || !fBroadcastTransactions) return;
1769 bool fFirst = (nNextResend == 0);
1770 // resend 12-36 hours from now, ~1 day on average.
1771 nNextResend = GetTime() + (12 * 60 * 60) + GetRand(24 * 60 * 60);
1772 if (fFirst) return;
1773
1774 int submitted_tx_count = 0;
1775
1776 { // cs_wallet scope
1777 LOCK(cs_wallet);
1778
1779 // Relay transactions
1780 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1781 CWalletTx& wtx = item.second;
1782 // Attempt to rebroadcast all txes more than 5 minutes older than
1783 // the last block. SubmitMemoryPoolAndRelay() will not rebroadcast
1784 // any confirmed or conflicting txs.
1785 if (wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
1786 std::string unused_err_string;
1787 if (wtx.SubmitMemoryPoolAndRelay(unused_err_string, true)) ++submitted_tx_count;
1788 }
1789 } // cs_wallet
1790
1791 if (submitted_tx_count > 0) {
1792 WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
1793 }
1794 }
1795
1796 /** @} */ // end of mapWallet
1797
MaybeResendWalletTxs()1798 void MaybeResendWalletTxs()
1799 {
1800 for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
1801 pwallet->ResendWalletTransactions();
1802 }
1803 }
1804
1805
1806 /** @defgroup Actions
1807 *
1808 * @{
1809 */
1810
SignTransaction(CMutableTransaction & tx) const1811 bool CWallet::SignTransaction(CMutableTransaction& tx) const
1812 {
1813 AssertLockHeld(cs_wallet);
1814
1815 // Build coins map
1816 std::map<COutPoint, Coin> coins;
1817 for (auto& input : tx.vin) {
1818 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
1819 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
1820 return false;
1821 }
1822 const CWalletTx& wtx = mi->second;
1823 coins[input.prevout] = Coin(wtx.tx->vout[input.prevout.n], wtx.m_confirm.block_height, wtx.IsCoinBase());
1824 }
1825 std::map<int, std::string> input_errors;
1826 return SignTransaction(tx, coins, SIGHASH_DEFAULT, input_errors);
1827 }
1828
SignTransaction(CMutableTransaction & tx,const std::map<COutPoint,Coin> & coins,int sighash,std::map<int,std::string> & input_errors) const1829 bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
1830 {
1831 // Try to sign with all ScriptPubKeyMans
1832 for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
1833 // spk_man->SignTransaction will return true if the transaction is complete,
1834 // so we can exit early and return true if that happens
1835 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
1836 return true;
1837 }
1838 }
1839
1840 // At this point, one input was not fully signed otherwise we would have exited already
1841 return false;
1842 }
1843
FillPSBT(PartiallySignedTransaction & psbtx,bool & complete,int sighash_type,bool sign,bool bip32derivs,size_t * n_signed) const1844 TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs, size_t * n_signed) const
1845 {
1846 if (n_signed) {
1847 *n_signed = 0;
1848 }
1849 const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
1850 LOCK(cs_wallet);
1851 // Get all of the previous transactions
1852 for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
1853 const CTxIn& txin = psbtx.tx->vin[i];
1854 PSBTInput& input = psbtx.inputs.at(i);
1855
1856 if (PSBTInputSigned(input)) {
1857 continue;
1858 }
1859
1860 // If we have no utxo, grab it from the wallet.
1861 if (!input.non_witness_utxo) {
1862 const uint256& txhash = txin.prevout.hash;
1863 const auto it = mapWallet.find(txhash);
1864 if (it != mapWallet.end()) {
1865 const CWalletTx& wtx = it->second;
1866 // We only need the non_witness_utxo, which is a superset of the witness_utxo.
1867 // The signing code will switch to the smaller witness_utxo if this is ok.
1868 input.non_witness_utxo = wtx.tx;
1869 }
1870 }
1871 }
1872
1873 // Fill in information from ScriptPubKeyMans
1874 for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
1875 int n_signed_this_spkm = 0;
1876 TransactionError res = spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm);
1877 if (res != TransactionError::OK) {
1878 return res;
1879 }
1880
1881 if (n_signed) {
1882 (*n_signed) += n_signed_this_spkm;
1883 }
1884 }
1885
1886 // Complete if every input is now signed
1887 complete = true;
1888 for (const auto& input : psbtx.inputs) {
1889 complete &= PSBTInputSigned(input);
1890 }
1891
1892 return TransactionError::OK;
1893 }
1894
SignMessage(const std::string & message,const PKHash & pkhash,std::string & str_sig) const1895 SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
1896 {
1897 SignatureData sigdata;
1898 CScript script_pub_key = GetScriptForDestination(pkhash);
1899 for (const auto& spk_man_pair : m_spk_managers) {
1900 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
1901 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
1902 }
1903 }
1904 return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
1905 }
1906
TransactionChangeType(const std::optional<OutputType> & change_type,const std::vector<CRecipient> & vecSend) const1907 OutputType CWallet::TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const
1908 {
1909 // If -changetype is specified, always use that change type.
1910 if (change_type) {
1911 return *change_type;
1912 }
1913
1914 // if m_default_address_type is legacy, use legacy address as change (even
1915 // if some of the outputs are P2WPKH or P2WSH).
1916 if (m_default_address_type == OutputType::LEGACY) {
1917 return OutputType::LEGACY;
1918 }
1919
1920 // if any destination is P2WPKH or P2WSH, use P2WPKH for the change
1921 // output.
1922 for (const auto& recipient : vecSend) {
1923 // Check if any destination contains a witness program:
1924 int witnessversion = 0;
1925 std::vector<unsigned char> witnessprogram;
1926 if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
1927 if (GetScriptPubKeyMan(OutputType::BECH32M, true)) {
1928 return OutputType::BECH32M;
1929 } else if (GetScriptPubKeyMan(OutputType::BECH32, true)) {
1930 return OutputType::BECH32;
1931 } else {
1932 return m_default_address_type;
1933 }
1934 }
1935 }
1936
1937 // else use m_default_address_type for change
1938 return m_default_address_type;
1939 }
1940
CommitTransaction(CTransactionRef tx,mapValue_t mapValue,std::vector<std::pair<std::string,std::string>> orderForm)1941 void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
1942 {
1943 LOCK(cs_wallet);
1944 WalletLogPrintf("CommitTransaction:\n%s", tx->ToString()); /* Continued */
1945
1946 // Add tx to wallet, because if it has change it's also ours,
1947 // otherwise just for transaction history.
1948 AddToWallet(tx, {}, [&](CWalletTx& wtx, bool new_tx) {
1949 CHECK_NONFATAL(wtx.mapValue.empty());
1950 CHECK_NONFATAL(wtx.vOrderForm.empty());
1951 wtx.mapValue = std::move(mapValue);
1952 wtx.vOrderForm = std::move(orderForm);
1953 wtx.fTimeReceivedIsTxTime = true;
1954 wtx.fFromMe = true;
1955 return true;
1956 });
1957
1958 // Notify that old coins are spent
1959 for (const CTxIn& txin : tx->vin) {
1960 CWalletTx &coin = mapWallet.at(txin.prevout.hash);
1961 coin.MarkDirty();
1962 NotifyTransactionChanged(coin.GetHash(), CT_UPDATED);
1963 }
1964
1965 // Get the inserted-CWalletTx from mapWallet so that the
1966 // fInMempool flag is cached properly
1967 CWalletTx& wtx = mapWallet.at(tx->GetHash());
1968
1969 if (!fBroadcastTransactions) {
1970 // Don't submit tx to the mempool
1971 return;
1972 }
1973
1974 std::string err_string;
1975 if (!wtx.SubmitMemoryPoolAndRelay(err_string, true)) {
1976 WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
1977 // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
1978 }
1979 }
1980
LoadWallet()1981 DBErrors CWallet::LoadWallet()
1982 {
1983 LOCK(cs_wallet);
1984
1985 DBErrors nLoadWalletRet = WalletBatch(GetDatabase()).LoadWallet(this);
1986 if (nLoadWalletRet == DBErrors::NEED_REWRITE)
1987 {
1988 if (GetDatabase().Rewrite("\x04pool"))
1989 {
1990 for (const auto& spk_man_pair : m_spk_managers) {
1991 spk_man_pair.second->RewriteDB();
1992 }
1993 }
1994 }
1995
1996 if (m_spk_managers.empty()) {
1997 assert(m_external_spk_managers.empty());
1998 assert(m_internal_spk_managers.empty());
1999 }
2000
2001 if (nLoadWalletRet != DBErrors::LOAD_OK)
2002 return nLoadWalletRet;
2003
2004 return DBErrors::LOAD_OK;
2005 }
2006
ZapSelectTx(std::vector<uint256> & vHashIn,std::vector<uint256> & vHashOut)2007 DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut)
2008 {
2009 AssertLockHeld(cs_wallet);
2010 DBErrors nZapSelectTxRet = WalletBatch(GetDatabase()).ZapSelectTx(vHashIn, vHashOut);
2011 for (const uint256& hash : vHashOut) {
2012 const auto& it = mapWallet.find(hash);
2013 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2014 for (const auto& txin : it->second.tx->vin)
2015 mapTxSpends.erase(txin.prevout);
2016 mapWallet.erase(it);
2017 NotifyTransactionChanged(hash, CT_DELETED);
2018 }
2019
2020 if (nZapSelectTxRet == DBErrors::NEED_REWRITE)
2021 {
2022 if (GetDatabase().Rewrite("\x04pool"))
2023 {
2024 for (const auto& spk_man_pair : m_spk_managers) {
2025 spk_man_pair.second->RewriteDB();
2026 }
2027 }
2028 }
2029
2030 if (nZapSelectTxRet != DBErrors::LOAD_OK)
2031 return nZapSelectTxRet;
2032
2033 MarkDirty();
2034
2035 return DBErrors::LOAD_OK;
2036 }
2037
SetAddressBookWithDB(WalletBatch & batch,const CTxDestination & address,const std::string & strName,const std::string & strPurpose)2038 bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::string& strPurpose)
2039 {
2040 bool fUpdated = false;
2041 bool is_mine;
2042 {
2043 LOCK(cs_wallet);
2044 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2045 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
2046 m_address_book[address].SetLabel(strName);
2047 if (!strPurpose.empty()) /* update purpose only if requested */
2048 m_address_book[address].purpose = strPurpose;
2049 is_mine = IsMine(address) != ISMINE_NO;
2050 }
2051 NotifyAddressBookChanged(address, strName, is_mine,
2052 strPurpose, (fUpdated ? CT_UPDATED : CT_NEW));
2053 if (!strPurpose.empty() && !batch.WritePurpose(EncodeDestination(address), strPurpose))
2054 return false;
2055 return batch.WriteName(EncodeDestination(address), strName);
2056 }
2057
SetAddressBook(const CTxDestination & address,const std::string & strName,const std::string & strPurpose)2058 bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& strPurpose)
2059 {
2060 WalletBatch batch(GetDatabase());
2061 return SetAddressBookWithDB(batch, address, strName, strPurpose);
2062 }
2063
DelAddressBook(const CTxDestination & address)2064 bool CWallet::DelAddressBook(const CTxDestination& address)
2065 {
2066 bool is_mine;
2067 WalletBatch batch(GetDatabase());
2068 {
2069 LOCK(cs_wallet);
2070 // If we want to delete receiving addresses, we need to take care that DestData "used" (and possibly newer DestData) gets preserved (and the "deleted" address transformed into a change entry instead of actually being deleted)
2071 // NOTE: This isn't a problem for sending addresses because they never have any DestData yet!
2072 // When adding new DestData, it should be considered here whether to retain or delete it (or move it?).
2073 if (IsMine(address)) {
2074 WalletLogPrintf("%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, PACKAGE_BUGREPORT);
2075 return false;
2076 }
2077 // Delete destdata tuples associated with address
2078 std::string strAddress = EncodeDestination(address);
2079 for (const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
2080 {
2081 batch.EraseDestData(strAddress, item.first);
2082 }
2083 m_address_book.erase(address);
2084 is_mine = IsMine(address) != ISMINE_NO;
2085 }
2086
2087 NotifyAddressBookChanged(address, "", is_mine, "", CT_DELETED);
2088
2089 batch.ErasePurpose(EncodeDestination(address));
2090 return batch.EraseName(EncodeDestination(address));
2091 }
2092
KeypoolCountExternalKeys() const2093 size_t CWallet::KeypoolCountExternalKeys() const
2094 {
2095 AssertLockHeld(cs_wallet);
2096
2097 auto legacy_spk_man = GetLegacyScriptPubKeyMan();
2098 if (legacy_spk_man) {
2099 return legacy_spk_man->KeypoolCountExternalKeys();
2100 }
2101
2102 unsigned int count = 0;
2103 for (auto spk_man : m_external_spk_managers) {
2104 count += spk_man.second->GetKeyPoolSize();
2105 }
2106
2107 return count;
2108 }
2109
GetKeyPoolSize() const2110 unsigned int CWallet::GetKeyPoolSize() const
2111 {
2112 AssertLockHeld(cs_wallet);
2113
2114 unsigned int count = 0;
2115 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2116 count += spk_man->GetKeyPoolSize();
2117 }
2118 return count;
2119 }
2120
TopUpKeyPool(unsigned int kpSize)2121 bool CWallet::TopUpKeyPool(unsigned int kpSize)
2122 {
2123 LOCK(cs_wallet);
2124 bool res = true;
2125 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2126 res &= spk_man->TopUp(kpSize);
2127 }
2128 return res;
2129 }
2130
GetNewDestination(const OutputType type,const std::string label,CTxDestination & dest,std::string & error)2131 bool CWallet::GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, std::string& error)
2132 {
2133 LOCK(cs_wallet);
2134 error.clear();
2135 bool result = false;
2136 auto spk_man = GetScriptPubKeyMan(type, false /* internal */);
2137 if (spk_man) {
2138 spk_man->TopUp();
2139 result = spk_man->GetNewDestination(type, dest, error);
2140 } else {
2141 error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type)).translated;
2142 }
2143 if (result) {
2144 SetAddressBook(dest, label, "receive");
2145 }
2146
2147 return result;
2148 }
2149
GetNewChangeDestination(const OutputType type,CTxDestination & dest,std::string & error)2150 bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& dest, std::string& error)
2151 {
2152 LOCK(cs_wallet);
2153 error.clear();
2154
2155 ReserveDestination reservedest(this, type);
2156 if (!reservedest.GetReservedDestination(dest, true, error)) {
2157 return false;
2158 }
2159
2160 reservedest.KeepDestination();
2161 return true;
2162 }
2163
GetOldestKeyPoolTime() const2164 int64_t CWallet::GetOldestKeyPoolTime() const
2165 {
2166 LOCK(cs_wallet);
2167 int64_t oldestKey = std::numeric_limits<int64_t>::max();
2168 for (const auto& spk_man_pair : m_spk_managers) {
2169 oldestKey = std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
2170 }
2171 return oldestKey;
2172 }
2173
MarkDestinationsDirty(const std::set<CTxDestination> & destinations)2174 void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) {
2175 for (auto& entry : mapWallet) {
2176 CWalletTx& wtx = entry.second;
2177 if (wtx.m_is_cache_empty) continue;
2178 for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
2179 CTxDestination dst;
2180 if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.count(dst)) {
2181 wtx.MarkDirty();
2182 break;
2183 }
2184 }
2185 }
2186 }
2187
GetLabelAddresses(const std::string & label) const2188 std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) const
2189 {
2190 LOCK(cs_wallet);
2191 std::set<CTxDestination> result;
2192 for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
2193 {
2194 if (item.second.IsChange()) continue;
2195 const CTxDestination& address = item.first;
2196 const std::string& strName = item.second.GetLabel();
2197 if (strName == label)
2198 result.insert(address);
2199 }
2200 return result;
2201 }
2202
GetReservedDestination(CTxDestination & dest,bool internal,std::string & error)2203 bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal, std::string& error)
2204 {
2205 m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
2206 if (!m_spk_man) {
2207 error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type)).translated;
2208 return false;
2209 }
2210
2211
2212 if (nIndex == -1)
2213 {
2214 m_spk_man->TopUp();
2215
2216 CKeyPool keypool;
2217 if (!m_spk_man->GetReservedDestination(type, internal, address, nIndex, keypool, error)) {
2218 return false;
2219 }
2220 fInternal = keypool.fInternal;
2221 }
2222 dest = address;
2223 return true;
2224 }
2225
KeepDestination()2226 void ReserveDestination::KeepDestination()
2227 {
2228 if (nIndex != -1) {
2229 m_spk_man->KeepDestination(nIndex, type);
2230 }
2231 nIndex = -1;
2232 address = CNoDestination();
2233 }
2234
ReturnDestination()2235 void ReserveDestination::ReturnDestination()
2236 {
2237 if (nIndex != -1) {
2238 m_spk_man->ReturnDestination(nIndex, fInternal, address);
2239 }
2240 nIndex = -1;
2241 address = CNoDestination();
2242 }
2243
DisplayAddress(const CTxDestination & dest)2244 bool CWallet::DisplayAddress(const CTxDestination& dest)
2245 {
2246 CScript scriptPubKey = GetScriptForDestination(dest);
2247 const auto spk_man = GetScriptPubKeyMan(scriptPubKey);
2248 if (spk_man == nullptr) {
2249 return false;
2250 }
2251 auto signer_spk_man = dynamic_cast<ExternalSignerScriptPubKeyMan*>(spk_man);
2252 if (signer_spk_man == nullptr) {
2253 return false;
2254 }
2255 ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
2256 return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2257 }
2258
LockCoin(const COutPoint & output)2259 void CWallet::LockCoin(const COutPoint& output)
2260 {
2261 AssertLockHeld(cs_wallet);
2262 setLockedCoins.insert(output);
2263 }
2264
UnlockCoin(const COutPoint & output)2265 void CWallet::UnlockCoin(const COutPoint& output)
2266 {
2267 AssertLockHeld(cs_wallet);
2268 setLockedCoins.erase(output);
2269 }
2270
UnlockAllCoins()2271 void CWallet::UnlockAllCoins()
2272 {
2273 AssertLockHeld(cs_wallet);
2274 setLockedCoins.clear();
2275 }
2276
IsLockedCoin(uint256 hash,unsigned int n) const2277 bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
2278 {
2279 AssertLockHeld(cs_wallet);
2280 COutPoint outpt(hash, n);
2281
2282 return (setLockedCoins.count(outpt) > 0);
2283 }
2284
ListLockedCoins(std::vector<COutPoint> & vOutpts) const2285 void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
2286 {
2287 AssertLockHeld(cs_wallet);
2288 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2289 it != setLockedCoins.end(); it++) {
2290 COutPoint outpt = (*it);
2291 vOutpts.push_back(outpt);
2292 }
2293 }
2294
2295 /** @} */ // end of Actions
2296
GetKeyBirthTimes(std::map<CKeyID,int64_t> & mapKeyBirth) const2297 void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
2298 AssertLockHeld(cs_wallet);
2299 mapKeyBirth.clear();
2300
2301 // map in which we'll infer heights of other keys
2302 std::map<CKeyID, const CWalletTx::Confirmation*> mapKeyFirstBlock;
2303 CWalletTx::Confirmation max_confirm;
2304 max_confirm.block_height = GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
2305 CHECK_NONFATAL(chain().findAncestorByHeight(GetLastBlockHash(), max_confirm.block_height, FoundBlock().hash(max_confirm.hashBlock)));
2306
2307 {
2308 LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
2309 assert(spk_man != nullptr);
2310 LOCK(spk_man->cs_KeyStore);
2311
2312 // get birth times for keys with metadata
2313 for (const auto& entry : spk_man->mapKeyMetadata) {
2314 if (entry.second.nCreateTime) {
2315 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2316 }
2317 }
2318
2319 // Prepare to infer birth heights for keys without metadata
2320 for (const CKeyID &keyid : spk_man->GetKeys()) {
2321 if (mapKeyBirth.count(keyid) == 0)
2322 mapKeyFirstBlock[keyid] = &max_confirm;
2323 }
2324
2325 // if there are no such keys, we're done
2326 if (mapKeyFirstBlock.empty())
2327 return;
2328
2329 // find first block that affects those keys, if there are any left
2330 for (const auto& entry : mapWallet) {
2331 // iterate over all wallet transactions...
2332 const CWalletTx &wtx = entry.second;
2333 if (wtx.m_confirm.status == CWalletTx::CONFIRMED) {
2334 // ... which are already in a block
2335 for (const CTxOut &txout : wtx.tx->vout) {
2336 // iterate over all their outputs
2337 for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
2338 // ... and all their affected keys
2339 auto rit = mapKeyFirstBlock.find(keyid);
2340 if (rit != mapKeyFirstBlock.end() && wtx.m_confirm.block_height < rit->second->block_height) {
2341 rit->second = &wtx.m_confirm;
2342 }
2343 }
2344 }
2345 }
2346 }
2347 }
2348
2349 // Extract block timestamps for those keys
2350 for (const auto& entry : mapKeyFirstBlock) {
2351 int64_t block_time;
2352 CHECK_NONFATAL(chain().findBlock(entry.second->hashBlock, FoundBlock().time(block_time)));
2353 mapKeyBirth[entry.first] = block_time - TIMESTAMP_WINDOW; // block times can be 2h off
2354 }
2355 }
2356
2357 /**
2358 * Compute smart timestamp for a transaction being added to the wallet.
2359 *
2360 * Logic:
2361 * - If sending a transaction, assign its timestamp to the current time.
2362 * - If receiving a transaction outside a block, assign its timestamp to the
2363 * current time.
2364 * - If receiving a block with a future timestamp, assign all its (not already
2365 * known) transactions' timestamps to the current time.
2366 * - If receiving a block with a past timestamp, before the most recent known
2367 * transaction (that we care about), assign all its (not already known)
2368 * transactions' timestamps to the same timestamp as that most-recent-known
2369 * transaction.
2370 * - If receiving a block with a past timestamp, but after the most recent known
2371 * transaction, assign all its (not already known) transactions' timestamps to
2372 * the block time.
2373 *
2374 * For more information see CWalletTx::nTimeSmart,
2375 * https://bitcointalk.org/?topic=54527, or
2376 * https://github.com/bitcoin/bitcoin/pull/1393.
2377 */
ComputeTimeSmart(const CWalletTx & wtx) const2378 unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
2379 {
2380 unsigned int nTimeSmart = wtx.nTimeReceived;
2381 if (!wtx.isUnconfirmed() && !wtx.isAbandoned()) {
2382 int64_t blocktime;
2383 if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(blocktime))) {
2384 int64_t latestNow = wtx.nTimeReceived;
2385 int64_t latestEntry = 0;
2386
2387 // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
2388 int64_t latestTolerated = latestNow + 300;
2389 const TxItems& txOrdered = wtxOrdered;
2390 for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2391 CWalletTx* const pwtx = it->second;
2392 if (pwtx == &wtx) {
2393 continue;
2394 }
2395 int64_t nSmartTime;
2396 nSmartTime = pwtx->nTimeSmart;
2397 if (!nSmartTime) {
2398 nSmartTime = pwtx->nTimeReceived;
2399 }
2400 if (nSmartTime <= latestTolerated) {
2401 latestEntry = nSmartTime;
2402 if (nSmartTime > latestNow) {
2403 latestNow = nSmartTime;
2404 }
2405 break;
2406 }
2407 }
2408
2409 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2410 } else {
2411 WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.m_confirm.hashBlock.ToString());
2412 }
2413 }
2414 return nTimeSmart;
2415 }
2416
SetAddressUsed(WalletBatch & batch,const CTxDestination & dest,bool used)2417 bool CWallet::SetAddressUsed(WalletBatch& batch, const CTxDestination& dest, bool used)
2418 {
2419 const std::string key{"used"};
2420 if (std::get_if<CNoDestination>(&dest))
2421 return false;
2422
2423 if (!used) {
2424 if (auto* data = util::FindKey(m_address_book, dest)) data->destdata.erase(key);
2425 return batch.EraseDestData(EncodeDestination(dest), key);
2426 }
2427
2428 const std::string value{"1"};
2429 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2430 return batch.WriteDestData(EncodeDestination(dest), key, value);
2431 }
2432
LoadDestData(const CTxDestination & dest,const std::string & key,const std::string & value)2433 void CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
2434 {
2435 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2436 }
2437
IsAddressUsed(const CTxDestination & dest) const2438 bool CWallet::IsAddressUsed(const CTxDestination& dest) const
2439 {
2440 const std::string key{"used"};
2441 std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
2442 if(i != m_address_book.end())
2443 {
2444 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
2445 if(j != i->second.destdata.end())
2446 {
2447 return true;
2448 }
2449 }
2450 return false;
2451 }
2452
GetAddressReceiveRequests() const2453 std::vector<std::string> CWallet::GetAddressReceiveRequests() const
2454 {
2455 const std::string prefix{"rr"};
2456 std::vector<std::string> values;
2457 for (const auto& address : m_address_book) {
2458 for (const auto& data : address.second.destdata) {
2459 if (!data.first.compare(0, prefix.size(), prefix)) {
2460 values.emplace_back(data.second);
2461 }
2462 }
2463 }
2464 return values;
2465 }
2466
SetAddressReceiveRequest(WalletBatch & batch,const CTxDestination & dest,const std::string & id,const std::string & value)2467 bool CWallet::SetAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id, const std::string& value)
2468 {
2469 const std::string key{"rr" + id}; // "rr" prefix = "receive request" in destdata
2470 CAddressBookData& data = m_address_book.at(dest);
2471 if (value.empty()) {
2472 if (!batch.EraseDestData(EncodeDestination(dest), key)) return false;
2473 data.destdata.erase(key);
2474 } else {
2475 if (!batch.WriteDestData(EncodeDestination(dest), key, value)) return false;
2476 data.destdata[key] = value;
2477 }
2478 return true;
2479 }
2480
MakeWalletDatabase(const std::string & name,const DatabaseOptions & options,DatabaseStatus & status,bilingual_str & error_string)2481 std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error_string)
2482 {
2483 // Do some checking on wallet path. It should be either a:
2484 //
2485 // 1. Path where a directory can be created.
2486 // 2. Path to an existing directory.
2487 // 3. Path to a symlink to a directory.
2488 // 4. For backwards compatibility, the name of a data file in -walletdir.
2489 const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), name);
2490 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2491 if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
2492 (path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
2493 (path_type == fs::regular_file && fs::path(name).filename() == name))) {
2494 error_string = Untranslated(strprintf(
2495 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2496 "database/log.?????????? files can be stored, a location where such a directory could be created, "
2497 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2498 name, GetWalletDir()));
2499 status = DatabaseStatus::FAILED_BAD_PATH;
2500 return nullptr;
2501 }
2502 return MakeDatabase(wallet_path, options, status, error_string);
2503 }
2504
Create(interfaces::Chain * chain,const std::string & name,std::unique_ptr<WalletDatabase> database,uint64_t wallet_creation_flags,bilingual_str & error,std::vector<bilingual_str> & warnings)2505 std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain* chain, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
2506 {
2507 const std::string& walletFile = database->Filename();
2508
2509 int64_t nStart = GetTimeMillis();
2510 // TODO: Can't use std::make_shared because we need a custom deleter but
2511 // should be possible to use std::allocate_shared.
2512 std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), ReleaseWallet);
2513 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2514 if (nLoadWalletRet != DBErrors::LOAD_OK) {
2515 if (nLoadWalletRet == DBErrors::CORRUPT) {
2516 error = strprintf(_("Error loading %s: Wallet corrupted"), walletFile);
2517 return nullptr;
2518 }
2519 else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
2520 {
2521 warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
2522 " or address book entries might be missing or incorrect."),
2523 walletFile));
2524 }
2525 else if (nLoadWalletRet == DBErrors::TOO_NEW) {
2526 error = strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, PACKAGE_NAME);
2527 return nullptr;
2528 }
2529 else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
2530 {
2531 error = strprintf(_("Wallet needed to be rewritten: restart %s to complete"), PACKAGE_NAME);
2532 return nullptr;
2533 }
2534 else {
2535 error = strprintf(_("Error loading %s"), walletFile);
2536 return nullptr;
2537 }
2538 }
2539
2540 // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
2541 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
2542 !walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
2543 !walletInstance->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
2544 if (fFirstRun)
2545 {
2546 // ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
2547 walletInstance->SetMinVersion(FEATURE_LATEST);
2548
2549 walletInstance->AddWalletFlags(wallet_creation_flags);
2550
2551 // Only create LegacyScriptPubKeyMan when not descriptor wallet
2552 if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
2553 walletInstance->SetupLegacyScriptPubKeyMan();
2554 }
2555
2556 if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) || !(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
2557 LOCK(walletInstance->cs_wallet);
2558 if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
2559 walletInstance->SetupDescriptorScriptPubKeyMans();
2560 // SetupDescriptorScriptPubKeyMans already calls SetupGeneration for us so we don't need to call SetupGeneration separately
2561 } else {
2562 // Legacy wallets need SetupGeneration here.
2563 for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2564 if (!spk_man->SetupGeneration()) {
2565 error = _("Unable to generate initial keys");
2566 return nullptr;
2567 }
2568 }
2569 }
2570 }
2571
2572 if (chain) {
2573 walletInstance->chainStateFlushed(chain->getTipLocator());
2574 }
2575 } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
2576 // Make it impossible to disable private keys after creation
2577 error = strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile);
2578 return NULL;
2579 } else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
2580 for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2581 if (spk_man->HavePrivateKeys()) {
2582 warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
2583 break;
2584 }
2585 }
2586 }
2587
2588 if (!gArgs.GetArg("-addresstype", "").empty()) {
2589 if (!ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) {
2590 error = strprintf(_("Unknown address type '%s'"), gArgs.GetArg("-addresstype", ""));
2591 return nullptr;
2592 }
2593 }
2594
2595 if (!gArgs.GetArg("-changetype", "").empty()) {
2596 OutputType out_type;
2597 if (!ParseOutputType(gArgs.GetArg("-changetype", ""), out_type)) {
2598 error = strprintf(_("Unknown change type '%s'"), gArgs.GetArg("-changetype", ""));
2599 return nullptr;
2600 }
2601 walletInstance->m_default_change_type = out_type;
2602 }
2603
2604 if (gArgs.IsArgSet("-mintxfee")) {
2605 CAmount n = 0;
2606 if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) {
2607 error = AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", ""));
2608 return nullptr;
2609 }
2610 if (n > HIGH_TX_FEE_PER_KB) {
2611 warnings.push_back(AmountHighWarn("-mintxfee") + Untranslated(" ") +
2612 _("This is the minimum transaction fee you pay on every transaction."));
2613 }
2614 walletInstance->m_min_fee = CFeeRate(n);
2615 }
2616
2617 if (gArgs.IsArgSet("-maxapsfee")) {
2618 const std::string max_aps_fee{gArgs.GetArg("-maxapsfee", "")};
2619 CAmount n = 0;
2620 if (max_aps_fee == "-1") {
2621 n = -1;
2622 } else if (!ParseMoney(max_aps_fee, n)) {
2623 error = AmountErrMsg("maxapsfee", max_aps_fee);
2624 return nullptr;
2625 }
2626 if (n > HIGH_APS_FEE) {
2627 warnings.push_back(AmountHighWarn("-maxapsfee") + Untranslated(" ") +
2628 _("This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
2629 }
2630 walletInstance->m_max_aps_fee = n;
2631 }
2632
2633 if (gArgs.IsArgSet("-fallbackfee")) {
2634 CAmount nFeePerK = 0;
2635 if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
2636 error = strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", ""));
2637 return nullptr;
2638 }
2639 if (nFeePerK > HIGH_TX_FEE_PER_KB) {
2640 warnings.push_back(AmountHighWarn("-fallbackfee") + Untranslated(" ") +
2641 _("This is the transaction fee you may pay when fee estimates are not available."));
2642 }
2643 walletInstance->m_fallback_fee = CFeeRate(nFeePerK);
2644 }
2645 // Disable fallback fee in case value was set to 0, enable if non-null value
2646 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
2647
2648 if (gArgs.IsArgSet("-discardfee")) {
2649 CAmount nFeePerK = 0;
2650 if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) {
2651 error = strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", ""));
2652 return nullptr;
2653 }
2654 if (nFeePerK > HIGH_TX_FEE_PER_KB) {
2655 warnings.push_back(AmountHighWarn("-discardfee") + Untranslated(" ") +
2656 _("This is the transaction fee you may discard if change is smaller than dust at this level"));
2657 }
2658 walletInstance->m_discard_rate = CFeeRate(nFeePerK);
2659 }
2660 if (gArgs.IsArgSet("-paytxfee")) {
2661 CAmount nFeePerK = 0;
2662 if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) {
2663 error = AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", ""));
2664 return nullptr;
2665 }
2666 if (nFeePerK > HIGH_TX_FEE_PER_KB) {
2667 warnings.push_back(AmountHighWarn("-paytxfee") + Untranslated(" ") +
2668 _("This is the transaction fee you will pay if you send a transaction."));
2669 }
2670 walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000);
2671 if (chain && walletInstance->m_pay_tx_fee < chain->relayMinFee()) {
2672 error = strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
2673 gArgs.GetArg("-paytxfee", ""), chain->relayMinFee().ToString());
2674 return nullptr;
2675 }
2676 }
2677
2678 if (gArgs.IsArgSet("-maxtxfee")) {
2679 CAmount nMaxFee = 0;
2680 if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) {
2681 error = AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", ""));
2682 return nullptr;
2683 }
2684 if (nMaxFee > HIGH_MAX_TX_FEE) {
2685 warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
2686 }
2687 if (chain && CFeeRate(nMaxFee, 1000) < chain->relayMinFee()) {
2688 error = strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
2689 gArgs.GetArg("-maxtxfee", ""), chain->relayMinFee().ToString());
2690 return nullptr;
2691 }
2692 walletInstance->m_default_max_tx_fee = nMaxFee;
2693 }
2694
2695 if (chain && chain->relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) {
2696 warnings.push_back(AmountHighWarn("-minrelaytxfee") + Untranslated(" ") +
2697 _("The wallet will avoid paying less than the minimum relay fee."));
2698 }
2699
2700 walletInstance->m_confirm_target = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
2701 walletInstance->m_spend_zero_conf_change = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
2702 walletInstance->m_signal_rbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
2703
2704 walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", GetTimeMillis() - nStart);
2705
2706 // Try to top up keypool. No-op if the wallet is locked.
2707 walletInstance->TopUpKeyPool();
2708
2709 LOCK(walletInstance->cs_wallet);
2710
2711 if (chain && !AttachChain(walletInstance, *chain, error, warnings)) {
2712 return nullptr;
2713 }
2714
2715 {
2716 LOCK(cs_wallets);
2717 for (auto& load_wallet : g_load_wallet_fns) {
2718 load_wallet(interfaces::MakeWallet(walletInstance));
2719 }
2720 }
2721
2722 walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
2723
2724 {
2725 walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
2726 walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
2727 walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size());
2728 }
2729
2730 return walletInstance;
2731 }
2732
AttachChain(const std::shared_ptr<CWallet> & walletInstance,interfaces::Chain & chain,bilingual_str & error,std::vector<bilingual_str> & warnings)2733 bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings)
2734 {
2735 LOCK(walletInstance->cs_wallet);
2736 // allow setting the chain if it hasn't been set already but prevent changing it
2737 assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
2738 walletInstance->m_chain = &chain;
2739
2740 // Register wallet with validationinterface. It's done before rescan to avoid
2741 // missing block connections between end of rescan and validation subscribing.
2742 // Because of wallet lock being hold, block connection notifications are going to
2743 // be pending on the validation-side until lock release. It's likely to have
2744 // block processing duplicata (if rescan block range overlaps with notification one)
2745 // but we guarantee at least than wallet state is correct after notifications delivery.
2746 // This is temporary until rescan and notifications delivery are unified under same
2747 // interface.
2748 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
2749
2750 int rescan_height = 0;
2751 if (!gArgs.GetBoolArg("-rescan", false))
2752 {
2753 WalletBatch batch(walletInstance->GetDatabase());
2754 CBlockLocator locator;
2755 if (batch.ReadBestBlock(locator)) {
2756 if (const std::optional<int> fork_height = chain.findLocatorFork(locator)) {
2757 rescan_height = *fork_height;
2758 }
2759 }
2760 }
2761
2762 const std::optional<int> tip_height = chain.getHeight();
2763 if (tip_height) {
2764 walletInstance->m_last_block_processed = chain.getBlockHash(*tip_height);
2765 walletInstance->m_last_block_processed_height = *tip_height;
2766 } else {
2767 walletInstance->m_last_block_processed.SetNull();
2768 walletInstance->m_last_block_processed_height = -1;
2769 }
2770
2771 if (tip_height && *tip_height != rescan_height)
2772 {
2773 if (chain.havePruned()) {
2774 int block_height = *tip_height;
2775 while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
2776 --block_height;
2777 }
2778
2779 if (rescan_height != block_height) {
2780 // We can't rescan beyond non-pruned blocks, stop and throw an error.
2781 // This might happen if a user uses an old wallet within a pruned node
2782 // or if they ran -disablewallet for a longer time, then decided to re-enable
2783 // Exit early and print an error.
2784 // If a block is pruned after this check, we will load the wallet,
2785 // but fail the rescan with a generic error.
2786 error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
2787 return false;
2788 }
2789 }
2790
2791 chain.initMessage(_("Rescanning…").translated);
2792 walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
2793
2794 // No need to read and scan block if block was created before
2795 // our wallet birthday (as adjusted for block time variability)
2796 std::optional<int64_t> time_first_key;
2797 for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
2798 int64_t time = spk_man->GetTimeFirstKey();
2799 if (!time_first_key || time < *time_first_key) time_first_key = time;
2800 }
2801 if (time_first_key) {
2802 chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, FoundBlock().height(rescan_height));
2803 }
2804
2805 {
2806 WalletRescanReserver reserver(*walletInstance);
2807 if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, {} /* max height */, reserver, true /* update */).status)) {
2808 error = _("Failed to rescan the wallet during initialization");
2809 return false;
2810 }
2811 }
2812 walletInstance->chainStateFlushed(chain.getTipLocator());
2813 walletInstance->GetDatabase().IncrementUpdateCounter();
2814 }
2815
2816 return true;
2817 }
2818
FindAddressBookEntry(const CTxDestination & dest,bool allow_change) const2819 const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
2820 {
2821 const auto& address_book_it = m_address_book.find(dest);
2822 if (address_book_it == m_address_book.end()) return nullptr;
2823 if ((!allow_change) && address_book_it->second.IsChange()) {
2824 return nullptr;
2825 }
2826 return &address_book_it->second;
2827 }
2828
UpgradeWallet(int version,bilingual_str & error)2829 bool CWallet::UpgradeWallet(int version, bilingual_str& error)
2830 {
2831 int prev_version = GetVersion();
2832 if (version == 0) {
2833 WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
2834 version = FEATURE_LATEST;
2835 } else {
2836 WalletLogPrintf("Allowing wallet upgrade up to %i\n", version);
2837 }
2838 if (version < prev_version) {
2839 error = strprintf(_("Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
2840 return false;
2841 }
2842
2843 LOCK(cs_wallet);
2844
2845 // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
2846 if (!CanSupportFeature(FEATURE_HD_SPLIT) && version >= FEATURE_HD_SPLIT && version < FEATURE_PRE_SPLIT_KEYPOOL) {
2847 error = strprintf(_("Cannot upgrade a non HD split wallet from version %i to version %i without upgrading to support pre-split keypool. Please use version %i or no version specified."), prev_version, version, FEATURE_PRE_SPLIT_KEYPOOL);
2848 return false;
2849 }
2850
2851 // Permanently upgrade to the version
2852 SetMinVersion(GetClosestWalletFeature(version));
2853
2854 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2855 if (!spk_man->Upgrade(prev_version, version, error)) {
2856 return false;
2857 }
2858 }
2859 return true;
2860 }
2861
postInitProcess()2862 void CWallet::postInitProcess()
2863 {
2864 LOCK(cs_wallet);
2865
2866 // Add wallet transactions that aren't already in a block to mempool
2867 // Do this here as mempool requires genesis block to be loaded
2868 ReacceptWalletTransactions();
2869
2870 // Update wallet transactions with current mempool transactions.
2871 chain().requestMempoolTransactions(*this);
2872 }
2873
BackupWallet(const std::string & strDest) const2874 bool CWallet::BackupWallet(const std::string& strDest) const
2875 {
2876 return GetDatabase().Backup(strDest);
2877 }
2878
CKeyPool()2879 CKeyPool::CKeyPool()
2880 {
2881 nTime = GetTime();
2882 fInternal = false;
2883 m_pre_split = false;
2884 }
2885
CKeyPool(const CPubKey & vchPubKeyIn,bool internalIn)2886 CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
2887 {
2888 nTime = GetTime();
2889 vchPubKey = vchPubKeyIn;
2890 fInternal = internalIn;
2891 m_pre_split = false;
2892 }
2893
GetDepthInMainChain() const2894 int CWalletTx::GetDepthInMainChain() const
2895 {
2896 assert(pwallet != nullptr);
2897 AssertLockHeld(pwallet->cs_wallet);
2898 if (isUnconfirmed() || isAbandoned()) return 0;
2899
2900 return (pwallet->GetLastBlockHeight() - m_confirm.block_height + 1) * (isConflicted() ? -1 : 1);
2901 }
2902
GetBlocksToMaturity() const2903 int CWalletTx::GetBlocksToMaturity() const
2904 {
2905 if (!IsCoinBase())
2906 return 0;
2907 int chain_depth = GetDepthInMainChain();
2908 assert(chain_depth >= 0); // coinbase tx should not be conflicted
2909 return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
2910 }
2911
IsImmatureCoinBase() const2912 bool CWalletTx::IsImmatureCoinBase() const
2913 {
2914 // note GetBlocksToMaturity is 0 for non-coinbase tx
2915 return GetBlocksToMaturity() > 0;
2916 }
2917
IsCrypted() const2918 bool CWallet::IsCrypted() const
2919 {
2920 return HasEncryptionKeys();
2921 }
2922
IsLocked() const2923 bool CWallet::IsLocked() const
2924 {
2925 if (!IsCrypted()) {
2926 return false;
2927 }
2928 LOCK(cs_wallet);
2929 return vMasterKey.empty();
2930 }
2931
Lock()2932 bool CWallet::Lock()
2933 {
2934 if (!IsCrypted())
2935 return false;
2936
2937 {
2938 LOCK(cs_wallet);
2939 vMasterKey.clear();
2940 }
2941
2942 NotifyStatusChanged(this);
2943 return true;
2944 }
2945
Unlock(const CKeyingMaterial & vMasterKeyIn,bool accept_no_keys)2946 bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys)
2947 {
2948 {
2949 LOCK(cs_wallet);
2950 for (const auto& spk_man_pair : m_spk_managers) {
2951 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
2952 return false;
2953 }
2954 }
2955 vMasterKey = vMasterKeyIn;
2956 }
2957 NotifyStatusChanged(this);
2958 return true;
2959 }
2960
GetActiveScriptPubKeyMans() const2961 std::set<ScriptPubKeyMan*> CWallet::GetActiveScriptPubKeyMans() const
2962 {
2963 std::set<ScriptPubKeyMan*> spk_mans;
2964 for (bool internal : {false, true}) {
2965 for (OutputType t : OUTPUT_TYPES) {
2966 auto spk_man = GetScriptPubKeyMan(t, internal);
2967 if (spk_man) {
2968 spk_mans.insert(spk_man);
2969 }
2970 }
2971 }
2972 return spk_mans;
2973 }
2974
GetAllScriptPubKeyMans() const2975 std::set<ScriptPubKeyMan*> CWallet::GetAllScriptPubKeyMans() const
2976 {
2977 std::set<ScriptPubKeyMan*> spk_mans;
2978 for (const auto& spk_man_pair : m_spk_managers) {
2979 spk_mans.insert(spk_man_pair.second.get());
2980 }
2981 return spk_mans;
2982 }
2983
GetScriptPubKeyMan(const OutputType & type,bool internal) const2984 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const OutputType& type, bool internal) const
2985 {
2986 const std::map<OutputType, ScriptPubKeyMan*>& spk_managers = internal ? m_internal_spk_managers : m_external_spk_managers;
2987 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
2988 if (it == spk_managers.end()) {
2989 return nullptr;
2990 }
2991 return it->second;
2992 }
2993
GetScriptPubKeyMans(const CScript & script,SignatureData & sigdata) const2994 std::set<ScriptPubKeyMan*> CWallet::GetScriptPubKeyMans(const CScript& script, SignatureData& sigdata) const
2995 {
2996 std::set<ScriptPubKeyMan*> spk_mans;
2997 for (const auto& spk_man_pair : m_spk_managers) {
2998 if (spk_man_pair.second->CanProvide(script, sigdata)) {
2999 spk_mans.insert(spk_man_pair.second.get());
3000 }
3001 }
3002 return spk_mans;
3003 }
3004
GetScriptPubKeyMan(const CScript & script) const3005 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const CScript& script) const
3006 {
3007 SignatureData sigdata;
3008 for (const auto& spk_man_pair : m_spk_managers) {
3009 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3010 return spk_man_pair.second.get();
3011 }
3012 }
3013 return nullptr;
3014 }
3015
GetScriptPubKeyMan(const uint256 & id) const3016 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const uint256& id) const
3017 {
3018 if (m_spk_managers.count(id) > 0) {
3019 return m_spk_managers.at(id).get();
3020 }
3021 return nullptr;
3022 }
3023
GetSolvingProvider(const CScript & script) const3024 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script) const
3025 {
3026 SignatureData sigdata;
3027 return GetSolvingProvider(script, sigdata);
3028 }
3029
GetSolvingProvider(const CScript & script,SignatureData & sigdata) const3030 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script, SignatureData& sigdata) const
3031 {
3032 for (const auto& spk_man_pair : m_spk_managers) {
3033 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3034 return spk_man_pair.second->GetSolvingProvider(script);
3035 }
3036 }
3037 return nullptr;
3038 }
3039
GetLegacyScriptPubKeyMan() const3040 LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
3041 {
3042 if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3043 return nullptr;
3044 }
3045 // Legacy wallets only have one ScriptPubKeyMan which is a LegacyScriptPubKeyMan.
3046 // Everything in m_internal_spk_managers and m_external_spk_managers point to the same legacyScriptPubKeyMan.
3047 auto it = m_internal_spk_managers.find(OutputType::LEGACY);
3048 if (it == m_internal_spk_managers.end()) return nullptr;
3049 return dynamic_cast<LegacyScriptPubKeyMan*>(it->second);
3050 }
3051
GetOrCreateLegacyScriptPubKeyMan()3052 LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
3053 {
3054 SetupLegacyScriptPubKeyMan();
3055 return GetLegacyScriptPubKeyMan();
3056 }
3057
SetupLegacyScriptPubKeyMan()3058 void CWallet::SetupLegacyScriptPubKeyMan()
3059 {
3060 if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty() || IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3061 return;
3062 }
3063
3064 auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new LegacyScriptPubKeyMan(*this));
3065 for (const auto& type : LEGACY_OUTPUT_TYPES) {
3066 m_internal_spk_managers[type] = spk_manager.get();
3067 m_external_spk_managers[type] = spk_manager.get();
3068 }
3069 m_spk_managers[spk_manager->GetID()] = std::move(spk_manager);
3070 }
3071
GetEncryptionKey() const3072 const CKeyingMaterial& CWallet::GetEncryptionKey() const
3073 {
3074 return vMasterKey;
3075 }
3076
HasEncryptionKeys() const3077 bool CWallet::HasEncryptionKeys() const
3078 {
3079 return !mapMasterKeys.empty();
3080 }
3081
ConnectScriptPubKeyManNotifiers()3082 void CWallet::ConnectScriptPubKeyManNotifiers()
3083 {
3084 for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
3085 spk_man->NotifyWatchonlyChanged.connect(NotifyWatchonlyChanged);
3086 spk_man->NotifyCanGetAddressesChanged.connect(NotifyCanGetAddressesChanged);
3087 }
3088 }
3089
LoadDescriptorScriptPubKeyMan(uint256 id,WalletDescriptor & desc)3090 void CWallet::LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc)
3091 {
3092 if (IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
3093 auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(*this, desc));
3094 m_spk_managers[id] = std::move(spk_manager);
3095 } else {
3096 auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc));
3097 m_spk_managers[id] = std::move(spk_manager);
3098 }
3099 }
3100
SetupDescriptorScriptPubKeyMans()3101 void CWallet::SetupDescriptorScriptPubKeyMans()
3102 {
3103 AssertLockHeld(cs_wallet);
3104
3105 if (!IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
3106 // Make a seed
3107 CKey seed_key;
3108 seed_key.MakeNewKey(true);
3109 CPubKey seed = seed_key.GetPubKey();
3110 assert(seed_key.VerifyPubKey(seed));
3111
3112 // Get the extended key
3113 CExtKey master_key;
3114 master_key.SetSeed(seed_key.begin(), seed_key.size());
3115
3116 for (bool internal : {false, true}) {
3117 for (OutputType t : OUTPUT_TYPES) {
3118 if (t == OutputType::BECH32M) {
3119 // Skip taproot (bech32m) for now
3120 // TODO: Setup taproot (bech32m) descriptors by default
3121 continue;
3122 }
3123 auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this));
3124 if (IsCrypted()) {
3125 if (IsLocked()) {
3126 throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
3127 }
3128 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, nullptr)) {
3129 throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
3130 }
3131 }
3132 spk_manager->SetupDescriptorGeneration(master_key, t, internal);
3133 uint256 id = spk_manager->GetID();
3134 m_spk_managers[id] = std::move(spk_manager);
3135 AddActiveScriptPubKeyMan(id, t, internal);
3136 }
3137 }
3138 } else {
3139 ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
3140
3141 // TODO: add account parameter
3142 int account = 0;
3143 UniValue signer_res = signer.GetDescriptors(account);
3144
3145 if (!signer_res.isObject()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3146 for (bool internal : {false, true}) {
3147 const UniValue& descriptor_vals = find_value(signer_res, internal ? "internal" : "receive");
3148 if (!descriptor_vals.isArray()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3149 for (const UniValue& desc_val : descriptor_vals.get_array().getValues()) {
3150 std::string desc_str = desc_val.getValStr();
3151 FlatSigningProvider keys;
3152 std::string dummy_error;
3153 std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, dummy_error, false);
3154 if (!desc->GetOutputType()) {
3155 continue;
3156 }
3157 OutputType t = *desc->GetOutputType();
3158 auto spk_manager = std::unique_ptr<ExternalSignerScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(*this));
3159 spk_manager->SetupDescriptor(std::move(desc));
3160 uint256 id = spk_manager->GetID();
3161 m_spk_managers[id] = std::move(spk_manager);
3162 AddActiveScriptPubKeyMan(id, t, internal);
3163 }
3164 }
3165 }
3166 }
3167
AddActiveScriptPubKeyMan(uint256 id,OutputType type,bool internal)3168 void CWallet::AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
3169 {
3170 WalletBatch batch(GetDatabase());
3171 if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
3172 throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
3173 }
3174 LoadActiveScriptPubKeyMan(id, type, internal);
3175 }
3176
LoadActiveScriptPubKeyMan(uint256 id,OutputType type,bool internal)3177 void CWallet::LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
3178 {
3179 // Activating ScriptPubKeyManager for a given output and change type is incompatible with legacy wallets.
3180 // Legacy wallets have only one ScriptPubKeyManager and it's active for all output and change types.
3181 Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
3182
3183 WalletLogPrintf("Setting spkMan to active: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
3184 auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3185 auto& spk_mans_other = internal ? m_external_spk_managers : m_internal_spk_managers;
3186 auto spk_man = m_spk_managers.at(id).get();
3187 spk_mans[type] = spk_man;
3188
3189 if (spk_mans_other[type] == spk_man) {
3190 spk_mans_other.erase(type);
3191 }
3192
3193 NotifyCanGetAddressesChanged();
3194 }
3195
DeactivateScriptPubKeyMan(uint256 id,OutputType type,bool internal)3196 void CWallet::DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
3197 {
3198 auto spk_man = GetScriptPubKeyMan(type, internal);
3199 if (spk_man != nullptr && spk_man->GetID() == id) {
3200 WalletLogPrintf("Deactivate spkMan: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
3201 WalletBatch batch(GetDatabase());
3202 if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type), internal)) {
3203 throw std::runtime_error(std::string(__func__) + ": erasing active ScriptPubKeyMan id failed");
3204 }
3205
3206 auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3207 spk_mans.erase(type);
3208 }
3209
3210 NotifyCanGetAddressesChanged();
3211 }
3212
IsLegacy() const3213 bool CWallet::IsLegacy() const
3214 {
3215 if (m_internal_spk_managers.count(OutputType::LEGACY) == 0) {
3216 return false;
3217 }
3218 auto spk_man = dynamic_cast<LegacyScriptPubKeyMan*>(m_internal_spk_managers.at(OutputType::LEGACY));
3219 return spk_man != nullptr;
3220 }
3221
GetDescriptorScriptPubKeyMan(const WalletDescriptor & desc) const3222 DescriptorScriptPubKeyMan* CWallet::GetDescriptorScriptPubKeyMan(const WalletDescriptor& desc) const
3223 {
3224 for (auto& spk_man_pair : m_spk_managers) {
3225 // Try to downcast to DescriptorScriptPubKeyMan then check if the descriptors match
3226 DescriptorScriptPubKeyMan* spk_manager = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man_pair.second.get());
3227 if (spk_manager != nullptr && spk_manager->HasWalletDescriptor(desc)) {
3228 return spk_manager;
3229 }
3230 }
3231
3232 return nullptr;
3233 }
3234
AddWalletDescriptor(WalletDescriptor & desc,const FlatSigningProvider & signing_provider,const std::string & label,bool internal)3235 ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal)
3236 {
3237 if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3238 WalletLogPrintf("Cannot add WalletDescriptor to a non-descriptor wallet\n");
3239 return nullptr;
3240 }
3241
3242 LOCK(cs_wallet);
3243 auto spk_man = GetDescriptorScriptPubKeyMan(desc);
3244 if (spk_man) {
3245 WalletLogPrintf("Update existing descriptor: %s\n", desc.descriptor->ToString());
3246 spk_man->UpdateWalletDescriptor(desc);
3247 } else {
3248 auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc));
3249 spk_man = new_spk_man.get();
3250
3251 // Save the descriptor to memory
3252 m_spk_managers[new_spk_man->GetID()] = std::move(new_spk_man);
3253 }
3254
3255 // Add the private keys to the descriptor
3256 for (const auto& entry : signing_provider.keys) {
3257 const CKey& key = entry.second;
3258 spk_man->AddDescriptorKey(key, key.GetPubKey());
3259 }
3260
3261 // Top up key pool, the manager will generate new scriptPubKeys internally
3262 if (!spk_man->TopUp()) {
3263 WalletLogPrintf("Could not top up scriptPubKeys\n");
3264 return nullptr;
3265 }
3266
3267 // Apply the label if necessary
3268 // Note: we disable labels for ranged descriptors
3269 if (!desc.descriptor->IsRange()) {
3270 auto script_pub_keys = spk_man->GetScriptPubKeys();
3271 if (script_pub_keys.empty()) {
3272 WalletLogPrintf("Could not generate scriptPubKeys (cache is empty)\n");
3273 return nullptr;
3274 }
3275
3276 CTxDestination dest;
3277 if (!internal && ExtractDestination(script_pub_keys.at(0), dest)) {
3278 SetAddressBook(dest, label, "receive");
3279 }
3280 }
3281
3282 // Save the descriptor to DB
3283 spk_man->WriteDescriptor();
3284
3285 return spk_man;
3286 }
3287