$ bitcoin-cli help walletpassphrase
walletpassphrase "passphrase" timeout

把钱包解密密钥存储在内存中的“超时”秒数。
在执行与私钥相关的交易前需要这样,如发送比特币

参数:
1. "passphrase"(字符串,必备)钱包密码
2. timeout     (整型,必备)保留解密密钥的以秒为单位的时间。

注:
在钱包已解锁的情况下发处 walletpassphrase 命令将设置一个覆盖旧解锁时间的新解锁时间。

例子:

解锁钱包 60 秒
> bitcoin-cli walletpassphrase "my pass phrase" 60

再次锁定钱包(60 秒前)
> bitcoin-cli walletlock

作为 json rpc 调用
> curl --user myusername:mypassword --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "walletpassphrase", "params": ["my pass phrase", 60] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/

源码剖析

walletpassphrase 对应的函数在文件 rpcserver.h 中被引用。

extern UniValue walletpassphrase(const UniValue& params, bool fHelp);

实现在文件 rpcwallet.cpp 中。

UniValue walletpassphrase(const UniValue& params, bool fHelp)
{
    if (!EnsureWalletIsAvailable(fHelp)) // 1. 确保钱包可用
        return NullUniValue;
    
    if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
        throw runtime_error(
            "walletpassphrase \"passphrase\" timeout\n"
            "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
            "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
            "\nArguments:\n"
            "1. \"passphrase\"     (string, required) The wallet passphrase\n"
            "2. timeout            (numeric, required) The time to keep the decryption key in seconds.\n"
            "\nNote:\n"
            "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
            "time that overrides the old one.\n"
            "\nExamples:\n"
            "\nunlock the wallet for 60 seconds\n"
            + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
            "\nLock the wallet again (before 60 seconds)\n"
            + HelpExampleCli("walletlock", "") +
            "\nAs json rpc call\n"
            + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
        ); // 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 walletpassphrase was called.");

    // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
    SecureString strWalletPass; // 注意 walletpassphrase 存储在 params[0] 中,而不是 mlock()ed
    strWalletPass.reserve(100);
    // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
    // Alternately, find a way to make params[0] mlock()'d to begin with.
    strWalletPass = params[0].get_str().c_str();

    if (strWalletPass.length() > 0)
    {
        if (!pwalletMain->Unlock(strWalletPass))
            throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
    }
    else
        throw runtime_error(
            "walletpassphrase <passphrase> <timeout>\n"
            "Stores the wallet decryption key in memory for <timeout> seconds.");

    pwalletMain->TopUpKeyPool(); // 充满密钥池

    int64_t nSleepTime = params[1].get_int64();
    LOCK(cs_nWalletUnlockTime);
    nWalletUnlockTime = GetTime() + nSleepTime;
    RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime); // 3. 创建锁定钱包线程

    return NullUniValue;
}

1. 确保钱包可用

参考比特币 RPC 命令「fundrawtransaction」1. 确保钱包可用

2. 帮助内容

参考比特币 RPC 命令「getbestblockhash」1. 帮助内容

3. 创建锁定钱包线程

创建线程函数 RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime) 声明在文件 rpcserver.h 中。

/**
 * Run func nSeconds from now.
 * Overrides previous timer <name> (if any).
 */
void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64_t nSeconds);

从现在开始运行函数 nSeconds 秒。 覆盖上一个定时器 <name>(如果有)。

定义在文件 rpcserver.cpp 中。

void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64_t nSeconds)
{
    if (timerInterfaces.empty())
        throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
    deadlineTimers.erase(name); // 擦除指定名字的定时器
    RPCTimerInterface* timerInterface = timerInterfaces.back(); // 取列表中最后一个定时器
    LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
    deadlineTimers.insert(std::make_pair(name, boost::shared_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)))); // 和定时器名字配对,插入到截止时间定时器映射列表中
}

定时器接口列表 timerInterfaces 和定时器映射列表 deadlineTimers 的定义在文件 rpcserver.cpp 中。

/* Timer-creating functions */
static std::vector<RPCTimerInterface*> timerInterfaces; // 定时器创建函数
/* Map of name to timer.
 * @note Can be changed to std::unique_ptr when C++11 */
static std::map<std::string, boost::shared_ptr<RPCTimerBase> > deadlineTimers; // 定时器名字映射。

参考链接