Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/rpcwallet.cpp
Show First 20 Lines • Show All 2,276 Lines • ▼ Show 20 Lines | RPCHelpMan{ | ||||
"\nUnlock the wallet for 60 seconds\n" + | "\nUnlock the wallet for 60 seconds\n" + | ||||
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; | |||||
{ | |||||
auto locked_chain = pwallet->chain().lock(); | auto locked_chain = pwallet->chain().lock(); | ||||
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."); | ||||
} | } | ||||
// Note that the walletpassphrase is stored in request.params[0] which is | // Note that the walletpassphrase is stored in request.params[0] which | ||||
// not mlock()ed | // is not mlock()ed | ||||
SecureString strWalletPass; | SecureString strWalletPass; | ||||
strWalletPass.reserve(100); | strWalletPass.reserve(100); | ||||
// TODO: get rid of this .c_str() by implementing | // TODO: get rid of this .c_str() by implementing | ||||
// SecureString::operator=(std::string) | // SecureString::operator=(std::string) | ||||
// Alternately, find a way to make request.params[0] mlock()'d to begin | // Alternately, find a way to make request.params[0] mlock()'d to begin | ||||
// with. | // with. | ||||
strWalletPass = request.params[0].get_str().c_str(); | strWalletPass = request.params[0].get_str().c_str(); | ||||
// Get the timeout | // Get the timeout | ||||
int64_t nSleepTime = request.params[1].get_int64(); | nSleepTime = request.params[1].get_int64(); | ||||
// Timeout cannot be negative, otherwise it will relock immediately | // Timeout cannot be negative, otherwise it will relock immediately | ||||
if (nSleepTime < 0) { | if (nSleepTime < 0) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Timeout cannot be negative."); | "Timeout cannot be negative."); | ||||
} | } | ||||
// Clamp timeout | // Clamp timeout | ||||
// larger values trigger a macos/libevent bug? | // larger values trigger a macos/libevent bug? | ||||
constexpr int64_t MAX_SLEEP_TIME = 100000000; | constexpr int64_t MAX_SLEEP_TIME = 100000000; | ||||
if (nSleepTime > MAX_SLEEP_TIME) { | if (nSleepTime > MAX_SLEEP_TIME) { | ||||
nSleepTime = MAX_SLEEP_TIME; | nSleepTime = MAX_SLEEP_TIME; | ||||
} | } | ||||
if (strWalletPass.empty()) { | if (strWalletPass.empty()) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"passphrase can not be empty"); | "passphrase can not be empty"); | ||||
} | } | ||||
if (!pwallet->Unlock(strWalletPass)) { | if (!pwallet->Unlock(strWalletPass)) { | ||||
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; | ||||
} | |||||
// rpcRunLater must be called without cs_wallet held otherwise a deadlock | |||||
// can occur. The deadlock would happen when RPCRunLater removes the | |||||
// previous timer (and waits for the callback to finish if already running) | |||||
// and the callback locks 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] { | ||||
if (auto shared_wallet = weak_wallet.lock()) { | if (auto shared_wallet = weak_wallet.lock()) { | ||||
▲ Show 20 Lines • Show All 2,549 Lines • Show Last 20 Lines |