wallet_migration.cpp
1 // Copyright (c) 2024 The Bitcoin Core 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 <bench/bench.h> 6 #include <interfaces/chain.h> 7 #include <interfaces/wallet.h> 8 #include <kernel/chain.h> 9 #include <node/context.h> 10 #include <test/util/mining.h> 11 #include <test/util/setup_common.h> 12 #include <wallet/context.h> 13 #include <wallet/receive.h> 14 #include <wallet/test/util.h> 15 #include <wallet/wallet.h> 16 17 #include <optional> 18 19 namespace wallet{ 20 21 static void WalletMigration(benchmark::Bench& bench) 22 { 23 const auto test_setup{MakeNoLogFileContext<TestingSetup>()}; 24 const auto loader{MakeWalletLoader(*test_setup->m_node.chain, test_setup->m_args)}; 25 26 // Number of imported watch only addresses 27 int NUM_WATCH_ONLY_ADDR = 20; 28 29 // Setup legacy wallet 30 std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(test_setup->m_node.chain.get(), "", CreateMockableWalletDatabase()); 31 LegacyDataSPKM* legacy_spkm = wallet->GetOrCreateLegacyDataSPKM(); 32 WalletBatch batch{wallet->GetDatabase()}; 33 34 // Write a best block record as migration expects one to exist 35 CBlockLocator loc; 36 batch.WriteBestBlock(loc); 37 38 // Add watch-only addresses 39 std::vector<CScript> scripts_watch_only; 40 for (int w = 0; w < NUM_WATCH_ONLY_ADDR; ++w) { 41 CKey key = GenerateRandomKey(); 42 LOCK(wallet->cs_wallet); 43 const PKHash dest{key.GetPubKey()}; 44 const CScript& script = scripts_watch_only.emplace_back(GetScriptForDestination(dest)); 45 assert(legacy_spkm->LoadWatchOnly(script)); 46 assert(wallet->SetAddressBook(dest, strprintf("watch_%d", w), /*purpose=*/std::nullopt)); 47 batch.WriteWatchOnly(script, CKeyMetadata()); 48 } 49 50 // Generate transactions and local addresses 51 for (int j = 0; j < 500; ++j) { 52 CKey key = GenerateRandomKey(); 53 CPubKey pubkey = key.GetPubKey(); 54 // Load key, scripts and create address book record 55 Assert(legacy_spkm->LoadKey(key, pubkey)); 56 CTxDestination dest{PKHash(pubkey)}; 57 Assert(wallet->SetAddressBook(dest, strprintf("legacy_%d", j), /*purpose=*/std::nullopt)); 58 59 CMutableTransaction mtx; 60 mtx.vout.emplace_back(COIN, GetScriptForDestination(dest)); 61 mtx.vout.emplace_back(COIN, scripts_watch_only.at(j % NUM_WATCH_ONLY_ADDR)); 62 mtx.vin.resize(2); 63 wallet->AddToWallet(MakeTransactionRef(mtx), TxStateInactive{}, /*update_wtx=*/nullptr, /*rescanning_old_block=*/true); 64 batch.WriteKey(pubkey, key.GetPrivKey(), CKeyMetadata()); 65 } 66 67 bench.epochs(/*numEpochs=*/1).epochIterations(/*numIters=*/1) // run the migration exactly once 68 .run([&] { 69 auto res{MigrateLegacyToDescriptor(std::move(wallet), /*passphrase=*/"", *loader->context())}; 70 assert(res); 71 assert(res->wallet); 72 assert(res->watchonly_wallet); 73 }); 74 } 75 76 BENCHMARK(WalletMigration, benchmark::PriorityLevel::LOW); 77 78 } // namespace wallet