Skip to content

Commit

Permalink
Add AssertLockHeld assertions in CWallet::ListCoins
Browse files Browse the repository at this point in the history
Summary:
 * Add AssertLockHeld assertions in CWallet::ListCoins
 * Add EXCLUSIVE_LOCKS_REQUIRED to CWallet::ListCoins

Suggested by MarcoFalke <falke.marco@gmail.com> in
bitcoin/bitcoin#10605 (comment)

This is a backport of Core PR10605

Test Plan:
 * Build with clang and make sure there are no warning related to locks.
 * Build in debug mode and run the extended test suite.

Reviewers: #bitcoin_abc, jasonbcox

Reviewed By: #bitcoin_abc, jasonbcox

Differential Revision: https://reviews.bitcoinabc.org/D4170
  • Loading branch information
ryanofsky authored and deadalnix committed Sep 28, 2019
1 parent af3079a commit b660a2d
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 14 deletions.
16 changes: 13 additions & 3 deletions src/wallet/test/wallet_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,11 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup) {

// Confirm ListCoins initially returns 1 coin grouped under coinbaseKey
// address.
auto list = wallet->ListCoins();
std::map<CTxDestination, std::vector<COutput>> list;
{
LOCK2(cs_main, wallet->cs_wallet);
list = wallet->ListCoins();
}
BOOST_CHECK_EQUAL(list.size(), 1U);
BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(),
coinbaseAddress);
Expand All @@ -353,7 +357,10 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup) {
// pubkey.
AddTx(CRecipient{GetScriptForRawPubKey({}), 1 * COIN,
false /* subtract fee */});
list = wallet->ListCoins();
{
LOCK2(cs_main, wallet->cs_wallet);
list = wallet->ListCoins();
}
BOOST_CHECK_EQUAL(list.size(), 1U);
BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(),
coinbaseAddress);
Expand All @@ -380,7 +387,10 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup) {
}
// Confirm ListCoins still returns same result as before, despite coins
// being locked.
list = wallet->ListCoins();
{
LOCK2(cs_main, wallet->cs_wallet);
list = wallet->ListCoins();
}
BOOST_CHECK_EQUAL(list.size(), 1U);
BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(),
coinbaseAddress);
Expand Down
12 changes: 2 additions & 10 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2520,20 +2520,12 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe,
}

std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins() const {
// TODO: Add AssertLockHeld(cs_wallet) here.
//
// Because the return value from this function contains pointers to
// CWalletTx objects, callers to this function really should acquire the
// cs_wallet lock before calling it. However, the current caller doesn't
// acquire this lock yet. There was an attempt to add the missing lock in
// https://github.com/bitcoin/bitcoin/pull/10340, but that change has been
// postponed until after https://github.com/bitcoin/bitcoin/pull/10244 to
// avoid adding some extra complexity to the Qt code.
AssertLockHeld(cs_main);
AssertLockHeld(cs_wallet);

std::map<CTxDestination, std::vector<COutput>> result;
std::vector<COutput> availableCoins;

LOCK2(cs_main, cs_wallet);
AvailableCoins(availableCoins);

for (auto &coin : availableCoins) {
Expand Down
3 changes: 2 additions & 1 deletion src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,8 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface {
* Return list of available coins and locked coins grouped by non-change
* output address.
*/
std::map<CTxDestination, std::vector<COutput>> ListCoins() const;
std::map<CTxDestination, std::vector<COutput>> ListCoins() const
EXCLUSIVE_LOCKS_REQUIRED(cs_main, cs_wallet);

/**
* Find non-change parent output.
Expand Down

0 comments on commit b660a2d

Please sign in to comment.