util.cpp raw

   1  // Copyright (c) 2021-present The Bitcoin Core developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #include <wallet/test/util.h>
   6  
   7  #include <chain.h>
   8  #include <key.h>
   9  #include <key_io.h>
  10  #include <test/util/setup_common.h>
  11  #include <validationinterface.h>
  12  #include <wallet/context.h>
  13  #include <wallet/wallet.h>
  14  #include <wallet/walletdb.h>
  15  
  16  #include <sqlite3.h>
  17  
  18  #include <memory>
  19  
  20  namespace wallet {
  21  std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key)
  22  {
  23      auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockableWalletDatabase());
  24      {
  25          LOCK2(wallet->cs_wallet, ::cs_main);
  26          wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash());
  27      }
  28      {
  29          LOCK(wallet->cs_wallet);
  30          wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
  31          wallet->SetupDescriptorScriptPubKeyMans();
  32  
  33          FlatSigningProvider provider;
  34          std::string error;
  35          auto descs = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
  36          assert(descs.size() == 1);
  37          auto& desc = descs.at(0);
  38          WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
  39          Assert(wallet->AddWalletDescriptor(w_desc, provider, "", false));
  40      }
  41      WalletRescanReserver reserver(*wallet);
  42      reserver.reserve();
  43      CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), /*start_height=*/0, /*max_height=*/{}, reserver, /*save_progress=*/false);
  44      assert(result.status == CWallet::ScanResult::SUCCESS);
  45      assert(result.last_scanned_block == cchain.Tip()->GetBlockHash());
  46      assert(*result.last_scanned_height == cchain.Height());
  47      assert(result.last_failed_block.IsNull());
  48      return wallet;
  49  }
  50  
  51  std::shared_ptr<CWallet> TestCreateWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, uint64_t create_flags)
  52  {
  53      bilingual_str _error;
  54      std::vector<bilingual_str> _warnings;
  55      auto wallet = CWallet::CreateNew(context, "", std::move(database), create_flags, /*born_encrypted=*/false, _error, _warnings);
  56      NotifyWalletLoaded(context, wallet);
  57      if (context.chain) {
  58          wallet->postInitProcess();
  59      }
  60      return wallet;
  61  }
  62  
  63  std::shared_ptr<CWallet> TestCreateWallet(WalletContext& context)
  64  {
  65      DatabaseOptions options;
  66      options.require_create = true;
  67      options.create_flags = WALLET_FLAG_DESCRIPTORS;
  68      DatabaseStatus status;
  69      bilingual_str error;
  70      std::vector<bilingual_str> warnings;
  71      auto database = MakeWalletDatabase("", options, status, error);
  72      return TestCreateWallet(std::move(database), context, options.create_flags);
  73  }
  74  
  75  
  76  std::shared_ptr<CWallet> TestLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context)
  77  {
  78      bilingual_str error;
  79      std::vector<bilingual_str> warnings;
  80      auto wallet = CWallet::LoadExisting(context, "", std::move(database), error, warnings);
  81      NotifyWalletLoaded(context, wallet);
  82      if (context.chain) {
  83          wallet->postInitProcess();
  84      }
  85      return wallet;
  86  }
  87  
  88  std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
  89  {
  90      DatabaseOptions options;
  91      options.require_existing = true;
  92      DatabaseStatus status;
  93      bilingual_str error;
  94      std::vector<bilingual_str> warnings;
  95      auto database = MakeWalletDatabase("", options, status, error);
  96      return TestLoadWallet(std::move(database), context);
  97  }
  98  
  99  void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
 100  {
 101      // Calls SyncWithValidationInterfaceQueue
 102      wallet->chain().waitForNotificationsIfTipChanged({});
 103      wallet->m_chain_notifications_handler.reset();
 104      WaitForDeleteWallet(std::move(wallet));
 105  }
 106  
 107  std::string getnewaddress(CWallet& w)
 108  {
 109      constexpr auto output_type = OutputType::BECH32;
 110      return EncodeDestination(getNewDestination(w, output_type));
 111  }
 112  
 113  CTxDestination getNewDestination(CWallet& w, OutputType output_type)
 114  {
 115      return *Assert(w.GetNewDestination(output_type, ""));
 116  }
 117  
 118  MockableSQLiteDatabase::MockableSQLiteDatabase()
 119      : InMemoryWalletDatabase()
 120  {}
 121  
 122  std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase()
 123  {
 124      return std::make_unique<MockableSQLiteDatabase>();
 125  }
 126  
 127  wallet::DescriptorScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success)
 128  {
 129      keystore.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
 130  
 131      FlatSigningProvider keys;
 132      std::string error;
 133      auto parsed_descs = Parse(desc_str, keys, error, false);
 134      Assert(success == (!parsed_descs.empty()));
 135      if (!success) return nullptr;
 136      auto& desc = parsed_descs.at(0);
 137  
 138      const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
 139  
 140      WalletDescriptor w_desc(std::move(desc), timestamp, range_start, range_end, next_index);
 141  
 142      LOCK(keystore.cs_wallet);
 143      auto spkm = Assert(keystore.AddWalletDescriptor(w_desc, keys,/*label=*/"", /*internal=*/false));
 144      return &spkm.value().get();
 145  };
 146  } // namespace wallet
 147