| 2549 | |
| 2550 | |
| 2551 | static UniValue walletpassphrase(const JSONRPCRequest& request) |
| 2552 | { |
| 2553 | std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); |
| 2554 | CWallet* const pwallet = wallet.get(); |
| 2555 | |
| 2556 | if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { |
| 2557 | return NullUniValue; |
| 2558 | } |
| 2559 | |
| 2560 | if (request.fHelp || request.params.size() != 2) { |
| 2561 | throw std::runtime_error( |
| 2562 | "walletpassphrase \"passphrase\" timeout\n" |
| 2563 | "\nStores the wallet decryption key in memory for 'timeout' seconds.\n" |
| 2564 | "This is needed prior to performing transactions related to private keys such as sending bitcoins\n" |
| 2565 | "\nArguments:\n" |
| 2566 | "1. \"passphrase\" (string, required) The wallet passphrase\n" |
| 2567 | "2. timeout (numeric, required) The time to keep the decryption key in seconds; capped at 100000000 (~3 years).\n" |
| 2568 | "\nNote:\n" |
| 2569 | "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n" |
| 2570 | "time that overrides the old one.\n" |
| 2571 | "\nExamples:\n" |
| 2572 | "\nUnlock the wallet for 60 seconds\n" |
| 2573 | + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") + |
| 2574 | "\nLock the wallet again (before 60 seconds)\n" |
| 2575 | + HelpExampleCli("walletlock", "") + |
| 2576 | "\nAs json rpc call\n" |
| 2577 | + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60") |
| 2578 | ); |
| 2579 | } |
| 2580 | |
| 2581 | LOCK2(cs_main, pwallet->cs_wallet); |
| 2582 | |
| 2583 | if (!pwallet->IsCrypted()) { |
| 2584 | throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called."); |
| 2585 | } |
| 2586 | |
| 2587 | // Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed |
| 2588 | SecureString strWalletPass; |
| 2589 | strWalletPass.reserve(100); |
| 2590 | // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) |
| 2591 | // Alternately, find a way to make request.params[0] mlock()'d to begin with. |
| 2592 | strWalletPass = request.params[0].get_str().c_str(); |
| 2593 | |
| 2594 | // Get the timeout |
| 2595 | int64_t nSleepTime = request.params[1].get_int64(); |
| 2596 | // Timeout cannot be negative, otherwise it will relock immediately |
| 2597 | if (nSleepTime < 0) { |
| 2598 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative."); |
| 2599 | } |
| 2600 | // Clamp timeout |
| 2601 | constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug? |
| 2602 | if (nSleepTime > MAX_SLEEP_TIME) { |
| 2603 | nSleepTime = MAX_SLEEP_TIME; |
| 2604 | } |
| 2605 | |
| 2606 | if (strWalletPass.length() > 0) |
| 2607 | { |
| 2608 | if (!pwallet->Unlock(strWalletPass)) { |
nothing calls this directly
no test coverage detected