Skip to content

Commit 80ace04

Browse files
committed
tests: Modify records directly in wallet ckey loading test
In the wallet ckey loading test, we modify various ckey records to test corruption handling. As the database is now a mockable database, we can modify the records that the database will be initialized with. This avoids having to use the verbose database reading and writing functions.
1 parent b3bb17d commit 80ace04

File tree

1 file changed

+42
-51
lines changed

1 file changed

+42
-51
lines changed

src/wallet/test/walletload_tests.cpp

Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -70,38 +70,45 @@ bool HasAnyRecordOfType(WalletDatabase& db, const std::string& key)
7070
return false;
7171
}
7272

73-
BOOST_FIXTURE_TEST_CASE(wallet_load_verif_crypted_key_checksum, TestingSetup)
73+
template<typename... Args>
74+
SerializeData MakeSerializeData(const Args&... args)
7475
{
75-
// The test duplicates the db so each case has its own db instance.
76-
int NUMBER_OF_TESTS = 4;
77-
std::vector<std::unique_ptr<WalletDatabase>> dbs;
78-
CKey first_key;
79-
auto get_db = [](std::vector<std::unique_ptr<WalletDatabase>>& dbs) {
80-
std::unique_ptr<WalletDatabase> db = std::move(dbs.back());
81-
dbs.pop_back();
82-
return db;
83-
};
84-
85-
{ // Context setup.
76+
CDataStream s(0, 0);
77+
SerializeMany(s, args...);
78+
return {s.begin(), s.end()};
79+
}
80+
81+
82+
BOOST_FIXTURE_TEST_CASE(wallet_load_ckey, TestingSetup)
83+
{
84+
SerializeData ckey_record_key;
85+
SerializeData ckey_record_value;
86+
std::map<SerializeData, SerializeData> records;
87+
88+
{
89+
// Context setup.
8690
// Create and encrypt legacy wallet
8791
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", CreateMockableWalletDatabase()));
8892
LOCK(wallet->cs_wallet);
8993
auto legacy_spkm = wallet->GetOrCreateLegacyScriptPubKeyMan();
9094
BOOST_CHECK(legacy_spkm->SetupGeneration(true));
9195

92-
// Get the first key in the wallet
96+
// Retrieve a key
9397
CTxDestination dest = *Assert(legacy_spkm->GetNewDestination(OutputType::LEGACY));
9498
CKeyID key_id = GetKeyForDestination(*legacy_spkm, dest);
99+
CKey first_key;
95100
BOOST_CHECK(legacy_spkm->GetKey(key_id, first_key));
96101

97-
// Encrypt the wallet and duplicate database
102+
// Encrypt the wallet
98103
BOOST_CHECK(wallet->EncryptWallet("encrypt"));
99104
wallet->Flush();
100105

101-
DatabaseOptions options;
102-
for (int i=0; i < NUMBER_OF_TESTS; i++) {
103-
dbs.emplace_back(DuplicateMockDatabase(wallet->GetDatabase()));
104-
}
106+
// Store a copy of all the records
107+
records = GetMockableDatabase(*wallet).m_records;
108+
109+
// Get the record for the retrieved key
110+
ckey_record_key = MakeSerializeData(DBKeys::CRYPTED_KEY, first_key.GetPubKey());
111+
ckey_record_value = records.at(ckey_record_key);
105112
}
106113

107114
{
@@ -112,7 +119,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_load_verif_crypted_key_checksum, TestingSetup)
112119
// the records every time that 'CWallet::Unlock' gets called, which is not good.
113120

114121
// Load the wallet and check that is encrypted
115-
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", get_db(dbs)));
122+
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", CreateMockableWalletDatabase(records)));
116123
BOOST_CHECK_EQUAL(wallet->LoadWallet(), DBErrors::LOAD_OK);
117124
BOOST_CHECK(wallet->IsCrypted());
118125
BOOST_CHECK(HasAnyRecordOfType(wallet->GetDatabase(), DBKeys::CRYPTED_KEY));
@@ -127,18 +134,12 @@ BOOST_FIXTURE_TEST_CASE(wallet_load_verif_crypted_key_checksum, TestingSetup)
127134
{
128135
// Second test case:
129136
// Verify that loading up a 'ckey' with no checksum triggers a complete re-write of the crypted keys.
130-
std::unique_ptr<WalletDatabase> db = get_db(dbs);
131-
{
132-
std::unique_ptr<DatabaseBatch> batch = db->MakeBatch(false);
133-
std::pair<std::vector<unsigned char>, uint256> value;
134-
BOOST_CHECK(batch->Read(std::make_pair(DBKeys::CRYPTED_KEY, first_key.GetPubKey()), value));
135137

136-
const auto key = std::make_pair(DBKeys::CRYPTED_KEY, first_key.GetPubKey());
137-
BOOST_CHECK(batch->Write(key, value.first, /*fOverwrite=*/true));
138-
}
138+
// Cut off the 32 byte checksum from a ckey record
139+
records[ckey_record_key].resize(ckey_record_value.size() - 32);
139140

140141
// Load the wallet and check that is encrypted
141-
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", std::move(db)));
142+
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", CreateMockableWalletDatabase(records)));
142143
BOOST_CHECK_EQUAL(wallet->LoadWallet(), DBErrors::LOAD_OK);
143144
BOOST_CHECK(wallet->IsCrypted());
144145
BOOST_CHECK(HasAnyRecordOfType(wallet->GetDatabase(), DBKeys::CRYPTED_KEY));
@@ -154,35 +155,25 @@ BOOST_FIXTURE_TEST_CASE(wallet_load_verif_crypted_key_checksum, TestingSetup)
154155
{
155156
// Third test case:
156157
// Verify that loading up a 'ckey' with an invalid checksum throws an error.
157-
std::unique_ptr<WalletDatabase> db = get_db(dbs);
158-
{
159-
std::unique_ptr<DatabaseBatch> batch = db->MakeBatch(false);
160-
std::vector<unsigned char> crypted_data;
161-
BOOST_CHECK(batch->Read(std::make_pair(DBKeys::CRYPTED_KEY, first_key.GetPubKey()), crypted_data));
162-
163-
// Write an invalid checksum
164-
std::pair<std::vector<unsigned char>, uint256> value = std::make_pair(crypted_data, uint256::ONE);
165-
const auto key = std::make_pair(DBKeys::CRYPTED_KEY, first_key.GetPubKey());
166-
BOOST_CHECK(batch->Write(key, value, /*fOverwrite=*/true));
167-
}
168-
169-
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", std::move(db)));
158+
159+
// Cut off the 32 byte checksum from a ckey record
160+
records[ckey_record_key].resize(ckey_record_value.size() - 32);
161+
// Fill in the checksum space with 0s
162+
records[ckey_record_key].resize(ckey_record_value.size());
163+
164+
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", CreateMockableWalletDatabase(records)));
170165
BOOST_CHECK_EQUAL(wallet->LoadWallet(), DBErrors::CORRUPT);
171166
}
172167

173168
{
174169
// Fourth test case:
175170
// Verify that loading up a 'ckey' with an invalid pubkey throws an error
176-
std::unique_ptr<WalletDatabase> db = get_db(dbs);
177-
{
178-
CPubKey invalid_key;
179-
BOOST_ASSERT(!invalid_key.IsValid());
180-
const auto key = std::make_pair(DBKeys::CRYPTED_KEY, invalid_key);
181-
std::pair<std::vector<unsigned char>, uint256> value;
182-
BOOST_CHECK(db->MakeBatch(false)->Write(key, value, /*fOverwrite=*/true));
183-
}
184-
185-
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", std::move(db)));
171+
CPubKey invalid_key;
172+
BOOST_ASSERT(!invalid_key.IsValid());
173+
SerializeData key = MakeSerializeData(DBKeys::CRYPTED_KEY, invalid_key);
174+
records[key] = ckey_record_value;
175+
176+
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", CreateMockableWalletDatabase(records)));
186177
BOOST_CHECK_EQUAL(wallet->LoadWallet(), DBErrors::CORRUPT);
187178
}
188179
}

0 commit comments

Comments
 (0)