Skip to content

Commit f3d27d1

Browse files
author
MarcoFalke
committed
Merge #16033: Hold cs_main when reading chainActive via getTipLocator(). Remove assumeLocked().
9402ef0 Remove temporary method assumeLocked(). Remove LockingStateImpl. Remove redundant cs_main locks. (practicalswift) 593a8e8 wallet: Use chain.lock() instead of temporary chain.assumeLocked() (practicalswift) Pull request description: Fixes #16028. Problem description: `LockAnnotation lock(::cs_main)` is a guarantee to the compiler thread analysis that `::cs_main` is locked (when it couldn't be determined otherwise). Despite being annotated with the locking guarantee ... https://github.com/bitcoin/bitcoin/blob/65526fc8666fef35ef908dbc225f706bef642c7e/src/interfaces/chain.cpp#L134-L138 ... `getTipLocator()` reads `chainActive` (via `::ChainActive()`) without holding `cs_main`. This can be verified by adding the following `AssertLockHeld(cs_main)`: ``` $ git diff diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 5962328..9fc693a0f 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -134,6 +134,7 @@ class LockImpl : public Chain::Lock CBlockLocator getTipLocator() override { LockAnnotation lock(::cs_main); + AssertLockHeld(::cs_main); return ::ChainActive().GetLocator(); } Optional<int> findLocatorFork(const CBlockLocator& locator) override $ make check ../build-aux/test-driver: line 107: 12881 Aborted "$@" > $log_file 2>&1 FAIL: qt/test/test_bitcoin-qt ``` ACKs for commit 9402ef: MarcoFalke: utACK 9402ef0 ryanofsky: utACK 9402ef0. Changes are consolidating commits and removing redundant lock2 cs_main calls Tree-SHA512: 0a030bf0c07eb53194ecc246f973ef389dd42a0979f51932bf94bdf7e90c52473ae03be49718ee1629582b05dd8e0dc020b5a210318c93378ea4ace90c0f9f72
2 parents 8f2f17f + 9402ef0 commit f3d27d1

File tree

4 files changed

+23
-25
lines changed

4 files changed

+23
-25
lines changed

src/interfaces/chain.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
namespace interfaces {
3838
namespace {
3939

40-
class LockImpl : public Chain::Lock
40+
class LockImpl : public Chain::Lock, public UniqueLock<CCriticalSection>
4141
{
4242
Optional<int> getHeight() override
4343
{
@@ -155,10 +155,7 @@ class LockImpl : public Chain::Lock
155155
return AcceptToMemoryPool(::mempool, state, tx, nullptr /* missing inputs */, nullptr /* txn replaced */,
156156
false /* bypass limits */, absurd_fee);
157157
}
158-
};
159158

160-
class LockingStateImpl : public LockImpl, public UniqueLock<CCriticalSection>
161-
{
162159
using UniqueLock::UniqueLock;
163160
};
164161

@@ -249,13 +246,12 @@ class ChainImpl : public Chain
249246
public:
250247
std::unique_ptr<Chain::Lock> lock(bool try_lock) override
251248
{
252-
auto result = MakeUnique<LockingStateImpl>(::cs_main, "cs_main", __FILE__, __LINE__, try_lock);
249+
auto result = MakeUnique<LockImpl>(::cs_main, "cs_main", __FILE__, __LINE__, try_lock);
253250
if (try_lock && result && !*result) return {};
254251
// std::move necessary on some compilers due to conversion from
255-
// LockingStateImpl to Lock pointer
252+
// LockImpl to Lock pointer
256253
return std::move(result);
257254
}
258-
std::unique_ptr<Chain::Lock> assumeLocked() override { return MakeUnique<LockImpl>(); }
259255
bool findBlock(const uint256& hash, CBlock* block, int64_t* time, int64_t* time_max) override
260256
{
261257
CBlockIndex* index;

src/interfaces/chain.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,6 @@ class Chain
138138
//! unlocked when the returned interface is freed.
139139
virtual std::unique_ptr<Lock> lock(bool try_lock = false) = 0;
140140

141-
//! Return Lock interface assuming chain is already locked. This
142-
//! method is temporary and is only used in a few places to avoid changing
143-
//! behavior while code is transitioned to use the Chain::Lock interface.
144-
virtual std::unique_ptr<Lock> assumeLocked() = 0;
145-
146141
//! Return whether node has the block and optionally return block metadata
147142
//! or contents.
148143
//!

src/wallet/test/wallet_tests.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,10 @@ class ListCoinsTestingSetup : public TestChain100Setup
368368
int changePos = -1;
369369
std::string error;
370370
CCoinControl dummy;
371-
BOOST_CHECK(wallet->CreateTransaction(*m_locked_chain, {recipient}, tx, reservekey, fee, changePos, error, dummy));
371+
{
372+
auto locked_chain = m_chain->lock();
373+
BOOST_CHECK(wallet->CreateTransaction(*locked_chain, {recipient}, tx, reservekey, fee, changePos, error, dummy));
374+
}
372375
CValidationState state;
373376
BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, reservekey, state));
374377
CMutableTransaction blocktx;
@@ -387,7 +390,6 @@ class ListCoinsTestingSetup : public TestChain100Setup
387390
}
388391

389392
std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
390-
std::unique_ptr<interfaces::Chain::Lock> m_locked_chain = m_chain->assumeLocked(); // Temporary. Removed in upcoming lock cleanup
391393
std::unique_ptr<CWallet> wallet;
392394
};
393395

@@ -399,8 +401,9 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
399401
// address.
400402
std::map<CTxDestination, std::vector<COutput>> list;
401403
{
402-
LOCK2(cs_main, wallet->cs_wallet);
403-
list = wallet->ListCoins(*m_locked_chain);
404+
auto locked_chain = m_chain->lock();
405+
LOCK(wallet->cs_wallet);
406+
list = wallet->ListCoins(*locked_chain);
404407
}
405408
BOOST_CHECK_EQUAL(list.size(), 1U);
406409
BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
@@ -415,18 +418,20 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
415418
// pubkey.
416419
AddTx(CRecipient{GetScriptForRawPubKey({}), 1 * COIN, false /* subtract fee */});
417420
{
418-
LOCK2(cs_main, wallet->cs_wallet);
419-
list = wallet->ListCoins(*m_locked_chain);
421+
auto locked_chain = m_chain->lock();
422+
LOCK(wallet->cs_wallet);
423+
list = wallet->ListCoins(*locked_chain);
420424
}
421425
BOOST_CHECK_EQUAL(list.size(), 1U);
422426
BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
423427
BOOST_CHECK_EQUAL(list.begin()->second.size(), 2U);
424428

425429
// Lock both coins. Confirm number of available coins drops to 0.
426430
{
427-
LOCK2(cs_main, wallet->cs_wallet);
431+
auto locked_chain = m_chain->lock();
432+
LOCK(wallet->cs_wallet);
428433
std::vector<COutput> available;
429-
wallet->AvailableCoins(*m_locked_chain, available);
434+
wallet->AvailableCoins(*locked_chain, available);
430435
BOOST_CHECK_EQUAL(available.size(), 2U);
431436
}
432437
for (const auto& group : list) {
@@ -436,16 +441,18 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
436441
}
437442
}
438443
{
439-
LOCK2(cs_main, wallet->cs_wallet);
444+
auto locked_chain = m_chain->lock();
445+
LOCK(wallet->cs_wallet);
440446
std::vector<COutput> available;
441-
wallet->AvailableCoins(*m_locked_chain, available);
447+
wallet->AvailableCoins(*locked_chain, available);
442448
BOOST_CHECK_EQUAL(available.size(), 0U);
443449
}
444450
// Confirm ListCoins still returns same result as before, despite coins
445451
// being locked.
446452
{
447-
LOCK2(cs_main, wallet->cs_wallet);
448-
list = wallet->ListCoins(*m_locked_chain);
453+
auto locked_chain = m_chain->lock();
454+
LOCK(wallet->cs_wallet);
455+
list = wallet->ListCoins(*locked_chain);
449456
}
450457
BOOST_CHECK_EQUAL(list.size(), 1U);
451458
BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);

src/wallet/wallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4074,7 +4074,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
40744074
return nullptr;
40754075
}
40764076

4077-
auto locked_chain = chain.assumeLocked(); // Temporary. Removed in upcoming lock cleanup
4077+
auto locked_chain = chain.lock();
40784078
walletInstance->ChainStateFlushed(locked_chain->getTipLocator());
40794079
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
40804080
// Make it impossible to disable private keys after creation

0 commit comments

Comments
 (0)