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

Code before:
    result.pushKV("time", blockindex.nTime);
    result.pushKV("mediantime", blockindex.GetMedianTimePast());
    result.pushKV("nonce", blockindex.nNonce);
    result.pushKV("bits", strprintf("%08x", blockindex.nBits));
    result.pushKV("target", GetTarget(blockindex, pow_limit).GetHex());
    result.pushKV("difficulty", GetDifficulty(blockindex));
    result.pushKV("chainwork", blockindex.nChainWork.GetHex());
    result.pushKV("nTx", blockindex.nTx);

    if (blockindex.pprev)
        result.pushKV("previousblockhash", blockindex.pprev->GetBlockHash().GetHex());
    if (pnext)
        result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
    return result;
}

/** Serialize coinbase transaction metadata */
UniValue coinbaseTxToJSON(const CTransaction& coinbase_tx)
{
    CHECK_NONFATAL(!coinbase_tx.vin.empty());
    const CTxIn& vin_0{coinbase_tx.vin[0]};
    UniValue coinbase_tx_obj(UniValue::VOBJ);
    coinbase_tx_obj.pushKV("version", coinbase_tx.version);
    coinbase_tx_obj.pushKV("locktime", (int64_t)coinbase_tx.nLockTime);
    coinbase_tx_obj.pushKV("sequence", (int64_t)vin_0.nSequence);
    coinbase_tx_obj.pushKV("is_final", vin_0.nSequence == CTxIn::SEQUENCE_FINAL);
    coinbase_tx_obj.pushKV("script_sig", HexStr(vin_0.scriptSig));
    const auto& witness_stack{vin_0.scriptWitness.stack};
    if (!witness_stack.empty()) {
        CHECK_NONFATAL(witness_stack.size() == 1);
        coinbase_tx_obj.pushKV("witness", HexStr(witness_stack[0]));
    }
    return coinbase_tx_obj;
}

UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIndex& tip, const CBlockIndex& blockindex, TxVerbosity verbosity, const uint256 pow_limit)
{
    UniValue result = blockheaderToJSON(tip, blockindex, pow_limit);

    result.pushKV("strippedsize", ::GetSerializeSize(TX_NO_WITNESS(block)));
    result.pushKV("size", ::GetSerializeSize(TX_WITH_WITNESS(block)));
    result.pushKV("weight", ::GetBlockWeight(block));

    CHECK_NONFATAL(!block.vtx.empty());
    result.pushKV("coinbase_tx", coinbaseTxToJSON(*block.vtx[0]));

    UniValue txs(UniValue::VARR);
    txs.reserve(block.vtx.size());

    switch (verbosity) {
        case TxVerbosity::SHOW_TXID:

Review comment (suggestion):
This is redunandant with `sequence`, but convenient in light of checking for BIP54 compliance.

`analyzepsbt` has this field as well, fwiw.

Code after:
    result.pushKV("time", blockindex.nTime);
    result.pushKV("mediantime", blockindex.GetMedianTimePast());
    result.pushKV("nonce", blockindex.nNonce);
    result.pushKV("bits", strprintf("%08x", blockindex.nBits));
    result.pushKV("target", GetTarget(blockindex, pow_limit).GetHex());
    result.pushKV("difficulty", GetDifficulty(blockindex));
    result.pushKV("chainwork", blockindex.nChainWork.GetHex());
    result.pushKV("nTx", blockindex.nTx);

    if (blockindex.pprev)
        result.pushKV("previousblockhash", blockindex.pprev->GetBlockHash().GetHex());
    if (pnext)
        result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
    return result;
}

/** Serialize coinbase transaction metadata */
UniValue coinbaseTxToJSON(const CTransaction& coinbase_tx)
{
    CHECK_NONFATAL(!coinbase_tx.vin.empty());
    const CTxIn& vin_0{coinbase_tx.vin[0]};
    UniValue coinbase_tx_obj(UniValue::VOBJ);
    coinbase_tx_obj.pushKV("version", coinbase_tx.version);
    coinbase_tx_obj.pushKV("locktime", coinbase_tx.nLockTime);
    coinbase_tx_obj.pushKV("sequence", vin_0.nSequence);
    coinbase_tx_obj.pushKV("coinbase", HexStr(vin_0.scriptSig));
    const auto& witness_stack{vin_0.scriptWitness.stack};
    if (!witness_stack.empty()) {
        CHECK_NONFATAL(witness_stack.size() == 1);
        coinbase_tx_obj.pushKV("witness", HexStr(witness_stack[0]));
    }
    return coinbase_tx_obj;
}

UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIndex& tip, const CBlockIndex& blockindex, TxVerbosity verbosity, const uint256 pow_limit)
{
    UniValue result = blockheaderToJSON(tip, blockindex, pow_limit);

    result.pushKV("strippedsize", ::GetSerializeSize(TX_NO_WITNESS(block)));
    result.pushKV("size", ::GetSerializeSize(TX_WITH_WITNESS(block)));
    result.pushKV("weight", ::GetBlockWeight(block));

    CHECK_NONFATAL(!block.vtx.empty());
    result.pushKV("coinbase_tx", coinbaseTxToJSON(*block.vtx[0]));

    UniValue txs(UniValue::VARR);
    txs.reserve(block.vtx.size());

    switch (verbosity) {
        case TxVerbosity::SHOW_TXID:
            for (const CTransactionRef& tx : block.vtx) {