1
1
mirror of https://github.com/bitcoin/bitcoin.git synced 2024-05-17 23:56:39 +00:00

rpc: Relock wallet only if most recent callback

Github-Pull: #18814
Rebased-From: 9f59dde9740d065118bdddde75ef9f4e4603a7b1
This commit is contained in:
João Barbosa 2020-04-29 10:45:12 +01:00 committed by fanquake
parent ca4dac48c5
commit 251e321ad7
No known key found for this signature in database
GPG Key ID: 2EEB9F5CC09526C1
2 changed files with 10 additions and 2 deletions

View File

@ -1917,6 +1917,9 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
}.Check(request);
int64_t nSleepTime;
int64_t relock_time;
// Prevent concurrent calls to walletpassphrase with the same wallet.
LOCK(pwallet->m_unlock_mutex);
{
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
@ -1955,6 +1958,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
pwallet->TopUpKeyPool();
pwallet->nRelockTime = GetTime() + nSleepTime;
relock_time = pwallet->nRelockTime;
}
// rpcRunLater must be called without cs_wallet held otherwise a deadlock
@ -1966,9 +1970,11 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
// wallet before the following callback is called. If a valid shared pointer
// is acquired in the callback then the wallet is still loaded.
std::weak_ptr<CWallet> weak_wallet = wallet;
pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet, relock_time] {
if (auto shared_wallet = weak_wallet.lock()) {
LOCK(shared_wallet->cs_wallet);
// Skip if this is not the most recent rpcRunLater callback.
if (shared_wallet->nRelockTime != relock_time) return;
shared_wallet->Lock();
shared_wallet->nRelockTime = 0;
}

View File

@ -867,8 +867,10 @@ public:
std::vector<std::string> GetDestValues(const std::string& prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
int64_t nRelockTime = 0;
int64_t nRelockTime GUARDED_BY(cs_wallet){0};
// Used to prevent concurrent calls to walletpassphrase RPC.
Mutex m_unlock_mutex;
bool Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys = false);
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);