refactor: Remove CAddressBookData::destdata

This is cleanup that doesn't change external behavior.

- Removes awkward `StringMap` intermediate representation
- Simplifies CWallet code, deals with used address and received request
  serialization in walletdb.cpp
- Adds test coverage and documentation
- Reduces memory usage

This PR doesn't change externally observable behavior. Internally, only change
in behavior is that EraseDestData deletes directly from database because the
`StringMap` is gone. This is more direct and efficient because it uses a single
btree lookup and scan instead of multiple lookups

Motivation for this cleanup is making changes like #18550, #18192, #13756
easier to reason about and less likely to result in unintended behavior and
bugs

Co-authored-by: furszy <matiasfurszyfer@protonmail.com>
This commit is contained in:
Ryan Ofsky
2020-04-12 13:40:43 -04:00
parent 5938ad0bdb
commit a5986e82dd
6 changed files with 164 additions and 86 deletions

View File

@@ -427,19 +427,63 @@ BOOST_AUTO_TEST_CASE(ComputeTimeSmart)
BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 5, 50, 600), 300);
}
BOOST_AUTO_TEST_CASE(LoadReceiveRequests)
{
CTxDestination dest = PKHash();
LOCK(m_wallet.cs_wallet);
WalletBatch batch{m_wallet.GetDatabase()};
m_wallet.SetAddressUsed(batch, dest, true);
m_wallet.SetAddressReceiveRequest(batch, dest, "0", "val_rr0");
m_wallet.SetAddressReceiveRequest(batch, dest, "1", "val_rr1");
static const DatabaseFormat DATABASE_FORMATS[] = {
#ifdef USE_SQLITE
DatabaseFormat::SQLITE,
#endif
#ifdef USE_BDB
DatabaseFormat::BERKELEY,
#endif
};
auto values = m_wallet.GetAddressReceiveRequests();
BOOST_CHECK_EQUAL(values.size(), 2U);
BOOST_CHECK_EQUAL(values[0], "val_rr0");
BOOST_CHECK_EQUAL(values[1], "val_rr1");
void TestLoadWallet(const std::string& name, DatabaseFormat format, std::function<void(std::shared_ptr<CWallet>)> f)
{
node::NodeContext node;
auto chain{interfaces::MakeChain(node)};
DatabaseOptions options;
options.require_format = format;
DatabaseStatus status;
bilingual_str error;
std::vector<bilingual_str> warnings;
auto database{MakeWalletDatabase(name, options, status, error)};
auto wallet{std::make_shared<CWallet>(chain.get(), "", std::move(database))};
BOOST_CHECK_EQUAL(wallet->LoadWallet(), DBErrors::LOAD_OK);
WITH_LOCK(wallet->cs_wallet, f(wallet));
}
BOOST_FIXTURE_TEST_CASE(LoadReceiveRequests, TestingSetup)
{
for (DatabaseFormat format : DATABASE_FORMATS) {
const std::string name{strprintf("receive-requests-%i", format)};
TestLoadWallet(name, format, [](std::shared_ptr<CWallet> wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet) {
BOOST_CHECK(!wallet->IsAddressPreviouslySpent(PKHash()));
WalletBatch batch{wallet->GetDatabase()};
BOOST_CHECK(batch.WriteAddressPreviouslySpent(PKHash(), true));
BOOST_CHECK(batch.WriteAddressPreviouslySpent(ScriptHash(), true));
BOOST_CHECK(wallet->SetAddressReceiveRequest(batch, PKHash(), "0", "val_rr00"));
BOOST_CHECK(wallet->EraseAddressReceiveRequest(batch, PKHash(), "0"));
BOOST_CHECK(wallet->SetAddressReceiveRequest(batch, PKHash(), "1", "val_rr10"));
BOOST_CHECK(wallet->SetAddressReceiveRequest(batch, PKHash(), "1", "val_rr11"));
BOOST_CHECK(wallet->SetAddressReceiveRequest(batch, ScriptHash(), "2", "val_rr20"));
});
TestLoadWallet(name, format, [](std::shared_ptr<CWallet> wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet) {
BOOST_CHECK(wallet->IsAddressPreviouslySpent(PKHash()));
BOOST_CHECK(wallet->IsAddressPreviouslySpent(ScriptHash()));
auto requests = wallet->GetAddressReceiveRequests();
auto erequests = {"val_rr11", "val_rr20"};
BOOST_CHECK_EQUAL_COLLECTIONS(requests.begin(), requests.end(), std::begin(erequests), std::end(erequests));
WalletBatch batch{wallet->GetDatabase()};
BOOST_CHECK(batch.WriteAddressPreviouslySpent(PKHash(), false));
BOOST_CHECK(batch.EraseAddressData(ScriptHash()));
});
TestLoadWallet(name, format, [](std::shared_ptr<CWallet> wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet) {
BOOST_CHECK(!wallet->IsAddressPreviouslySpent(PKHash()));
BOOST_CHECK(!wallet->IsAddressPreviouslySpent(ScriptHash()));
auto requests = wallet->GetAddressReceiveRequests();
auto erequests = {"val_rr11"};
BOOST_CHECK_EQUAL_COLLECTIONS(requests.begin(), requests.end(), std::begin(erequests), std::end(erequests));
});
}
}
// Test some watch-only LegacyScriptPubKeyMan methods by the procedure of loading (LoadWatchOnly),