From cf4d72a75e9603e947b3d47e1f3ac7c7f37bb401 Mon Sep 17 00:00:00 2001 From: furszy Date: Thu, 8 Feb 2024 12:34:26 -0300 Subject: [PATCH] wallet: db, introduce 'RunWithinTxn()' helper function 'RunWithinTxn()' provides a way to execute db operations within a transactional context. It avoids writing repetitive boilerplate code for starting and committing the database transaction. --- src/wallet/wallet.cpp | 5 +++-- src/wallet/walletdb.cpp | 24 ++++++++++++++++++++++++ src/wallet/walletdb.h | 14 ++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 11203ca3a40..db5f54cbb74 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2411,8 +2411,9 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s bool CWallet::DelAddressBook(const CTxDestination& address) { - WalletBatch batch(GetDatabase()); - return DelAddressBookWithDB(batch, address); + return RunWithinTxn(GetDatabase(), /*process_desc=*/"address book entry removal", [&](WalletBatch& batch){ + return DelAddressBookWithDB(batch, address); + }); } bool CWallet::DelAddressBookWithDB(WalletBatch& batch, const CTxDestination& address) diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 6e37bc2930e..c66b09628eb 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1230,6 +1230,30 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet) return result; } +bool RunWithinTxn(WalletDatabase& database, std::string_view process_desc, const std::function& func) +{ + WalletBatch batch(database); + if (!batch.TxnBegin()) { + LogPrint(BCLog::WALLETDB, "Error: cannot create db txn for %s\n", process_desc); + return false; + } + + // Run procedure + if (!func(batch)) { + LogPrint(BCLog::WALLETDB, "Error: %s failed\n", process_desc); + batch.TxnAbort(); + return false; + } + + if (!batch.TxnCommit()) { + LogPrint(BCLog::WALLETDB, "Error: cannot commit db txn for %s\n", process_desc); + return false; + } + + // All good + return true; +} + void MaybeCompactWalletDB(WalletContext& context) { static std::atomic fOneThread(false); diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 62449eb64ec..9474a59660f 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -294,6 +294,20 @@ private: WalletDatabase& m_database; }; +/** + * Executes the provided function 'func' within a database transaction context. + * + * This function ensures that all db modifications performed within 'func()' are + * atomically committed to the db at the end of the process. And, in case of a + * failure during execution, all performed changes are rolled back. + * + * @param database The db connection instance to perform the transaction on. + * @param process_desc A description of the process being executed, used for logging purposes in the event of a failure. + * @param func The function to be executed within the db txn context. It returns a boolean indicating whether to commit or roll back the txn. + * @return true if the db txn executed successfully, false otherwise. + */ +bool RunWithinTxn(WalletDatabase& database, std::string_view process_desc, const std::function& func); + //! Compacts BDB state so that wallet.dat is self-contained (if there are changes) void MaybeCompactWalletDB(WalletContext& context);