Skip to content

Commit 5690848

Browse files
committed
Merge bitcoin/bitcoin#26532: wallet: bugfix, invalid crypted key "checksum_valid" set
13d9760 test: load wallet, coverage for crypted keys (furszy) 373c996 refactor: move DuplicateMockDatabase to wallet/test/util.h (furszy) ee7a984 refactor: unify test/util/wallet.h with wallet/test/util.h (furszy) cc5a5e8 wallet: bugfix, invalid crypted key "checksum_valid" set (furszy) Pull request description: At wallet load time, the crypted key "checksum_valid" variable is always set to false. Which, on every wallet decryption call, forces the process to re-write all the ckeys to db when it's not needed. Note: The first commit fixes the issue, the two commits in the middle are cleanups so `DuplicateMockDatabase` can be used without duplicating code. And, the last one is pure test coverage for the crypted keys loading process. Includes test coverage for the following scenarios: 1) "All ckeys checksums valid" test: Loads an encrypted wallet with all the crypted keys with a valid checksum and verifies that 'CWallet::Unlock' doesn't force an entire crypted keys re-write. (we force a complete ckeys re-write if we find any missing crypted key checksum during the wallet loading process) 2) "Missing checksum in one ckey" test: Verifies that loading up a wallet with, at least one, 'ckey' with no checksum triggers a complete re-write of the crypted keys. 3) "Invalid ckey checksum error" test: Verifies that loading up a ckey with an invalid checksum stops the wallet loading process with a corruption error. 4) "Invalid ckey pubkey error" test: Verifies that loading up a ckey with an invalid pubkey stops the wallet loading process with a corruption error. ACKs for top commit: achow101: ACK 13d9760 aureleoules: ACK 13d9760 Tree-SHA512: 9ea630ee4a355282fbeee61ca04737294382577bb4b2631f50e732568fdab8f72491930807fbda58206446c4f26200cdc34d8afa14dbe1241aec713887d06a0b
2 parents a63192a + 13d9760 commit 5690848

12 files changed

+206
-103
lines changed

src/Makefile.test.include

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,6 @@ FUZZ_WALLET_SRC += \
199199
endif # USE_SQLITE
200200

201201
BITCOIN_TEST_SUITE += \
202-
wallet/test/util.cpp \
203-
wallet/test/util.h \
204202
wallet/test/wallet_test_fixture.cpp \
205203
wallet/test/wallet_test_fixture.h \
206204
wallet/test/init_test_fixture.cpp \

src/Makefile.test_util.include

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ TEST_UTIL_H = \
1818
test/util/str.h \
1919
test/util/transaction_utils.h \
2020
test/util/txmempool.h \
21-
test/util/validation.h \
22-
test/util/wallet.h
21+
test/util/validation.h
22+
23+
if ENABLE_WALLET
24+
TEST_UTIL_H += wallet/test/util.h
25+
endif # ENABLE_WALLET
2326

2427
libtest_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS)
2528
libtest_util_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
@@ -33,6 +36,10 @@ libtest_util_a_SOURCES = \
3336
test/util/str.cpp \
3437
test/util/transaction_utils.cpp \
3538
test/util/txmempool.cpp \
36-
test/util/validation.cpp \
37-
test/util/wallet.cpp \
38-
$(TEST_UTIL_H)
39+
test/util/validation.cpp
40+
41+
if ENABLE_WALLET
42+
libtest_util_a_SOURCES += wallet/test/util.cpp
43+
endif # ENABLE_WALLET
44+
45+
libtest_util_a_SOURCES += $(TEST_UTIL_H)

src/bench/block_assemble.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include <test/util/mining.h>
99
#include <test/util/script.h>
1010
#include <test/util/setup_common.h>
11-
#include <test/util/wallet.h>
1211
#include <txmempool.h>
1312
#include <validation.h>
1413

src/bench/wallet_balance.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <node/context.h>
88
#include <test/util/mining.h>
99
#include <test/util/setup_common.h>
10-
#include <test/util/wallet.h>
10+
#include <wallet/test/util.h>
1111
#include <validationinterface.h>
1212
#include <wallet/receive.h>
1313
#include <wallet/wallet.h>
@@ -20,6 +20,8 @@ using wallet::DBErrors;
2020
using wallet::GetBalance;
2121
using wallet::WALLET_FLAG_DESCRIPTORS;
2222

23+
const std::string ADDRESS_BCRT1_UNSPENDABLE = "bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj";
24+
2325
static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const bool add_mine)
2426
{
2527
const auto test_setup = MakeNoLogFileContext<const TestingSetup>();

src/bench/wallet_create_tx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
#include <kernel/chain.h>
1010
#include <node/context.h>
1111
#include <test/util/setup_common.h>
12-
#include <test/util/wallet.h>
1312
#include <validation.h>
1413
#include <wallet/spend.h>
14+
#include <wallet/test/util.h>
1515
#include <wallet/wallet.h>
1616

1717
using wallet::CWallet;

src/bench/wallet_loading.cpp

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <node/context.h>
88
#include <test/util/mining.h>
99
#include <test/util/setup_common.h>
10-
#include <test/util/wallet.h>
10+
#include <wallet/test/util.h>
1111
#include <util/translation.h>
1212
#include <validationinterface.h>
1313
#include <wallet/context.h>
@@ -52,30 +52,6 @@ static void AddTx(CWallet& wallet)
5252
wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInactive{});
5353
}
5454

55-
static std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database, DatabaseOptions& options)
56-
{
57-
auto new_database = CreateMockWalletDatabase(options);
58-
59-
// Get a cursor to the original database
60-
auto batch = database.MakeBatch();
61-
batch->StartCursor();
62-
63-
// Get a batch for the new database
64-
auto new_batch = new_database->MakeBatch();
65-
66-
// Read all records from the original database and write them to the new one
67-
while (true) {
68-
CDataStream key(SER_DISK, CLIENT_VERSION);
69-
CDataStream value(SER_DISK, CLIENT_VERSION);
70-
bool complete;
71-
batch->ReadAtCursor(key, value, complete);
72-
if (complete) break;
73-
new_batch->Write(key, value);
74-
}
75-
76-
return new_database;
77-
}
78-
7955
static void WalletLoading(benchmark::Bench& bench, bool legacy_wallet)
8056
{
8157
const auto test_setup = MakeNoLogFileContext<TestingSetup>();

src/test/util/wallet.cpp

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/test/util/wallet.h

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/wallet/test/util.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
#include <wallet/wallet.h>
1212
#include <wallet/walletdb.h>
1313

14-
#include <boost/test/unit_test.hpp>
15-
1614
#include <memory>
1715

1816
namespace wallet {
@@ -39,10 +37,46 @@ std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cc
3937
WalletRescanReserver reserver(*wallet);
4038
reserver.reserve();
4139
CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/false);
42-
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
43-
BOOST_CHECK_EQUAL(result.last_scanned_block, cchain.Tip()->GetBlockHash());
44-
BOOST_CHECK_EQUAL(*result.last_scanned_height, cchain.Height());
45-
BOOST_CHECK(result.last_failed_block.IsNull());
40+
assert(result.status == CWallet::ScanResult::SUCCESS);
41+
assert(result.last_scanned_block == cchain.Tip()->GetBlockHash());
42+
assert(*result.last_scanned_height == cchain.Height());
43+
assert(result.last_failed_block.IsNull());
4644
return wallet;
4745
}
46+
47+
std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database, DatabaseOptions& options)
48+
{
49+
auto new_database = CreateMockWalletDatabase(options);
50+
51+
// Get a cursor to the original database
52+
auto batch = database.MakeBatch();
53+
batch->StartCursor();
54+
55+
// Get a batch for the new database
56+
auto new_batch = new_database->MakeBatch();
57+
58+
// Read all records from the original database and write them to the new one
59+
while (true) {
60+
CDataStream key(SER_DISK, CLIENT_VERSION);
61+
CDataStream value(SER_DISK, CLIENT_VERSION);
62+
bool complete;
63+
batch->ReadAtCursor(key, value, complete);
64+
if (complete) break;
65+
new_batch->Write(key, value);
66+
}
67+
68+
return new_database;
69+
}
70+
71+
std::string getnewaddress(CWallet& w)
72+
{
73+
constexpr auto output_type = OutputType::BECH32;
74+
return EncodeDestination(getNewDestination(w, output_type));
75+
}
76+
77+
CTxDestination getNewDestination(CWallet& w, OutputType output_type)
78+
{
79+
return *Assert(w.GetNewDestination(output_type, ""));
80+
}
81+
4882
} // namespace wallet

src/wallet/test/util.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,32 @@
55
#ifndef BITCOIN_WALLET_TEST_UTIL_H
66
#define BITCOIN_WALLET_TEST_UTIL_H
77

8+
#include <script/standard.h>
89
#include <memory>
910

1011
class ArgsManager;
1112
class CChain;
1213
class CKey;
14+
enum class OutputType;
1315
namespace interfaces {
1416
class Chain;
1517
} // namespace interfaces
1618

1719
namespace wallet {
1820
class CWallet;
21+
struct DatabaseOptions;
22+
class WalletDatabase;
1923

2024
std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, ArgsManager& args, const CKey& key);
25+
26+
// Creates a copy of the provided database
27+
std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database, DatabaseOptions& options);
28+
29+
/** Returns a new encoded destination from the wallet (hardcoded to BECH32) */
30+
std::string getnewaddress(CWallet& w);
31+
/** Returns a new destination, of an specific type, from the wallet */
32+
CTxDestination getNewDestination(CWallet& w, OutputType output_type);
33+
2134
} // namespace wallet
2235

2336
#endif // BITCOIN_WALLET_TEST_UTIL_H

0 commit comments

Comments
 (0)