diff options
author | furszy <matiasfurszyfer@protonmail.com> | 2024-02-06 16:28:23 -0300 |
---|---|---|
committer | furszy <matiasfurszyfer@protonmail.com> | 2024-02-12 16:05:15 -0300 |
commit | 33757814ceb04102141d3fd5ef2f87abf0422310 (patch) | |
tree | 40f8af126fcb333f3d2c62e725f3b101155addf3 /src/wallet/test | |
parent | cf4d72a75e9603e947b3d47e1f3ac7c7f37bb401 (diff) | |
download | bitcoin-33757814ceb04102141d3fd5ef2f87abf0422310.tar.xz |
wallet: bdb batch 'ErasePrefix', do not create txn internally
Transactions are intended to be started on upper layers rather than
internally by the bdb batch object. This enables us to consolidate
different write operations within a procedure in the same db txn,
improving consistency due to the atomic property of the transaction,
as well as its performance due to the reduction of disk write
operations.
Important Note:
This approach also ensures that the BerkeleyBatch::ErasePrefix
function behaves exactly as the SQLiteBatch::ErasePrefix function,
which does not create a db txn internally.
Furthermore, since the `BerkeleyBatch::ErasePrefix' implementation
erases records one by one (by traversing the db), this change
ensures that the function is always called within an active txn
context. Without this measure, there's a potential risk to consistency;
certain records may be removed while others could persist due to an
internal failure during the procedure.
Diffstat (limited to 'src/wallet/test')
-rw-r--r-- | src/wallet/test/db_tests.cpp | 33 | ||||
-rw-r--r-- | src/wallet/test/wallet_tests.cpp | 8 |
2 files changed, 38 insertions, 3 deletions
diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp index adbbb94318..c933366354 100644 --- a/src/wallet/test/db_tests.cpp +++ b/src/wallet/test/db_tests.cpp @@ -228,6 +228,39 @@ BOOST_AUTO_TEST_CASE(db_availability_after_write_error) } } +// Verify 'ErasePrefix' functionality using db keys similar to the ones used by the wallet. +// Keys are in the form of std::pair<TYPE, ENTRY_ID> +BOOST_AUTO_TEST_CASE(erase_prefix) +{ + const std::string key = "key"; + const std::string key2 = "key2"; + const std::string value = "value"; + const std::string value2 = "value_2"; + auto make_key = [](std::string type, std::string id) { return std::make_pair(type, id); }; + + for (const auto& database : TestDatabases(m_path_root)) { + std::unique_ptr<DatabaseBatch> batch = database->MakeBatch(); + + // Write two entries with the same key type prefix, a third one with a different prefix + // and a fourth one with the type-id values inverted + BOOST_CHECK(batch->Write(make_key(key, value), value)); + BOOST_CHECK(batch->Write(make_key(key, value2), value2)); + BOOST_CHECK(batch->Write(make_key(key2, value), value)); + BOOST_CHECK(batch->Write(make_key(value, key), value)); + + // Erase the ones with the same prefix and verify result + BOOST_CHECK(batch->TxnBegin()); + BOOST_CHECK(batch->ErasePrefix(DataStream() << key)); + BOOST_CHECK(batch->TxnCommit()); + + BOOST_CHECK(!batch->Exists(make_key(key, value))); + BOOST_CHECK(!batch->Exists(make_key(key, value2))); + // Also verify that entries with a different prefix were not erased + BOOST_CHECK(batch->Exists(make_key(key2, value))); + BOOST_CHECK(batch->Exists(make_key(value, key))); + } +} + #ifdef USE_SQLITE // Test-only statement execution error diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 7396a43c50..27a81b3669 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -445,9 +445,11 @@ BOOST_FIXTURE_TEST_CASE(LoadReceiveRequests, TestingSetup) 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())); + RunWithinTxn(wallet->GetDatabase(), /*process_desc*/"test", [](WalletBatch& batch){ + BOOST_CHECK(batch.WriteAddressPreviouslySpent(PKHash(), false)); + BOOST_CHECK(batch.EraseAddressData(ScriptHash())); + return true; + }); }); TestLoadWallet(name, format, [](std::shared_ptr<CWallet> wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet) { BOOST_CHECK(!wallet->IsAddressPreviouslySpent(PKHash())); |