wallet_migration.cpp raw

   1  // Copyright (c) 2024 The Limenka developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or https://www.opensource.org/licenses/mit-license.php.
   4  
   5  #include <limenka-build-config.h> // IWYU pragma: keep
   6  
   7  #include <bench/bench.h>
   8  #include <kernel/chain.h>
   9  #include <interfaces/chain.h>
  10  #include <node/context.h>
  11  #include <test/util/mining.h>
  12  #include <test/util/setup_common.h>
  13  #include <wallet/test/util.h>
  14  #include <wallet/context.h>
  15  #include <wallet/receive.h>
  16  #include <wallet/wallet.h>
  17  
  18  #include <optional>
  19  
  20  #if defined(USE_SQLITE) // only enable benchmark when sqlite is enabled
  21  
  22  namespace wallet{
  23  
  24  static void WalletMigration(benchmark::Bench& bench)
  25  {
  26      const auto test_setup = MakeNoLogFileContext<TestingSetup>();
  27  
  28      WalletContext context;
  29      context.args = &test_setup->m_args;
  30      context.chain = test_setup->m_node.chain.get();
  31  
  32      // Number of imported watch only addresses
  33      int NUM_WATCH_ONLY_ADDR = 20;
  34  
  35      // Setup legacy wallet
  36      std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(test_setup->m_node.chain.get(), "", CreateMockableWalletDatabase());
  37      LegacyDataSPKM* legacy_spkm = wallet->GetOrCreateLegacyDataSPKM();
  38      WalletBatch batch{wallet->GetDatabase()};
  39  
  40      // Write a best block record as migration expects one to exist
  41      CBlockLocator loc;
  42      batch.WriteBestBlock(loc);
  43  
  44      // Add watch-only addresses
  45      std::vector<CScript> scripts_watch_only;
  46      for (int w = 0; w < NUM_WATCH_ONLY_ADDR; ++w) {
  47          CKey key = GenerateRandomKey();
  48          LOCK(wallet->cs_wallet);
  49          const auto& dest = GetDestinationForKey(key.GetPubKey(), OutputType::LEGACY);
  50          const CScript& script = scripts_watch_only.emplace_back(GetScriptForDestination(dest));
  51          assert(legacy_spkm->LoadWatchOnly(script));
  52          assert(wallet->SetAddressBook(dest, strprintf("watch_%d", w), /*purpose=*/std::nullopt));
  53          batch.WriteWatchOnly(script, CKeyMetadata());
  54      }
  55  
  56      // Generate transactions and local addresses
  57      for (int j = 0; j < 500; ++j) {
  58          CKey key = GenerateRandomKey();
  59          CPubKey pubkey = key.GetPubKey();
  60          // Load key, scripts and create address book record
  61          Assert(legacy_spkm->LoadKey(key, pubkey));
  62          CTxDestination dest{PKHash(pubkey)};
  63          Assert(wallet->SetAddressBook(dest, strprintf("legacy_%d", j), /*purpose=*/std::nullopt));
  64  
  65          CMutableTransaction mtx;
  66          mtx.vout.emplace_back(COIN, GetScriptForDestination(dest));
  67          mtx.vout.emplace_back(COIN, scripts_watch_only.at(j % NUM_WATCH_ONLY_ADDR));
  68          mtx.vin.resize(2);
  69          wallet->AddToWallet(MakeTransactionRef(mtx), TxStateInactive{}, /*update_wtx=*/nullptr, /*fFlushOnClose=*/false, /*rescanning_old_block=*/true);
  70          batch.WriteKey(pubkey, key.GetPrivKey(), CKeyMetadata());
  71      }
  72  
  73      bench.epochs(/*numEpochs=*/1).run([&context, &wallet] {
  74          util::Result<MigrationResult> res = MigrateLegacyToDescriptor(std::move(wallet), /*passphrase=*/"", context, /*was_loaded=*/false);
  75          assert(res);
  76          assert(res->wallet);
  77          assert(res->watchonly_wallet);
  78      });
  79  }
  80  
  81  BENCHMARK(WalletMigration, benchmark::PriorityLevel::LOW);
  82  
  83  } // namespace wallet
  84  
  85  #endif // end USE_SQLITE && USE_BDB
  86