Merge #14880: 0.17: Backport #14453

dcb032dcdf qa: Ensure wallet unload during walletpassphrase timeout (João Barbosa)
75b5d8c4ea rpc: Fix wallet unload during walletpassphrase timeout (João Barbosa)

Pull request description:

  Backport #14453 to 0.17

Tree-SHA512: fce0adccbb07b6635bb773a71beb4a9b814bceb77bbe7bbc5bcb7d151aabb1148c791622f58c990afe202012ca1971cd466cb536fc6f37e22cdc58738720b593
This commit is contained in:
MarcoFalke 2018-12-06 13:07:21 -05:00
commit abae8aeff1
No known key found for this signature in database
GPG key ID: D2EA4850E7528B25
2 changed files with 21 additions and 8 deletions

View file

@ -2546,13 +2546,6 @@ static UniValue keypoolrefill(const JSONRPCRequest& request)
} }
static void LockWallet(CWallet* pWallet)
{
LOCK(pWallet->cs_wallet);
pWallet->nRelockTime = 0;
pWallet->Lock();
}
static UniValue walletpassphrase(const JSONRPCRequest& request) static UniValue walletpassphrase(const JSONRPCRequest& request)
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@ -2622,7 +2615,18 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
pwallet->TopUpKeyPool(); pwallet->TopUpKeyPool();
pwallet->nRelockTime = GetTime() + nSleepTime; pwallet->nRelockTime = GetTime() + nSleepTime;
RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), std::bind(LockWallet, pwallet), nSleepTime);
// Keep a weak pointer to the wallet so that it is possible to unload the
// 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;
RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
if (auto shared_wallet = weak_wallet.lock()) {
LOCK(shared_wallet->cs_wallet);
shared_wallet->Lock();
shared_wallet->nRelockTime = 0;
}
}, nSleepTime);
return NullUniValue; return NullUniValue;
} }

View file

@ -8,6 +8,7 @@ Verify that a bitcoind node can load multiple wallet files
""" """
import os import os
import shutil import shutil
import time
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.test_node import ErrorMatch from test_framework.test_node import ErrorMatch
@ -262,7 +263,15 @@ class MultiWalletTest(BitcoinTestFramework):
assert 'w1' not in self.nodes[0].listwallets() assert 'w1' not in self.nodes[0].listwallets()
# Successfully unload the wallet referenced by the request endpoint # Successfully unload the wallet referenced by the request endpoint
# Also ensure unload works during walletpassphrase timeout
wallets = node.listwallets()
w2.encryptwallet('test')
self.restart_node(0, ['-wallet={}'.format(wallet) for wallet in wallets])
w1 = node.get_wallet_rpc(wallet_names[0])
w2 = node.get_wallet_rpc(wallet_names[1])
w2.walletpassphrase('test', 1)
w2.unloadwallet() w2.unloadwallet()
time.sleep(1.1)
assert 'w2' not in self.nodes[0].listwallets() assert 'w2' not in self.nodes[0].listwallets()
# Successfully unload all wallets # Successfully unload all wallets