Bitcoin Core 31.99.0
P2P Digital Currency
wallet_encrypt.cpp
Go to the documentation of this file.
1// Copyright (c) 2025-present 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 <key_io.h>
7#include <outputtype.h>
8#include <random.h>
11#include <util/time.h>
12#include <wallet/context.h>
13#include <wallet/test/util.h>
14#include <wallet/wallet.h>
15#include <wallet/walletutil.h>
16
17#include <cassert>
18
19namespace wallet {
20static void WalletEncrypt(benchmark::Bench& bench, unsigned int key_count)
21{
22 auto test_setup = MakeNoLogFileContext<TestingSetup>();
23 FastRandomContext rand{/*fDeterministic=*/true};
24
25 auto password{rand.randbytes(20)};
26 SecureString secure_pass{password.begin(), password.end()};
27
28 WalletContext context;
29 context.args = &test_setup->m_args;
30 context.chain = test_setup->m_node.chain.get();
31
32 uint64_t create_flags = WALLET_FLAG_DESCRIPTORS;
33 auto database = CreateMockableWalletDatabase();
34 auto wallet = TestCreateWallet(std::move(database), context, create_flags);
35
36 {
37 LOCK(wallet->cs_wallet);
38 for (unsigned int i = 0; i < key_count; i++) {
39 CKey key = GenerateRandomKey();
41 std::string error;
42 std::vector<std::unique_ptr<Descriptor>> desc = Parse("combo(" + EncodeSecret(key) + ")", keys, error, /*require_checksum=*/false);
43 WalletDescriptor w_desc(std::move(desc.at(0)), /*creation_time=*/0, /*range_start=*/0, /*range_end=*/0, /*next_index=*/0);
44 Assert(wallet->AddWalletDescriptor(w_desc, keys, /*label=*/"", /*internal=*/false));
45 }
46 }
47
48 database = DuplicateMockDatabase(wallet->GetDatabase());
49
50 // reload the wallet for the actual benchmark
51 TestUnloadWallet(std::move(wallet));
52
53 // Setting a mock time is necessary to force default derive iteration count during
54 // wallet encryption.
55 SetMockTime(1);
56
57 // This benchmark has a lot of overhead, this should be good enough to catch
58 // any regressions, but for an accurate measurement of how long wallet
59 // encryption takes, this should be reworked after something like
60 // https://github.com/bitcoin/bitcoin/pull/34208 is merged.
61 bench.batch(key_count).unit("key").run([&] {
62 wallet = TestLoadWallet(std::move(database), context);
63
64 // Save a copy of the db before encrypting
65 database = DuplicateMockDatabase(wallet->GetDatabase());
66
67 wallet->EncryptWallet(secure_pass);
68
69 for (const auto& [_, key] : wallet->mapMasterKeys){
70 assert(key.nDeriveIterations == CMasterKey::DEFAULT_DERIVE_ITERATIONS);
71 }
72
73 TestUnloadWallet(std::move(wallet));
74 });
75}
76
77constexpr unsigned int KEY_COUNT = 2000;
78
79static void WalletEncryptDescriptors(benchmark::Bench& bench) { WalletEncrypt(bench, /*key_count=*/KEY_COUNT); }
81
82} // namespace wallet
#define Assert(val)
Identity function.
Definition: check.h:113
An encapsulated private key.
Definition: key.h:36
Fast randomness source.
Definition: random.h:386
std::vector< B > randbytes(size_t len) noexcept
Generate random bytes.
Definition: random.h:297
Main entry point to nanobench's benchmarking facility.
Definition: nanobench.h:627
Bench & run(char const *benchmarkName, Op &&op)
Repeatedly calls op() based on the configuration, and performs measurements.
Definition: nanobench.h:1234
Bench & batch(T b) noexcept
Sets the batch size.
Definition: nanobench.h:1258
Bench & unit(char const *unit)
Sets the operation unit.
static constexpr unsigned int DEFAULT_DERIVE_ITERATIONS
Default/minimum number of key derivation rounds.
Definition: crypter.h:48
Descriptor with some wallet metadata.
Definition: walletutil.h:64
static UniValue Parse(std::string_view raw, ParamFormat format=ParamFormat::JSON)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:395
CKey GenerateRandomKey(bool compressed) noexcept
Definition: key.cpp:475
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:232
BENCHMARK(WalletBalanceDirty)
constexpr unsigned int KEY_COUNT
static void WalletEncryptDescriptors(benchmark::Bench &bench)
void TestUnloadWallet(std::shared_ptr< CWallet > &&wallet)
Definition: util.cpp:98
std::unique_ptr< WalletDatabase > CreateMockableWalletDatabase(MockableData records)
Definition: util.cpp:211
std::unique_ptr< WalletDatabase > DuplicateMockDatabase(WalletDatabase &database)
Definition: util.cpp:106
static void WalletEncrypt(benchmark::Bench &bench, unsigned int key_count)
std::shared_ptr< CWallet > TestLoadWallet(std::unique_ptr< WalletDatabase > database, WalletContext &context)
Definition: util.cpp:75
std::shared_ptr< CWallet > TestCreateWallet(std::unique_ptr< WalletDatabase > database, WalletContext &context, uint64_t create_flags)
Definition: util.cpp:50
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:53
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:53
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:36
interfaces::Chain * chain
Definition: context.h:37
ArgsManager * args
Definition: context.h:39
#define LOCK(cs)
Definition: sync.h:258
consteval auto _(util::TranslatedLiteral str)
Definition: translation.h:79
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
Definition: time.cpp:44
assert(!tx.IsCoinBase())