wallet.cpp raw

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