Repository: bitcoin/bitcoin
File: src/rpc/blockchain.cpp (C++)

Code before:
                        {RPCResult::Type::NUM, "height", "Block height"},
                    }},
                RPCExamples{
                    HelpExampleCli("waitfornewblock", "1000")
            + HelpExampleRpc("waitfornewblock", "1000")
                },
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
    int timeout = 0;
    if (!request.params[0].isNull())
        timeout = request.params[0].getInt<int>();
    if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");

    NodeContext& node = EnsureAnyNodeContext(request.context);
    Mining& miner = EnsureMining(node);

    // Abort if RPC came out of warmup too early
    BlockRef current_block{CHECK_NONFATAL(miner.getTip()).value()};
    std::optional<BlockRef> block = timeout ? miner.waitTipChanged(current_block.hash, std::chrono::milliseconds(timeout)) :
                                              miner.waitTipChanged(current_block.hash);

    // Return current block upon shutdown
    if (block) current_block = *block;

    UniValue ret(UniValue::VOBJ);
    ret.pushKV("hash", current_block.hash.GetHex());
    ret.pushKV("height", current_block.height);
    return ret;
},
    };
}

static RPCHelpMan waitforblock()
{
    return RPCHelpMan{"waitforblock",
                "\nWaits for a specific new block and returns useful info about it.\n"
                "\nReturns the current block on timeout or exit.\n"
                "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
                {
                    {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Block hash to wait for."},
                    {"timeout", RPCArg::Type::NUM, RPCArg::Default{0}, "Time in milliseconds to wait for a response. 0 indicates no timeout."},
                },
                RPCResult{
                    RPCResult::Type::OBJ, "", "",
                    {
                        {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
                        {RPCResult::Type::NUM, "height", "Block height"},
                    }},
                RPCExamples{
                    HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\" 1000")
            + HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")

Review comment (suggestion):
In commit "rpc: add optional blockhash to waitfornewblock" (0625f26b09084fcbd4daa48b3456f54eff6b22de)

Do we think "Abort if RPC came out of warmup too early." comment is still accurate? I've having trouble understanding what it could mean and I don't think there are cases where this aborted even before this change. Would probably suggest dropping this comment or trying to make it clearer.

Also could replace /** with a normal comment above since /** normally indicates a doxygen comment.

Code after:
                        {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
                        {RPCResult::Type::NUM, "height", "Block height"},
                    }},
                RPCExamples{
                    HelpExampleCli("waitfornewblock", "1000")
            + HelpExampleRpc("waitfornewblock", "1000")
                },
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
    int timeout = 0;
    if (!request.params[0].isNull())
        timeout = request.params[0].getInt<int>();
    if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");

    NodeContext& node = EnsureAnyNodeContext(request.context);
    Mining& miner = EnsureMining(node);

    // If the caller provided a current_tip value, pass it to waitTipChanged().
    //
    // If the caller did not provide a current tip hash, call getTip() to get
    // one and wait for the tip to be different from this value. This mode is
    // less reliable because if the tip changed between waitfornewblock calls,
    // it will need to change a second time before this call returns.
    BlockRef current_block{CHECK_NONFATAL(miner.getTip()).value()};

    uint256 tip_hash{request.params[1].isNull()
        ? current_block.hash
        : ParseHashV(request.params[1], "current_tip")};

    // If the user provided an invalid current_tip then this call immediately
    // returns the current tip.
    std::optional<BlockRef> block = timeout ? miner.waitTipChanged(tip_hash, std::chrono::milliseconds(timeout)) :
                                              miner.waitTipChanged(tip_hash);

    // Return current block upon shutdown
    if (block) current_block = *block;

    UniValue ret(UniValue::VOBJ);
    ret.pushKV("hash", current_block.hash.GetHex());
    ret.pushKV("height", current_block.height);
    return ret;
},
    };
}

static RPCHelpMan waitforblock()
{
    return RPCHelpMan{"waitforblock",
                "\nWaits for a specific new block and returns useful info about it.\n"
                "\nReturns the current block on timeout or exit.\n"
                "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",