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