Skip to content

Commit 9f59dde

Browse files
committed
rpc: Relock wallet only if most recent callback
1 parent a2e6db5 commit 9f59dde

File tree

2 files changed

+10
-2
lines changed

2 files changed

+10
-2
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,9 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
19081908
}.Check(request);
19091909

19101910
int64_t nSleepTime;
1911+
int64_t relock_time;
1912+
// Prevent concurrent calls to walletpassphrase with the same wallet.
1913+
LOCK(pwallet->m_unlock_mutex);
19111914
{
19121915
auto locked_chain = pwallet->chain().lock();
19131916
LOCK(pwallet->cs_wallet);
@@ -1946,6 +1949,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
19461949
pwallet->TopUpKeyPool();
19471950

19481951
pwallet->nRelockTime = GetTime() + nSleepTime;
1952+
relock_time = pwallet->nRelockTime;
19491953
}
19501954

19511955
// rpcRunLater must be called without cs_wallet held otherwise a deadlock
@@ -1957,9 +1961,11 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
19571961
// wallet before the following callback is called. If a valid shared pointer
19581962
// is acquired in the callback then the wallet is still loaded.
19591963
std::weak_ptr<CWallet> weak_wallet = wallet;
1960-
pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
1964+
pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet, relock_time] {
19611965
if (auto shared_wallet = weak_wallet.lock()) {
19621966
LOCK(shared_wallet->cs_wallet);
1967+
// Skip if this is not the most recent rpcRunLater callback.
1968+
if (shared_wallet->nRelockTime != relock_time) return;
19631969
shared_wallet->Lock();
19641970
shared_wallet->nRelockTime = 0;
19651971
}

src/wallet/wallet.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,8 +869,10 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
869869
std::vector<std::string> GetDestValues(const std::string& prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
870870

871871
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
872-
int64_t nRelockTime = 0;
872+
int64_t nRelockTime GUARDED_BY(cs_wallet){0};
873873

874+
// Used to prevent concurrent calls to walletpassphrase RPC.
875+
Mutex m_unlock_mutex;
874876
bool Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys = false);
875877
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
876878
bool EncryptWallet(const SecureString& strWalletPassphrase);

0 commit comments

Comments
 (0)