wallet.cpp raw

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