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