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