Skip to content

Commit 79d579f

Browse files
committed
Remove uses of cs_main in wallet code
This commit does not change behavior. It is easiest to review this change with: git log -p -n1 -U0
1 parent ea961c3 commit 79d579f

File tree

9 files changed

+227
-94
lines changed

9 files changed

+227
-94
lines changed

src/interfaces/chain.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,37 @@
44

55
#include <interfaces/chain.h>
66

7+
#include <sync.h>
78
#include <util/system.h>
9+
#include <validation.h>
10+
11+
#include <memory>
12+
#include <utility>
813

914
namespace interfaces {
1015
namespace {
1116

17+
class LockImpl : public Chain::Lock
18+
{
19+
};
20+
21+
class LockingStateImpl : public LockImpl, public UniqueLock<CCriticalSection>
22+
{
23+
using UniqueLock::UniqueLock;
24+
};
25+
1226
class ChainImpl : public Chain
1327
{
28+
public:
29+
std::unique_ptr<Chain::Lock> lock(bool try_lock) override
30+
{
31+
auto result = MakeUnique<LockingStateImpl>(::cs_main, "cs_main", __FILE__, __LINE__, try_lock);
32+
if (try_lock && result && !*result) return {};
33+
// std::move necessary on some compilers due to conversion from
34+
// LockingStateImpl to Lock pointer
35+
return std::move(result);
36+
}
37+
std::unique_ptr<Chain::Lock> assumeLocked() override { return MakeUnique<LockImpl>(); }
1438
};
1539

1640
} // namespace

src/interfaces/chain.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ class Chain
1818
{
1919
public:
2020
virtual ~Chain() {}
21+
22+
//! Interface for querying locked chain state, used by legacy code that
23+
//! assumes state won't change between calls. New code should avoid using
24+
//! the Lock interface and instead call higher-level Chain methods
25+
//! that return more information so the chain doesn't need to stay locked
26+
//! between calls.
27+
class Lock
28+
{
29+
public:
30+
virtual ~Lock() {}
31+
};
32+
33+
//! Return Lock interface. Chain is locked when this is called, and
34+
//! unlocked when the returned interface is freed.
35+
virtual std::unique_ptr<Lock> lock(bool try_lock = false) = 0;
36+
37+
//! Return Lock interface assuming chain is already locked. This
38+
//! method is temporary and is only used in a few places to avoid changing
39+
//! behavior while code is transitioned to use the Chain::Lock interface.
40+
virtual std::unique_ptr<Lock> assumeLocked() = 0;
2141
};
2242

2343
//! Interface to let node manage chain clients (wallets, or maybe tools for

src/interfaces/wallet.cpp

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class PendingWalletTxImpl : public PendingWalletTx
5353
WalletOrderForm order_form,
5454
std::string& reject_reason) override
5555
{
56-
LOCK2(cs_main, m_wallet.cs_wallet);
56+
auto locked_chain = m_wallet.chain().lock();
57+
LOCK(m_wallet.cs_wallet);
5758
CValidationState state;
5859
if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), m_key, g_connman.get(), state)) {
5960
reject_reason = state.GetRejectReason();
@@ -209,22 +210,26 @@ class WalletImpl : public Wallet
209210
}
210211
void lockCoin(const COutPoint& output) override
211212
{
212-
LOCK2(cs_main, m_wallet.cs_wallet);
213+
auto locked_chain = m_wallet.chain().lock();
214+
LOCK(m_wallet.cs_wallet);
213215
return m_wallet.LockCoin(output);
214216
}
215217
void unlockCoin(const COutPoint& output) override
216218
{
217-
LOCK2(cs_main, m_wallet.cs_wallet);
219+
auto locked_chain = m_wallet.chain().lock();
220+
LOCK(m_wallet.cs_wallet);
218221
return m_wallet.UnlockCoin(output);
219222
}
220223
bool isLockedCoin(const COutPoint& output) override
221224
{
222-
LOCK2(cs_main, m_wallet.cs_wallet);
225+
auto locked_chain = m_wallet.chain().lock();
226+
LOCK(m_wallet.cs_wallet);
223227
return m_wallet.IsLockedCoin(output.hash, output.n);
224228
}
225229
void listLockedCoins(std::vector<COutPoint>& outputs) override
226230
{
227-
LOCK2(cs_main, m_wallet.cs_wallet);
231+
auto locked_chain = m_wallet.chain().lock();
232+
LOCK(m_wallet.cs_wallet);
228233
return m_wallet.ListLockedCoins(outputs);
229234
}
230235
std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients,
@@ -234,7 +239,8 @@ class WalletImpl : public Wallet
234239
CAmount& fee,
235240
std::string& fail_reason) override
236241
{
237-
LOCK2(cs_main, m_wallet.cs_wallet);
242+
auto locked_chain = m_wallet.chain().lock();
243+
LOCK(m_wallet.cs_wallet);
238244
auto pending = MakeUnique<PendingWalletTxImpl>(m_wallet);
239245
if (!m_wallet.CreateTransaction(recipients, pending->m_tx, pending->m_key, fee, change_pos,
240246
fail_reason, coin_control, sign)) {
@@ -245,7 +251,8 @@ class WalletImpl : public Wallet
245251
bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet.TransactionCanBeAbandoned(txid); }
246252
bool abandonTransaction(const uint256& txid) override
247253
{
248-
LOCK2(cs_main, m_wallet.cs_wallet);
254+
auto locked_chain = m_wallet.chain().lock();
255+
LOCK(m_wallet.cs_wallet);
249256
return m_wallet.AbandonTransaction(txid);
250257
}
251258
bool transactionCanBeBumped(const uint256& txid) override
@@ -274,7 +281,8 @@ class WalletImpl : public Wallet
274281
}
275282
CTransactionRef getTx(const uint256& txid) override
276283
{
277-
LOCK2(::cs_main, m_wallet.cs_wallet);
284+
auto locked_chain = m_wallet.chain().lock();
285+
LOCK(m_wallet.cs_wallet);
278286
auto mi = m_wallet.mapWallet.find(txid);
279287
if (mi != m_wallet.mapWallet.end()) {
280288
return mi->second.tx;
@@ -283,7 +291,8 @@ class WalletImpl : public Wallet
283291
}
284292
WalletTx getWalletTx(const uint256& txid) override
285293
{
286-
LOCK2(::cs_main, m_wallet.cs_wallet);
294+
auto locked_chain = m_wallet.chain().lock();
295+
LOCK(m_wallet.cs_wallet);
287296
auto mi = m_wallet.mapWallet.find(txid);
288297
if (mi != m_wallet.mapWallet.end()) {
289298
return MakeWalletTx(m_wallet, mi->second);
@@ -292,7 +301,8 @@ class WalletImpl : public Wallet
292301
}
293302
std::vector<WalletTx> getWalletTxs() override
294303
{
295-
LOCK2(::cs_main, m_wallet.cs_wallet);
304+
auto locked_chain = m_wallet.chain().lock();
305+
LOCK(m_wallet.cs_wallet);
296306
std::vector<WalletTx> result;
297307
result.reserve(m_wallet.mapWallet.size());
298308
for (const auto& entry : m_wallet.mapWallet) {
@@ -304,7 +314,7 @@ class WalletImpl : public Wallet
304314
interfaces::WalletTxStatus& tx_status,
305315
int& num_blocks) override
306316
{
307-
TRY_LOCK(::cs_main, locked_chain);
317+
auto locked_chain = m_wallet.chain().lock(true /* try_lock */);
308318
if (!locked_chain) {
309319
return false;
310320
}
@@ -326,7 +336,8 @@ class WalletImpl : public Wallet
326336
bool& in_mempool,
327337
int& num_blocks) override
328338
{
329-
LOCK2(::cs_main, m_wallet.cs_wallet);
339+
auto locked_chain = m_wallet.chain().lock();
340+
LOCK(m_wallet.cs_wallet);
330341
auto mi = m_wallet.mapWallet.find(txid);
331342
if (mi != m_wallet.mapWallet.end()) {
332343
num_blocks = ::chainActive.Height();
@@ -353,7 +364,7 @@ class WalletImpl : public Wallet
353364
}
354365
bool tryGetBalances(WalletBalances& balances, int& num_blocks) override
355366
{
356-
TRY_LOCK(cs_main, locked_chain);
367+
auto locked_chain = m_wallet.chain().lock(true /* try_lock */);
357368
if (!locked_chain) return false;
358369
TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
359370
if (!locked_wallet) {
@@ -370,27 +381,32 @@ class WalletImpl : public Wallet
370381
}
371382
isminetype txinIsMine(const CTxIn& txin) override
372383
{
373-
LOCK2(::cs_main, m_wallet.cs_wallet);
384+
auto locked_chain = m_wallet.chain().lock();
385+
LOCK(m_wallet.cs_wallet);
374386
return m_wallet.IsMine(txin);
375387
}
376388
isminetype txoutIsMine(const CTxOut& txout) override
377389
{
378-
LOCK2(::cs_main, m_wallet.cs_wallet);
390+
auto locked_chain = m_wallet.chain().lock();
391+
LOCK(m_wallet.cs_wallet);
379392
return m_wallet.IsMine(txout);
380393
}
381394
CAmount getDebit(const CTxIn& txin, isminefilter filter) override
382395
{
383-
LOCK2(::cs_main, m_wallet.cs_wallet);
396+
auto locked_chain = m_wallet.chain().lock();
397+
LOCK(m_wallet.cs_wallet);
384398
return m_wallet.GetDebit(txin, filter);
385399
}
386400
CAmount getCredit(const CTxOut& txout, isminefilter filter) override
387401
{
388-
LOCK2(::cs_main, m_wallet.cs_wallet);
402+
auto locked_chain = m_wallet.chain().lock();
403+
LOCK(m_wallet.cs_wallet);
389404
return m_wallet.GetCredit(txout, filter);
390405
}
391406
CoinsList listCoins() override
392407
{
393-
LOCK2(::cs_main, m_wallet.cs_wallet);
408+
auto locked_chain = m_wallet.chain().lock();
409+
LOCK(m_wallet.cs_wallet);
394410
CoinsList result;
395411
for (const auto& entry : m_wallet.ListCoins()) {
396412
auto& group = result[entry.first];
@@ -403,7 +419,8 @@ class WalletImpl : public Wallet
403419
}
404420
std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) override
405421
{
406-
LOCK2(::cs_main, m_wallet.cs_wallet);
422+
auto locked_chain = m_wallet.chain().lock();
423+
LOCK(m_wallet.cs_wallet);
407424
std::vector<WalletTxOut> result;
408425
result.reserve(outputs.size());
409426
for (const auto& output : outputs) {

src/qt/test/wallettests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ void TestGUI()
143143
wallet->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
144144
}
145145
{
146-
LOCK(cs_main);
146+
auto locked_chain = wallet->chain().lock();
147147
WalletRescanReserver reserver(wallet.get());
148148
reserver.reserve();
149149
wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver, true);

src/wallet/feebumper.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <consensus/validation.h>
6+
#include <interfaces/chain.h>
67
#include <wallet/coincontrol.h>
78
#include <wallet/feebumper.h>
89
#include <wallet/fees.h>
@@ -64,7 +65,8 @@ namespace feebumper {
6465

6566
bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid)
6667
{
67-
LOCK2(cs_main, wallet->cs_wallet);
68+
auto locked_chain = wallet->chain().lock();
69+
LOCK(wallet->cs_wallet);
6870
const CWalletTx* wtx = wallet->GetWalletTx(txid);
6971
if (wtx == nullptr) return false;
7072

@@ -76,7 +78,8 @@ bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid)
7678
Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors,
7779
CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
7880
{
79-
LOCK2(cs_main, wallet->cs_wallet);
81+
auto locked_chain = wallet->chain().lock();
82+
LOCK(wallet->cs_wallet);
8083
errors.clear();
8184
auto it = wallet->mapWallet.find(txid);
8285
if (it == wallet->mapWallet.end()) {
@@ -212,13 +215,15 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
212215
}
213216

214217
bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx) {
215-
LOCK2(cs_main, wallet->cs_wallet);
218+
auto locked_chain = wallet->chain().lock();
219+
LOCK(wallet->cs_wallet);
216220
return wallet->SignTransaction(mtx);
217221
}
218222

219223
Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid)
220224
{
221-
LOCK2(cs_main, wallet->cs_wallet);
225+
auto locked_chain = wallet->chain().lock();
226+
LOCK(wallet->cs_wallet);
222227
if (!errors.empty()) {
223228
return Result::MISC_ERROR;
224229
}

src/wallet/rpcdump.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <chain.h>
6+
#include <interfaces/chain.h>
67
#include <key_io.h>
78
#include <rpc/server.h>
89
#include <validation.h>
@@ -133,7 +134,8 @@ UniValue importprivkey(const JSONRPCRequest& request)
133134
WalletRescanReserver reserver(pwallet);
134135
bool fRescan = true;
135136
{
136-
LOCK2(cs_main, pwallet->cs_wallet);
137+
auto locked_chain = pwallet->chain().lock();
138+
LOCK(pwallet->cs_wallet);
137139

138140
EnsureWalletIsUnlocked(pwallet);
139141

@@ -305,7 +307,8 @@ UniValue importaddress(const JSONRPCRequest& request)
305307
fP2SH = request.params[3].get_bool();
306308

307309
{
308-
LOCK2(cs_main, pwallet->cs_wallet);
310+
auto locked_chain = pwallet->chain().lock();
311+
LOCK(pwallet->cs_wallet);
309312

310313
CTxDestination dest = DecodeDestination(request.params[0].get_str());
311314
if (IsValidDestination(dest)) {
@@ -362,7 +365,7 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
362365
unsigned int txnIndex = 0;
363366
if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == merkleBlock.header.hashMerkleRoot) {
364367

365-
LOCK(cs_main);
368+
auto locked_chain = pwallet->chain().lock();
366369
const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash());
367370
if (!pindex || !chainActive.Contains(pindex)) {
368371
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
@@ -382,7 +385,8 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
382385
wtx.nIndex = txnIndex;
383386
wtx.hashBlock = merkleBlock.header.GetHash();
384387

385-
LOCK2(cs_main, pwallet->cs_wallet);
388+
auto locked_chain = pwallet->chain().lock();
389+
LOCK(pwallet->cs_wallet);
386390

387391
if (pwallet->IsMine(*wtx.tx)) {
388392
pwallet->AddToWallet(wtx, false);
@@ -412,7 +416,8 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
412416
+ HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
413417
);
414418

415-
LOCK2(cs_main, pwallet->cs_wallet);
419+
auto locked_chain = pwallet->chain().lock();
420+
LOCK(pwallet->cs_wallet);
416421

417422
uint256 hash(ParseHashV(request.params[0], "txid"));
418423
std::vector<uint256> vHash;
@@ -483,7 +488,8 @@ UniValue importpubkey(const JSONRPCRequest& request)
483488
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
484489

485490
{
486-
LOCK2(cs_main, pwallet->cs_wallet);
491+
auto locked_chain = pwallet->chain().lock();
492+
LOCK(pwallet->cs_wallet);
487493

488494
for (const auto& dest : GetAllDestinationsForKey(pubKey)) {
489495
ImportAddress(pwallet, dest, strLabel);
@@ -535,7 +541,8 @@ UniValue importwallet(const JSONRPCRequest& request)
535541
int64_t nTimeBegin = 0;
536542
bool fGood = true;
537543
{
538-
LOCK2(cs_main, pwallet->cs_wallet);
544+
auto locked_chain = pwallet->chain().lock();
545+
LOCK(pwallet->cs_wallet);
539546

540547
EnsureWalletIsUnlocked(pwallet);
541548

@@ -653,7 +660,8 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
653660
+ HelpExampleRpc("dumpprivkey", "\"myaddress\"")
654661
);
655662

656-
LOCK2(cs_main, pwallet->cs_wallet);
663+
auto locked_chain = pwallet->chain().lock();
664+
LOCK(pwallet->cs_wallet);
657665

658666
EnsureWalletIsUnlocked(pwallet);
659667

@@ -700,7 +708,8 @@ UniValue dumpwallet(const JSONRPCRequest& request)
700708
+ HelpExampleRpc("dumpwallet", "\"test\"")
701709
);
702710

703-
LOCK2(cs_main, pwallet->cs_wallet);
711+
auto locked_chain = pwallet->chain().lock();
712+
LOCK(pwallet->cs_wallet);
704713

705714
EnsureWalletIsUnlocked(pwallet);
706715

@@ -1134,7 +1143,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
11341143
int64_t nLowestTimestamp = 0;
11351144
UniValue response(UniValue::VARR);
11361145
{
1137-
LOCK2(cs_main, pwallet->cs_wallet);
1146+
auto locked_chain = pwallet->chain().lock();
1147+
LOCK(pwallet->cs_wallet);
11381148
EnsureWalletIsUnlocked(pwallet);
11391149

11401150
// Verify all timestamps are present before importing any keys.

0 commit comments

Comments
 (0)