wallet_encrypt.cpp raw

   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.h>
   7  #include <key_io.h>
   8  #include <random.h>
   9  #include <script/descriptor.h>
  10  #include <script/signingprovider.h>
  11  #include <support/allocators/secure.h>
  12  #include <sync.h>
  13  #include <test/util/setup_common.h>
  14  #include <test/util/time.h>
  15  #include <util/check.h>
  16  #include <wallet/context.h>
  17  #include <wallet/crypter.h>
  18  #include <wallet/db.h>
  19  #include <wallet/sqlite.h>
  20  #include <wallet/test/util.h>
  21  #include <wallet/wallet.h>
  22  #include <wallet/walletutil.h>
  23  
  24  #include <cstdint>
  25  #include <functional>
  26  #include <memory>
  27  #include <string>
  28  #include <utility>
  29  #include <vector>
  30  
  31  namespace wallet {
  32  static void WalletEncrypt(benchmark::Bench& bench, unsigned int key_count)
  33  {
  34      auto test_setup = MakeNoLogFileContext<TestingSetup>();
  35      FastRandomContext rand{/*fDeterministic=*/true};
  36  
  37      auto password{rand.randbytes(20)};
  38      SecureString secure_pass{password.begin(), password.end()};
  39  
  40      WalletContext context;
  41      context.args = &test_setup->m_args;
  42      context.chain = test_setup->m_node.chain.get();
  43  
  44      uint64_t create_flags = WALLET_FLAG_DESCRIPTORS;
  45  
  46      std::vector<std::pair<WalletDescriptor, FlatSigningProvider>> descs;
  47      descs.reserve(key_count);
  48      for (unsigned int i = 0; i < key_count; i++) {
  49          CKey key = GenerateRandomKey();
  50          FlatSigningProvider keys;
  51          std::string error;
  52          std::vector<std::unique_ptr<Descriptor>> desc = Parse("combo(" + EncodeSecret(key) + ")", keys, error, /*require_checksum=*/false);
  53          WalletDescriptor w_desc(std::move(desc.at(0)), /*creation_time=*/0, /*range_start=*/0, /*range_end=*/0, /*next_index=*/0);
  54          descs.emplace_back(w_desc, keys);
  55      }
  56  
  57      // Setting a mock time is necessary to force default derive iteration count during
  58      // wallet encryption.
  59      FakeNodeClock clock{1s};
  60  
  61      std::unique_ptr<WalletDatabase> database;
  62      std::shared_ptr<CWallet> wallet;
  63      bench.batch(key_count).unit("key").setup([&] {
  64              if (wallet) {
  65                  TestUnloadWallet(std::move(wallet));
  66              }
  67  
  68              std::unique_ptr<WalletDatabase> database = MakeInMemoryWalletDatabase();
  69              wallet = TestCreateWallet(std::move(database), context, create_flags);
  70  
  71              {
  72                  LOCK(wallet->cs_wallet);
  73                  for (auto& [desc, keys] : descs) {
  74                      Assert(wallet->AddWalletDescriptor(desc, keys, /*label=*/"", /*internal=*/false));
  75                  }
  76              }
  77          })
  78          .run([&] {
  79              wallet->EncryptWallet(secure_pass);
  80  
  81              for (const auto& [_, key] : wallet->mapMasterKeys){
  82                  assert(key.nDeriveIterations == CMasterKey::DEFAULT_DERIVE_ITERATIONS);
  83              }
  84          });
  85      TestUnloadWallet(std::move(wallet));
  86  }
  87  
  88  constexpr unsigned int KEY_COUNT = 2000;
  89  
  90  static void WalletEncryptDescriptors(benchmark::Bench& bench) { WalletEncrypt(bench, /*key_count=*/KEY_COUNT); }
  91  BENCHMARK(WalletEncryptDescriptors);
  92  
  93  } // namespace wallet
  94