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