Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/rpcwallet.cpp
Show First 20 Lines • Show All 2,322 Lines • ▼ Show 20 Lines | RPCHelpMan{ | ||||
HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") + | HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") + | ||||
"\nLock the wallet again (before 60 seconds)\n" + | "\nLock the wallet again (before 60 seconds)\n" + | ||||
HelpExampleCli("walletlock", "") + "\nAs a JSON-RPC call\n" + | HelpExampleCli("walletlock", "") + "\nAs a JSON-RPC call\n" + | ||||
HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")}, | HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")}, | ||||
} | } | ||||
.Check(request); | .Check(request); | ||||
int64_t nSleepTime; | int64_t nSleepTime; | ||||
int64_t relock_time; | |||||
// Prevent concurrent calls to walletpassphrase with the same wallet. | |||||
LOCK(pwallet->m_unlock_mutex); | |||||
{ | { | ||||
LOCK(pwallet->cs_wallet); | LOCK(pwallet->cs_wallet); | ||||
if (!pwallet->IsCrypted()) { | if (!pwallet->IsCrypted()) { | ||||
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, | throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, | ||||
"Error: running with an unencrypted wallet, but " | "Error: running with an unencrypted wallet, but " | ||||
"walletpassphrase was called."); | "walletpassphrase was called."); | ||||
} | } | ||||
Show All 31 Lines | LOCK(pwallet->m_unlock_mutex); | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_WALLET_PASSPHRASE_INCORRECT, | RPC_WALLET_PASSPHRASE_INCORRECT, | ||||
"Error: The wallet passphrase entered was incorrect."); | "Error: The wallet passphrase entered was incorrect."); | ||||
} | } | ||||
pwallet->TopUpKeyPool(); | pwallet->TopUpKeyPool(); | ||||
pwallet->nRelockTime = GetTime() + nSleepTime; | pwallet->nRelockTime = GetTime() + nSleepTime; | ||||
relock_time = pwallet->nRelockTime; | |||||
} | } | ||||
// rpcRunLater must be called without cs_wallet held otherwise a deadlock | // rpcRunLater must be called without cs_wallet held otherwise a deadlock | ||||
// can occur. The deadlock would happen when RPCRunLater removes the | // can occur. The deadlock would happen when RPCRunLater removes the | ||||
// previous timer (and waits for the callback to finish if already running) | // previous timer (and waits for the callback to finish if already running) | ||||
// and the callback locks cs_wallet. | // and the callback locks cs_wallet. | ||||
AssertLockNotHeld(wallet->cs_wallet); | AssertLockNotHeld(wallet->cs_wallet); | ||||
// Keep a weak pointer to the wallet so that it is possible to unload the | // 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 | // wallet before the following callback is called. If a valid shared pointer | ||||
// is acquired in the callback then the wallet is still loaded. | // is acquired in the callback then the wallet is still loaded. | ||||
std::weak_ptr<CWallet> weak_wallet = wallet; | std::weak_ptr<CWallet> weak_wallet = wallet; | ||||
pwallet->chain().rpcRunLater( | pwallet->chain().rpcRunLater( | ||||
strprintf("lockwallet(%s)", pwallet->GetName()), | strprintf("lockwallet(%s)", pwallet->GetName()), | ||||
[weak_wallet] { | [weak_wallet, relock_time] { | ||||
if (auto shared_wallet = weak_wallet.lock()) { | if (auto shared_wallet = weak_wallet.lock()) { | ||||
LOCK(shared_wallet->cs_wallet); | 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->Lock(); | ||||
shared_wallet->nRelockTime = 0; | shared_wallet->nRelockTime = 0; | ||||
} | } | ||||
}, | }, | ||||
nSleepTime); | nSleepTime); | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 2,685 Lines • Show Last 20 Lines |