diff options
author | João Barbosa <joao.paulo.barbosa@gmail.com> | 2020-04-29 10:45:12 +0100 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2020-05-15 07:42:08 +0800 |
commit | 251e321ad7d9ddb938e8a07ddfbe90739f0bafdd (patch) | |
tree | 30b31ffc3f9e3af24ae2d90e1656ae9846b56ad9 /src | |
parent | ca4dac48c5675af3fc53db6740a0b70fef622b0a (diff) | |
download | bitcoin-251e321ad7d9ddb938e8a07ddfbe90739f0bafdd.tar.xz |
rpc: Relock wallet only if most recent callback
Github-Pull: #18814
Rebased-From: 9f59dde9740d065118bdddde75ef9f4e4603a7b1
Diffstat (limited to 'src')
-rw-r--r-- | src/wallet/rpcwallet.cpp | 8 | ||||
-rw-r--r-- | src/wallet/wallet.h | 4 |
2 files changed, 10 insertions, 2 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 61ad2f1198..a5036413c8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -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; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 6c54c72e76..7446a4889a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -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); |