比特币 RPC 命令「walletpassphrasechange」
$ bitcoin-cli help walletpassphrasechange walletpassphrasechange "oldpassphrase" "newpassphrase" 把钱包密码 'oldpassphrase' 改为 'newpassphrase'。 参数: 1. "oldpassphrase"(字符串)当前的密码 2. "newpassphrase"(字符串)新的密码 例子: > bitcoin-cli walletpassphrase "old one" "new one" > curl --user myusername:mypassword --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "walletpassphrasechange", "params": ["old one", "new one"] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/
源码剖析
walletpassphrase
对应的函数在文件 rpcserver.h
中被引用。
extern UniValue walletpassphrasechange(const UniValue& params, bool fHelp);
实现在文件 rpcwallet.cpp
中。
UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp)) // 1. 确保钱包可用
return NullUniValue;
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
throw runtime_error(
"walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
"\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
"\nArguments:\n"
"1. \"oldpassphrase\" (string) The current passphrase\n"
"2. \"newpassphrase\" (string) The new passphrase\n"
"\nExamples:\n"
+ HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
+ HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
); // 2. 帮助内容
LOCK2(cs_main, pwalletMain->cs_wallet);
if (fHelp)
return true;
if (!pwalletMain->IsCrypted())
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
// TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
// Alternately, find a way to make params[0] mlock()'d to begin with.
SecureString strOldWalletPass;
strOldWalletPass.reserve(100);
strOldWalletPass = params[0].get_str().c_str();
SecureString strNewWalletPass;
strNewWalletPass.reserve(100);
strNewWalletPass = params[1].get_str().c_str();
if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
throw runtime_error(
"walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
"Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) // 3. 更改钱包密码
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
return NullUniValue;
}
1. 确保钱包可用
参考比特币 RPC 命令「fundrawtransaction」1. 确保钱包可用。
2. 帮助内容
参考比特币 RPC 命令「getbestblockhash」1. 帮助内容。
3. 更改钱包密码
更改钱包密码函数 pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)
定义在文件 wallet.cpp
中。
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
{
bool fWasLocked = IsLocked(); // 获取当前钱包加密状态作为以前加密状态
{
LOCK(cs_wallet); // 钱包上锁
Lock(); // 锁定(加密)钱包
CCrypter crypter;
CKeyingMaterial vMasterKey;
BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys) // 遍历主密钥映射列表
{
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) // 从旧密码设置密钥
return false;
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) // 解密
return false;
if (CCryptoKeyStore::Unlock(vMasterKey)) // 解锁
{
int64_t nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod); // 使用新密码获取密钥
pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))); // 计算迭代计数
nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod); // 第 2 次设置
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2; // 重新计算迭代计数
if (pMasterKey.second.nDeriveIterations < 25000) // 迭代计数最小 25000
pMasterKey.second.nDeriveIterations = 25000;
LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) // 第 3 次设置
return false;
if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey)) // 加密
return false;
CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second); // 把新密钥写入钱包数据库
if (fWasLocked) // 若密码改变前未加密状态
Lock(); // 锁定(加密)
return true;
}
}
}
return false;
}