aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/rpcdump.cpp
diff options
context:
space:
mode:
authorAndrew Chow <achow101-github@achow101.com>2021-07-18 22:53:26 -0400
committerAndrew Chow <achow101-github@achow101.com>2021-07-19 12:25:11 -0400
commit25d99e6511d8c43b2025a89bcd8295de755346a7 (patch)
tree467679d286c6ed7b36ca85e8d23c70f32ea6252d /src/wallet/rpcdump.cpp
parente8f85e0e86e92e583b8984455b7bf9d0a777578a (diff)
Reorder dumpwallet so that cs_main functions go first
DEBUG_LOCKORDER expects cs_wallet, cs_main, and cs_KeyStore to be acquired in that order. However dumpwallet would take these in the order cs_wallet, cs_KeyStore, cs_main. So when configured with `--enable-debug`, it is possible to hit the lock order assertion when using dumpwallet. To fix this, cs_wallet and cs_KeyStore are no longer locked at the same time. Instead cs_wallet will be locked first. Then the functions which lock cs_main will be run. Lastly cs_KeyStore will be locked afterwards. This avoids the lock order issue. Furthermore, since GetKeyBirthTimes (only used by dumpwallet) also uses a function that locks cs_main, and itself also locks cs_KeyStore, the same reordering is done here.
Diffstat (limited to 'src/wallet/rpcdump.cpp')
-rw-r--r--src/wallet/rpcdump.cpp13
1 files changed, 9 insertions, 4 deletions
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index ea97b339cf..ac60504419 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -740,7 +740,7 @@ RPCHelpMan dumpwallet()
// the user could have gotten from another RPC command prior to now
wallet.BlockUntilSyncedToCurrentChain();
- LOCK2(wallet.cs_wallet, spk_man.cs_KeyStore);
+ LOCK(wallet.cs_wallet);
EnsureWalletIsUnlocked(wallet);
@@ -762,9 +762,16 @@ RPCHelpMan dumpwallet()
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
std::map<CKeyID, int64_t> mapKeyBirth;
- const std::map<CKeyID, int64_t>& mapKeyPool = spk_man.GetAllReserveKeys();
wallet.GetKeyBirthTimes(mapKeyBirth);
+ int64_t block_time = 0;
+ CHECK_NONFATAL(wallet.chain().findBlock(wallet.GetLastBlockHash(), FoundBlock().time(block_time)));
+
+ // Note: To avoid a lock order issue, access to cs_main must be locked before cs_KeyStore.
+ // So we do the two things in this function that lock cs_main first: GetKeyBirthTimes, and findBlock.
+ LOCK(spk_man.cs_KeyStore);
+
+ const std::map<CKeyID, int64_t>& mapKeyPool = spk_man.GetAllReserveKeys();
std::set<CScriptID> scripts = spk_man.GetCScripts();
// sort time/key pairs
@@ -779,8 +786,6 @@ RPCHelpMan dumpwallet()
file << strprintf("# Wallet dump created by Bitcoin %s\n", CLIENT_BUILD);
file << strprintf("# * Created on %s\n", FormatISO8601DateTime(GetTime()));
file << strprintf("# * Best block at time of backup was %i (%s),\n", wallet.GetLastBlockHeight(), wallet.GetLastBlockHash().ToString());
- int64_t block_time = 0;
- CHECK_NONFATAL(wallet.chain().findBlock(wallet.GetLastBlockHash(), FoundBlock().time(block_time)));
file << strprintf("# mined on %s\n", FormatISO8601DateTime(block_time));
file << "\n";