Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2011-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <rpc/util.h>6#include <scheduler.h>7#include <wallet/context.h>8#include <wallet/rpc/util.h>9#include <wallet/wallet.h>12namespace wallet {13RPCMethod walletpassphrase()14{15return RPCMethod{16"walletpassphrase",17"Stores the wallet decryption key in memory for 'timeout' seconds.\n"18"This is needed prior to performing transactions related to private keys such as sending bitcoins\n"19"\nNote:\n"20"Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"21"time that overrides the old one.\n",22{23{"passphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet passphrase"},24{"timeout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The time to keep the decryption key in seconds; capped at 100000000 (~3 years)."},25},26RPCResult{RPCResult::Type::NONE, "", ""},27RPCExamples{28"\nUnlock the wallet for 60 seconds\n"29+ HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +30"\nLock the wallet again (before 60 seconds)\n"31+ HelpExampleCli("walletlock", "") +32"\nAs a JSON-RPC call\n"33+ HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")34},35[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue36{37std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);38if (!wallet) return UniValue::VNULL;39CWallet* const pwallet = wallet.get();41int64_t nSleepTime;42int64_t relock_time;43// Prevent concurrent calls to walletpassphrase with the same wallet.44LOCK(pwallet->m_unlock_mutex);45{46LOCK(pwallet->cs_wallet);48if (!pwallet->HasEncryptionKeys()) {49throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");50}52// Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed53SecureString strWalletPass;54strWalletPass.reserve(100);55strWalletPass = std::string_view{request.params[0].get_str()};57// Get the timeout58nSleepTime = request.params[1].getInt<int64_t>();59// Timeout cannot be negative, otherwise it will relock immediately60if (nSleepTime < 0) {61throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");62}63// Clamp timeout to ~3 years to avoid overflow when computing the relock time64constexpr int64_t MAX_SLEEP_TIME = 100000000;65if (nSleepTime > MAX_SLEEP_TIME) {66nSleepTime = MAX_SLEEP_TIME;67}69if (strWalletPass.empty()) {70throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase cannot be empty");71}73if (!pwallet->Unlock(strWalletPass)) {74// Check if the passphrase has a null character (see #27067 for details)75if (strWalletPass.find('\0') == std::string::npos) {76throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");77} else {78throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered is incorrect. "79"It contains a null character (ie - a zero byte). "80"If the passphrase was set with a version of this software prior to 25.0, "81"please try again with only the characters up to — but not including — "82"the first null character. If this is successful, please set a new "83"passphrase to avoid this issue in the future.");84}85}87pwallet->TopUpKeyPool();89pwallet->nRelockTime = GetTime() + nSleepTime;90relock_time = pwallet->nRelockTime;91}93// Get wallet scheduler to queue up the relock callback in the future.94// Scheduled events don't get destructed until they are executed,95// and they are executed in series in a single scheduler thread so96// no cs_wallet lock is needed.97WalletContext& context = EnsureWalletContext(request.context);98// Keep a weak pointer to the wallet so that it is possible to unload the99// wallet before the following callback is called. If a valid shared pointer100// is acquired in the callback then the wallet is still loaded.101std::weak_ptr<CWallet> weak_wallet = wallet;102context.scheduler->scheduleFromNow([weak_wallet, relock_time] {103if (auto shared_wallet = weak_wallet.lock()) {104LOCK2(shared_wallet->m_relock_mutex, shared_wallet->cs_wallet);105// Skip if this is not the most recent relock callback.106if (shared_wallet->nRelockTime != relock_time) return;107shared_wallet->Lock();108shared_wallet->nRelockTime = 0;109}110}, std::chrono::seconds(nSleepTime));112return UniValue::VNULL;113},114};115}118RPCMethod walletpassphrasechange()119{120return RPCMethod{121"walletpassphrasechange",122"Changes the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n",123{124{"oldpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The current passphrase"},125{"newpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The new passphrase"},126},127RPCResult{RPCResult::Type::NONE, "", ""},128RPCExamples{129HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")130+ HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")131},132[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue133{134std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);135if (!pwallet) return UniValue::VNULL;137if (!pwallet->HasEncryptionKeys()) {138throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");139}141if (pwallet->IsScanningWithPassphrase()) {142throw JSONRPCError(RPC_WALLET_ERROR, "Error: the wallet is currently being used to rescan the blockchain for related transactions. Please call `abortrescan` before changing the passphrase.");143}145LOCK2(pwallet->m_relock_mutex, pwallet->cs_wallet);147SecureString strOldWalletPass;148strOldWalletPass.reserve(100);149strOldWalletPass = std::string_view{request.params[0].get_str()};151SecureString strNewWalletPass;152strNewWalletPass.reserve(100);153strNewWalletPass = std::string_view{request.params[1].get_str()};155if (strOldWalletPass.empty() || strNewWalletPass.empty()) {156throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase cannot be empty");157}159if (!pwallet->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) {160// Check if the old passphrase had a null character (see #27067 for details)161if (strOldWalletPass.find('\0') == std::string::npos) {162throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");163} else {164throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The old wallet passphrase entered is incorrect. "165"It contains a null character (ie - a zero byte). "166"If the old passphrase was set with a version of this software prior to 25.0, "167"please try again with only the characters up to — but not including — "168"the first null character.");169}170}172return UniValue::VNULL;173},174};175}178RPCMethod walletlock()179{180return RPCMethod{181"walletlock",182"Removes the wallet encryption key from memory, locking the wallet.\n"183"After calling this method, you will need to call walletpassphrase again\n"184"before being able to call any methods which require the wallet to be unlocked.\n",185{},186RPCResult{RPCResult::Type::NONE, "", ""},187RPCExamples{188"\nSet the passphrase for 2 minutes to perform a transaction\n"189+ HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +190"\nPerform a send (requires passphrase set)\n"191+ HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 1.0") +192"\nClear the passphrase since we are done before 2 minutes is up\n"193+ HelpExampleCli("walletlock", "") +194"\nAs a JSON-RPC call\n"195+ HelpExampleRpc("walletlock", "")196},197[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue198{199std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);200if (!pwallet) return UniValue::VNULL;202if (!pwallet->HasEncryptionKeys()) {203throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");204}206if (pwallet->IsScanningWithPassphrase()) {207throw JSONRPCError(RPC_WALLET_ERROR, "Error: the wallet is currently being used to rescan the blockchain for related transactions. Please call `abortrescan` before locking the wallet.");208}210LOCK2(pwallet->m_relock_mutex, pwallet->cs_wallet);212pwallet->Lock();213pwallet->nRelockTime = 0;215return UniValue::VNULL;216},217};218}221RPCMethod encryptwallet()222{223return RPCMethod{224"encryptwallet",225"Encrypts the wallet with 'passphrase'. This is for first time encryption.\n"226"After this, any calls that interact with private keys such as sending or signing \n"227"will require the passphrase to be set prior to making these calls.\n"228"Use the walletpassphrase call for this, and then walletlock call.\n"229"If the wallet is already encrypted, use the walletpassphrasechange call.\n"230"** IMPORTANT **\n"231"For security reasons, the encryption process will generate a new HD seed, resulting\n"232"in the creation of a fresh set of active descriptors. Therefore, it is crucial to\n"233"securely back up the newly generated wallet file using the backupwallet RPC.\n",234{235{"passphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long."},236},237RPCResult{RPCResult::Type::STR, "", "A string with further instructions"},238RPCExamples{239"\nEncrypt your wallet\n"240+ HelpExampleCli("encryptwallet", "\"my pass phrase\"") +241"\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"242+ HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +243"\nNow we can do something like sign\n"244+ HelpExampleCli("signmessage", "\"address\" \"test message\"") +245"\nNow lock the wallet again by removing the passphrase\n"246+ HelpExampleCli("walletlock", "") +247"\nAs a JSON-RPC call\n"248+ HelpExampleRpc("encryptwallet", "\"my pass phrase\"")249},250[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue