Bitcoin Core  27.99.0
P2P Digital Currency
wallet.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 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 #if defined(HAVE_CONFIG_H)
10 #endif
11 #include <addresstype.h>
12 #include <blockfilter.h>
13 #include <chain.h>
14 #include <coins.h>
15 #include <common/args.h>
16 #include <common/settings.h>
17 #include <common/system.h>
18 #include <consensus/amount.h>
19 #include <consensus/consensus.h>
20 #include <consensus/validation.h>
21 #include <external_signer.h>
22 #include <interfaces/chain.h>
23 #include <interfaces/handler.h>
24 #include <interfaces/wallet.h>
25 #include <kernel/chain.h>
27 #include <key.h>
28 #include <key_io.h>
29 #include <logging.h>
30 #include <outputtype.h>
31 #include <policy/feerate.h>
32 #include <primitives/block.h>
33 #include <primitives/transaction.h>
34 #include <psbt.h>
35 #include <pubkey.h>
36 #include <random.h>
37 #include <script/descriptor.h>
38 #include <script/interpreter.h>
39 #include <script/script.h>
40 #include <script/sign.h>
41 #include <script/signingprovider.h>
42 #include <script/solver.h>
43 #include <serialize.h>
44 #include <span.h>
45 #include <streams.h>
48 #include <support/cleanse.h>
49 #include <sync.h>
50 #include <tinyformat.h>
51 #include <uint256.h>
52 #include <univalue.h>
53 #include <util/check.h>
54 #include <util/error.h>
55 #include <util/fs.h>
56 #include <util/fs_helpers.h>
57 #include <util/message.h>
58 #include <util/moneystr.h>
59 #include <util/result.h>
60 #include <util/string.h>
61 #include <util/time.h>
62 #include <util/translation.h>
63 #include <wallet/coincontrol.h>
64 #include <wallet/context.h>
65 #include <wallet/crypter.h>
66 #include <wallet/db.h>
68 #include <wallet/scriptpubkeyman.h>
69 #include <wallet/transaction.h>
70 #include <wallet/types.h>
71 #include <wallet/walletdb.h>
72 #include <wallet/walletutil.h>
73 
74 #include <algorithm>
75 #include <cassert>
76 #include <condition_variable>
77 #include <exception>
78 #include <optional>
79 #include <stdexcept>
80 #include <thread>
81 #include <tuple>
82 #include <variant>
83 
84 struct KeyOriginInfo;
85 
87 
88 namespace wallet {
89 
90 bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
91 {
92  common::SettingsValue setting_value = chain.getRwSetting("wallet");
93  if (!setting_value.isArray()) setting_value.setArray();
94  for (const common::SettingsValue& value : setting_value.getValues()) {
95  if (value.isStr() && value.get_str() == wallet_name) return true;
96  }
97  setting_value.push_back(wallet_name);
98  return chain.updateRwSetting("wallet", setting_value);
99 }
100 
101 bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
102 {
103  common::SettingsValue setting_value = chain.getRwSetting("wallet");
104  if (!setting_value.isArray()) return true;
106  for (const common::SettingsValue& value : setting_value.getValues()) {
107  if (!value.isStr() || value.get_str() != wallet_name) new_value.push_back(value);
108  }
109  if (new_value.size() == setting_value.size()) return true;
110  return chain.updateRwSetting("wallet", new_value);
111 }
112 
114  const std::string& wallet_name,
115  std::optional<bool> load_on_startup,
116  std::vector<bilingual_str>& warnings)
117 {
118  if (!load_on_startup) return;
119  if (load_on_startup.value() && !AddWalletSetting(chain, wallet_name)) {
120  warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
121  } else if (!load_on_startup.value() && !RemoveWalletSetting(chain, wallet_name)) {
122  warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
123  }
124 }
125 
132 {
133  if (chain.isInMempool(tx.GetHash())) {
134  tx.m_state = TxStateInMempool();
135  } else if (tx.state<TxStateInMempool>()) {
136  tx.m_state = TxStateInactive();
137  }
138 }
139 
140 bool AddWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet)
141 {
142  LOCK(context.wallets_mutex);
143  assert(wallet);
144  std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(context.wallets.begin(), context.wallets.end(), wallet);
145  if (i != context.wallets.end()) return false;
146  context.wallets.push_back(wallet);
147  wallet->ConnectScriptPubKeyManNotifiers();
148  wallet->NotifyCanGetAddressesChanged();
149  return true;
150 }
151 
152 bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
153 {
154  assert(wallet);
155 
156  interfaces::Chain& chain = wallet->chain();
157  std::string name = wallet->GetName();
158 
159  // Unregister with the validation interface which also drops shared pointers.
160  wallet->m_chain_notifications_handler.reset();
161  LOCK(context.wallets_mutex);
162  std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(), wallet);
163  if (i == context.wallets.end()) return false;
164  context.wallets.erase(i);
165 
166  // Write the wallet setting
167  UpdateWalletSetting(chain, name, load_on_start, warnings);
168 
169  return true;
170 }
171 
172 bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start)
173 {
174  std::vector<bilingual_str> warnings;
175  return RemoveWallet(context, wallet, load_on_start, warnings);
176 }
177 
178 std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext& context)
179 {
180  LOCK(context.wallets_mutex);
181  return context.wallets;
182 }
183 
184 std::shared_ptr<CWallet> GetDefaultWallet(WalletContext& context, size_t& count)
185 {
186  LOCK(context.wallets_mutex);
187  count = context.wallets.size();
188  return count == 1 ? context.wallets[0] : nullptr;
189 }
190 
191 std::shared_ptr<CWallet> GetWallet(WalletContext& context, const std::string& name)
192 {
193  LOCK(context.wallets_mutex);
194  for (const std::shared_ptr<CWallet>& wallet : context.wallets) {
195  if (wallet->GetName() == name) return wallet;
196  }
197  return nullptr;
198 }
199 
200 std::unique_ptr<interfaces::Handler> HandleLoadWallet(WalletContext& context, LoadWalletFn load_wallet)
201 {
202  LOCK(context.wallets_mutex);
203  auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
204  return interfaces::MakeCleanupHandler([&context, it] { LOCK(context.wallets_mutex); context.wallet_load_fns.erase(it); });
205 }
206 
207 void NotifyWalletLoaded(WalletContext& context, const std::shared_ptr<CWallet>& wallet)
208 {
209  LOCK(context.wallets_mutex);
210  for (auto& load_wallet : context.wallet_load_fns) {
211  load_wallet(interfaces::MakeWallet(context, wallet));
212  }
213 }
214 
217 static std::condition_variable g_wallet_release_cv;
218 static std::set<std::string> g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex);
219 static std::set<std::string> g_unloading_wallet_set GUARDED_BY(g_wallet_release_mutex);
220 
221 // Custom deleter for shared_ptr<CWallet>.
223 {
224  const std::string name = wallet->GetName();
225  wallet->WalletLogPrintf("Releasing wallet\n");
226  wallet->Flush();
227  delete wallet;
228  // Wallet is now released, notify UnloadWallet, if any.
229  {
231  if (g_unloading_wallet_set.erase(name) == 0) {
232  // UnloadWallet was not called for this wallet, all done.
233  return;
234  }
235  }
236  g_wallet_release_cv.notify_all();
237 }
238 
239 void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
240 {
241  // Mark wallet for unloading.
242  const std::string name = wallet->GetName();
243  {
245  auto it = g_unloading_wallet_set.insert(name);
246  assert(it.second);
247  }
248  // The wallet can be in use so it's not possible to explicitly unload here.
249  // Notify the unload intent so that all remaining shared pointers are
250  // released.
251  wallet->NotifyUnload();
252 
253  // Time to ditch our shared_ptr and wait for ReleaseWallet call.
254  wallet.reset();
255  {
257  while (g_unloading_wallet_set.count(name) == 1) {
258  g_wallet_release_cv.wait(lock);
259  }
260  }
261 }
262 
263 namespace {
264 std::shared_ptr<CWallet> LoadWalletInternal(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
265 {
266  try {
267  std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
268  if (!database) {
269  error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
270  return nullptr;
271  }
272 
273  context.chain->initMessage(_("Loading wallet…").translated);
274  std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), options.create_flags, error, warnings);
275  if (!wallet) {
276  error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error;
278  return nullptr;
279  }
280 
281  // Legacy wallets are being deprecated, warn if the loaded wallet is legacy
282  if (!wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
283  warnings.push_back(_("Wallet loaded successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future. Legacy wallets can be migrated to a descriptor wallet with migratewallet."));
284  }
285 
286  NotifyWalletLoaded(context, wallet);
287  AddWallet(context, wallet);
288  wallet->postInitProcess();
289 
290  // Write the wallet setting
291  UpdateWalletSetting(*context.chain, name, load_on_start, warnings);
292 
293  return wallet;
294  } catch (const std::runtime_error& e) {
295  error = Untranslated(e.what());
297  return nullptr;
298  }
299 }
300 
301 class FastWalletRescanFilter
302 {
303 public:
304  FastWalletRescanFilter(const CWallet& wallet) : m_wallet(wallet)
305  {
306  // fast rescanning via block filters is only supported by descriptor wallets right now
307  assert(!m_wallet.IsLegacy());
308 
309  // create initial filter with scripts from all ScriptPubKeyMans
310  for (auto spkm : m_wallet.GetAllScriptPubKeyMans()) {
311  auto desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
312  assert(desc_spkm != nullptr);
313  AddScriptPubKeys(desc_spkm);
314  // save each range descriptor's end for possible future filter updates
315  if (desc_spkm->IsHDEnabled()) {
316  m_last_range_ends.emplace(desc_spkm->GetID(), desc_spkm->GetEndRange());
317  }
318  }
319  }
320 
321  void UpdateIfNeeded()
322  {
323  // repopulate filter with new scripts if top-up has happened since last iteration
324  for (const auto& [desc_spkm_id, last_range_end] : m_last_range_ends) {
325  auto desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
326  assert(desc_spkm != nullptr);
327  int32_t current_range_end{desc_spkm->GetEndRange()};
328  if (current_range_end > last_range_end) {
329  AddScriptPubKeys(desc_spkm, last_range_end);
330  m_last_range_ends.at(desc_spkm->GetID()) = current_range_end;
331  }
332  }
333  }
334 
335  std::optional<bool> MatchesBlock(const uint256& block_hash) const
336  {
337  return m_wallet.chain().blockFilterMatchesAny(BlockFilterType::BASIC, block_hash, m_filter_set);
338  }
339 
340 private:
341  const CWallet& m_wallet;
348  std::map<uint256, int32_t> m_last_range_ends;
350 
351  void AddScriptPubKeys(const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
352  {
353  for (const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
354  m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
355  }
356  }
357 };
358 } // namespace
359 
360 std::shared_ptr<CWallet> LoadWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
361 {
362  auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(name));
363  if (!result.second) {
364  error = Untranslated("Wallet already loading.");
366  return nullptr;
367  }
368  auto wallet = LoadWalletInternal(context, name, load_on_start, options, status, error, warnings);
369  WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
370  return wallet;
371 }
372 
373 std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
374 {
375  uint64_t wallet_creation_flags = options.create_flags;
376  const SecureString& passphrase = options.create_passphrase;
377 
378  if (wallet_creation_flags & WALLET_FLAG_DESCRIPTORS) options.require_format = DatabaseFormat::SQLITE;
379 
380  // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
381  bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
382 
383  // Born encrypted wallets need to be created blank first.
384  if (!passphrase.empty()) {
385  wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
386  }
387 
388  // Private keys must be disabled for an external signer wallet
389  if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
390  error = Untranslated("Private keys must be disabled when using an external signer");
392  return nullptr;
393  }
394 
395  // Descriptor support must be enabled for an external signer wallet
396  if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DESCRIPTORS)) {
397  error = Untranslated("Descriptor support must be enabled when using an external signer");
399  return nullptr;
400  }
401 
402  // Do not allow a passphrase when private keys are disabled
403  if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
404  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.");
406  return nullptr;
407  }
408 
409  // Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
410  std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
411  if (!database) {
412  error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
414  return nullptr;
415  }
416 
417  // Make the wallet
418  context.chain->initMessage(_("Loading wallet…").translated);
419  std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), wallet_creation_flags, error, warnings);
420  if (!wallet) {
421  error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error;
423  return nullptr;
424  }
425 
426  // Encrypt the wallet
427  if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
428  if (!wallet->EncryptWallet(passphrase)) {
429  error = Untranslated("Error: Wallet created but failed to encrypt.");
431  return nullptr;
432  }
433  if (!create_blank) {
434  // Unlock the wallet
435  if (!wallet->Unlock(passphrase)) {
436  error = Untranslated("Error: Wallet was encrypted but could not be unlocked");
438  return nullptr;
439  }
440 
441  // Set a seed for the wallet
442  {
443  LOCK(wallet->cs_wallet);
444  if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
445  wallet->SetupDescriptorScriptPubKeyMans();
446  } else {
447  for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
448  if (!spk_man->SetupGeneration()) {
449  error = Untranslated("Unable to generate initial keys");
451  return nullptr;
452  }
453  }
454  }
455  }
456 
457  // Relock the wallet
458  wallet->Lock();
459  }
460  }
461 
462  NotifyWalletLoaded(context, wallet);
463  AddWallet(context, wallet);
464  wallet->postInitProcess();
465 
466  // Write the wallet settings
467  UpdateWalletSetting(*context.chain, name, load_on_start, warnings);
468 
469  // Legacy wallets are being deprecated, warn if a newly created wallet is legacy
470  if (!(wallet_creation_flags & WALLET_FLAG_DESCRIPTORS)) {
471  warnings.push_back(_("Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future."));
472  }
473 
474  status = DatabaseStatus::SUCCESS;
475  return wallet;
476 }
477 
478 std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& backup_file, const std::string& wallet_name, std::optional<bool> load_on_start, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
479 {
480  DatabaseOptions options;
481  ReadDatabaseArgs(*context.args, options);
482  options.require_existing = true;
483 
484  const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name));
485  auto wallet_file = wallet_path / "wallet.dat";
486  std::shared_ptr<CWallet> wallet;
487 
488  try {
489  if (!fs::exists(backup_file)) {
490  error = Untranslated("Backup file does not exist");
492  return nullptr;
493  }
494 
495  if (fs::exists(wallet_path) || !TryCreateDirectories(wallet_path)) {
496  error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(wallet_path)));
498  return nullptr;
499  }
500 
501  fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
502 
503  wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
504  } catch (const std::exception& e) {
505  assert(!wallet);
506  if (!error.empty()) error += Untranslated("\n");
507  error += strprintf(Untranslated("Unexpected exception: %s"), e.what());
508  }
509  if (!wallet) {
510  fs::remove_all(wallet_path);
511  }
512 
513  return wallet;
514 }
515 
521 const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
522 {
524  const auto it = mapWallet.find(hash);
525  if (it == mapWallet.end())
526  return nullptr;
527  return &(it->second);
528 }
529 
531 {
533  return;
534  }
535 
536  auto spk_man = GetLegacyScriptPubKeyMan();
537  if (!spk_man) {
538  return;
539  }
540 
541  spk_man->UpgradeKeyMetadata();
542  SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
543 }
544 
546 {
548  return;
549  }
550 
551  for (ScriptPubKeyMan* spkm : GetAllScriptPubKeyMans()) {
552  DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
553  desc_spkm->UpgradeDescriptorCache();
554  }
556 }
557 
558 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
559 {
560  CCrypter crypter;
561  CKeyingMaterial _vMasterKey;
562 
563  {
564  LOCK(cs_wallet);
565  for (const MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
566  {
567  if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
568  return false;
569  if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
570  continue; // try another master key
571  if (Unlock(_vMasterKey)) {
572  // Now that we've unlocked, upgrade the key metadata
574  // Now that we've unlocked, upgrade the descriptor cache
576  return true;
577  }
578  }
579  }
580  return false;
581 }
582 
583 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
584 {
585  bool fWasLocked = IsLocked();
586 
587  {
589  Lock();
590 
591  CCrypter crypter;
592  CKeyingMaterial _vMasterKey;
593  for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
594  {
595  if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
596  return false;
597  if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
598  return false;
599  if (Unlock(_vMasterKey))
600  {
601  constexpr MillisecondsDouble target{100};
602  auto start{SteadyClock::now()};
603  crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
604  pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
605 
606  start = SteadyClock::now();
607  crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
608  pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
609 
610  if (pMasterKey.second.nDeriveIterations < 25000)
611  pMasterKey.second.nDeriveIterations = 25000;
612 
613  WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
614 
615  if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
616  return false;
617  if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
618  return false;
619  WalletBatch(GetDatabase()).WriteMasterKey(pMasterKey.first, pMasterKey.second);
620  if (fWasLocked)
621  Lock();
622  return true;
623  }
624  }
625  }
626 
627  return false;
628 }
629 
631 {
632  // Don't update the best block until the chain is attached so that in case of a shutdown,
633  // the rescan will be restarted at next startup.
635  return;
636  }
637  WalletBatch batch(GetDatabase());
638  batch.WriteBestBlock(loc);
639 }
640 
641 void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in)
642 {
643  LOCK(cs_wallet);
644  if (nWalletVersion >= nVersion)
645  return;
646  WalletLogPrintf("Setting minversion to %d\n", nVersion);
647  nWalletVersion = nVersion;
648 
649  {
650  WalletBatch* batch = batch_in ? batch_in : new WalletBatch(GetDatabase());
651  if (nWalletVersion > 40000)
652  batch->WriteMinVersion(nWalletVersion);
653  if (!batch_in)
654  delete batch;
655  }
656 }
657 
658 std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
659 {
660  std::set<uint256> result;
662 
663  const auto it = mapWallet.find(txid);
664  if (it == mapWallet.end())
665  return result;
666  const CWalletTx& wtx = it->second;
667 
668  std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
669 
670  for (const CTxIn& txin : wtx.tx->vin)
671  {
672  if (mapTxSpends.count(txin.prevout) <= 1)
673  continue; // No conflict if zero or one spends
674  range = mapTxSpends.equal_range(txin.prevout);
675  for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
676  result.insert(_it->second);
677  }
678  return result;
679 }
680 
682 {
684  const Txid& txid = tx->GetHash();
685  for (unsigned int i = 0; i < tx->vout.size(); ++i) {
686  if (IsSpent(COutPoint(txid, i))) {
687  return true;
688  }
689  }
690  return false;
691 }
692 
694 {
695  GetDatabase().Flush();
696 }
697 
699 {
700  GetDatabase().Close();
701 }
702 
703 void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> range)
704 {
705  // We want all the wallet transactions in range to have the same metadata as
706  // the oldest (smallest nOrderPos).
707  // So: find smallest nOrderPos:
708 
709  int nMinOrderPos = std::numeric_limits<int>::max();
710  const CWalletTx* copyFrom = nullptr;
711  for (TxSpends::iterator it = range.first; it != range.second; ++it) {
712  const CWalletTx* wtx = &mapWallet.at(it->second);
713  if (wtx->nOrderPos < nMinOrderPos) {
714  nMinOrderPos = wtx->nOrderPos;
715  copyFrom = wtx;
716  }
717  }
718 
719  if (!copyFrom) {
720  return;
721  }
722 
723  // Now copy data from copyFrom to rest:
724  for (TxSpends::iterator it = range.first; it != range.second; ++it)
725  {
726  const uint256& hash = it->second;
727  CWalletTx* copyTo = &mapWallet.at(hash);
728  if (copyFrom == copyTo) continue;
729  assert(copyFrom && "Oldest wallet transaction in range assumed to have been found.");
730  if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
731  copyTo->mapValue = copyFrom->mapValue;
732  copyTo->vOrderForm = copyFrom->vOrderForm;
733  // fTimeReceivedIsTxTime not copied on purpose
734  // nTimeReceived not copied on purpose
735  copyTo->nTimeSmart = copyFrom->nTimeSmart;
736  copyTo->fFromMe = copyFrom->fFromMe;
737  // nOrderPos not copied on purpose
738  // cached members not copied on purpose
739  }
740 }
741 
746 bool CWallet::IsSpent(const COutPoint& outpoint) const
747 {
748  std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
749  range = mapTxSpends.equal_range(outpoint);
750 
751  for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
752  const uint256& wtxid = it->second;
753  const auto mit = mapWallet.find(wtxid);
754  if (mit != mapWallet.end()) {
755  const auto& wtx = mit->second;
756  if (!wtx.isAbandoned() && !wtx.isBlockConflicted() && !wtx.isMempoolConflicted())
757  return true; // Spent
758  }
759  }
760  return false;
761 }
762 
763 void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch)
764 {
765  mapTxSpends.insert(std::make_pair(outpoint, wtxid));
766 
767  if (batch) {
768  UnlockCoin(outpoint, batch);
769  } else {
770  WalletBatch temp_batch(GetDatabase());
771  UnlockCoin(outpoint, &temp_batch);
772  }
773 
774  std::pair<TxSpends::iterator, TxSpends::iterator> range;
775  range = mapTxSpends.equal_range(outpoint);
776  SyncMetaData(range);
777 }
778 
779 
781 {
782  if (wtx.IsCoinBase()) // Coinbases don't spend anything!
783  return;
784 
785  for (const CTxIn& txin : wtx.tx->vin)
786  AddToSpends(txin.prevout, wtx.GetHash(), batch);
787 }
788 
789 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
790 {
791  if (IsCrypted())
792  return false;
793 
794  CKeyingMaterial _vMasterKey;
795 
796  _vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
797  GetStrongRandBytes(_vMasterKey);
798 
799  CMasterKey kMasterKey;
800 
801  kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
802  GetStrongRandBytes(kMasterKey.vchSalt);
803 
804  CCrypter crypter;
805  constexpr MillisecondsDouble target{100};
806  auto start{SteadyClock::now()};
807  crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
808  kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
809 
810  start = SteadyClock::now();
811  crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
812  kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
813 
814  if (kMasterKey.nDeriveIterations < 25000)
815  kMasterKey.nDeriveIterations = 25000;
816 
817  WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
818 
819  if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
820  return false;
821  if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey))
822  return false;
823 
824  {
826  mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
827  WalletBatch* encrypted_batch = new WalletBatch(GetDatabase());
828  if (!encrypted_batch->TxnBegin()) {
829  delete encrypted_batch;
830  encrypted_batch = nullptr;
831  return false;
832  }
833  encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
834 
835  for (const auto& spk_man_pair : m_spk_managers) {
836  auto spk_man = spk_man_pair.second.get();
837  if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
838  encrypted_batch->TxnAbort();
839  delete encrypted_batch;
840  encrypted_batch = nullptr;
841  // We now probably have half of our keys encrypted in memory, and half not...
842  // die and let the user reload the unencrypted wallet.
843  assert(false);
844  }
845  }
846 
847  // Encryption was introduced in version 0.4.0
848  SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch);
849 
850  if (!encrypted_batch->TxnCommit()) {
851  delete encrypted_batch;
852  encrypted_batch = nullptr;
853  // We now have keys encrypted in memory, but not on disk...
854  // die to avoid confusion and let the user reload the unencrypted wallet.
855  assert(false);
856  }
857 
858  delete encrypted_batch;
859  encrypted_batch = nullptr;
860 
861  Lock();
862  Unlock(strWalletPassphrase);
863 
864  // If we are using descriptors, make new descriptors with a new seed
867  } else if (auto spk_man = GetLegacyScriptPubKeyMan()) {
868  // if we are using HD, replace the HD seed with a new one
869  if (spk_man->IsHDEnabled()) {
870  if (!spk_man->SetupGeneration(true)) {
871  return false;
872  }
873  }
874  }
875  Lock();
876 
877  // Need to completely rewrite the wallet file; if we don't, bdb might keep
878  // bits of the unencrypted private key in slack space in the database file.
879  GetDatabase().Rewrite();
880 
881  // BDB seems to have a bad habit of writing old data into
882  // slack space in .dat files; that is bad if the old data is
883  // unencrypted private keys. So:
885 
886  }
887  NotifyStatusChanged(this);
888 
889  return true;
890 }
891 
893 {
894  LOCK(cs_wallet);
895  WalletBatch batch(GetDatabase());
896 
897  // Old wallets didn't have any defined order for transactions
898  // Probably a bad idea to change the output of this
899 
900  // First: get all CWalletTx into a sorted-by-time multimap.
901  typedef std::multimap<int64_t, CWalletTx*> TxItems;
902  TxItems txByTime;
903 
904  for (auto& entry : mapWallet)
905  {
906  CWalletTx* wtx = &entry.second;
907  txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
908  }
909 
910  nOrderPosNext = 0;
911  std::vector<int64_t> nOrderPosOffsets;
912  for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
913  {
914  CWalletTx *const pwtx = (*it).second;
915  int64_t& nOrderPos = pwtx->nOrderPos;
916 
917  if (nOrderPos == -1)
918  {
919  nOrderPos = nOrderPosNext++;
920  nOrderPosOffsets.push_back(nOrderPos);
921 
922  if (!batch.WriteTx(*pwtx))
923  return DBErrors::LOAD_FAIL;
924  }
925  else
926  {
927  int64_t nOrderPosOff = 0;
928  for (const int64_t& nOffsetStart : nOrderPosOffsets)
929  {
930  if (nOrderPos >= nOffsetStart)
931  ++nOrderPosOff;
932  }
933  nOrderPos += nOrderPosOff;
934  nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
935 
936  if (!nOrderPosOff)
937  continue;
938 
939  // Since we're changing the order, write it back
940  if (!batch.WriteTx(*pwtx))
941  return DBErrors::LOAD_FAIL;
942  }
943  }
944  batch.WriteOrderPosNext(nOrderPosNext);
945 
946  return DBErrors::LOAD_OK;
947 }
948 
950 {
952  int64_t nRet = nOrderPosNext++;
953  if (batch) {
954  batch->WriteOrderPosNext(nOrderPosNext);
955  } else {
956  WalletBatch(GetDatabase()).WriteOrderPosNext(nOrderPosNext);
957  }
958  return nRet;
959 }
960 
962 {
963  {
964  LOCK(cs_wallet);
965  for (std::pair<const uint256, CWalletTx>& item : mapWallet)
966  item.second.MarkDirty();
967  }
968 }
969 
970 bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
971 {
972  LOCK(cs_wallet);
973 
974  auto mi = mapWallet.find(originalHash);
975 
976  // There is a bug if MarkReplaced is not called on an existing wallet transaction.
977  assert(mi != mapWallet.end());
978 
979  CWalletTx& wtx = (*mi).second;
980 
981  // Ensure for now that we're not overwriting data
982  assert(wtx.mapValue.count("replaced_by_txid") == 0);
983 
984  wtx.mapValue["replaced_by_txid"] = newHash.ToString();
985 
986  // Refresh mempool status without waiting for transactionRemovedFromMempool or transactionAddedToMempool
987  RefreshMempoolStatus(wtx, chain());
988 
989  WalletBatch batch(GetDatabase());
990 
991  bool success = true;
992  if (!batch.WriteTx(wtx)) {
993  WalletLogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
994  success = false;
995  }
996 
997  NotifyTransactionChanged(originalHash, CT_UPDATED);
998 
999  return success;
1000 }
1001 
1002 void CWallet::SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations)
1003 {
1005  const CWalletTx* srctx = GetWalletTx(hash);
1006  if (!srctx) return;
1007 
1008  CTxDestination dst;
1009  if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
1010  if (IsMine(dst)) {
1011  if (used != IsAddressPreviouslySpent(dst)) {
1012  if (used) {
1013  tx_destinations.insert(dst);
1014  }
1015  SetAddressPreviouslySpent(batch, dst, used);
1016  }
1017  }
1018  }
1019 }
1020 
1021 bool CWallet::IsSpentKey(const CScript& scriptPubKey) const
1022 {
1024  CTxDestination dest;
1025  if (!ExtractDestination(scriptPubKey, dest)) {
1026  return false;
1027  }
1028  if (IsAddressPreviouslySpent(dest)) {
1029  return true;
1030  }
1031  if (IsLegacy()) {
1033  assert(spk_man != nullptr);
1034  for (const auto& keyid : GetAffectedKeys(scriptPubKey, *spk_man)) {
1035  WitnessV0KeyHash wpkh_dest(keyid);
1036  if (IsAddressPreviouslySpent(wpkh_dest)) {
1037  return true;
1038  }
1039  ScriptHash sh_wpkh_dest(GetScriptForDestination(wpkh_dest));
1040  if (IsAddressPreviouslySpent(sh_wpkh_dest)) {
1041  return true;
1042  }
1043  PKHash pkh_dest(keyid);
1044  if (IsAddressPreviouslySpent(pkh_dest)) {
1045  return true;
1046  }
1047  }
1048  }
1049  return false;
1050 }
1051 
1052 CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const TxState& state, const UpdateWalletTxFn& update_wtx, bool fFlushOnClose, bool rescanning_old_block)
1053 {
1054  LOCK(cs_wallet);
1055 
1056  WalletBatch batch(GetDatabase(), fFlushOnClose);
1057 
1058  uint256 hash = tx->GetHash();
1059 
1061  // Mark used destinations
1062  std::set<CTxDestination> tx_destinations;
1063 
1064  for (const CTxIn& txin : tx->vin) {
1065  const COutPoint& op = txin.prevout;
1066  SetSpentKeyState(batch, op.hash, op.n, true, tx_destinations);
1067  }
1068 
1069  MarkDestinationsDirty(tx_destinations);
1070  }
1071 
1072  // Inserts only if not already there, returns tx inserted or tx found
1073  auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1074  CWalletTx& wtx = (*ret.first).second;
1075  bool fInsertedNew = ret.second;
1076  bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1077  if (fInsertedNew) {
1078  wtx.nTimeReceived = GetTime();
1079  wtx.nOrderPos = IncOrderPosNext(&batch);
1080  wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1081  wtx.nTimeSmart = ComputeTimeSmart(wtx, rescanning_old_block);
1082  AddToSpends(wtx, &batch);
1083 
1084  // Update birth time when tx time is older than it.
1086  }
1087 
1088  if (!fInsertedNew)
1089  {
1090  if (state.index() != wtx.m_state.index()) {
1091  wtx.m_state = state;
1092  fUpdated = true;
1093  } else {
1096  }
1097  // If we have a witness-stripped version of this transaction, and we
1098  // see a new version with a witness, then we must be upgrading a pre-segwit
1099  // wallet. Store the new version of the transaction with the witness,
1100  // as the stripped-version must be invalid.
1101  // TODO: Store all versions of the transaction, instead of just one.
1102  if (tx->HasWitness() && !wtx.tx->HasWitness()) {
1103  wtx.SetTx(tx);
1104  fUpdated = true;
1105  }
1106  }
1107 
1108  // Mark inactive coinbase transactions and their descendants as abandoned
1109  if (wtx.IsCoinBase() && wtx.isInactive()) {
1110  std::vector<CWalletTx*> txs{&wtx};
1111 
1112  TxStateInactive inactive_state = TxStateInactive{/*abandoned=*/true};
1113 
1114  while (!txs.empty()) {
1115  CWalletTx* desc_tx = txs.back();
1116  txs.pop_back();
1117  desc_tx->m_state = inactive_state;
1118  // Break caches since we have changed the state
1119  desc_tx->MarkDirty();
1120  batch.WriteTx(*desc_tx);
1121  MarkInputsDirty(desc_tx->tx);
1122  for (unsigned int i = 0; i < desc_tx->tx->vout.size(); ++i) {
1123  COutPoint outpoint(desc_tx->GetHash(), i);
1124  std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1125  for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1126  const auto wit = mapWallet.find(it->second);
1127  if (wit != mapWallet.end()) {
1128  txs.push_back(&wit->second);
1129  }
1130  }
1131  }
1132  }
1133  }
1134 
1136  WalletLogPrintf("AddToWallet %s %s%s %s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""), TxStateString(state));
1137 
1138  // Write to disk
1139  if (fInsertedNew || fUpdated)
1140  if (!batch.WriteTx(wtx))
1141  return nullptr;
1142 
1143  // Break debit/credit balance caches:
1144  wtx.MarkDirty();
1145 
1146  // Notify UI of new or updated transaction
1147  NotifyTransactionChanged(hash, fInsertedNew ? CT_NEW : CT_UPDATED);
1148 
1149 #if HAVE_SYSTEM
1150  // notify an external script when a wallet transaction comes in or is updated
1151  std::string strCmd = m_notify_tx_changed_script;
1152 
1153  if (!strCmd.empty())
1154  {
1155  ReplaceAll(strCmd, "%s", hash.GetHex());
1156  if (auto* conf = wtx.state<TxStateConfirmed>())
1157  {
1158  ReplaceAll(strCmd, "%b", conf->confirmed_block_hash.GetHex());
1159  ReplaceAll(strCmd, "%h", ToString(conf->confirmed_block_height));
1160  } else {
1161  ReplaceAll(strCmd, "%b", "unconfirmed");
1162  ReplaceAll(strCmd, "%h", "-1");
1163  }
1164 #ifndef WIN32
1165  // Substituting the wallet name isn't currently supported on windows
1166  // because windows shell escaping has not been implemented yet:
1167  // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-537384875
1168  // A few ways it could be implemented in the future are described in:
1169  // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-461288094
1170  ReplaceAll(strCmd, "%w", ShellEscape(GetName()));
1171 #endif
1172  std::thread t(runCommand, strCmd);
1173  t.detach(); // thread runs free
1174  }
1175 #endif
1176 
1177  return &wtx;
1178 }
1179 
1180 bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx)
1181 {
1182  const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(nullptr, TxStateInactive{}));
1183  CWalletTx& wtx = ins.first->second;
1184  if (!fill_wtx(wtx, ins.second)) {
1185  return false;
1186  }
1187  // If wallet doesn't have a chain (e.g when using bitcoin-wallet tool),
1188  // don't bother to update txn.
1189  if (HaveChain()) {
1190  wtx.updateState(chain());
1191  }
1192  if (/* insertion took place */ ins.second) {
1193  wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1194  }
1195  AddToSpends(wtx);
1196  for (const CTxIn& txin : wtx.tx->vin) {
1197  auto it = mapWallet.find(txin.prevout.hash);
1198  if (it != mapWallet.end()) {
1199  CWalletTx& prevtx = it->second;
1200  if (auto* prev = prevtx.state<TxStateBlockConflicted>()) {
1201  MarkConflicted(prev->conflicting_block_hash, prev->conflicting_block_height, wtx.GetHash());
1202  }
1203  }
1204  }
1205 
1206  // Update birth time when tx time is older than it.
1208 
1209  return true;
1210 }
1211 
1212 bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const SyncTxState& state, bool fUpdate, bool rescanning_old_block)
1213 {
1214  const CTransaction& tx = *ptx;
1215  {
1217 
1218  if (auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1219  for (const CTxIn& txin : tx.vin) {
1220  std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
1221  while (range.first != range.second) {
1222  if (range.first->second != tx.GetHash()) {
1223  WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), conf->confirmed_block_hash.ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
1224  MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1225  }
1226  range.first++;
1227  }
1228  }
1229  }
1230 
1231  bool fExisted = mapWallet.count(tx.GetHash()) != 0;
1232  if (fExisted && !fUpdate) return false;
1233  if (fExisted || IsMine(tx) || IsFromMe(tx))
1234  {
1235  /* Check if any keys in the wallet keypool that were supposed to be unused
1236  * have appeared in a new transaction. If so, remove those keys from the keypool.
1237  * This can happen when restoring an old wallet backup that does not contain
1238  * the mostly recently created transactions from newer versions of the wallet.
1239  */
1240 
1241  // loop though all outputs
1242  for (const CTxOut& txout: tx.vout) {
1243  for (const auto& spk_man : GetScriptPubKeyMans(txout.scriptPubKey)) {
1244  for (auto &dest : spk_man->MarkUnusedAddresses(txout.scriptPubKey)) {
1245  // If internal flag is not defined try to infer it from the ScriptPubKeyMan
1246  if (!dest.internal.has_value()) {
1247  dest.internal = IsInternalScriptPubKeyMan(spk_man);
1248  }
1249 
1250  // skip if can't determine whether it's a receiving address or not
1251  if (!dest.internal.has_value()) continue;
1252 
1253  // If this is a receiving address and it's not in the address book yet
1254  // (e.g. it wasn't generated on this node or we're restoring from backup)
1255  // add it to the address book for proper transaction accounting
1256  if (!*dest.internal && !FindAddressBookEntry(dest.dest, /* allow_change= */ false)) {
1257  SetAddressBook(dest.dest, "", AddressPurpose::RECEIVE);
1258  }
1259  }
1260  }
1261  }
1262 
1263  // Block disconnection override an abandoned tx as unconfirmed
1264  // which means user may have to call abandontransaction again
1265  TxState tx_state = std::visit([](auto&& s) -> TxState { return s; }, state);
1266  CWalletTx* wtx = AddToWallet(MakeTransactionRef(tx), tx_state, /*update_wtx=*/nullptr, /*fFlushOnClose=*/false, rescanning_old_block);
1267  if (!wtx) {
1268  // Can only be nullptr if there was a db write error (missing db, read-only db or a db engine internal writing error).
1269  // As we only store arriving transaction in this process, and we don't want an inconsistent state, let's throw an error.
1270  throw std::runtime_error("DB error adding transaction to wallet, write failed");
1271  }
1272  return true;
1273  }
1274  }
1275  return false;
1276 }
1277 
1279 {
1280  LOCK(cs_wallet);
1281  const CWalletTx* wtx = GetWalletTx(hashTx);
1282  return wtx && !wtx->isAbandoned() && GetTxDepthInMainChain(*wtx) == 0 && !wtx->InMempool();
1283 }
1284 
1286 {
1287  for (const CTxIn& txin : tx->vin) {
1288  auto it = mapWallet.find(txin.prevout.hash);
1289  if (it != mapWallet.end()) {
1290  it->second.MarkDirty();
1291  }
1292  }
1293 }
1294 
1296 {
1297  LOCK(cs_wallet);
1298 
1299  // Can't mark abandoned if confirmed or in mempool
1300  auto it = mapWallet.find(hashTx);
1301  assert(it != mapWallet.end());
1302  const CWalletTx& origtx = it->second;
1303  if (GetTxDepthInMainChain(origtx) != 0 || origtx.InMempool()) {
1304  return false;
1305  }
1306 
1307  auto try_updating_state = [](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1308  // If the orig tx was not in block/mempool, none of its spends can be.
1309  assert(!wtx.isConfirmed());
1310  assert(!wtx.InMempool());
1311  // If already conflicted or abandoned, no need to set abandoned
1312  if (!wtx.isBlockConflicted() && !wtx.isAbandoned()) {
1313  wtx.m_state = TxStateInactive{/*abandoned=*/true};
1314  return TxUpdate::NOTIFY_CHANGED;
1315  }
1316  return TxUpdate::UNCHANGED;
1317  };
1318 
1319  // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too.
1320  // States are not permanent, so these transactions can become unabandoned if they are re-added to the
1321  // mempool, or confirmed in a block, or conflicted.
1322  // Note: If the reorged coinbase is re-added to the main chain, the descendants that have not had their
1323  // states change will remain abandoned and will require manual broadcast if the user wants them.
1324 
1325  RecursiveUpdateTxState(hashTx, try_updating_state);
1326 
1327  return true;
1328 }
1329 
1330 void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
1331 {
1332  LOCK(cs_wallet);
1333 
1334  // If number of conflict confirms cannot be determined, this means
1335  // that the block is still unknown or not yet part of the main chain,
1336  // for example when loading the wallet during a reindex. Do nothing in that
1337  // case.
1338  if (m_last_block_processed_height < 0 || conflicting_height < 0) {
1339  return;
1340  }
1341  int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1342  if (conflictconfirms >= 0)
1343  return;
1344 
1345  auto try_updating_state = [&](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1346  if (conflictconfirms < GetTxDepthInMainChain(wtx)) {
1347  // Block is 'more conflicted' than current confirm; update.
1348  // Mark transaction as conflicted with this block.
1349  wtx.m_state = TxStateBlockConflicted{hashBlock, conflicting_height};
1350  return TxUpdate::CHANGED;
1351  }
1352  return TxUpdate::UNCHANGED;
1353  };
1354 
1355  // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too.
1356  RecursiveUpdateTxState(hashTx, try_updating_state);
1357 
1358 }
1359 
1360 void CWallet::RecursiveUpdateTxState(const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1361  // Do not flush the wallet here for performance reasons
1362  WalletBatch batch(GetDatabase(), false);
1363  RecursiveUpdateTxState(&batch, tx_hash, try_updating_state);
1364 }
1365 
1366 void CWallet::RecursiveUpdateTxState(WalletBatch* batch, const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1367  std::set<uint256> todo;
1368  std::set<uint256> done;
1369 
1370  todo.insert(tx_hash);
1371 
1372  while (!todo.empty()) {
1373  uint256 now = *todo.begin();
1374  todo.erase(now);
1375  done.insert(now);
1376  auto it = mapWallet.find(now);
1377  assert(it != mapWallet.end());
1378  CWalletTx& wtx = it->second;
1379 
1380  TxUpdate update_state = try_updating_state(wtx);
1381  if (update_state != TxUpdate::UNCHANGED) {
1382  wtx.MarkDirty();
1383  if (batch) batch->WriteTx(wtx);
1384  // Iterate over all its outputs, and update those tx states as well (if applicable)
1385  for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
1386  std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(Txid::FromUint256(now), i));
1387  for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1388  if (!done.count(iter->second)) {
1389  todo.insert(iter->second);
1390  }
1391  }
1392  }
1393 
1394  if (update_state == TxUpdate::NOTIFY_CHANGED) {
1396  }
1397 
1398  // If a transaction changes its tx state, that usually changes the balance
1399  // available of the outputs it spends. So force those to be recomputed
1400  MarkInputsDirty(wtx.tx);
1401  }
1402  }
1403 }
1404 
1405 void CWallet::SyncTransaction(const CTransactionRef& ptx, const SyncTxState& state, bool update_tx, bool rescanning_old_block)
1406 {
1407  if (!AddToWalletIfInvolvingMe(ptx, state, update_tx, rescanning_old_block))
1408  return; // Not one of ours
1409 
1410  // If a transaction changes 'conflicted' state, that changes the balance
1411  // available of the outputs it spends. So force those to be
1412  // recomputed, also:
1413  MarkInputsDirty(ptx);
1414 }
1415 
1417  LOCK(cs_wallet);
1419 
1420  auto it = mapWallet.find(tx->GetHash());
1421  if (it != mapWallet.end()) {
1422  RefreshMempoolStatus(it->second, chain());
1423  }
1424 
1425  const Txid& txid = tx->GetHash();
1426 
1427  for (const CTxIn& tx_in : tx->vin) {
1428  // For each wallet transaction spending this prevout..
1429  for (auto range = mapTxSpends.equal_range(tx_in.prevout); range.first != range.second; range.first++) {
1430  const uint256& spent_id = range.first->second;
1431  // Skip the recently added tx
1432  if (spent_id == txid) continue;
1433  RecursiveUpdateTxState(/*batch=*/nullptr, spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1434  return wtx.mempool_conflicts.insert(txid).second ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
1435  });
1436  }
1437  }
1438 }
1439 
1441  LOCK(cs_wallet);
1442  auto it = mapWallet.find(tx->GetHash());
1443  if (it != mapWallet.end()) {
1444  RefreshMempoolStatus(it->second, chain());
1445  }
1446  // Handle transactions that were removed from the mempool because they
1447  // conflict with transactions in a newly connected block.
1448  if (reason == MemPoolRemovalReason::CONFLICT) {
1449  // Trigger external -walletnotify notifications for these transactions.
1450  // Set Status::UNCONFIRMED instead of Status::CONFLICTED for a few reasons:
1451  //
1452  // 1. The transactionRemovedFromMempool callback does not currently
1453  // provide the conflicting block's hash and height, and for backwards
1454  // compatibility reasons it may not be not safe to store conflicted
1455  // wallet transactions with a null block hash. See
1456  // https://github.com/bitcoin/bitcoin/pull/18600#discussion_r420195993.
1457  // 2. For most of these transactions, the wallet's internal conflict
1458  // detection in the blockConnected handler will subsequently call
1459  // MarkConflicted and update them with CONFLICTED status anyway. This
1460  // applies to any wallet transaction that has inputs spent in the
1461  // block, or that has ancestors in the wallet with inputs spent by
1462  // the block.
1463  // 3. Longstanding behavior since the sync implementation in
1464  // https://github.com/bitcoin/bitcoin/pull/9371 and the prior sync
1465  // implementation before that was to mark these transactions
1466  // unconfirmed rather than conflicted.
1467  //
1468  // Nothing described above should be seen as an unchangeable requirement
1469  // when improving this code in the future. The wallet's heuristics for
1470  // distinguishing between conflicted and unconfirmed transactions are
1471  // imperfect, and could be improved in general, see
1472  // https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
1474  }
1475 
1476  const Txid& txid = tx->GetHash();
1477 
1478  for (const CTxIn& tx_in : tx->vin) {
1479  // Iterate over all wallet transactions spending txin.prev
1480  // and recursively mark them as no longer conflicting with
1481  // txid
1482  for (auto range = mapTxSpends.equal_range(tx_in.prevout); range.first != range.second; range.first++) {
1483  const uint256& spent_id = range.first->second;
1484 
1485  RecursiveUpdateTxState(/*batch=*/nullptr, spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1486  return wtx.mempool_conflicts.erase(txid) ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
1487  });
1488  }
1489  }
1490 }
1491 
1493 {
1494  if (role == ChainstateRole::BACKGROUND) {
1495  return;
1496  }
1497  assert(block.data);
1498  LOCK(cs_wallet);
1499 
1500  m_last_block_processed_height = block.height;
1501  m_last_block_processed = block.hash;
1502 
1503  // No need to scan block if it was created before the wallet birthday.
1504  // Uses chain max time and twice the grace period to adjust time for block time variability.
1505  if (block.chain_time_max < m_birth_time.load() - (TIMESTAMP_WINDOW * 2)) return;
1506 
1507  // Scan block
1508  for (size_t index = 0; index < block.data->vtx.size(); index++) {
1509  SyncTransaction(block.data->vtx[index], TxStateConfirmed{block.hash, block.height, static_cast<int>(index)});
1511  }
1512 }
1513 
1515 {
1516  assert(block.data);
1517  LOCK(cs_wallet);
1518 
1519  // At block disconnection, this will change an abandoned transaction to
1520  // be unconfirmed, whether or not the transaction is added back to the mempool.
1521  // User may have to call abandontransaction again. It may be addressed in the
1522  // future with a stickier abandoned state or even removing abandontransaction call.
1523  m_last_block_processed_height = block.height - 1;
1524  m_last_block_processed = *Assert(block.prev_hash);
1525 
1526  int disconnect_height = block.height;
1527 
1528  for (const CTransactionRef& ptx : Assert(block.data)->vtx) {
1530 
1531  for (const CTxIn& tx_in : ptx->vin) {
1532  // No other wallet transactions conflicted with this transaction
1533  if (mapTxSpends.count(tx_in.prevout) < 1) continue;
1534 
1535  std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.prevout);
1536 
1537  // For all of the spends that conflict with this transaction
1538  for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1539  CWalletTx& wtx = mapWallet.find(_it->second)->second;
1540 
1541  if (!wtx.isBlockConflicted()) continue;
1542 
1543  auto try_updating_state = [&](CWalletTx& tx) {
1544  if (!tx.isBlockConflicted()) return TxUpdate::UNCHANGED;
1545  if (tx.state<TxStateBlockConflicted>()->conflicting_block_height >= disconnect_height) {
1546  tx.m_state = TxStateInactive{};
1547  return TxUpdate::CHANGED;
1548  }
1549  return TxUpdate::UNCHANGED;
1550  };
1551 
1552  RecursiveUpdateTxState(wtx.tx->GetHash(), try_updating_state);
1553  }
1554  }
1555  }
1556 }
1557 
1559 {
1561 }
1562 
1563 void CWallet::BlockUntilSyncedToCurrentChain() const {
1565  // Skip the queue-draining stuff if we know we're caught up with
1566  // chain().Tip(), otherwise put a callback in the validation interface queue and wait
1567  // for the queue to drain enough to execute it (indicating we are caught up
1568  // at least with the time we entered this function).
1569  uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed);
1570  chain().waitForNotificationsIfTipChanged(last_block_hash);
1571 }
1572 
1573 // Note that this function doesn't distinguish between a 0-valued input,
1574 // and a not-"is mine" (according to the filter) input.
1575 CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
1576 {
1577  {
1578  LOCK(cs_wallet);
1579  const auto mi = mapWallet.find(txin.prevout.hash);
1580  if (mi != mapWallet.end())
1581  {
1582  const CWalletTx& prev = (*mi).second;
1583  if (txin.prevout.n < prev.tx->vout.size())
1584  if (IsMine(prev.tx->vout[txin.prevout.n]) & filter)
1585  return prev.tx->vout[txin.prevout.n].nValue;
1586  }
1587  }
1588  return 0;
1589 }
1590 
1591 isminetype CWallet::IsMine(const CTxOut& txout) const
1592 {
1594  return IsMine(txout.scriptPubKey);
1595 }
1596 
1598 {
1600  return IsMine(GetScriptForDestination(dest));
1601 }
1602 
1603 isminetype CWallet::IsMine(const CScript& script) const
1604 {
1606 
1607  // Search the cache so that IsMine is called only on the relevant SPKMs instead of on everything in m_spk_managers
1608  const auto& it = m_cached_spks.find(script);
1609  if (it != m_cached_spks.end()) {
1610  isminetype res = ISMINE_NO;
1611  for (const auto& spkm : it->second) {
1612  res = std::max(res, spkm->IsMine(script));
1613  }
1614  Assume(res == ISMINE_SPENDABLE);
1615  return res;
1616  }
1617 
1618  // Legacy wallet
1619  if (IsLegacy()) return GetLegacyScriptPubKeyMan()->IsMine(script);
1620 
1621  return ISMINE_NO;
1622 }
1623 
1624 bool CWallet::IsMine(const CTransaction& tx) const
1625 {
1627  for (const CTxOut& txout : tx.vout)
1628  if (IsMine(txout))
1629  return true;
1630  return false;
1631 }
1632 
1633 isminetype CWallet::IsMine(const COutPoint& outpoint) const
1634 {
1636  auto wtx = GetWalletTx(outpoint.hash);
1637  if (!wtx) {
1638  return ISMINE_NO;
1639  }
1640  if (outpoint.n >= wtx->tx->vout.size()) {
1641  return ISMINE_NO;
1642  }
1643  return IsMine(wtx->tx->vout[outpoint.n]);
1644 }
1645 
1646 bool CWallet::IsFromMe(const CTransaction& tx) const
1647 {
1648  return (GetDebit(tx, ISMINE_ALL) > 0);
1649 }
1650 
1651 CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
1652 {
1653  CAmount nDebit = 0;
1654  for (const CTxIn& txin : tx.vin)
1655  {
1656  nDebit += GetDebit(txin, filter);
1657  if (!MoneyRange(nDebit))
1658  throw std::runtime_error(std::string(__func__) + ": value out of range");
1659  }
1660  return nDebit;
1661 }
1662 
1664 {
1665  // All Active ScriptPubKeyMans must be HD for this to be true
1666  bool result = false;
1667  for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
1668  if (!spk_man->IsHDEnabled()) return false;
1669  result = true;
1670  }
1671  return result;
1672 }
1673 
1674 bool CWallet::CanGetAddresses(bool internal) const
1675 {
1676  LOCK(cs_wallet);
1677  if (m_spk_managers.empty()) return false;
1678  for (OutputType t : OUTPUT_TYPES) {
1679  auto spk_man = GetScriptPubKeyMan(t, internal);
1680  if (spk_man && spk_man->CanGetAddresses(internal)) {
1681  return true;
1682  }
1683  }
1684  return false;
1685 }
1686 
1687 void CWallet::SetWalletFlag(uint64_t flags)
1688 {
1689  LOCK(cs_wallet);
1690  m_wallet_flags |= flags;
1691  if (!WalletBatch(GetDatabase()).WriteWalletFlags(m_wallet_flags))
1692  throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1693 }
1694 
1695 void CWallet::UnsetWalletFlag(uint64_t flag)
1696 {
1697  WalletBatch batch(GetDatabase());
1698  UnsetWalletFlagWithDB(batch, flag);
1699 }
1700 
1701 void CWallet::UnsetWalletFlagWithDB(WalletBatch& batch, uint64_t flag)
1702 {
1703  LOCK(cs_wallet);
1704  m_wallet_flags &= ~flag;
1705  if (!batch.WriteWalletFlags(m_wallet_flags))
1706  throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1707 }
1708 
1710 {
1712 }
1713 
1714 bool CWallet::IsWalletFlagSet(uint64_t flag) const
1715 {
1716  return (m_wallet_flags & flag);
1717 }
1718 
1720 {
1721  LOCK(cs_wallet);
1722  if (((flags & KNOWN_WALLET_FLAGS) >> 32) ^ (flags >> 32)) {
1723  // contains unknown non-tolerable wallet flags
1724  return false;
1725  }
1727 
1728  return true;
1729 }
1730 
1732 {
1733  LOCK(cs_wallet);
1734 
1735  // We should never be writing unknown non-tolerable wallet flags
1736  assert(((flags & KNOWN_WALLET_FLAGS) >> 32) == (flags >> 32));
1737  // This should only be used once, when creating a new wallet - so current flags are expected to be blank
1738  assert(m_wallet_flags == 0);
1739 
1740  if (!WalletBatch(GetDatabase()).WriteWalletFlags(flags)) {
1741  throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1742  }
1743 
1744  if (!LoadWalletFlags(flags)) assert(false);
1745 }
1746 
1747 bool CWallet::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
1748 {
1749  auto spk_man = GetLegacyScriptPubKeyMan();
1750  if (!spk_man) {
1751  return false;
1752  }
1753  LOCK(spk_man->cs_KeyStore);
1754  return spk_man->ImportScripts(scripts, timestamp);
1755 }
1756 
1757 bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp)
1758 {
1759  auto spk_man = GetLegacyScriptPubKeyMan();
1760  if (!spk_man) {
1761  return false;
1762  }
1763  LOCK(spk_man->cs_KeyStore);
1764  return spk_man->ImportPrivKeys(privkey_map, timestamp);
1765 }
1766 
1767 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)
1768 {
1769  auto spk_man = GetLegacyScriptPubKeyMan();
1770  if (!spk_man) {
1771  return false;
1772  }
1773  LOCK(spk_man->cs_KeyStore);
1774  return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, internal, timestamp);
1775 }
1776 
1777 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)
1778 {
1779  auto spk_man = GetLegacyScriptPubKeyMan();
1780  if (!spk_man) {
1781  return false;
1782  }
1783  LOCK(spk_man->cs_KeyStore);
1784  if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1785  return false;
1786  }
1787  if (apply_label) {
1788  WalletBatch batch(GetDatabase());
1789  for (const CScript& script : script_pub_keys) {
1790  CTxDestination dest;
1791  ExtractDestination(script, dest);
1792  if (IsValidDestination(dest)) {
1793  SetAddressBookWithDB(batch, dest, label, AddressPurpose::RECEIVE);
1794  }
1795  }
1796  }
1797  return true;
1798 }
1799 
1801 {
1802  int64_t birthtime = m_birth_time.load();
1803  if (time < birthtime) {
1804  m_birth_time = time;
1805  }
1806 }
1807 
1816 int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
1817 {
1818  // Find starting block. May be null if nCreateTime is greater than the
1819  // highest blockchain timestamp, in which case there is nothing that needs
1820  // to be scanned.
1821  int start_height = 0;
1822  uint256 start_block;
1823  bool start = chain().findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, FoundBlock().hash(start_block).height(start_height));
1824  WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) - start_height + 1 : 0);
1825 
1826  if (start) {
1827  // TODO: this should take into account failure by ScanResult::USER_ABORT
1828  ScanResult result = ScanForWalletTransactions(start_block, start_height, /*max_height=*/{}, reserver, /*fUpdate=*/update, /*save_progress=*/false);
1829  if (result.status == ScanResult::FAILURE) {
1830  int64_t time_max;
1831  CHECK_NONFATAL(chain().findBlock(result.last_failed_block, FoundBlock().maxTime(time_max)));
1832  return time_max + TIMESTAMP_WINDOW + 1;
1833  }
1834  }
1835  return startTime;
1836 }
1837 
1860 CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate, const bool save_progress)
1861 {
1862  constexpr auto INTERVAL_TIME{60s};
1863  auto current_time{reserver.now()};
1864  auto start_time{reserver.now()};
1865 
1866  assert(reserver.isReserved());
1867 
1868  uint256 block_hash = start_block;
1869  ScanResult result;
1870 
1871  std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1872  if (!IsLegacy() && chain().hasBlockFilterIndex(BlockFilterType::BASIC)) fast_rescan_filter = std::make_unique<FastWalletRescanFilter>(*this);
1873 
1874  WalletLogPrintf("Rescan started from block %s... (%s)\n", start_block.ToString(),
1875  fast_rescan_filter ? "fast variant using block filters" : "slow variant inspecting all blocks");
1876 
1877  fAbortRescan = false;
1878  ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if rescan required on startup (e.g. due to corruption)
1879  uint256 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1880  uint256 end_hash = tip_hash;
1881  if (max_height) chain().findAncestorByHeight(tip_hash, *max_height, FoundBlock().hash(end_hash));
1882  double progress_begin = chain().guessVerificationProgress(block_hash);
1883  double progress_end = chain().guessVerificationProgress(end_hash);
1884  double progress_current = progress_begin;
1885  int block_height = start_height;
1886  while (!fAbortRescan && !chain().shutdownRequested()) {
1887  if (progress_end - progress_begin > 0.0) {
1888  m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1889  } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal)
1890  m_scanning_progress = 0;
1891  }
1892  if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1893  ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
1894  }
1895 
1896  bool next_interval = reserver.now() >= current_time + INTERVAL_TIME;
1897  if (next_interval) {
1898  current_time = reserver.now();
1899  WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1900  }
1901 
1902  bool fetch_block{true};
1903  if (fast_rescan_filter) {
1904  fast_rescan_filter->UpdateIfNeeded();
1905  auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1906  if (matches_block.has_value()) {
1907  if (*matches_block) {
1908  LogPrint(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (filter matched)\n", block_height, block_hash.ToString());
1909  } else {
1910  result.last_scanned_block = block_hash;
1911  result.last_scanned_height = block_height;
1912  fetch_block = false;
1913  }
1914  } else {
1915  LogPrint(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.ToString());
1916  }
1917  }
1918 
1919  // Find next block separately from reading data above, because reading
1920  // is slow and there might be a reorg while it is read.
1921  bool block_still_active = false;
1922  bool next_block = false;
1923  uint256 next_block_hash;
1924  chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
1925 
1926  if (fetch_block) {
1927  // Read block data
1928  CBlock block;
1929  chain().findBlock(block_hash, FoundBlock().data(block));
1930 
1931  if (!block.IsNull()) {
1932  LOCK(cs_wallet);
1933  if (!block_still_active) {
1934  // Abort scan if current block is no longer active, to prevent
1935  // marking transactions as coming from the wrong block.
1936  result.last_failed_block = block_hash;
1937  result.status = ScanResult::FAILURE;
1938  break;
1939  }
1940  for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
1941  SyncTransaction(block.vtx[posInBlock], TxStateConfirmed{block_hash, block_height, static_cast<int>(posInBlock)}, fUpdate, /*rescanning_old_block=*/true);
1942  }
1943  // scan succeeded, record block as most recent successfully scanned
1944  result.last_scanned_block = block_hash;
1945  result.last_scanned_height = block_height;
1946 
1947  if (save_progress && next_interval) {
1948  CBlockLocator loc = m_chain->getActiveChainLocator(block_hash);
1949 
1950  if (!loc.IsNull()) {
1951  WalletLogPrintf("Saving scan progress %d.\n", block_height);
1952  WalletBatch batch(GetDatabase());
1953  batch.WriteBestBlock(loc);
1954  }
1955  }
1956  } else {
1957  // could not scan block, keep scanning but record this block as the most recent failure
1958  result.last_failed_block = block_hash;
1959  result.status = ScanResult::FAILURE;
1960  }
1961  }
1962  if (max_height && block_height >= *max_height) {
1963  break;
1964  }
1965  {
1966  if (!next_block) {
1967  // break successfully when rescan has reached the tip, or
1968  // previous block is no longer on the chain due to a reorg
1969  break;
1970  }
1971 
1972  // increment block and verification progress
1973  block_hash = next_block_hash;
1974  ++block_height;
1975  progress_current = chain().guessVerificationProgress(block_hash);
1976 
1977  // handle updated tip hash
1978  const uint256 prev_tip_hash = tip_hash;
1979  tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1980  if (!max_height && prev_tip_hash != tip_hash) {
1981  // in case the tip has changed, update progress max
1982  progress_end = chain().guessVerificationProgress(tip_hash);
1983  }
1984  }
1985  }
1986  if (!max_height) {
1987  WalletLogPrintf("Scanning current mempool transactions.\n");
1988  WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
1989  }
1990  ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), 100); // hide progress dialog in GUI
1991  if (block_height && fAbortRescan) {
1992  WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1993  result.status = ScanResult::USER_ABORT;
1994  } else if (block_height && chain().shutdownRequested()) {
1995  WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1996  result.status = ScanResult::USER_ABORT;
1997  } else {
1998  WalletLogPrintf("Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.now() - start_time));
1999  }
2000  return result;
2001 }
2002 
2003 bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const
2004 {
2006 
2007  // Can't relay if wallet is not broadcasting
2008  if (!GetBroadcastTransactions()) return false;
2009  // Don't relay abandoned transactions
2010  if (wtx.isAbandoned()) return false;
2011  // Don't try to submit coinbase transactions. These would fail anyway but would
2012  // cause log spam.
2013  if (wtx.IsCoinBase()) return false;
2014  // Don't try to submit conflicted or confirmed transactions.
2015  if (GetTxDepthInMainChain(wtx) != 0) return false;
2016 
2017  // Submit transaction to mempool for relay
2018  WalletLogPrintf("Submitting wtx %s to mempool for relay\n", wtx.GetHash().ToString());
2019  // We must set TxStateInMempool here. Even though it will also be set later by the
2020  // entered-mempool callback, if we did not there would be a race where a
2021  // user could call sendmoney in a loop and hit spurious out of funds errors
2022  // because we think that this newly generated transaction's change is
2023  // unavailable as we're not yet aware that it is in the mempool.
2024  //
2025  // If broadcast fails for any reason, trying to set wtx.m_state here would be incorrect.
2026  // If transaction was previously in the mempool, it should be updated when
2027  // TransactionRemovedFromMempool fires.
2028  bool ret = chain().broadcastTransaction(wtx.tx, m_default_max_tx_fee, relay, err_string);
2029  if (ret) wtx.m_state = TxStateInMempool{};
2030  return ret;
2031 }
2032 
2033 std::set<uint256> CWallet::GetTxConflicts(const CWalletTx& wtx) const
2034 {
2036 
2037  const uint256 myHash{wtx.GetHash()};
2038  std::set<uint256> result{GetConflicts(myHash)};
2039  result.erase(myHash);
2040  return result;
2041 }
2042 
2044 {
2045  // Don't attempt to resubmit if the wallet is configured to not broadcast
2046  if (!fBroadcastTransactions) return false;
2047 
2048  // During reindex, importing and IBD, old wallet transactions become
2049  // unconfirmed. Don't resend them as that would spam other nodes.
2050  // We only allow forcing mempool submission when not relaying to avoid this spam.
2051  if (!chain().isReadyToBroadcast()) return false;
2052 
2053  // Do this infrequently and randomly to avoid giving away
2054  // that these are our transactions.
2055  if (NodeClock::now() < m_next_resend) return false;
2056 
2057  return true;
2058 }
2059 
2061 
2062 // Resubmit transactions from the wallet to the mempool, optionally asking the
2063 // mempool to relay them. On startup, we will do this for all unconfirmed
2064 // transactions but will not ask the mempool to relay them. We do this on startup
2065 // to ensure that our own mempool is aware of our transactions. There
2066 // is a privacy side effect here as not broadcasting on startup also means that we won't
2067 // inform the world of our wallet's state, particularly if the wallet (or node) is not
2068 // yet synced.
2069 //
2070 // Otherwise this function is called periodically in order to relay our unconfirmed txs.
2071 // We do this on a random timer to slightly obfuscate which transactions
2072 // come from our wallet.
2073 //
2074 // TODO: Ideally, we'd only resend transactions that we think should have been
2075 // mined in the most recent block. Any transaction that wasn't in the top
2076 // blockweight of transactions in the mempool shouldn't have been mined,
2077 // and so is probably just sitting in the mempool waiting to be confirmed.
2078 // Rebroadcasting does nothing to speed up confirmation and only damages
2079 // privacy.
2080 //
2081 // The `force` option results in all unconfirmed transactions being submitted to
2082 // the mempool. This does not necessarily result in those transactions being relayed,
2083 // that depends on the `relay` option. Periodic rebroadcast uses the pattern
2084 // relay=true force=false, while loading into the mempool
2085 // (on start, or after import) uses relay=false force=true.
2086 void CWallet::ResubmitWalletTransactions(bool relay, bool force)
2087 {
2088  // Don't attempt to resubmit if the wallet is configured to not broadcast,
2089  // even if forcing.
2090  if (!fBroadcastTransactions) return;
2091 
2092  int submitted_tx_count = 0;
2093 
2094  { // cs_wallet scope
2095  LOCK(cs_wallet);
2096 
2097  // First filter for the transactions we want to rebroadcast.
2098  // We use a set with WalletTxOrderComparator so that rebroadcasting occurs in insertion order
2099  std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2100  for (auto& [txid, wtx] : mapWallet) {
2101  // Only rebroadcast unconfirmed txs
2102  if (!wtx.isUnconfirmed()) continue;
2103 
2104  // Attempt to rebroadcast all txes more than 5 minutes older than
2105  // the last block, or all txs if forcing.
2106  if (!force && wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
2107  to_submit.insert(&wtx);
2108  }
2109  // Now try submitting the transactions to the memory pool and (optionally) relay them.
2110  for (auto wtx : to_submit) {
2111  std::string unused_err_string;
2112  if (SubmitTxMemoryPoolAndRelay(*wtx, unused_err_string, relay)) ++submitted_tx_count;
2113  }
2114  } // cs_wallet
2115 
2116  if (submitted_tx_count > 0) {
2117  WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2118  }
2119 }
2120  // end of mapWallet
2122 
2124 {
2125  for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
2126  if (!pwallet->ShouldResend()) continue;
2127  pwallet->ResubmitWalletTransactions(/*relay=*/true, /*force=*/false);
2128  pwallet->SetNextResend();
2129  }
2130 }
2131 
2132 
2139 {
2141 
2142  // Build coins map
2143  std::map<COutPoint, Coin> coins;
2144  for (auto& input : tx.vin) {
2145  const auto mi = mapWallet.find(input.prevout.hash);
2146  if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2147  return false;
2148  }
2149  const CWalletTx& wtx = mi->second;
2150  int prev_height = wtx.state<TxStateConfirmed>() ? wtx.state<TxStateConfirmed>()->confirmed_block_height : 0;
2151  coins[input.prevout] = Coin(wtx.tx->vout[input.prevout.n], prev_height, wtx.IsCoinBase());
2152  }
2153  std::map<int, bilingual_str> input_errors;
2154  return SignTransaction(tx, coins, SIGHASH_DEFAULT, input_errors);
2155 }
2156 
2157 bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
2158 {
2159  // Try to sign with all ScriptPubKeyMans
2160  for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
2161  // spk_man->SignTransaction will return true if the transaction is complete,
2162  // so we can exit early and return true if that happens
2163  if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2164  return true;
2165  }
2166  }
2167 
2168  // At this point, one input was not fully signed otherwise we would have exited already
2169  return false;
2170 }
2171 
2172 TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs, size_t * n_signed, bool finalize) const
2173 {
2174  if (n_signed) {
2175  *n_signed = 0;
2176  }
2177  LOCK(cs_wallet);
2178  // Get all of the previous transactions
2179  for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
2180  const CTxIn& txin = psbtx.tx->vin[i];
2181  PSBTInput& input = psbtx.inputs.at(i);
2182 
2183  if (PSBTInputSigned(input)) {
2184  continue;
2185  }
2186 
2187  // If we have no utxo, grab it from the wallet.
2188  if (!input.non_witness_utxo) {
2189  const uint256& txhash = txin.prevout.hash;
2190  const auto it = mapWallet.find(txhash);
2191  if (it != mapWallet.end()) {
2192  const CWalletTx& wtx = it->second;
2193  // We only need the non_witness_utxo, which is a superset of the witness_utxo.
2194  // The signing code will switch to the smaller witness_utxo if this is ok.
2195  input.non_witness_utxo = wtx.tx;
2196  }
2197  }
2198  }
2199 
2200  const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
2201 
2202  // Fill in information from ScriptPubKeyMans
2203  for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
2204  int n_signed_this_spkm = 0;
2205  TransactionError res = spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm, finalize);
2206  if (res != TransactionError::OK) {
2207  return res;
2208  }
2209 
2210  if (n_signed) {
2211  (*n_signed) += n_signed_this_spkm;
2212  }
2213  }
2214 
2215  RemoveUnnecessaryTransactions(psbtx, sighash_type);
2216 
2217  // Complete if every input is now signed
2218  complete = true;
2219  for (const auto& input : psbtx.inputs) {
2220  complete &= PSBTInputSigned(input);
2221  }
2222 
2223  return TransactionError::OK;
2224 }
2225 
2226 SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
2227 {
2228  SignatureData sigdata;
2229  CScript script_pub_key = GetScriptForDestination(pkhash);
2230  for (const auto& spk_man_pair : m_spk_managers) {
2231  if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2232  LOCK(cs_wallet); // DescriptorScriptPubKeyMan calls IsLocked which can lock cs_wallet in a deadlocking order
2233  return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2234  }
2235  }
2237 }
2238 
2239 OutputType CWallet::TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const
2240 {
2241  // If -changetype is specified, always use that change type.
2242  if (change_type) {
2243  return *change_type;
2244  }
2245 
2246  // if m_default_address_type is legacy, use legacy address as change.
2248  return OutputType::LEGACY;
2249  }
2250 
2251  bool any_tr{false};
2252  bool any_wpkh{false};
2253  bool any_sh{false};
2254  bool any_pkh{false};
2255 
2256  for (const auto& recipient : vecSend) {
2257  if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2258  any_tr = true;
2259  } else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2260  any_wpkh = true;
2261  } else if (std::get_if<ScriptHash>(&recipient.dest)) {
2262  any_sh = true;
2263  } else if (std::get_if<PKHash>(&recipient.dest)) {
2264  any_pkh = true;
2265  }
2266  }
2267 
2268  const bool has_bech32m_spkman(GetScriptPubKeyMan(OutputType::BECH32M, /*internal=*/true));
2269  if (has_bech32m_spkman && any_tr) {
2270  // Currently tr is the only type supported by the BECH32M spkman
2271  return OutputType::BECH32M;
2272  }
2273  const bool has_bech32_spkman(GetScriptPubKeyMan(OutputType::BECH32, /*internal=*/true));
2274  if (has_bech32_spkman && any_wpkh) {
2275  // Currently wpkh is the only type supported by the BECH32 spkman
2276  return OutputType::BECH32;
2277  }
2278  const bool has_p2sh_segwit_spkman(GetScriptPubKeyMan(OutputType::P2SH_SEGWIT, /*internal=*/true));
2279  if (has_p2sh_segwit_spkman && any_sh) {
2280  // Currently sh_wpkh is the only type supported by the P2SH_SEGWIT spkman
2281  // As of 2021 about 80% of all SH are wrapping WPKH, so use that
2282  return OutputType::P2SH_SEGWIT;
2283  }
2284  const bool has_legacy_spkman(GetScriptPubKeyMan(OutputType::LEGACY, /*internal=*/true));
2285  if (has_legacy_spkman && any_pkh) {
2286  // Currently pkh is the only type supported by the LEGACY spkman
2287  return OutputType::LEGACY;
2288  }
2289 
2290  if (has_bech32m_spkman) {
2291  return OutputType::BECH32M;
2292  }
2293  if (has_bech32_spkman) {
2294  return OutputType::BECH32;
2295  }
2296  // else use m_default_address_type for change
2297  return m_default_address_type;
2298 }
2299 
2300 void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
2301 {
2302  LOCK(cs_wallet);
2303  WalletLogPrintf("CommitTransaction:\n%s", tx->ToString()); // NOLINT(bitcoin-unterminated-logprintf)
2304 
2305  // Add tx to wallet, because if it has change it's also ours,
2306  // otherwise just for transaction history.
2307  CWalletTx* wtx = AddToWallet(tx, TxStateInactive{}, [&](CWalletTx& wtx, bool new_tx) {
2308  CHECK_NONFATAL(wtx.mapValue.empty());
2309  CHECK_NONFATAL(wtx.vOrderForm.empty());
2310  wtx.mapValue = std::move(mapValue);
2311  wtx.vOrderForm = std::move(orderForm);
2312  wtx.fTimeReceivedIsTxTime = true;
2313  wtx.fFromMe = true;
2314  return true;
2315  });
2316 
2317  // wtx can only be null if the db write failed.
2318  if (!wtx) {
2319  throw std::runtime_error(std::string(__func__) + ": Wallet db error, transaction commit failed");
2320  }
2321 
2322  // Notify that old coins are spent
2323  for (const CTxIn& txin : tx->vin) {
2324  CWalletTx &coin = mapWallet.at(txin.prevout.hash);
2325  coin.MarkDirty();
2327  }
2328 
2329  if (!fBroadcastTransactions) {
2330  // Don't submit tx to the mempool
2331  return;
2332  }
2333 
2334  std::string err_string;
2335  if (!SubmitTxMemoryPoolAndRelay(*wtx, err_string, true)) {
2336  WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2337  // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
2338  }
2339 }
2340 
2342 {
2343  LOCK(cs_wallet);
2344 
2345  Assert(m_spk_managers.empty());
2346  Assert(m_wallet_flags == 0);
2347  DBErrors nLoadWalletRet = WalletBatch(GetDatabase()).LoadWallet(this);
2348  if (nLoadWalletRet == DBErrors::NEED_REWRITE)
2349  {
2350  if (GetDatabase().Rewrite("\x04pool"))
2351  {
2352  for (const auto& spk_man_pair : m_spk_managers) {
2353  spk_man_pair.second->RewriteDB();
2354  }
2355  }
2356  }
2357 
2358  if (m_spk_managers.empty()) {
2361  }
2362 
2363  return nLoadWalletRet;
2364 }
2365 
2366 util::Result<void> CWallet::RemoveTxs(std::vector<uint256>& txs_to_remove)
2367 {
2369  WalletBatch batch(GetDatabase());
2370  if (!batch.TxnBegin()) return util::Error{_("Error starting db txn for wallet transactions removal")};
2371 
2372  // Check for transaction existence and remove entries from disk
2373  using TxIterator = std::unordered_map<uint256, CWalletTx, SaltedTxidHasher>::const_iterator;
2374  std::vector<TxIterator> erased_txs;
2375  bilingual_str str_err;
2376  for (const uint256& hash : txs_to_remove) {
2377  auto it_wtx = mapWallet.find(hash);
2378  if (it_wtx == mapWallet.end()) {
2379  str_err = strprintf(_("Transaction %s does not belong to this wallet"), hash.GetHex());
2380  break;
2381  }
2382  if (!batch.EraseTx(hash)) {
2383  str_err = strprintf(_("Failure removing transaction: %s"), hash.GetHex());
2384  break;
2385  }
2386  erased_txs.emplace_back(it_wtx);
2387  }
2388 
2389  // Roll back removals in case of an error
2390  if (!str_err.empty()) {
2391  batch.TxnAbort();
2392  return util::Error{str_err};
2393  }
2394 
2395  // Dump changes to disk
2396  if (!batch.TxnCommit()) return util::Error{_("Error committing db txn for wallet transactions removal")};
2397 
2398  // Update the in-memory state and notify upper layers about the removals
2399  for (const auto& it : erased_txs) {
2400  const uint256 hash{it->first};
2401  wtxOrdered.erase(it->second.m_it_wtxOrdered);
2402  for (const auto& txin : it->second.tx->vin)
2403  mapTxSpends.erase(txin.prevout);
2404  mapWallet.erase(it);
2406  }
2407 
2408  MarkDirty();
2409 
2410  return {}; // all good
2411 }
2412 
2413 bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::optional<AddressPurpose>& new_purpose)
2414 {
2415  bool fUpdated = false;
2416  bool is_mine;
2417  std::optional<AddressPurpose> purpose;
2418  {
2419  LOCK(cs_wallet);
2420  std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2421  fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2422 
2423  CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2424  record.SetLabel(strName);
2425  is_mine = IsMine(address) != ISMINE_NO;
2426  if (new_purpose) { /* update purpose only if requested */
2427  record.purpose = new_purpose;
2428  }
2429  purpose = record.purpose;
2430  }
2431 
2432  const std::string& encoded_dest = EncodeDestination(address);
2433  if (new_purpose && !batch.WritePurpose(encoded_dest, PurposeToString(*new_purpose))) {
2434  WalletLogPrintf("Error: fail to write address book 'purpose' entry\n");
2435  return false;
2436  }
2437  if (!batch.WriteName(encoded_dest, strName)) {
2438  WalletLogPrintf("Error: fail to write address book 'name' entry\n");
2439  return false;
2440  }
2441 
2442  // In very old wallets, address purpose may not be recorded so we derive it from IsMine
2443  NotifyAddressBookChanged(address, strName, is_mine,
2444  purpose.value_or(is_mine ? AddressPurpose::RECEIVE : AddressPurpose::SEND),
2445  (fUpdated ? CT_UPDATED : CT_NEW));
2446  return true;
2447 }
2448 
2449 bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& strName, const std::optional<AddressPurpose>& purpose)
2450 {
2451  WalletBatch batch(GetDatabase());
2452  return SetAddressBookWithDB(batch, address, strName, purpose);
2453 }
2454 
2456 {
2457  return RunWithinTxn(GetDatabase(), /*process_desc=*/"address book entry removal", [&](WalletBatch& batch){
2458  return DelAddressBookWithDB(batch, address);
2459  });
2460 }
2461 
2463 {
2464  const std::string& dest = EncodeDestination(address);
2465  {
2466  LOCK(cs_wallet);
2467  // If we want to delete receiving addresses, we should avoid calling EraseAddressData because it will delete the previously_spent value. Could instead just erase the label so it becomes a change address, and keep the data.
2468  // NOTE: This isn't a problem for sending addresses because they don't have any data that needs to be kept.
2469  // When adding new address data, it should be considered here whether to retain or delete it.
2470  if (IsMine(address)) {
2471  WalletLogPrintf("%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, PACKAGE_BUGREPORT);
2472  return false;
2473  }
2474  // Delete data rows associated with this address
2475  if (!batch.EraseAddressData(address)) {
2476  WalletLogPrintf("Error: cannot erase address book entry data\n");
2477  return false;
2478  }
2479 
2480  // Delete purpose entry
2481  if (!batch.ErasePurpose(dest)) {
2482  WalletLogPrintf("Error: cannot erase address book entry purpose\n");
2483  return false;
2484  }
2485 
2486  // Delete name entry
2487  if (!batch.EraseName(dest)) {
2488  WalletLogPrintf("Error: cannot erase address book entry name\n");
2489  return false;
2490  }
2491 
2492  // finally, remove it from the map
2493  m_address_book.erase(address);
2494  }
2495 
2496  // All good, signal changes
2497  NotifyAddressBookChanged(address, "", /*is_mine=*/false, AddressPurpose::SEND, CT_DELETED);
2498  return true;
2499 }
2500 
2502 {
2504 
2505  auto legacy_spk_man = GetLegacyScriptPubKeyMan();
2506  if (legacy_spk_man) {
2507  return legacy_spk_man->KeypoolCountExternalKeys();
2508  }
2509 
2510  unsigned int count = 0;
2511  for (auto spk_man : m_external_spk_managers) {
2512  count += spk_man.second->GetKeyPoolSize();
2513  }
2514 
2515  return count;
2516 }
2517 
2518 unsigned int CWallet::GetKeyPoolSize() const
2519 {
2521 
2522  unsigned int count = 0;
2523  for (auto spk_man : GetActiveScriptPubKeyMans()) {
2524  count += spk_man->GetKeyPoolSize();
2525  }
2526  return count;
2527 }
2528 
2529 bool CWallet::TopUpKeyPool(unsigned int kpSize)
2530 {
2531  LOCK(cs_wallet);
2532  bool res = true;
2533  for (auto spk_man : GetActiveScriptPubKeyMans()) {
2534  res &= spk_man->TopUp(kpSize);
2535  }
2536  return res;
2537 }
2538 
2540 {
2541  LOCK(cs_wallet);
2542  auto spk_man = GetScriptPubKeyMan(type, /*internal=*/false);
2543  if (!spk_man) {
2544  return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
2545  }
2546 
2547  auto op_dest = spk_man->GetNewDestination(type);
2548  if (op_dest) {
2549  SetAddressBook(*op_dest, label, AddressPurpose::RECEIVE);
2550  }
2551 
2552  return op_dest;
2553 }
2554 
2556 {
2557  LOCK(cs_wallet);
2558 
2559  ReserveDestination reservedest(this, type);
2560  auto op_dest = reservedest.GetReservedDestination(true);
2561  if (op_dest) reservedest.KeepDestination();
2562 
2563  return op_dest;
2564 }
2565 
2566 std::optional<int64_t> CWallet::GetOldestKeyPoolTime() const
2567 {
2568  LOCK(cs_wallet);
2569  if (m_spk_managers.empty()) {
2570  return std::nullopt;
2571  }
2572 
2573  std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2574  for (const auto& spk_man_pair : m_spk_managers) {
2575  oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2576  }
2577  return oldest_key;
2578 }
2579 
2580 void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) {
2581  for (auto& entry : mapWallet) {
2582  CWalletTx& wtx = entry.second;
2583  if (wtx.m_is_cache_empty) continue;
2584  for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
2585  CTxDestination dst;
2586  if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.count(dst)) {
2587  wtx.MarkDirty();
2588  break;
2589  }
2590  }
2591  }
2592 }
2593 
2595 {
2597  for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2598  const auto& entry = item.second;
2599  func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2600  }
2601 }
2602 
2603 std::vector<CTxDestination> CWallet::ListAddrBookAddresses(const std::optional<AddrBookFilter>& _filter) const
2604 {
2606  std::vector<CTxDestination> result;
2607  AddrBookFilter filter = _filter ? *_filter : AddrBookFilter();
2608  ForEachAddrBookEntry([&result, &filter](const CTxDestination& dest, const std::string& label, bool is_change, const std::optional<AddressPurpose>& purpose) {
2609  // Filter by change
2610  if (filter.ignore_change && is_change) return;
2611  // Filter by label
2612  if (filter.m_op_label && *filter.m_op_label != label) return;
2613  // All good
2614  result.emplace_back(dest);
2615  });
2616  return result;
2617 }
2618 
2619 std::set<std::string> CWallet::ListAddrBookLabels(const std::optional<AddressPurpose> purpose) const
2620 {
2622  std::set<std::string> label_set;
2623  ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label,
2624  bool _is_change, const std::optional<AddressPurpose>& _purpose) {
2625  if (_is_change) return;
2626  if (!purpose || purpose == _purpose) {
2627  label_set.insert(_label);
2628  }
2629  });
2630  return label_set;
2631 }
2632 
2634 {
2635  m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
2636  if (!m_spk_man) {
2637  return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
2638  }
2639 
2640  if (nIndex == -1) {
2641  CKeyPool keypool;
2642  int64_t index;
2643  auto op_address = m_spk_man->GetReservedDestination(type, internal, index, keypool);
2644  if (!op_address) return op_address;
2645  nIndex = index;
2646  address = *op_address;
2647  fInternal = keypool.fInternal;
2648  }
2649  return address;
2650 }
2651 
2653 {
2654  if (nIndex != -1) {
2656  }
2657  nIndex = -1;
2658  address = CNoDestination();
2659 }
2660 
2662 {
2663  if (nIndex != -1) {
2665  }
2666  nIndex = -1;
2667  address = CNoDestination();
2668 }
2669 
2671 {
2672  CScript scriptPubKey = GetScriptForDestination(dest);
2673  for (const auto& spk_man : GetScriptPubKeyMans(scriptPubKey)) {
2674  auto signer_spk_man = dynamic_cast<ExternalSignerScriptPubKeyMan *>(spk_man);
2675  if (signer_spk_man == nullptr) {
2676  continue;
2677  }
2679  return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2680  }
2681  return false;
2682 }
2683 
2684 bool CWallet::LockCoin(const COutPoint& output, WalletBatch* batch)
2685 {
2687  setLockedCoins.insert(output);
2688  if (batch) {
2689  return batch->WriteLockedUTXO(output);
2690  }
2691  return true;
2692 }
2693 
2694 bool CWallet::UnlockCoin(const COutPoint& output, WalletBatch* batch)
2695 {
2697  bool was_locked = setLockedCoins.erase(output);
2698  if (batch && was_locked) {
2699  return batch->EraseLockedUTXO(output);
2700  }
2701  return true;
2702 }
2703 
2705 {
2707  bool success = true;
2708  WalletBatch batch(GetDatabase());
2709  for (auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2710  success &= batch.EraseLockedUTXO(*it);
2711  }
2712  setLockedCoins.clear();
2713  return success;
2714 }
2715 
2716 bool CWallet::IsLockedCoin(const COutPoint& output) const
2717 {
2719  return setLockedCoins.count(output) > 0;
2720 }
2721 
2722 void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
2723 {
2725  for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2726  it != setLockedCoins.end(); it++) {
2727  COutPoint outpt = (*it);
2728  vOutpts.push_back(outpt);
2729  }
2730 }
2731  // end of Actions
2733 
2734 void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
2736  mapKeyBirth.clear();
2737 
2738  // map in which we'll infer heights of other keys
2739  std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
2740  TxStateConfirmed max_confirm{uint256{}, /*height=*/-1, /*index=*/-1};
2741  max_confirm.confirmed_block_height = GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
2742  CHECK_NONFATAL(chain().findAncestorByHeight(GetLastBlockHash(), max_confirm.confirmed_block_height, FoundBlock().hash(max_confirm.confirmed_block_hash)));
2743 
2744  {
2746  assert(spk_man != nullptr);
2747  LOCK(spk_man->cs_KeyStore);
2748 
2749  // get birth times for keys with metadata
2750  for (const auto& entry : spk_man->mapKeyMetadata) {
2751  if (entry.second.nCreateTime) {
2752  mapKeyBirth[entry.first] = entry.second.nCreateTime;
2753  }
2754  }
2755 
2756  // Prepare to infer birth heights for keys without metadata
2757  for (const CKeyID &keyid : spk_man->GetKeys()) {
2758  if (mapKeyBirth.count(keyid) == 0)
2759  mapKeyFirstBlock[keyid] = &max_confirm;
2760  }
2761 
2762  // if there are no such keys, we're done
2763  if (mapKeyFirstBlock.empty())
2764  return;
2765 
2766  // find first block that affects those keys, if there are any left
2767  for (const auto& entry : mapWallet) {
2768  // iterate over all wallet transactions...
2769  const CWalletTx &wtx = entry.second;
2770  if (auto* conf = wtx.state<TxStateConfirmed>()) {
2771  // ... which are already in a block
2772  for (const CTxOut &txout : wtx.tx->vout) {
2773  // iterate over all their outputs
2774  for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
2775  // ... and all their affected keys
2776  auto rit = mapKeyFirstBlock.find(keyid);
2777  if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
2778  rit->second = conf;
2779  }
2780  }
2781  }
2782  }
2783  }
2784  }
2785 
2786  // Extract block timestamps for those keys
2787  for (const auto& entry : mapKeyFirstBlock) {
2788  int64_t block_time;
2789  CHECK_NONFATAL(chain().findBlock(entry.second->confirmed_block_hash, FoundBlock().time(block_time)));
2790  mapKeyBirth[entry.first] = block_time - TIMESTAMP_WINDOW; // block times can be 2h off
2791  }
2792 }
2793 
2817 unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const
2818 {
2819  std::optional<uint256> block_hash;
2820  if (auto* conf = wtx.state<TxStateConfirmed>()) {
2821  block_hash = conf->confirmed_block_hash;
2822  } else if (auto* conf = wtx.state<TxStateBlockConflicted>()) {
2823  block_hash = conf->conflicting_block_hash;
2824  }
2825 
2826  unsigned int nTimeSmart = wtx.nTimeReceived;
2827  if (block_hash) {
2828  int64_t blocktime;
2829  int64_t block_max_time;
2830  if (chain().findBlock(*block_hash, FoundBlock().time(blocktime).maxTime(block_max_time))) {
2831  if (rescanning_old_block) {
2832  nTimeSmart = block_max_time;
2833  } else {
2834  int64_t latestNow = wtx.nTimeReceived;
2835  int64_t latestEntry = 0;
2836 
2837  // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
2838  int64_t latestTolerated = latestNow + 300;
2839  const TxItems& txOrdered = wtxOrdered;
2840  for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2841  CWalletTx* const pwtx = it->second;
2842  if (pwtx == &wtx) {
2843  continue;
2844  }
2845  int64_t nSmartTime;
2846  nSmartTime = pwtx->nTimeSmart;
2847  if (!nSmartTime) {
2848  nSmartTime = pwtx->nTimeReceived;
2849  }
2850  if (nSmartTime <= latestTolerated) {
2851  latestEntry = nSmartTime;
2852  if (nSmartTime > latestNow) {
2853  latestNow = nSmartTime;
2854  }
2855  break;
2856  }
2857  }
2858 
2859  nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2860  }
2861  } else {
2862  WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), block_hash->ToString());
2863  }
2864  }
2865  return nTimeSmart;
2866 }
2867 
2869 {
2870  if (std::get_if<CNoDestination>(&dest))
2871  return false;
2872 
2873  if (!used) {
2874  if (auto* data{common::FindKey(m_address_book, dest)}) data->previously_spent = false;
2875  return batch.WriteAddressPreviouslySpent(dest, false);
2876  }
2877 
2879  return batch.WriteAddressPreviouslySpent(dest, true);
2880 }
2881 
2883 {
2884  m_address_book[dest].previously_spent = true;
2885 }
2886 
2887 void CWallet::LoadAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& request)
2888 {
2889  m_address_book[dest].receive_requests[id] = request;
2890 }
2891 
2893 {
2894  if (auto* data{common::FindKey(m_address_book, dest)}) return data->previously_spent;
2895  return false;
2896 }
2897 
2898 std::vector<std::string> CWallet::GetAddressReceiveRequests() const
2899 {
2900  std::vector<std::string> values;
2901  for (const auto& [dest, entry] : m_address_book) {
2902  for (const auto& [id, request] : entry.receive_requests) {
2903  values.emplace_back(request);
2904  }
2905  }
2906  return values;
2907 }
2908 
2909 bool CWallet::SetAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id, const std::string& value)
2910 {
2911  if (!batch.WriteAddressReceiveRequest(dest, id, value)) return false;
2912  m_address_book[dest].receive_requests[id] = value;
2913  return true;
2914 }
2915 
2916 bool CWallet::EraseAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id)
2917 {
2918  if (!batch.EraseAddressReceiveRequest(dest, id)) return false;
2919  m_address_book[dest].receive_requests.erase(id);
2920  return true;
2921 }
2922 
2923 std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error_string)
2924 {
2925  // Do some checking on wallet path. It should be either a:
2926  //
2927  // 1. Path where a directory can be created.
2928  // 2. Path to an existing directory.
2929  // 3. Path to a symlink to a directory.
2930  // 4. For backwards compatibility, the name of a data file in -walletdir.
2932  fs::file_type path_type = fs::symlink_status(wallet_path).type();
2933  if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2934  (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2935  (path_type == fs::file_type::regular && fs::PathFromString(name).filename() == fs::PathFromString(name)))) {
2936  error_string = Untranslated(strprintf(
2937  "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2938  "database/log.?????????? files can be stored, a location where such a directory could be created, "
2939  "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2942  return nullptr;
2943  }
2944  return MakeDatabase(wallet_path, options, status, error_string);
2945 }
2946 
2947 std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
2948 {
2949  interfaces::Chain* chain = context.chain;
2950  ArgsManager& args = *Assert(context.args);
2951  const std::string& walletFile = database->Filename();
2952 
2953  const auto start{SteadyClock::now()};
2954  // TODO: Can't use std::make_shared because we need a custom deleter but
2955  // should be possible to use std::allocate_shared.
2956  std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), ReleaseWallet);
2957  walletInstance->m_keypool_size = std::max(args.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), int64_t{1});
2958  walletInstance->m_notify_tx_changed_script = args.GetArg("-walletnotify", "");
2959 
2960  // Load wallet
2961  bool rescan_required = false;
2962  DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2963  if (nLoadWalletRet != DBErrors::LOAD_OK) {
2964  if (nLoadWalletRet == DBErrors::CORRUPT) {
2965  error = strprintf(_("Error loading %s: Wallet corrupted"), walletFile);
2966  return nullptr;
2967  }
2968  else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
2969  {
2970  warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
2971  " or address metadata may be missing or incorrect."),
2972  walletFile));
2973  }
2974  else if (nLoadWalletRet == DBErrors::TOO_NEW) {
2975  error = strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, PACKAGE_NAME);
2976  return nullptr;
2977  }
2978  else if (nLoadWalletRet == DBErrors::EXTERNAL_SIGNER_SUPPORT_REQUIRED) {
2979  error = strprintf(_("Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
2980  return nullptr;
2981  }
2982  else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
2983  {
2984  error = strprintf(_("Wallet needed to be rewritten: restart %s to complete"), PACKAGE_NAME);
2985  return nullptr;
2986  } else if (nLoadWalletRet == DBErrors::NEED_RESCAN) {
2987  warnings.push_back(strprintf(_("Error reading %s! Transaction data may be missing or incorrect."
2988  " Rescanning wallet."), walletFile));
2989  rescan_required = true;
2990  } else if (nLoadWalletRet == DBErrors::UNKNOWN_DESCRIPTOR) {
2991  error = strprintf(_("Unrecognized descriptor found. Loading wallet %s\n\n"
2992  "The wallet might had been created on a newer version.\n"
2993  "Please try running the latest software version.\n"), walletFile);
2994  return nullptr;
2995  } else if (nLoadWalletRet == DBErrors::UNEXPECTED_LEGACY_ENTRY) {
2996  error = strprintf(_("Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
2997  "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
2998  return nullptr;
2999  } else {
3000  error = strprintf(_("Error loading %s"), walletFile);
3001  return nullptr;
3002  }
3003  }
3004 
3005  // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
3006  const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
3007  !walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
3008  !walletInstance->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
3009  if (fFirstRun)
3010  {
3011  // ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
3012  walletInstance->SetMinVersion(FEATURE_LATEST);
3013 
3014  walletInstance->InitWalletFlags(wallet_creation_flags);
3015 
3016  // Only create LegacyScriptPubKeyMan when not descriptor wallet
3017  if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3018  walletInstance->SetupLegacyScriptPubKeyMan();
3019  }
3020 
3021  if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) || !(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
3022  LOCK(walletInstance->cs_wallet);
3023  if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3024  walletInstance->SetupDescriptorScriptPubKeyMans();
3025  // SetupDescriptorScriptPubKeyMans already calls SetupGeneration for us so we don't need to call SetupGeneration separately
3026  } else {
3027  // Legacy wallets need SetupGeneration here.
3028  for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3029  if (!spk_man->SetupGeneration()) {
3030  error = _("Unable to generate initial keys");
3031  return nullptr;
3032  }
3033  }
3034  }
3035  }
3036 
3037  if (chain) {
3038  walletInstance->chainStateFlushed(ChainstateRole::NORMAL, chain->getTipLocator());
3039  }
3040  } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
3041  // Make it impossible to disable private keys after creation
3042  error = strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile);
3043  return nullptr;
3044  } else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
3045  for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3046  if (spk_man->HavePrivateKeys()) {
3047  warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3048  break;
3049  }
3050  }
3051  }
3052 
3053  if (!args.GetArg("-addresstype", "").empty()) {
3054  std::optional<OutputType> parsed = ParseOutputType(args.GetArg("-addresstype", ""));
3055  if (!parsed) {
3056  error = strprintf(_("Unknown address type '%s'"), args.GetArg("-addresstype", ""));
3057  return nullptr;
3058  }
3059  walletInstance->m_default_address_type = parsed.value();
3060  }
3061 
3062  if (!args.GetArg("-changetype", "").empty()) {
3063  std::optional<OutputType> parsed = ParseOutputType(args.GetArg("-changetype", ""));
3064  if (!parsed) {
3065  error = strprintf(_("Unknown change type '%s'"), args.GetArg("-changetype", ""));
3066  return nullptr;
3067  }
3068  walletInstance->m_default_change_type = parsed.value();
3069  }
3070 
3071  if (args.IsArgSet("-mintxfee")) {
3072  std::optional<CAmount> min_tx_fee = ParseMoney(args.GetArg("-mintxfee", ""));
3073  if (!min_tx_fee) {
3074  error = AmountErrMsg("mintxfee", args.GetArg("-mintxfee", ""));
3075  return nullptr;
3076  } else if (min_tx_fee.value() > HIGH_TX_FEE_PER_KB) {
3077  warnings.push_back(AmountHighWarn("-mintxfee") + Untranslated(" ") +
3078  _("This is the minimum transaction fee you pay on every transaction."));
3079  }
3080 
3081  walletInstance->m_min_fee = CFeeRate{min_tx_fee.value()};
3082  }
3083 
3084  if (args.IsArgSet("-maxapsfee")) {
3085  const std::string max_aps_fee{args.GetArg("-maxapsfee", "")};
3086  if (max_aps_fee == "-1") {
3087  walletInstance->m_max_aps_fee = -1;
3088  } else if (std::optional<CAmount> max_fee = ParseMoney(max_aps_fee)) {
3089  if (max_fee.value() > HIGH_APS_FEE) {
3090  warnings.push_back(AmountHighWarn("-maxapsfee") + Untranslated(" ") +
3091  _("This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3092  }
3093  walletInstance->m_max_aps_fee = max_fee.value();
3094  } else {
3095  error = AmountErrMsg("maxapsfee", max_aps_fee);
3096  return nullptr;
3097  }
3098  }
3099 
3100  if (args.IsArgSet("-fallbackfee")) {
3101  std::optional<CAmount> fallback_fee = ParseMoney(args.GetArg("-fallbackfee", ""));
3102  if (!fallback_fee) {
3103  error = strprintf(_("Invalid amount for %s=<amount>: '%s'"), "-fallbackfee", args.GetArg("-fallbackfee", ""));
3104  return nullptr;
3105  } else if (fallback_fee.value() > HIGH_TX_FEE_PER_KB) {
3106  warnings.push_back(AmountHighWarn("-fallbackfee") + Untranslated(" ") +
3107  _("This is the transaction fee you may pay when fee estimates are not available."));
3108  }
3109  walletInstance->m_fallback_fee = CFeeRate{fallback_fee.value()};
3110  }
3111 
3112  // Disable fallback fee in case value was set to 0, enable if non-null value
3113  walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
3114 
3115  if (args.IsArgSet("-discardfee")) {
3116  std::optional<CAmount> discard_fee = ParseMoney(args.GetArg("-discardfee", ""));
3117  if (!discard_fee) {
3118  error = strprintf(_("Invalid amount for %s=<amount>: '%s'"), "-discardfee", args.GetArg("-discardfee", ""));
3119  return nullptr;
3120  } else if (discard_fee.value() > HIGH_TX_FEE_PER_KB) {
3121  warnings.push_back(AmountHighWarn("-discardfee") + Untranslated(" ") +
3122  _("This is the transaction fee you may discard if change is smaller than dust at this level"));
3123  }
3124  walletInstance->m_discard_rate = CFeeRate{discard_fee.value()};
3125  }
3126 
3127  if (args.IsArgSet("-paytxfee")) {
3128  std::optional<CAmount> pay_tx_fee = ParseMoney(args.GetArg("-paytxfee", ""));
3129  if (!pay_tx_fee) {
3130  error = AmountErrMsg("paytxfee", args.GetArg("-paytxfee", ""));
3131  return nullptr;
3132  } else if (pay_tx_fee.value() > HIGH_TX_FEE_PER_KB) {
3133  warnings.push_back(AmountHighWarn("-paytxfee") + Untranslated(" ") +
3134  _("This is the transaction fee you will pay if you send a transaction."));
3135  }
3136 
3137  walletInstance->m_pay_tx_fee = CFeeRate{pay_tx_fee.value(), 1000};
3138 
3139  if (chain && walletInstance->m_pay_tx_fee < chain->relayMinFee()) {
3140  error = strprintf(_("Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3141  "-paytxfee", args.GetArg("-paytxfee", ""), chain->relayMinFee().ToString());
3142  return nullptr;
3143  }
3144  }
3145 
3146  if (args.IsArgSet("-maxtxfee")) {
3147  std::optional<CAmount> max_fee = ParseMoney(args.GetArg("-maxtxfee", ""));
3148  if (!max_fee) {
3149  error = AmountErrMsg("maxtxfee", args.GetArg("-maxtxfee", ""));
3150  return nullptr;
3151  } else if (max_fee.value() > HIGH_MAX_TX_FEE) {
3152  warnings.push_back(strprintf(_("%s is set very high! Fees this large could be paid on a single transaction."), "-maxtxfee"));
3153  }
3154 
3155  if (chain && CFeeRate{max_fee.value(), 1000} < chain->relayMinFee()) {
3156  error = strprintf(_("Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3157  "-maxtxfee", args.GetArg("-maxtxfee", ""), chain->relayMinFee().ToString());
3158  return nullptr;
3159  }
3160 
3161  walletInstance->m_default_max_tx_fee = max_fee.value();
3162  }
3163 
3164  if (args.IsArgSet("-consolidatefeerate")) {
3165  if (std::optional<CAmount> consolidate_feerate = ParseMoney(args.GetArg("-consolidatefeerate", ""))) {
3166  walletInstance->m_consolidate_feerate = CFeeRate(*consolidate_feerate);
3167  } else {
3168  error = AmountErrMsg("consolidatefeerate", args.GetArg("-consolidatefeerate", ""));
3169  return nullptr;
3170  }
3171  }
3172 
3174  warnings.push_back(AmountHighWarn("-minrelaytxfee") + Untranslated(" ") +
3175  _("The wallet will avoid paying less than the minimum relay fee."));
3176  }
3177 
3178  walletInstance->m_confirm_target = args.GetIntArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
3179  walletInstance->m_spend_zero_conf_change = args.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
3180  walletInstance->m_signal_rbf = args.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
3181 
3182  walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3183 
3184  // Try to top up keypool. No-op if the wallet is locked.
3185  walletInstance->TopUpKeyPool();
3186 
3187  // Cache the first key time
3188  std::optional<int64_t> time_first_key;
3189  for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3190  int64_t time = spk_man->GetTimeFirstKey();
3191  if (!time_first_key || time < *time_first_key) time_first_key = time;
3192  }
3193  if (time_first_key) walletInstance->MaybeUpdateBirthTime(*time_first_key);
3194 
3195  if (chain && !AttachChain(walletInstance, *chain, rescan_required, error, warnings)) {
3196  walletInstance->m_chain_notifications_handler.reset(); // Reset this pointer so that the wallet will actually be unloaded
3197  return nullptr;
3198  }
3199 
3200  {
3201  LOCK(walletInstance->cs_wallet);
3202  walletInstance->SetBroadcastTransactions(args.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
3203  walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3204  walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3205  walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3206  }
3207 
3208  return walletInstance;
3209 }
3210 
3211 bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings)
3212 {
3213  LOCK(walletInstance->cs_wallet);
3214  // allow setting the chain if it hasn't been set already but prevent changing it
3215  assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
3216  walletInstance->m_chain = &chain;
3217 
3218  // Unless allowed, ensure wallet files are not reused across chains:
3219  if (!gArgs.GetBoolArg("-walletcrosschain", DEFAULT_WALLETCROSSCHAIN)) {
3220  WalletBatch batch(walletInstance->GetDatabase());
3221  CBlockLocator locator;
3222  if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 && chain.getHeight()) {
3223  // Wallet is assumed to be from another chain, if genesis block in the active
3224  // chain differs from the genesis block known to the wallet.
3225  if (chain.getBlockHash(0) != locator.vHave.back()) {
3226  error = Untranslated("Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3227  return false;
3228  }
3229  }
3230  }
3231 
3232  // Register wallet with validationinterface. It's done before rescan to avoid
3233  // missing block connections between end of rescan and validation subscribing.
3234  // Because of wallet lock being hold, block connection notifications are going to
3235  // be pending on the validation-side until lock release. It's likely to have
3236  // block processing duplicata (if rescan block range overlaps with notification one)
3237  // but we guarantee at least than wallet state is correct after notifications delivery.
3238  // However, chainStateFlushed notifications are ignored until the rescan is finished
3239  // so that in case of a shutdown event, the rescan will be repeated at the next start.
3240  // This is temporary until rescan and notifications delivery are unified under same
3241  // interface.
3242  walletInstance->m_attaching_chain = true; //ignores chainStateFlushed notifications
3243  walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3244 
3245  // If rescan_required = true, rescan_height remains equal to 0
3246  int rescan_height = 0;
3247  if (!rescan_required)
3248  {
3249  WalletBatch batch(walletInstance->GetDatabase());
3250  CBlockLocator locator;
3251  if (batch.ReadBestBlock(locator)) {
3252  if (const std::optional<int> fork_height = chain.findLocatorFork(locator)) {
3253  rescan_height = *fork_height;
3254  }
3255  }
3256  }
3257 
3258  const std::optional<int> tip_height = chain.getHeight();
3259  if (tip_height) {
3260  walletInstance->m_last_block_processed = chain.getBlockHash(*tip_height);
3261  walletInstance->m_last_block_processed_height = *tip_height;
3262  } else {
3263  walletInstance->m_last_block_processed.SetNull();
3264  walletInstance->m_last_block_processed_height = -1;
3265  }
3266 
3267  if (tip_height && *tip_height != rescan_height)
3268  {
3269  // No need to read and scan block if block was created before
3270  // our wallet birthday (as adjusted for block time variability)
3271  std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3272  if (time_first_key) {
3273  FoundBlock found = FoundBlock().height(rescan_height);
3274  chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, found);
3275  if (!found.found) {
3276  // We were unable to find a block that had a time more recent than our earliest timestamp
3277  // or a height higher than the wallet was synced to, indicating that the wallet is newer than the
3278  // current chain tip. Skip rescanning in this case.
3279  rescan_height = *tip_height;
3280  }
3281  }
3282 
3283  // Technically we could execute the code below in any case, but performing the
3284  // `while` loop below can make startup very slow, so only check blocks on disk
3285  // if necessary.
3287  int block_height = *tip_height;
3288  while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3289  --block_height;
3290  }
3291 
3292  if (rescan_height != block_height) {
3293  // We can't rescan beyond blocks we don't have data for, stop and throw an error.
3294  // This might happen if a user uses an old wallet within a pruned node
3295  // or if they ran -disablewallet for a longer time, then decided to re-enable
3296  // Exit early and print an error.
3297  // It also may happen if an assumed-valid chain is in use and therefore not
3298  // all block data is available.
3299  // If a block is pruned after this check, we will load the wallet,
3300  // but fail the rescan with a generic error.
3301 
3302  error = chain.havePruned() ?
3303  _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)") :
3304  strprintf(_(
3305  "Error loading wallet. Wallet requires blocks to be downloaded, "
3306  "and software does not currently support loading wallets while "
3307  "blocks are being downloaded out of order when using assumeutxo "
3308  "snapshots. Wallet should be able to load successfully after "
3309  "node sync reaches height %s"), block_height);
3310  return false;
3311  }
3312  }
3313 
3314  chain.initMessage(_("Rescanning…").translated);
3315  walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3316 
3317  {
3318  WalletRescanReserver reserver(*walletInstance);
3319  if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/true).status)) {
3320  error = _("Failed to rescan the wallet during initialization");
3321  return false;
3322  }
3323  }
3324  walletInstance->m_attaching_chain = false;
3325  walletInstance->chainStateFlushed(ChainstateRole::NORMAL, chain.getTipLocator());
3326  walletInstance->GetDatabase().IncrementUpdateCounter();
3327  }
3328  walletInstance->m_attaching_chain = false;
3329 
3330  return true;
3331 }
3332 
3333 const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
3334 {
3335  const auto& address_book_it = m_address_book.find(dest);
3336  if (address_book_it == m_address_book.end()) return nullptr;
3337  if ((!allow_change) && address_book_it->second.IsChange()) {
3338  return nullptr;
3339  }
3340  return &address_book_it->second;
3341 }
3342 
3343 bool CWallet::UpgradeWallet(int version, bilingual_str& error)
3344 {
3345  int prev_version = GetVersion();
3346  if (version == 0) {
3347  WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
3348  version = FEATURE_LATEST;
3349  } else {
3350  WalletLogPrintf("Allowing wallet upgrade up to %i\n", version);
3351  }
3352  if (version < prev_version) {
3353  error = strprintf(_("Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3354  return false;
3355  }
3356 
3357  LOCK(cs_wallet);
3358 
3359  // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
3361  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);
3362  return false;
3363  }
3364 
3365  // Permanently upgrade to the version
3367 
3368  for (auto spk_man : GetActiveScriptPubKeyMans()) {
3369  if (!spk_man->Upgrade(prev_version, version, error)) {
3370  return false;
3371  }
3372  }
3373  return true;
3374 }
3375 
3377 {
3378  // Add wallet transactions that aren't already in a block to mempool
3379  // Do this here as mempool requires genesis block to be loaded
3380  ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
3381 
3382  // Update wallet transactions with current mempool transactions.
3383  WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
3384 }
3385 
3386 bool CWallet::BackupWallet(const std::string& strDest) const
3387 {
3388  return GetDatabase().Backup(strDest);
3389 }
3390 
3392 {
3393  nTime = GetTime();
3394  fInternal = false;
3395  m_pre_split = false;
3396 }
3397 
3398 CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
3399 {
3400  nTime = GetTime();
3401  vchPubKey = vchPubKeyIn;
3402  fInternal = internalIn;
3403  m_pre_split = false;
3404 }
3405 
3407 {
3409  if (auto* conf = wtx.state<TxStateConfirmed>()) {
3410  assert(conf->confirmed_block_height >= 0);
3411  return GetLastBlockHeight() - conf->confirmed_block_height + 1;
3412  } else if (auto* conf = wtx.state<TxStateBlockConflicted>()) {
3413  assert(conf->conflicting_block_height >= 0);
3414  return -1 * (GetLastBlockHeight() - conf->conflicting_block_height + 1);
3415  } else {
3416  return 0;
3417  }
3418 }
3419 
3421 {
3423 
3424  if (!wtx.IsCoinBase()) {
3425  return 0;
3426  }
3427  int chain_depth = GetTxDepthInMainChain(wtx);
3428  assert(chain_depth >= 0); // coinbase tx should not be conflicted
3429  return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
3430 }
3431 
3433 {
3435 
3436  // note GetBlocksToMaturity is 0 for non-coinbase tx
3437  return GetTxBlocksToMaturity(wtx) > 0;
3438 }
3439 
3441 {
3442  return HasEncryptionKeys();
3443 }
3444 
3445 bool CWallet::IsLocked() const
3446 {
3447  if (!IsCrypted()) {
3448  return false;
3449  }
3450  LOCK(cs_wallet);
3451  return vMasterKey.empty();
3452 }
3453 
3455 {
3456  if (!IsCrypted())
3457  return false;
3458 
3459  {
3461  if (!vMasterKey.empty()) {
3462  memory_cleanse(vMasterKey.data(), vMasterKey.size() * sizeof(decltype(vMasterKey)::value_type));
3463  vMasterKey.clear();
3464  }
3465  }
3466 
3467  NotifyStatusChanged(this);
3468  return true;
3469 }
3470 
3471 bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn)
3472 {
3473  {
3474  LOCK(cs_wallet);
3475  for (const auto& spk_man_pair : m_spk_managers) {
3476  if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3477  return false;
3478  }
3479  }
3480  vMasterKey = vMasterKeyIn;
3481  }
3482  NotifyStatusChanged(this);
3483  return true;
3484 }
3485 
3486 std::set<ScriptPubKeyMan*> CWallet::GetActiveScriptPubKeyMans() const
3487 {
3488  std::set<ScriptPubKeyMan*> spk_mans;
3489  for (bool internal : {false, true}) {
3490  for (OutputType t : OUTPUT_TYPES) {
3491  auto spk_man = GetScriptPubKeyMan(t, internal);
3492  if (spk_man) {
3493  spk_mans.insert(spk_man);
3494  }
3495  }
3496  }
3497  return spk_mans;
3498 }
3499 
3501 {
3502  for (const auto& [_, ext_spkm] : m_external_spk_managers) {
3503  if (ext_spkm == &spkm) return true;
3504  }
3505  for (const auto& [_, int_spkm] : m_internal_spk_managers) {
3506  if (int_spkm == &spkm) return true;
3507  }
3508  return false;
3509 }
3510 
3511 std::set<ScriptPubKeyMan*> CWallet::GetAllScriptPubKeyMans() const
3512 {
3513  std::set<ScriptPubKeyMan*> spk_mans;
3514  for (const auto& spk_man_pair : m_spk_managers) {
3515  spk_mans.insert(spk_man_pair.second.get());
3516  }
3517  return spk_mans;
3518 }
3519 
3520 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const OutputType& type, bool internal) const
3521 {
3522  const std::map<OutputType, ScriptPubKeyMan*>& spk_managers = internal ? m_internal_spk_managers : m_external_spk_managers;
3523  std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3524  if (it == spk_managers.end()) {
3525  return nullptr;
3526  }
3527  return it->second;
3528 }
3529 
3530 std::set<ScriptPubKeyMan*> CWallet::GetScriptPubKeyMans(const CScript& script) const
3531 {
3532  std::set<ScriptPubKeyMan*> spk_mans;
3533 
3534  // Search the cache for relevant SPKMs instead of iterating m_spk_managers
3535  const auto& it = m_cached_spks.find(script);
3536  if (it != m_cached_spks.end()) {
3537  spk_mans.insert(it->second.begin(), it->second.end());
3538  }
3539  SignatureData sigdata;
3540  Assume(std::all_of(spk_mans.begin(), spk_mans.end(), [&script, &sigdata](ScriptPubKeyMan* spkm) { return spkm->CanProvide(script, sigdata); }));
3541 
3542  // Legacy wallet
3543  if (IsLegacy() && GetLegacyScriptPubKeyMan()->CanProvide(script, sigdata)) spk_mans.insert(GetLegacyScriptPubKeyMan());
3544 
3545  return spk_mans;
3546 }
3547 
3549 {
3550  if (m_spk_managers.count(id) > 0) {
3551  return m_spk_managers.at(id).get();
3552  }
3553  return nullptr;
3554 }
3555 
3556 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script) const
3557 {
3558  SignatureData sigdata;
3559  return GetSolvingProvider(script, sigdata);
3560 }
3561 
3562 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script, SignatureData& sigdata) const
3563 {
3564  // Search the cache for relevant SPKMs instead of iterating m_spk_managers
3565  const auto& it = m_cached_spks.find(script);
3566  if (it != m_cached_spks.end()) {
3567  // All spkms for a given script must already be able to make a SigningProvider for the script, so just return the first one.
3568  Assume(it->second.at(0)->CanProvide(script, sigdata));
3569  return it->second.at(0)->GetSolvingProvider(script);
3570  }
3571 
3572  // Legacy wallet
3573  if (IsLegacy() && GetLegacyScriptPubKeyMan()->CanProvide(script, sigdata)) return GetLegacyScriptPubKeyMan()->GetSolvingProvider(script);
3574 
3575  return nullptr;
3576 }
3577 
3578 std::vector<WalletDescriptor> CWallet::GetWalletDescriptors(const CScript& script) const
3579 {
3580  std::vector<WalletDescriptor> descs;
3581  for (const auto spk_man: GetScriptPubKeyMans(script)) {
3582  if (const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) {
3583  LOCK(desc_spk_man->cs_desc_man);
3584  descs.push_back(desc_spk_man->GetWalletDescriptor());
3585  }
3586  }
3587  return descs;
3588 }
3589 
3591 {
3593  return nullptr;
3594  }
3595  // Legacy wallets only have one ScriptPubKeyMan which is a LegacyScriptPubKeyMan.
3596  // Everything in m_internal_spk_managers and m_external_spk_managers point to the same legacyScriptPubKeyMan.
3598  if (it == m_internal_spk_managers.end()) return nullptr;
3599  return dynamic_cast<LegacyScriptPubKeyMan*>(it->second);
3600 }
3601 
3603 {
3605  return GetLegacyScriptPubKeyMan();
3606 }
3607 
3608 void CWallet::AddScriptPubKeyMan(const uint256& id, std::unique_ptr<ScriptPubKeyMan> spkm_man)
3609 {
3610  // Add spkm_man to m_spk_managers before calling any method
3611  // that might access it.
3612  const auto& spkm = m_spk_managers[id] = std::move(spkm_man);
3613 
3614  // Update birth time if needed
3615  MaybeUpdateBirthTime(spkm->GetTimeFirstKey());
3616 }
3617 
3619 {
3621  return;
3622  }
3623 
3624  auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new LegacyScriptPubKeyMan(*this, m_keypool_size));
3625  for (const auto& type : LEGACY_OUTPUT_TYPES) {
3626  m_internal_spk_managers[type] = spk_manager.get();
3627  m_external_spk_managers[type] = spk_manager.get();
3628  }
3629  uint256 id = spk_manager->GetID();
3630  AddScriptPubKeyMan(id, std::move(spk_manager));
3631 }
3632 
3633 bool CWallet::WithEncryptionKey(std::function<bool (const CKeyingMaterial&)> cb) const
3634 {
3635  LOCK(cs_wallet);
3636  return cb(vMasterKey);
3637 }
3638 
3640 {
3641  return !mapMasterKeys.empty();
3642 }
3643 
3645 {
3646  for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
3647  spk_man->NotifyWatchonlyChanged.connect(NotifyWatchonlyChanged);
3648  spk_man->NotifyCanGetAddressesChanged.connect(NotifyCanGetAddressesChanged);
3649  spk_man->NotifyFirstKeyTimeChanged.connect(std::bind(&CWallet::MaybeUpdateBirthTime, this, std::placeholders::_2));
3650  }
3651 }
3652 
3654 {
3655  DescriptorScriptPubKeyMan* spk_manager;
3657  spk_manager = new ExternalSignerScriptPubKeyMan(*this, desc, m_keypool_size);
3658  } else {
3659  spk_manager = new DescriptorScriptPubKeyMan(*this, desc, m_keypool_size);
3660  }
3661  AddScriptPubKeyMan(id, std::unique_ptr<ScriptPubKeyMan>(spk_manager));
3662  return *spk_manager;
3663 }
3664 
3665 DescriptorScriptPubKeyMan& CWallet::SetupDescriptorScriptPubKeyMan(WalletBatch& batch, const CExtKey& master_key, const OutputType& output_type, bool internal)
3666 {
3668  auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, m_keypool_size));
3669  if (IsCrypted()) {
3670  if (IsLocked()) {
3671  throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
3672  }
3673  if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3674  throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
3675  }
3676  }
3677  spk_manager->SetupDescriptorGeneration(batch, master_key, output_type, internal);
3678  DescriptorScriptPubKeyMan* out = spk_manager.get();
3679  uint256 id = spk_manager->GetID();
3680  AddScriptPubKeyMan(id, std::move(spk_manager));
3681  AddActiveScriptPubKeyManWithDb(batch, id, output_type, internal);
3682  return *out;
3683 }
3684 
3686 {
3688 
3689  // Create single batch txn
3690  WalletBatch batch(GetDatabase());
3691  if (!batch.TxnBegin()) throw std::runtime_error("Error: cannot create db transaction for descriptors setup");
3692 
3693  for (bool internal : {false, true}) {
3694  for (OutputType t : OUTPUT_TYPES) {
3695  SetupDescriptorScriptPubKeyMan(batch, master_key, t, internal);
3696  }
3697  }
3698 
3699  // Ensure information is committed to disk
3700  if (!batch.TxnCommit()) throw std::runtime_error("Error: cannot commit db transaction for descriptors setup");
3701 }
3702 
3704 {
3706 
3708  // Make a seed
3709  CKey seed_key = GenerateRandomKey();
3710  CPubKey seed = seed_key.GetPubKey();
3711  assert(seed_key.VerifyPubKey(seed));
3712 
3713  // Get the extended key
3714  CExtKey master_key;
3715  master_key.SetSeed(seed_key);
3716 
3717  SetupDescriptorScriptPubKeyMans(master_key);
3718  } else {
3720 
3721  // TODO: add account parameter
3722  int account = 0;
3723  UniValue signer_res = signer.GetDescriptors(account);
3724 
3725  if (!signer_res.isObject()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3726 
3727  WalletBatch batch(GetDatabase());
3728  if (!batch.TxnBegin()) throw std::runtime_error("Error: cannot create db transaction for descriptors import");
3729 
3730  for (bool internal : {false, true}) {
3731  const UniValue& descriptor_vals = signer_res.find_value(internal ? "internal" : "receive");
3732  if (!descriptor_vals.isArray()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3733  for (const UniValue& desc_val : descriptor_vals.get_array().getValues()) {
3734  const std::string& desc_str = desc_val.getValStr();
3735  FlatSigningProvider keys;
3736  std::string desc_error;
3737  std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, desc_error, false);
3738  if (desc == nullptr) {
3739  throw std::runtime_error(std::string(__func__) + ": Invalid descriptor \"" + desc_str + "\" (" + desc_error + ")");
3740  }
3741  if (!desc->GetOutputType()) {
3742  continue;
3743  }
3744  OutputType t = *desc->GetOutputType();
3745  auto spk_manager = std::unique_ptr<ExternalSignerScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(*this, m_keypool_size));
3746  spk_manager->SetupDescriptor(batch, std::move(desc));
3747  uint256 id = spk_manager->GetID();
3748  AddScriptPubKeyMan(id, std::move(spk_manager));
3749  AddActiveScriptPubKeyManWithDb(batch, id, t, internal);
3750  }
3751  }
3752 
3753  // Ensure imported descriptors are committed to disk
3754  if (!batch.TxnCommit()) throw std::runtime_error("Error: cannot commit db transaction for descriptors import");
3755  }
3756 }
3757 
3759 {
3760  WalletBatch batch(GetDatabase());
3761  return AddActiveScriptPubKeyManWithDb(batch, id, type, internal);
3762 }
3763 
3765 {
3766  if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
3767  throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
3768  }
3769  LoadActiveScriptPubKeyMan(id, type, internal);
3770 }
3771 
3773 {
3774  // Activating ScriptPubKeyManager for a given output and change type is incompatible with legacy wallets.
3775  // Legacy wallets have only one ScriptPubKeyManager and it's active for all output and change types.
3777 
3778  WalletLogPrintf("Setting spkMan to active: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
3779  auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3780  auto& spk_mans_other = internal ? m_external_spk_managers : m_internal_spk_managers;
3781  auto spk_man = m_spk_managers.at(id).get();
3782  spk_mans[type] = spk_man;
3783 
3784  const auto it = spk_mans_other.find(type);
3785  if (it != spk_mans_other.end() && it->second == spk_man) {
3786  spk_mans_other.erase(type);
3787  }
3788 
3790 }
3791 
3793 {
3794  auto spk_man = GetScriptPubKeyMan(type, internal);
3795  if (spk_man != nullptr && spk_man->GetID() == id) {
3796  WalletLogPrintf("Deactivate spkMan: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
3797  WalletBatch batch(GetDatabase());
3798  if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type), internal)) {
3799  throw std::runtime_error(std::string(__func__) + ": erasing active ScriptPubKeyMan id failed");
3800  }
3801 
3802  auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3803  spk_mans.erase(type);
3804  }
3805 
3807 }
3808 
3809 bool CWallet::IsLegacy() const
3810 {
3811  if (m_internal_spk_managers.count(OutputType::LEGACY) == 0) {
3812  return false;
3813  }
3814  auto spk_man = dynamic_cast<LegacyScriptPubKeyMan*>(m_internal_spk_managers.at(OutputType::LEGACY));
3815  return spk_man != nullptr;
3816 }
3817 
3819 {
3820  for (auto& spk_man_pair : m_spk_managers) {
3821  // Try to downcast to DescriptorScriptPubKeyMan then check if the descriptors match
3822  DescriptorScriptPubKeyMan* spk_manager = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man_pair.second.get());
3823  if (spk_manager != nullptr && spk_manager->HasWalletDescriptor(desc)) {
3824  return spk_manager;
3825  }
3826  }
3827 
3828  return nullptr;
3829 }
3830 
3831 std::optional<bool> CWallet::IsInternalScriptPubKeyMan(ScriptPubKeyMan* spk_man) const
3832 {
3833  // Legacy script pubkey man can't be either external or internal
3834  if (IsLegacy()) {
3835  return std::nullopt;
3836  }
3837 
3838  // only active ScriptPubKeyMan can be internal
3839  if (!GetActiveScriptPubKeyMans().count(spk_man)) {
3840  return std::nullopt;
3841  }
3842 
3843  const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
3844  if (!desc_spk_man) {
3845  throw std::runtime_error(std::string(__func__) + ": unexpected ScriptPubKeyMan type.");
3846  }
3847 
3848  LOCK(desc_spk_man->cs_desc_man);
3849  const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3850  assert(type.has_value());
3851 
3852  return GetScriptPubKeyMan(*type, /* internal= */ true) == desc_spk_man;
3853 }
3854 
3855 ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal)
3856 {
3858 
3860  WalletLogPrintf("Cannot add WalletDescriptor to a non-descriptor wallet\n");
3861  return nullptr;
3862  }
3863 
3864  auto spk_man = GetDescriptorScriptPubKeyMan(desc);
3865  if (spk_man) {
3866  WalletLogPrintf("Update existing descriptor: %s\n", desc.descriptor->ToString());
3867  spk_man->UpdateWalletDescriptor(desc);
3868  } else {
3869  auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc, m_keypool_size));
3870  spk_man = new_spk_man.get();
3871 
3872  // Save the descriptor to memory
3873  uint256 id = new_spk_man->GetID();
3874  AddScriptPubKeyMan(id, std::move(new_spk_man));
3875  }
3876 
3877  // Add the private keys to the descriptor
3878  for (const auto& entry : signing_provider.keys) {
3879  const CKey& key = entry.second;
3880  spk_man->AddDescriptorKey(key, key.GetPubKey());
3881  }
3882 
3883  // Top up key pool, the manager will generate new scriptPubKeys internally
3884  if (!spk_man->TopUp()) {
3885  WalletLogPrintf("Could not top up scriptPubKeys\n");
3886  return nullptr;
3887  }
3888 
3889  // Apply the label if necessary
3890  // Note: we disable labels for ranged descriptors
3891  if (!desc.descriptor->IsRange()) {
3892  auto script_pub_keys = spk_man->GetScriptPubKeys();
3893  if (script_pub_keys.empty()) {
3894  WalletLogPrintf("Could not generate scriptPubKeys (cache is empty)\n");
3895  return nullptr;
3896  }
3897 
3898  if (!internal) {
3899  for (const auto& script : script_pub_keys) {
3900  CTxDestination dest;
3901  if (ExtractDestination(script, dest)) {
3903  }
3904  }
3905  }
3906  }
3907 
3908  // Save the descriptor to DB
3909  spk_man->WriteDescriptor();
3910 
3911  return spk_man;
3912 }
3913 
3915 {
3917 
3918  WalletLogPrintf("Migrating wallet storage database from BerkeleyDB to SQLite.\n");
3919 
3920  if (m_database->Format() == "sqlite") {
3921  error = _("Error: This wallet already uses SQLite");
3922  return false;
3923  }
3924 
3925  // Get all of the records for DB type migration
3926  std::unique_ptr<DatabaseBatch> batch = m_database->MakeBatch();
3927  std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
3928  std::vector<std::pair<SerializeData, SerializeData>> records;
3929  if (!cursor) {
3930  error = _("Error: Unable to begin reading all records in the database");
3931  return false;
3932  }
3934  while (true) {
3935  DataStream ss_key{};
3936  DataStream ss_value{};
3937  status = cursor->Next(ss_key, ss_value);
3938  if (status != DatabaseCursor::Status::MORE) {
3939  break;
3940  }
3941  SerializeData key(ss_key.begin(), ss_key.end());
3942  SerializeData value(ss_value.begin(), ss_value.end());
3943  records.emplace_back(key, value);
3944  }
3945  cursor.reset();
3946  batch.reset();
3947  if (status != DatabaseCursor::Status::DONE) {
3948  error = _("Error: Unable to read all records in the database");
3949  return false;
3950  }
3951 
3952  // Close this database and delete the file
3953  fs::path db_path = fs::PathFromString(m_database->Filename());
3954  m_database->Close();
3955  fs::remove(db_path);
3956 
3957  // Generate the path for the location of the migrated wallet
3958  // Wallets that are plain files rather than wallet directories will be migrated to be wallet directories.
3960 
3961  // Make new DB
3962  DatabaseOptions opts;
3963  opts.require_create = true;
3965  DatabaseStatus db_status;
3966  std::unique_ptr<WalletDatabase> new_db = MakeDatabase(wallet_path, opts, db_status, error);
3967  assert(new_db); // This is to prevent doing anything further with this wallet. The original file was deleted, but a backup exists.
3968  m_database.reset();
3969  m_database = std::move(new_db);
3970 
3971  // Write existing records into the new DB
3972  batch = m_database->MakeBatch();
3973  bool began = batch->TxnBegin();
3974  assert(began); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
3975  for (const auto& [key, value] : records) {
3976  if (!batch->Write(Span{key}, Span{value})) {
3977  batch->TxnAbort();
3978  m_database->Close();
3979  fs::remove(m_database->Filename());
3980  assert(false); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
3981  }
3982  }
3983  bool committed = batch->TxnCommit();
3984  assert(committed); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
3985  return true;
3986 }
3987 
3988 std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& error) const
3989 {
3991 
3993  if (!Assume(legacy_spkm)) {
3994  // This shouldn't happen
3995  error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));
3996  return std::nullopt;
3997  }
3998 
3999  std::optional<MigrationData> res = legacy_spkm->MigrateToDescriptor();
4000  if (res == std::nullopt) {
4001  error = _("Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
4002  return std::nullopt;
4003  }
4004  return res;
4005 }
4006 
4008 {
4010 
4012  if (!Assume(legacy_spkm)) {
4013  // This shouldn't happen
4014  error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));
4015  return false;
4016  }
4017 
4018  // Get all invalid or non-watched scripts that will not be migrated
4019  std::set<CTxDestination> not_migrated_dests;
4020  for (const auto& script : legacy_spkm->GetNotMineScriptPubKeys()) {
4021  CTxDestination dest;
4022  if (ExtractDestination(script, dest)) not_migrated_dests.emplace(dest);
4023  }
4024 
4025  Assume(!m_cached_spks.empty());
4026 
4027  for (auto& desc_spkm : data.desc_spkms) {
4028  if (m_spk_managers.count(desc_spkm->GetID()) > 0) {
4029  error = _("Error: Duplicate descriptors created during migration. Your wallet may be corrupted.");
4030  return false;
4031  }
4032  uint256 id = desc_spkm->GetID();
4033  AddScriptPubKeyMan(id, std::move(desc_spkm));
4034  }
4035 
4036  // Remove the LegacyScriptPubKeyMan from disk
4037  if (!legacy_spkm->DeleteRecords()) {
4038  return false;
4039  }
4040 
4041  // Remove the LegacyScriptPubKeyMan from memory
4042  m_spk_managers.erase(legacy_spkm->GetID());
4043  m_external_spk_managers.clear();
4044  m_internal_spk_managers.clear();
4045 
4046  // Setup new descriptors
4047  SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
4049  // Use the existing master key if we have it
4050  if (data.master_key.key.IsValid()) {
4052  } else {
4053  // Setup with a new seed if we don't.
4055  }
4056  }
4057 
4058  // Get best block locator so that we can copy it to the watchonly and solvables
4059  CBlockLocator best_block_locator;
4060  if (!WalletBatch(GetDatabase()).ReadBestBlock(best_block_locator)) {
4061  error = _("Error: Unable to read wallet's best block locator record");
4062  return false;
4063  }
4064 
4065  // Check if the transactions in the wallet are still ours. Either they belong here, or they belong in the watchonly wallet.
4066  // We need to go through these in the tx insertion order so that lookups to spends works.
4067  std::vector<uint256> txids_to_delete;
4068  std::unique_ptr<WalletBatch> watchonly_batch;
4069  if (data.watchonly_wallet) {
4070  watchonly_batch = std::make_unique<WalletBatch>(data.watchonly_wallet->GetDatabase());
4071  // Copy the next tx order pos to the watchonly wallet
4072  LOCK(data.watchonly_wallet->cs_wallet);
4073  data.watchonly_wallet->nOrderPosNext = nOrderPosNext;
4074  watchonly_batch->WriteOrderPosNext(data.watchonly_wallet->nOrderPosNext);
4075  // Write the best block locator to avoid rescanning on reload
4076  if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
4077  error = _("Error: Unable to write watchonly wallet best block locator record");
4078  return false;
4079  }
4080  }
4081  if (data.solvable_wallet) {
4082  // Write the best block locator to avoid rescanning on reload
4083  if (!WalletBatch(data.solvable_wallet->GetDatabase()).WriteBestBlock(best_block_locator)) {
4084  error = _("Error: Unable to write solvable wallet best block locator record");
4085  return false;
4086  }
4087  }
4088  for (const auto& [_pos, wtx] : wtxOrdered) {
4089  // Check it is the watchonly wallet's
4090  // solvable_wallet doesn't need to be checked because transactions for those scripts weren't being watched for
4091  bool is_mine = IsMine(*wtx->tx) || IsFromMe(*wtx->tx);
4092  if (data.watchonly_wallet) {
4093  LOCK(data.watchonly_wallet->cs_wallet);
4094  if (data.watchonly_wallet->IsMine(*wtx->tx) || data.watchonly_wallet->IsFromMe(*wtx->tx)) {
4095  // Add to watchonly wallet
4096  const uint256& hash = wtx->GetHash();
4097  const CWalletTx& to_copy_wtx = *wtx;
4098  if (!data.watchonly_wallet->LoadToWallet(hash, [&](CWalletTx& ins_wtx, bool new_tx) EXCLUSIVE_LOCKS_REQUIRED(data.watchonly_wallet->cs_wallet) {
4099  if (!new_tx) return false;
4100  ins_wtx.SetTx(to_copy_wtx.tx);
4101  ins_wtx.CopyFrom(to_copy_wtx);
4102  return true;
4103  })) {
4104  error = strprintf(_("Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex());
4105  return false;
4106  }
4107  watchonly_batch->WriteTx(data.watchonly_wallet->mapWallet.at(hash));
4108  // Mark as to remove from the migrated wallet only if it does not also belong to it
4109  if (!is_mine) {
4110  txids_to_delete.push_back(hash);
4111  }
4112  continue;
4113  }
4114  }
4115  if (!is_mine) {
4116  // Both not ours and not in the watchonly wallet
4117  error = strprintf(_("Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex());
4118  return false;
4119  }
4120  }
4121  watchonly_batch.reset(); // Flush
4122  // Do the removes
4123  if (txids_to_delete.size() > 0) {
4124  if (auto res = RemoveTxs(txids_to_delete); !res) {
4125  error = _("Error: Could not delete watchonly transactions. ") + util::ErrorString(res);
4126  return false;
4127  }
4128  }
4129 
4130  // Pair external wallets with their corresponding db handler
4131  std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4132  for (const auto& ext_wallet : {data.watchonly_wallet, data.solvable_wallet}) {
4133  if (!ext_wallet) continue;
4134 
4135  std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(ext_wallet->GetDatabase());
4136  if (!batch->TxnBegin()) {
4137  error = strprintf(_("Error: database transaction cannot be executed for wallet %s"), ext_wallet->GetName());
4138  return false;
4139  }
4140  wallets_vec.emplace_back(ext_wallet, std::move(batch));
4141  }
4142 
4143  // Write address book entry to disk
4144  auto func_store_addr = [](WalletBatch& batch, const CTxDestination& dest, const CAddressBookData& entry) {
4145  auto address{EncodeDestination(dest)};
4146  if (entry.purpose) batch.WritePurpose(address, PurposeToString(*entry.purpose));
4147  if (entry.label) batch.WriteName(address, *entry.label);
4148  for (const auto& [id, request] : entry.receive_requests) {
4149  batch.WriteAddressReceiveRequest(dest, id, request);
4150  }
4151  if (entry.previously_spent) batch.WriteAddressPreviouslySpent(dest, true);
4152  };
4153 
4154  // Check the address book data in the same way we did for transactions
4155  std::vector<CTxDestination> dests_to_delete;
4156  for (const auto& [dest, record] : m_address_book) {
4157  // Ensure "receive" entries that are no longer part of the original wallet are transferred to another wallet
4158  // Entries for everything else ("send") will be cloned to all wallets.
4159  bool require_transfer = record.purpose == AddressPurpose::RECEIVE && !IsMine(dest);
4160  bool copied = false;
4161  for (auto& [wallet, batch] : wallets_vec) {
4162  LOCK(wallet->cs_wallet);
4163  if (require_transfer && !wallet->IsMine(dest)) continue;
4164 
4165  // Copy the entire address book entry
4166  wallet->m_address_book[dest] = record;
4167  func_store_addr(*batch, dest, record);
4168 
4169  copied = true;
4170  // Only delete 'receive' records that are no longer part of the original wallet
4171  if (require_transfer) {
4172  dests_to_delete.push_back(dest);
4173  break;
4174  }
4175  }
4176 
4177  // Fail immediately if we ever found an entry that was ours and cannot be transferred
4178  // to any of the created wallets (watch-only, solvable).
4179  // Means that no inferred descriptor maps to the stored entry. Which mustn't happen.
4180  if (require_transfer && !copied) {
4181 
4182  // Skip invalid/non-watched scripts that will not be migrated
4183  if (not_migrated_dests.count(dest) > 0) {
4184  dests_to_delete.push_back(dest);
4185  continue;
4186  }
4187 
4188  error = _("Error: Address book data in wallet cannot be identified to belong to migrated wallets");
4189  return false;
4190  }
4191  }
4192 
4193  // Persist external wallets address book entries
4194  for (auto& [wallet, batch] : wallets_vec) {
4195  if (!batch->TxnCommit()) {
4196  error = strprintf(_("Error: address book copy failed for wallet %s"), wallet->GetName());
4197  return false;
4198  }
4199  }
4200 
4201  // Remove the things to delete in this wallet
4202  WalletBatch local_wallet_batch(GetDatabase());
4203  local_wallet_batch.TxnBegin();
4204  if (dests_to_delete.size() > 0) {
4205  for (const auto& dest : dests_to_delete) {
4206  if (!DelAddressBookWithDB(local_wallet_batch, dest)) {
4207  error = _("Error: Unable to remove watchonly address book data");
4208  return false;
4209  }
4210  }
4211  }
4212  local_wallet_batch.TxnCommit();
4213 
4214  // Connect the SPKM signals
4217 
4218  WalletLogPrintf("Wallet migration complete.\n");
4219 
4220  return true;
4221 }
4222 
4224 {
4226 }
4227 
4229 {
4230  AssertLockHeld(wallet.cs_wallet);
4231 
4232  // Get all of the descriptors from the legacy wallet
4233  std::optional<MigrationData> data = wallet.GetDescriptorsForLegacy(error);
4234  if (data == std::nullopt) return false;
4235 
4236  // Create the watchonly and solvable wallets if necessary
4237  if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
4238  DatabaseOptions options;
4239  options.require_existing = false;
4240  options.require_create = true;
4242 
4243  WalletContext empty_context;
4244  empty_context.args = context.args;
4245 
4246  // Make the wallets
4248  if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
4250  }
4251  if (wallet.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
4253  }
4254  if (data->watch_descs.size() > 0) {
4255  wallet.WalletLogPrintf("Making a new watchonly wallet containing the watched scripts\n");
4256 
4257  DatabaseStatus status;
4258  std::vector<bilingual_str> warnings;
4259  std::string wallet_name = wallet.GetName() + "_watchonly";
4260  std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4261  if (!database) {
4262  error = strprintf(_("Wallet file creation failed: %s"), error);
4263  return false;
4264  }
4265 
4266  data->watchonly_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4267  if (!data->watchonly_wallet) {
4268  error = _("Error: Failed to create new watchonly wallet");
4269  return false;
4270  }
4271  res.watchonly_wallet = data->watchonly_wallet;
4272  LOCK(data->watchonly_wallet->cs_wallet);
4273 
4274  // Parse the descriptors and add them to the new wallet
4275  for (const auto& [desc_str, creation_time] : data->watch_descs) {
4276  // Parse the descriptor
4277  FlatSigningProvider keys;
4278  std::string parse_err;
4279  std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, parse_err, /* require_checksum */ true);
4280  assert(desc); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor
4281  assert(!desc->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
4282 
4283  // Add to the wallet
4284  WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
4285  data->watchonly_wallet->AddWalletDescriptor(w_desc, keys, "", false);
4286  }
4287 
4288  // Add the wallet to settings
4289  UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
4290  }
4291  if (data->solvable_descs.size() > 0) {
4292  wallet.WalletLogPrintf("Making a new watchonly wallet containing the unwatched solvable scripts\n");
4293 
4294  DatabaseStatus status;
4295  std::vector<bilingual_str> warnings;
4296  std::string wallet_name = wallet.GetName() + "_solvables";
4297  std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4298  if (!database) {
4299  error = strprintf(_("Wallet file creation failed: %s"), error);
4300  return false;
4301  }
4302 
4303  data->solvable_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4304  if (!data->solvable_wallet) {
4305  error = _("Error: Failed to create new watchonly wallet");
4306  return false;
4307  }
4308  res.solvables_wallet = data->solvable_wallet;
4309  LOCK(data->solvable_wallet->cs_wallet);
4310 
4311  // Parse the descriptors and add them to the new wallet
4312  for (const auto& [desc_str, creation_time] : data->solvable_descs) {
4313  // Parse the descriptor
4314  FlatSigningProvider keys;
4315  std::string parse_err;
4316  std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, parse_err, /* require_checksum */ true);
4317  assert(desc); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor
4318  assert(!desc->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
4319 
4320  // Add to the wallet
4321  WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
4322  data->solvable_wallet->AddWalletDescriptor(w_desc, keys, "", false);
4323  }
4324 
4325  // Add the wallet to settings
4326  UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
4327  }
4328  }
4329 
4330  // Add the descriptors to wallet, remove LegacyScriptPubKeyMan, and cleanup txs and address book data
4331  if (!wallet.ApplyMigrationData(*data, error)) {
4332  return false;
4333  }
4334  return true;
4335 }
4336 
4337 util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context)
4338 {
4339  MigrationResult res;
4340  bilingual_str error;
4341  std::vector<bilingual_str> warnings;
4342 
4343  // If the wallet is still loaded, unload it so that nothing else tries to use it while we're changing it
4344  bool was_loaded = false;
4345  if (auto wallet = GetWallet(context, wallet_name)) {
4346  if (!RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt, warnings)) {
4347  return util::Error{_("Unable to unload the wallet before migrating")};
4348  }
4349  UnloadWallet(std::move(wallet));
4350  was_loaded = true;
4351  }
4352 
4353  // Load the wallet but only in the context of this function.
4354  // No signals should be connected nor should anything else be aware of this wallet
4355  WalletContext empty_context;
4356  empty_context.args = context.args;
4357  DatabaseOptions options;
4358  options.require_existing = true;
4359  DatabaseStatus status;
4360  std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4361  if (!database) {
4362  return util::Error{Untranslated("Wallet file verification failed.") + Untranslated(" ") + error};
4363  }
4364 
4365  // Make the local wallet
4366  std::shared_ptr<CWallet> local_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4367  if (!local_wallet) {
4368  return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
4369  }
4370 
4371  // Helper to reload as normal for some of our exit scenarios
4372  const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4373  assert(to_reload.use_count() == 1);
4374  std::string name = to_reload->GetName();
4375  to_reload.reset();
4376  to_reload = LoadWallet(context, name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
4377  return to_reload != nullptr;
4378  };
4379 
4380  // Before anything else, check if there is something to migrate.
4381  if (local_wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4382  if (was_loaded) {
4383  reload_wallet(local_wallet);
4384  }
4385  return util::Error{_("Error: This wallet is already a descriptor wallet")};
4386  }
4387 
4388  // Make a backup of the DB
4389  fs::path this_wallet_dir = fs::absolute(fs::PathFromString(local_wallet->GetDatabase().Filename())).parent_path();
4390  fs::path backup_filename = fs::PathFromString(strprintf("%s_%d.legacy.bak", (wallet_name.empty() ? "default_wallet" : wallet_name), GetTime()));
4391  fs::path backup_path = this_wallet_dir / backup_filename;
4392  if (!local_wallet->BackupWallet(fs::PathToString(backup_path))) {
4393  if (was_loaded) {
4394  reload_wallet(local_wallet);
4395  }
4396  return util::Error{_("Error: Unable to make a backup of your wallet")};
4397  }
4398  res.backup_path = backup_path;
4399 
4400  bool success = false;
4401 
4402  // Unlock the wallet if needed
4403  if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4404  if (was_loaded) {
4405  reload_wallet(local_wallet);
4406  }
4407  if (passphrase.find('\0') == std::string::npos) {
4408  return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4409  } else {
4410  return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4411  "The passphrase contains a null character (ie - a zero byte). "
4412  "If this passphrase was set with a version of this software prior to 25.0, "
4413  "please try again with only the characters up to — but not including — "
4414  "the first null character.")};
4415  }
4416  }
4417 
4418  {
4419  LOCK(local_wallet->cs_wallet);
4420  // First change to using SQLite
4421  if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
4422 
4423  // Do the migration of keys and scripts for non-blank wallets, and cleanup if it fails
4424  success = local_wallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
4425  if (!success) {
4426  success = DoMigration(*local_wallet, context, error, res);
4427  } else {
4428  // Make sure that descriptors flag is actually set
4429  local_wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
4430  }
4431  }
4432 
4433  // In case of reloading failure, we need to remember the wallet dirs to remove
4434  // Set is used as it may be populated with the same wallet directory paths multiple times,
4435  // both before and after reloading. This ensures the set is complete even if one of the wallets
4436  // fails to reload.
4437  std::set<fs::path> wallet_dirs;
4438  if (success) {
4439  // Migration successful, unload all wallets locally, then reload them.
4440  // Reload the main wallet
4441  wallet_dirs.insert(fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4442  success = reload_wallet(local_wallet);
4443  res.wallet = local_wallet;
4444  res.wallet_name = wallet_name;
4445  if (success && res.watchonly_wallet) {
4446  // Reload watchonly
4447  wallet_dirs.insert(fs::PathFromString(res.watchonly_wallet->GetDatabase().Filename()).parent_path());
4448  success = reload_wallet(res.watchonly_wallet);
4449  }
4450  if (success && res.solvables_wallet) {
4451  // Reload solvables
4452  wallet_dirs.insert(fs::PathFromString(res.solvables_wallet->GetDatabase().Filename()).parent_path());
4453  success = reload_wallet(res.solvables_wallet);
4454  }
4455  }
4456  if (!success) {
4457  // Migration failed, cleanup
4458  // Copy the backup to the actual wallet dir
4459  fs::path temp_backup_location = fsbridge::AbsPathJoin(GetWalletDir(), backup_filename);
4460  fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4461 
4462  // Make list of wallets to cleanup
4463  std::vector<std::shared_ptr<CWallet>> created_wallets;
4464  if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4465  if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));
4466  if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));
4467 
4468  // Get the directories to remove after unloading
4469  for (std::shared_ptr<CWallet>& w : created_wallets) {
4470  wallet_dirs.emplace(fs::PathFromString(w->GetDatabase().Filename()).parent_path());
4471  }
4472 
4473  // Unload the wallets
4474  for (std::shared_ptr<CWallet>& w : created_wallets) {
4475  if (w->HaveChain()) {
4476  // Unloading for wallets that were loaded for normal use
4477  if (!RemoveWallet(context, w, /*load_on_start=*/false)) {
4478  error += _("\nUnable to cleanup failed migration");
4479  return util::Error{error};
4480  }
4481  UnloadWallet(std::move(w));
4482  } else {
4483  // Unloading for wallets in local context
4484  assert(w.use_count() == 1);
4485  w.reset();
4486  }
4487  }
4488 
4489  // Delete the wallet directories
4490  for (const fs::path& dir : wallet_dirs) {
4491  fs::remove_all(dir);
4492  }
4493 
4494  // Restore the backup
4495  DatabaseStatus status;
4496  std::vector<bilingual_str> warnings;
4497  if (!RestoreWallet(context, temp_backup_location, wallet_name, /*load_on_start=*/std::nullopt, status, error, warnings)) {
4498  error += _("\nUnable to restore backup of wallet.");
4499  return util::Error{error};
4500  }
4501 
4502  // Move the backup to the wallet dir
4503  fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4504  fs::remove(temp_backup_location);
4505 
4506  return util::Error{error};
4507  }
4508  return res;
4509 }
4510 
4511 void CWallet::CacheNewScriptPubKeys(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)
4512 {
4513  for (const auto& script : spks) {
4514  m_cached_spks[script].push_back(spkm);
4515  }
4516 }
4517 
4518 void CWallet::TopUpCallback(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)
4519 {
4520  // Update scriptPubKey cache
4521  CacheNewScriptPubKeys(spks, spkm);
4522 }
4523 
4524 std::set<CExtPubKey> CWallet::GetActiveHDPubKeys() const
4525 {
4527 
4529 
4530  std::set<CExtPubKey> active_xpubs;
4531  for (const auto& spkm : GetActiveScriptPubKeyMans()) {
4532  const DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
4533  assert(desc_spkm);
4534  LOCK(desc_spkm->cs_desc_man);
4535  WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
4536 
4537  std::set<CPubKey> desc_pubkeys;
4538  std::set<CExtPubKey> desc_xpubs;
4539  w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
4540  active_xpubs.merge(std::move(desc_xpubs));
4541  }
4542  return active_xpubs;
4543 }
4544 
4545 std::optional<CKey> CWallet::GetKey(const CKeyID& keyid) const
4546 {
4548 
4549  for (const auto& spkm : GetAllScriptPubKeyMans()) {
4550  const DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
4551  assert(desc_spkm);
4552  LOCK(desc_spkm->cs_desc_man);
4553  if (std::optional<CKey> key = desc_spkm->GetKey(keyid)) {
4554  return key;
4555  }
4556  }
4557  return std::nullopt;
4558 }
4559 } // namespace wallet
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
Definition: addresstype.cpp:49
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:131
bool MoneyRange(const CAmount &nValue)
Definition: amount.h:27
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
ArgsManager gArgs
Definition: args.cpp:41
int ret
if(!SetupNetworking())
#define PACKAGE_NAME
#define PACKAGE_BUGREPORT
int flags
Definition: bitcoin-tx.cpp:530
ArgsManager & args
Definition: bitcoind.cpp:268
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
Definition: chain.h:37
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:73
#define Assert(val)
Identity function.
Definition: check.h:77
#define STR_INTERNAL_BUG(msg)
Definition: check.h:60
#define Assume(val)
Assume is the identity function.
Definition: check.h:89
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: args.cpp:369
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
Definition: args.cpp:480
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:455
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:505
bool IsNull() const
Definition: block.h:49
Definition: block.h:69
std::vector< CTransactionRef > vtx
Definition: block.h:72
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
Definition: feerate.h:33
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
Definition: feerate.cpp:39
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
Definition: feerate.h:65
An encapsulated private key.
Definition: key.h:33
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:119
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:188
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition: key.cpp:242
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:24
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
uint32_t n
Definition: transaction.h:32
Txid hash
Definition: transaction.h:31
An encapsulated public key.
Definition: pubkey.h:34
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:414
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:296
const Txid & GetHash() const LIFETIMEBOUND
Definition: transaction.h:343
const std::vector< CTxOut > vout
Definition: transaction.h:307
const std::vector< CTxIn > vin
Definition: transaction.h:306
An input of a transaction.
Definition: transaction.h:67
COutPoint prevout
Definition: transaction.h:69
An output of a transaction.
Definition: transaction.h:150
CScript scriptPubKey
Definition: transaction.h:153
A UTXO entry.
Definition: coins.h:32
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:147
Enables interaction with an external signing device or service, such as a hardware wallet.
UniValue GetDescriptors(const int account)
Get receive and change Descriptor(s) from device for a given account.
Fast randomness source.
Definition: random.h:145
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range)
Return the time point advanced by a uniform random duration.
Definition: random.h:232
RecursiveMutex cs_KeyStore
std::unordered_set< Element, ByteVectorHash > ElementSet
Definition: blockfilter.h:32
Different type to mark Mutex at global scope.
Definition: sync.h:140
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:98
void push_back(UniValue val)
Definition: univalue.cpp:104
bool isArray() const
Definition: univalue.h:85
const UniValue & find_value(std::string_view key) const
Definition: univalue.cpp:233
@ VARR
Definition: univalue.h:24
void setArray()
Definition: univalue.cpp:92
size_t size() const
Definition: univalue.h:71
const std::vector< UniValue > & getValues() const
const UniValue & get_array() const
bool isObject() const
Definition: univalue.h:86
std::string ToString() const
Definition: uint256.cpp:55
constexpr unsigned char * begin()
Definition: uint256.h:68
constexpr void SetNull()
Definition: uint256.h:49
std::string GetHex() const
Definition: uint256.cpp:11
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:33
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:124
virtual CBlockLocator getTipLocator()=0
Get locator for the current chain tip.
virtual CBlockLocator getActiveChainLocator(const uint256 &block_hash)=0
Return a locator that refers to a block in the active chain.
virtual uint256 getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock &block={})=0
Find first block in the chain with timestamp >= the given time and height >= than the given height,...
virtual bool havePruned()=0
Check if any block has been pruned.
virtual common::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
virtual bool hasAssumedValidChain()=0
Return true if an assumed-valid chain is in use.
virtual bool findAncestorByHeight(const uint256 &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
Find ancestor of block at specified height and optionally return ancestor information.
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
virtual double guessVerificationProgress(const uint256 &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
virtual std::optional< int > findLocatorFork(const CBlockLocator &locator)=0
Return height of the highest block on chain in common with the locator, which will either be the orig...
virtual void waitForNotificationsIfTipChanged(const uint256 &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip.
virtual void initMessage(const std::string &message)=0
Send init message.
virtual bool isInMempool(const uint256 &txid)=0
Check if transaction is in mempool.
virtual bool broadcastTransaction(const CTransactionRef &tx, const CAmount &max_tx_fee, bool relay, std::string &err_string)=0
Transaction is added to memory pool, if the transaction fee is below the amount specified by max_tx_f...
virtual bool updateRwSetting(const std::string &name, const common::SettingsValue &value, bool write=true)=0
Write a setting to <datadir>/settings.json.
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings).
Helper for findBlock to selectively return pieces of block data.
Definition: chain.h:54
FoundBlock & height(int &height)
Definition: chain.h:57
std::string ToString() const
static transaction_identifier FromUint256(const uint256 &id)
256-bit opaque blob.
Definition: uint256.h:106
Encryption/decryption context with key information.
Definition: crypter.h:71
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Definition: crypter.cpp:90
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
Definition: crypter.cpp:72
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< unsigned char > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
Definition: crypter.cpp:40
A key from a CWallet's keypool.
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
CPubKey vchPubKey
The public key.
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
bool m_pre_split
Whether this key was generated for a keypool before the wallet was upgraded to HD-split.
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key.
Definition: crypter.h:35
std::vector< unsigned char > vchSalt
Definition: crypter.h:38
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
Definition: crypter.h:41
std::vector< unsigned char > vchCryptedKey
Definition: crypter.h:37
unsigned int nDeriveIterations
Definition: crypter.h:42
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:301
std::atomic< bool > fAbortRescan
Definition: wallet.h:307
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition: wallet.h:453
bool HaveChain() const
Interface to assert chain access.
Definition: wallet.h:478
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
Definition: wallet.h:862
bool IsCrypted() const
Definition: wallet.cpp:3440
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
Definition: wallet.h:602
CAmount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
Definition: wallet.h:729
bool IsActiveScriptPubKeyMan(const ScriptPubKeyMan &spkm) const
Definition: wallet.cpp:3500
OutputType m_default_address_type
Definition: wallet.h:720
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
Definition: wallet.cpp:3590
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
Definition: wallet.cpp:3758
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
Definition: wallet.cpp:3772
std::unique_ptr< WalletDatabase > m_database
Internal database handle.
Definition: wallet.h:394
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
Definition: wallet.h:460
std::function< void(const CTxDestination &dest, const std::string &label, bool is_change, const std::optional< AddressPurpose > purpose)> ListAddrBookFunc
Walk-through the address book entries.
Definition: wallet.h:764
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
Definition: wallet.cpp:3556
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3432
void AddActiveScriptPubKeyManWithDb(WalletBatch &batch, uint256 id, OutputType type, bool internal)
Definition: wallet.cpp:3764
void TopUpCallback(const std::set< CScript > &spks, ScriptPubKeyMan *spkm) override
Callback function for after TopUp completes containing any scripts that were added by a SPKMan.
Definition: wallet.cpp:4518
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
Definition: wallet.cpp:3486
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3333
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
Definition: wallet.cpp:3376
int GetTxDepthInMainChain(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
Definition: wallet.cpp:3406
unsigned int nMasterKeyMaxID
Definition: wallet.h:457
bool SetAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2909
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
Definition: wallet.h:973
std::atomic< double > m_scanning_progress
Definition: wallet.h:312
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
Definition: wallet.h:850
WalletDatabase & GetDatabase() const override
Definition: wallet.h:445
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
Definition: wallet.cpp:3818
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
Definition: wallet.h:412
DescriptorScriptPubKeyMan & LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
Definition: wallet.cpp:3653
bool IsLegacy() const
Determine if we are a legacy wallet.
Definition: wallet.cpp:3809
std::optional< MigrationData > GetDescriptorsForLegacy(bilingual_str &error) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all of the descriptors from a legacy wallet.
Definition: wallet.cpp:3988
bool Unlock(const CKeyingMaterial &vMasterKeyIn)
Definition: wallet.cpp:3471
bool MigrateToSQLite(bilingual_str &error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Move all records from the BDB database to a new SQLite database for storage.
Definition: wallet.cpp:3914
bool BackupWallet(const std::string &strDest) const
Definition: wallet.cpp:3386
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
Definition: wallet.h:413
std::string m_name
Wallet name: relative directory name or "" for default wallet.
Definition: wallet.h:391
bool SetAddressPreviouslySpent(WalletBatch &batch, const CTxDestination &dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2868
RecursiveMutex m_relock_mutex
Definition: wallet.h:578
std::string m_notify_tx_changed_script
Notify external script when a wallet transaction comes in or is updated (handled by -walletnotify)
Definition: wallet.h:735
std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
Definition: wallet.h:923
std::vector< std::string > GetAddressReceiveRequests() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2898
std::vector< WalletDescriptor > GetWalletDescriptors(const CScript &script) const
Get the wallet descriptors for a script.
Definition: wallet.cpp:3578
std::atomic< bool > m_attaching_chain
Definition: wallet.h:309
bool fBroadcastTransactions
Whether this wallet will submit newly created transactions to the node's mempool and prompt rebroadca...
Definition: wallet.h:322
void CacheNewScriptPubKeys(const std::set< CScript > &spks, ScriptPubKeyMan *spkm)
Add scriptPubKeys for this ScriptPubKeyMan into the scriptPubKey cache.
Definition: wallet.cpp:4511
int GetTxBlocksToMaturity(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3420
bool HasEncryptionKeys() const override
Definition: wallet.cpp:3639
static std::shared_ptr< CWallet > Create(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:2947
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
Definition: wallet.h:814
bool CanGrindR() const
Whether the (external) signer performs R-value signature grinding.
Definition: wallet.cpp:4223
std::optional< bool > IsInternalScriptPubKeyMan(ScriptPubKeyMan *spk_man) const
Returns whether the provided ScriptPubKeyMan is internal.
Definition: wallet.cpp:3831
TxItems wtxOrdered
Definition: wallet.h:485
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we support the named feature
Definition: wallet.h:532
MasterKeyMap mapMasterKeys
Definition: wallet.h:456
NodeClock::time_point m_next_resend
The next scheduled rebroadcast of wallet transactions.
Definition: wallet.h:319
void WalletLogPrintf(const char *fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
Definition: wallet.h:931
std::optional< CKey > GetKey(const CKeyID &keyid) const
Find the private key for the given key id from the wallet's descriptors, if available Returns nullopt...
Definition: wallet.cpp:4545
bool EraseAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2916
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition: wallet.h:847
void LoadAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &request) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Appends payment request to destination.
Definition: wallet.cpp:2887
void AddScriptPubKeyMan(const uint256 &id, std::unique_ptr< ScriptPubKeyMan > spkm_man)
Definition: wallet.cpp:3608
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Remove specified ScriptPubKeyMan from set of active SPK managers.
Definition: wallet.cpp:3792
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
Definition: wallet.cpp:3343
std::atomic< uint64_t > m_wallet_flags
WalletFlags set on this wallet.
Definition: wallet.h:377
interfaces::Chain * m_chain
Interface for accessing chain state.
Definition: wallet.h:388
std::set< CExtPubKey > GetActiveHDPubKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve the xpubs in use by the active descriptors.
Definition: wallet.cpp:4524
bool IsLocked() const override
Definition: wallet.cpp:3445
boost::signals2::signal< void(const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
Definition: wallet.h:844
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
Definition: wallet.h:853
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
Definition: wallet.cpp:3511
unsigned int ComputeTimeSmart(const CWalletTx &wtx, bool rescanning_old_block) const
Compute smart timestamp for a transaction being added to the wallet.
Definition: wallet.cpp:2817
ScriptPubKeyMan * AddWalletDescriptor(WalletDescriptor &desc, const FlatSigningProvider &signing_provider, const std::string &label, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type.
Definition: wallet.cpp:3855
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
Definition: wallet.cpp:3520
bool IsAddressPreviouslySpent(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2892
bool WithEncryptionKey(std::function< bool(const CKeyingMaterial &)> cb) const override
Pass the encryption key to cb().
Definition: wallet.cpp:3633
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2734
uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.h:979
int64_t m_keypool_size
Number of pre-generated keys/scripts by each spkm (part of the look-ahead process,...
Definition: wallet.h:732
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:443
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
Definition: wallet.cpp:3644
std::atomic< int64_t > m_best_block_time
Definition: wallet.h:324
std::unordered_map< CScript, std::vector< ScriptPubKeyMan * >, SaltedSipHasher > m_cached_spks
Cache of descriptor ScriptPubKeys used for IsMine. Maps ScriptPubKey to set of spkms.
Definition: wallet.h:427
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
Definition: wallet.cpp:3618
static bool AttachChain(const std::shared_ptr< CWallet > &wallet, interfaces::Chain &chain, const bool rescan_required, bilingual_str &error, std::vector< bilingual_str > &warnings)
Catch wallet up to current chain, scanning new blocks, updating the best block locator and m_last_blo...
Definition: wallet.cpp:3211
boost::signals2::signal< void(const CTxDestination &address, const std::string &label, bool isMine, AddressPurpose purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
Definition: wallet.h:838
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
Definition: wallet.cpp:3602
std::multimap< int64_t, CWalletTx * > TxItems
Definition: wallet.h:484
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
Definition: wallet.h:859
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3703
DescriptorScriptPubKeyMan & SetupDescriptorScriptPubKeyMan(WalletBatch &batch, const CExtKey &master_key, const OutputType &output_type, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMan and add it to the wallet.
Definition: wallet.cpp:3665
bool ApplyMigrationData(MigrationData &data, bilingual_str &error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds the ScriptPubKeyMans given in MigrationData to this wallet, removes LegacyScriptPubKeyMan,...
Definition: wallet.cpp:4007
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
Definition: wallet.h:417
std::function< TxUpdate(CWalletTx &wtx)> TryUpdatingStateFn
Definition: wallet.h:363
std::atomic< int64_t > m_birth_time
Definition: wallet.h:328
void LoadAddressPreviouslySpent(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Marks destination as previously spent.
Definition: wallet.cpp:2882
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
Definition: wallet.cpp:3530
interfaces::Chain & chain() const
Interface for accessing chain state.
Definition: wallet.h:502
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:177
bool isBlockConflicted() const
Definition: transaction.h:347
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
Definition: transaction.cpp:12
const T * state() const
Definition: transaction.h:338
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: transaction.h:205
const Txid & GetHash() const LIFETIMEBOUND
Definition: transaction.h:351
std::set< Txid > mempool_conflicts
Definition: transaction.h:267
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: transaction.h:204
void updateState(interfaces::Chain &chain)
Update transaction state when attaching to a chain, filling in heights of conflicted and confirmed bl...
Definition: transaction.cpp:32
int64_t nOrderPos
position in ordered transaction list
Definition: transaction.h:224
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node,...
Definition: transaction.h:223
unsigned int nTimeReceived
time received by this node
Definition: transaction.h:207
CTransactionRef tx
Definition: transaction.h:258
void SetTx(CTransactionRef arg)
Definition: transaction.h:315
bool IsCoinBase() const
Definition: transaction.h:353
unsigned int fTimeReceivedIsTxTime
Definition: transaction.h:206
bool InMempool() const
Definition: transaction.cpp:21
bool isAbandoned() const
Definition: transaction.h:345
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
Definition: transaction.h:225
bool isInactive() const
Definition: transaction.h:348
int64_t GetTxTime() const
Definition: transaction.cpp:26
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
Definition: transaction.h:236
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
Definition: transaction.h:217
void MarkDirty()
make sure balances are recalculated
Definition: transaction.h:321
WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
std::optional< CKey > GetKey(const CKeyID &keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
Retrieve the particular key if it is available. Returns nullopt if the key is not in the wallet,...
bool HasWalletDescriptor(const WalletDescriptor &desc) const
bool DeleteRecords()
Delete all the records ofthis LegacyScriptPubKeyMan from disk.
uint256 GetID() const override
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const override
std::unordered_set< CScript, SaltedSipHasher > GetNotMineScriptPubKeys() const
Retrieves scripts that were imported by bugs into the legacy spkm and are simply invalid,...
std::set< CKeyID > GetKeys() const override
isminetype IsMine(const CScript &script) const override
std::optional< MigrationData > MigrateToDescriptor()
Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this Legac...
A wrapper to reserve an address from a wallet.
Definition: wallet.h:189
const CWallet *const pwallet
The wallet to reserve from.
Definition: wallet.h:192
CTxDestination address
The destination.
Definition: wallet.h:199
bool fInternal
Whether this is from the internal (change output) keypool.
Definition: wallet.h:201
ScriptPubKeyMan * m_spk_man
The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called.
Definition: wallet.h:194
int64_t nIndex
The index of the address's key in the keypool.
Definition: wallet.h:197
OutputType const type
Definition: wallet.h:195
virtual void KeepDestination(int64_t index, const OutputType &type)
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
virtual util::Result< CTxDestination > GetReservedDestination(const OutputType type, bool internal, int64_t &index, CKeyPool &keypool)
Access to the wallet database.
Definition: walletdb.h:191
bool TxnAbort()
Abort current transaction.
Definition: walletdb.cpp:1345
bool EraseName(const std::string &strAddress)
Definition: walletdb.cpp:80
DBErrors LoadWallet(CWallet *pwallet)
Definition: walletdb.cpp:1150
bool WriteBestBlock(const CBlockLocator &locator)
Definition: walletdb.cpp:179
bool ReadBestBlock(CBlockLocator &locator)
Definition: walletdb.cpp:185
bool EraseTx(uint256 hash)
Definition: walletdb.cpp:102
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
Definition: walletdb.cpp:153
bool WriteMinVersion(int nVersion)
Definition: walletdb.cpp:211
bool TxnBegin()
Begin a new transaction.
Definition: walletdb.cpp:1335
bool WriteAddressPreviouslySpent(const CTxDestination &dest, bool previously_spent)
Definition: walletdb.cpp:1293
bool EraseAddressReceiveRequest(const CTxDestination &dest, const std::string &id)
Definition: walletdb.cpp:1304
bool TxnCommit()
Commit current transaction.
Definition: walletdb.cpp:1340
bool WriteName(const std::string &strAddress, const std::string &strName)
Definition: walletdb.cpp:75
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
Definition: walletdb.cpp:87
bool WriteWalletFlags(const uint64_t flags)
Definition: walletdb.cpp:1321
bool EraseAddressData(const CTxDestination &dest)
Definition: walletdb.cpp:1309
bool WriteOrderPosNext(int64_t nOrderPosNext)
Definition: walletdb.cpp:191
bool WriteTx(const CWalletTx &wtx)
Definition: walletdb.cpp:97
bool ErasePurpose(const std::string &strAddress)
Definition: walletdb.cpp:92
bool EraseLockedUTXO(const COutPoint &output)
Definition: walletdb.cpp:301
bool WriteLockedUTXO(const COutPoint &output)
Definition: walletdb.cpp:296
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
Definition: walletdb.cpp:216
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
Definition: walletdb.cpp:222
bool WriteAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &receive_request)
Definition: walletdb.cpp:1299
virtual bool Rewrite(const char *pszSkip=nullptr)=0
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
virtual void ReloadDbEnv()=0
virtual void Close()=0
Flush to the database file and close the database.
virtual bool Backup(const std::string &strDest) const =0
Back up the entire database to a file.
virtual void Flush()=0
Make sure all changes are flushed to database file.
Descriptor with some wallet metadata.
Definition: walletutil.h:85
std::shared_ptr< Descriptor > descriptor
Definition: walletutil.h:87
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1072
Clock::time_point now() const
Definition: wallet.h:1100
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1082
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
Definition: cleanse.cpp:14
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:318
std::string ShellEscape(const std::string &arg)
Definition: system.cpp:37
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
Definition: consensus.h:19
bilingual_str AmountHighWarn(const std::string &optname)
Definition: error.cpp:59
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
Definition: error.cpp:64
TransactionError
Definition: error.h:22
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
Definition: fs_helpers.cpp:262
void MarkDestinationsDirty(const std::set< CTxDestination > &destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Marks all outputs in each one of the destinations dirty, so their cache is reset and does not return ...
Definition: wallet.cpp:2580
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &purpose)
Definition: wallet.cpp:2449
bool TopUpKeyPool(unsigned int kpSize=0)
Definition: wallet.cpp:2529
bool UnlockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2694
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2518
void KeepDestination()
Keep the address. Do not return its key to the keypool when this object goes out of scope.
Definition: wallet.cpp:2652
bool IsLockedCoin(const COutPoint &output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2716
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Fetch the inputs and sign with SIGHASH_ALL.
Definition: wallet.cpp:2138
DBErrors LoadWallet()
Definition: wallet.cpp:2341
std::vector< CTxDestination > ListAddrBookAddresses(const std::optional< AddrBookFilter > &filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Filter and retrieve destinations stored in the addressbook.
Definition: wallet.cpp:2603
void ReturnDestination()
Return reserved address.
Definition: wallet.cpp:2661
util::Result< CTxDestination > GetNewDestination(const OutputType type, const std::string label)
Definition: wallet.cpp:2539
util::Result< void > RemoveTxs(std::vector< uint256 > &txs_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases the provided transactions from the wallet.
Definition: wallet.cpp:2366
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2501
bool LockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2684
std::optional< int64_t > GetOldestKeyPoolTime() const
Definition: wallet.cpp:2566
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
Definition: wallet.cpp:2226
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm)
Submit the transaction to the node's mempool and then relay to peers.
Definition: wallet.cpp:2300
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &strPurpose)
Definition: wallet.cpp:2413
bool DelAddressBookWithDB(WalletBatch &batch, const CTxDestination &address)
Definition: wallet.cpp:2462
bool DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
Definition: wallet.cpp:2670
std::set< std::string > ListAddrBookLabels(const std::optional< AddressPurpose > purpose) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve all the known labels in the address book.
Definition: wallet.cpp:2619
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
Definition: wallet.cpp:2239
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2722
bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2704
util::Result< CTxDestination > GetNewChangeDestination(const OutputType type)
Definition: wallet.cpp:2555
void ForEachAddrBookEntry(const ListAddrBookFunc &func) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2594
bool DelAddressBook(const CTxDestination &address)
Definition: wallet.cpp:2455
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
Definition: wallet.cpp:2633
TransactionError FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, int sighash_type=SIGHASH_DEFAULT, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr, bool finalize=true) const
Fills out a PSBT with information from the wallet.
Definition: wallet.cpp:2172
bool IsSpentKey(const CScript &scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1021
void SyncTransaction(const CTransactionRef &tx, const SyncTxState &state, bool update_tx=true, bool rescanning_old_block=false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1405
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1180
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
Definition: wallet.cpp:949
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed.
Definition: wallet.cpp:1285
bool HasWalletSpend(const CTransactionRef &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Check if a given transaction has any of its outputs spent by another transaction in the wallet.
Definition: wallet.cpp:681
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
Definition: wallet.cpp:641
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
Definition: wallet.cpp:583
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:703
bool 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) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1777
void MarkConflicted(const uint256 &hashBlock, int conflicting_height, const uint256 &hashTx)
Mark a transaction (and its in-wallet descendants) as conflicting with a particular block.
Definition: wallet.cpp:1330
void updatedBlockTip() override
Definition: wallet.cpp:1558
bool TransactionCanBeAbandoned(const uint256 &hashTx) const
Return whether transaction can be abandoned.
Definition: wallet.cpp:1278
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1747
void blockConnected(ChainstateRole role, const interfaces::BlockInfo &block) override
Definition: wallet.cpp:1492
void MaybeUpdateBirthTime(int64_t time)
Updates wallet birth time if 'time' is below it.
Definition: wallet.cpp:1800
void Flush()
Flush wallet (bitdb flush)
Definition: wallet.cpp:693
void blockDisconnected(const interfaces::BlockInfo &block) override
Definition: wallet.cpp:1514
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
Definition: wallet.cpp:1714
std::set< uint256 > GetConflicts(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs)
Definition: wallet.cpp:658
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
Definition: wallet.cpp:1701
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction spends it:
Definition: wallet.cpp:746
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
Definition: wallet.cpp:1709
void ResubmitWalletTransactions(bool relay, bool force)
Definition: wallet.cpp:2086
void SetSpentKeyState(WalletBatch &batch, const uint256 &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1002
void RecursiveUpdateTxState(const uint256 &tx_hash, const TryUpdatingStateFn &try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction (and its in-wallet descendants) as a particular tx state.
Definition: wallet.cpp:1360
bool CanGetAddresses(bool internal=false) const
Definition: wallet.cpp:1674
void MarkDirty()
Definition: wallet.cpp:961
ScanResult ScanForWalletTransactions(const uint256 &start_block, int start_height, std::optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate, const bool save_progress)
Scan the block chain (starting in start_block) for transactions from or to us.
Definition: wallet.cpp:1860
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
Definition: wallet.cpp:1719
std::set< uint256 > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2033
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
Definition: wallet.cpp:530
bool IsHDEnabled() const
Definition: wallet.cpp:1663
bool 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) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1767
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason) override
Definition: wallet.cpp:1440
static NodeClock::time_point GetDefaultNextResend()
Definition: wallet.cpp:2060
bool ShouldResend() const
Return true if all conditions for periodically resending transactions are met.
Definition: wallet.cpp:2043
void InitWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t flags must be uninitialised (or 0) only known flags may be ...
Definition: wallet.cpp:1731
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
Definition: wallet.cpp:1695
bool AbandonTransaction(const uint256 &hashTx)
Definition: wallet.cpp:1295
CAmount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
Definition: wallet.cpp:1575
bool EncryptWallet(const SecureString &strWalletPassphrase)
Definition: wallet.cpp:789
CWalletTx * AddToWallet(CTransactionRef tx, const TxState &state, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block=false)
Add the transaction to the wallet, wrapping it up inside a CWalletTx.
Definition: wallet.cpp:1052
void AddToSpends(const COutPoint &outpoint, const uint256 &wtxid, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:763
bool MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction.
Definition: wallet.cpp:970
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1757
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
Definition: wallet.cpp:1816
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1597
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
Definition: wallet.cpp:1646
DBErrors ReorderTransactions()
Definition: wallet.cpp:892
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, const SyncTxState &state, bool fUpdate, bool rescanning_old_block) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
Definition: wallet.cpp:1212
void chainStateFlushed(ChainstateRole role, const CBlockLocator &loc) override
Definition: wallet.cpp:630
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
Definition: wallet.cpp:545
const CWalletTx * GetWalletTx(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:521
void transactionAddedToMempool(const CTransactionRef &tx) override
Definition: wallet.cpp:1416
void Close()
Close wallet database.
Definition: wallet.cpp:698
bool SubmitTxMemoryPoolAndRelay(CWalletTx &wtx, std::string &err_string, bool relay) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Pass this transaction to node for mempool insertion and relay to peers if flag set to true.
Definition: wallet.cpp:2003
@ SIGHASH_DEFAULT
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
Definition: interpreter.h:35
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
Definition: chain.h:25
CKey GenerateRandomKey(bool compressed) noexcept
Definition: key.cpp:372
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:287
#define LogPrint(category,...)
Definition: logging.h:263
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
@ BLOCK
Removed for block.
@ CONFLICT
Removed for conflict with in-block transaction.
SigningResult
Definition: message.h:43
@ PRIVATE_KEY_NOT_AVAILABLE
std::optional< CAmount > ParseMoney(const std::string &money_string)
Parse an amount denoted in full coins.
Definition: moneystr.cpp:42
@ SCAN
Definition: logging.h:70
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
Definition: settings.h:107
static path absolute(const path &p)
Definition: fs.h:82
static path u8path(const std::string &utf8_str)
Definition: fs.h:75
static auto quoted(const std::string &s)
Definition: fs.h:95
static bool exists(const path &p)
Definition: fs.h:89
static bool copy_file(const path &from, const path &to, copy_options options)
Definition: fs.h:128
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:151
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:174
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:36
std::unique_ptr< Handler > MakeCleanupHandler(std::function< void()> cleanup)
Return handler wrapping a cleanup function.
Definition: interfaces.cpp:42
std::unique_ptr< Wallet > MakeWallet(wallet::WalletContext &context, const std::shared_ptr< wallet::CWallet > &wallet)
Return implementation of Wallet interface.
Definition: interfaces.cpp:688
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:81
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
Definition: wallet.cpp:239
constexpr CAmount HIGH_APS_FEE
discourage APS fee higher than this amount
Definition: wallet.h:123
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition: db.cpp:142
std::shared_ptr< CWallet > LoadWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:360
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Definition: walletdb.cpp:1350
void MaybeResendWalletTxs(WalletContext &context)
Called periodically by the schedule thread.
Definition: wallet.cpp:2123
std::variant< TxStateConfirmed, TxStateInMempool, TxStateInactive > SyncTxState
Subset of states transaction sync logic is implemented to handle.
Definition: transaction.h:81
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
Definition: context.h:24
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition: wallet.cpp:178
static bool RunWithinTxn(WalletBatch &batch, std::string_view process_desc, const std::function< bool(WalletBatch &)> &func)
Definition: walletdb.cpp:1237
std::variant< TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
Definition: transaction.h:78
std::map< std::string, std::string > mapValue_t
Definition: transaction.h:149
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition: crypter.h:62
DBErrors
Error statuses for the wallet database.
Definition: walletdb.h:48
@ EXTERNAL_SIGNER_SUPPORT_REQUIRED
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:111
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
Definition: wallet.cpp:90
static GlobalMutex g_wallet_release_mutex
Definition: wallet.cpp:216
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
Definition: wallet.cpp:101
const unsigned int WALLET_CRYPTO_KEY_SIZE
Definition: crypter.h:14
static void RefreshMempoolStatus(CWalletTx &tx, interfaces::Chain &chain)
Refresh mempool status so the wallet is in an internally consistent state and immediately knows the t...
Definition: wallet.cpp:131
static std::set< std::string > g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex)
static const bool DEFAULT_WALLETCROSSCHAIN
Definition: wallet.h:136
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
Definition: wallet.cpp:200
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
Definition: wallet.h:43
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
static const std::unordered_set< OutputType > LEGACY_OUTPUT_TYPES
OutputTypes supported by the LegacyScriptPubKeyMan.
static void ReleaseWallet(CWallet *wallet)
Definition: wallet.cpp:222
util::Result< MigrationResult > MigrateLegacyToDescriptor(const std::string &wallet_name, const SecureString &passphrase, WalletContext &context)
Do all steps to migrate a legacy wallet to a descriptor wallet.
Definition: wallet.cpp:4337
static const bool DEFAULT_WALLET_RBF
-walletrbf default
Definition: wallet.h:133
constexpr CAmount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
Definition: wallet.h:140
static std::condition_variable g_wallet_release_cv
Definition: wallet.cpp:217
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
Definition: wallet.cpp:2923
void NotifyWalletLoaded(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition: wallet.cpp:207
constexpr CAmount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
Definition: wallet.h:142
static const unsigned int DEFAULT_TX_CONFIRM_TARGET
-txconfirmtarget default
Definition: wallet.h:131
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: types.h:40
@ ISMINE_NO
Definition: types.h:41
@ ISMINE_SPENDABLE
Definition: types.h:43
@ ISMINE_ALL
Definition: types.h:45
std::string PurposeToString(AddressPurpose p)
Definition: wallet.h:271
static const bool DEFAULT_WALLETBROADCAST
Definition: wallet.h:134
std::shared_ptr< CWallet > RestoreWallet(WalletContext &context, const fs::path &backup_file, const std::string &wallet_name, std::optional< bool > load_on_start, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:478
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition: wallet.cpp:140
bool DoMigration(CWallet &wallet, WalletContext &context, bilingual_str &error, MigrationResult &res) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
Definition: wallet.cpp:4228
WalletFeature
(client) version numbers for particular wallet features
Definition: walletutil.h:16
@ FEATURE_HD_SPLIT
Definition: walletutil.h:24
@ FEATURE_WALLETCRYPT
Definition: walletutil.h:19
@ FEATURE_LATEST
Definition: walletutil.h:30
@ FEATURE_PRE_SPLIT_KEYPOOL
Definition: walletutil.h:28
static uint256 TxStateSerializedBlockHash(const TxState &state)
Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
Definition: transaction.h:99
static constexpr uint64_t KNOWN_WALLET_FLAGS
Definition: wallet.h:151
static void UpdateWalletSetting(interfaces::Chain &chain, const std::string &wallet_name, std::optional< bool > load_on_startup, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:113
static GlobalMutex g_loading_wallet_mutex
Definition: wallet.cpp:215
const unsigned int WALLET_CRYPTO_SALT_SIZE
Definition: crypter.h:15
std::shared_ptr< CWallet > CreateWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:373
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
Definition: walletutil.h:77
@ WALLET_FLAG_LAST_HARDENED_XPUB_CACHED
Definition: walletutil.h:48
@ WALLET_FLAG_KEY_ORIGIN_METADATA
Definition: walletutil.h:45
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:42
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:74
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:51
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
Definition: walletutil.h:71
std::string TxStateString(const T &state)
Return TxState or SyncTxState as a string for logging or debugging.
Definition: transaction.h:124
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:191
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
Definition: wallet.h:127
WalletFeature GetClosestWalletFeature(int version)
Definition: walletutil.cpp:40
DatabaseStatus
Definition: db.h:196
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:152
std::shared_ptr< CWallet > GetDefaultWallet(WalletContext &context, size_t &count)
Definition: wallet.cpp:184
std::shared_ptr< CWallet > wallet
const std::string & FormatOutputType(OutputType type)
Definition: outputtype.cpp:38
std::optional< OutputType > ParseOutputType(const std::string &type)
Definition: outputtype.cpp:24
OutputType
Definition: outputtype.h:17
static constexpr auto OUTPUT_TYPES
Definition: outputtype.h:25
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:424
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
void RemoveUnnecessaryTransactions(PartiallySignedTransaction &psbtx, const int &sighash_type)
Reduces the size of the PSBT by dropping unnecessary non_witness_utxos (i.e.
Definition: psbt.cpp:448
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed by checking for non-null finalized fields.
Definition: psbt.cpp:293
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction &psbt)
Compute a PrecomputedTransactionData object from a psbt.
Definition: psbt.cpp:358
void GetStrongRandBytes(Span< unsigned char > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
Definition: random.cpp:639
const char * name
Definition: rest.cpp:50
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:58
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:110
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:124
std::vector< uint256 > vHave
Definition: block.h:134
bool IsNull() const
Definition: block.h:152
Definition: key.h:210
CKey key
Definition: key.h:215
void SetSeed(Span< const std::byte > seed)
Definition: key.cpp:388
A mutable version of CTransaction.
Definition: transaction.h:378
std::vector< CTxIn > vin
Definition: transaction.h:379
std::map< CKeyID, CKey > keys
static time_point now() noexcept
Return current system time or mocked time, if set.
Definition: time.cpp:21
std::chrono::time_point< NodeClock > time_point
Definition: time.h:17
A structure for PSBTs which contain per-input information.
Definition: psbt.h:194
CTransactionRef non_witness_utxo
Definition: psbt.h:195
A version of CTransaction with the PSBT format.
Definition: psbt.h:947
std::vector< PSBTInput > inputs
Definition: psbt.h:952
std::optional< CMutableTransaction > tx
Definition: psbt.h:948
Bilingual messages:
Definition: translation.h:18
bool empty() const
Definition: translation.h:29
Block data sent with blockConnected, blockDisconnected notifications.
Definition: chain.h:84
const uint256 * prev_hash
Definition: chain.h:86
const CBlock * data
Definition: chain.h:90
const uint256 & hash
Definition: chain.h:85
unsigned int chain_time_max
Definition: chain.h:94
Address book data.
Definition: wallet.h:230
std::optional< AddressPurpose > purpose
Address purpose which was originally recorded for payment protocol support but now serves as a cached...
Definition: wallet.h:245
void SetLabel(std::string name)
Definition: wallet.h:268
std::optional< std::string > m_op_label
Definition: wallet.h:745
std::optional< int > last_scanned_height
Definition: wallet.h:623
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
Definition: wallet.h:622
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
Definition: wallet.h:629
enum wallet::CWallet::ScanResult::@18 status
bool require_existing
Definition: db.h:183
SecureString create_passphrase
Definition: db.h:187
std::optional< DatabaseFormat > require_format
Definition: db.h:185
uint64_t create_flags
Definition: db.h:186
struct containing information needed for migrating legacy wallets to descriptor wallets
std::vector< std::unique_ptr< DescriptorScriptPubKeyMan > > desc_spkms
std::shared_ptr< CWallet > watchonly_wallet
std::shared_ptr< CWallet > solvable_wallet
std::shared_ptr< CWallet > watchonly_wallet
Definition: wallet.h:1122
std::string wallet_name
Definition: wallet.h:1120
std::shared_ptr< CWallet > solvables_wallet
Definition: wallet.h:1123
std::shared_ptr< CWallet > wallet
Definition: wallet.h:1121
State of rejected transaction that conflicts with a confirmed block.
Definition: transaction.h:46
State of transaction confirmed in a block.
Definition: transaction.h:31
State of transaction added to mempool.
Definition: transaction.h:41
State of transaction not confirmed or conflicting with a known block and not in the mempool.
Definition: transaction.h:58
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:36
interfaces::Chain * chain
Definition: context.h:37
ArgsManager * args
Definition: context.h:39
#define WAIT_LOCK(cs, name)
Definition: sync.h:262
#define AssertLockNotHeld(cs)
Definition: sync.h:147
#define LOCK2(cs1, cs2)
Definition: sync.h:258
#define LOCK(cs)
Definition: sync.h:257
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:301
static int count
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
int64_t GetTime()
Definition: time.cpp:48
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble
Definition: time.h:60
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:74
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:48
@ CT_UPDATED
@ CT_DELETED
@ CT_NEW
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
Definition: string.cpp:10
AssertLockHeld(pool.cs)
assert(!tx.IsCoinBase())
GCSFilter::ElementSet m_filter_set
Definition: wallet.cpp:349
std::map< uint256, int32_t > m_last_range_ends
Map for keeping track of each range descriptor's last seen end range.
Definition: wallet.cpp:348
const CWallet & m_wallet
Definition: wallet.cpp:341
static void NotifyTransactionChanged(WalletModel *walletmodel, const uint256 &hash, ChangeType status)
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.
Definition: zeroafterfree.h:49