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

Code before:
    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:
            for (const CTransactionRef& tx : block.vtx) {
                txs.push_back(tx->GetHash().GetHex());
            }
            break;

Review comment (suggestion):
Fun fact: block [485919](https://mempool.space/en/block/00000000000000000096cef4bfd159307030923b0111acd39bfb6561b277a375) was the first to use a non-default coinbase transaction witness (`[P2Pool][P2Pool][P2Pool][P2Pool]`).

Code after:
    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) {
                txs.push_back(tx->GetHash().GetHex());
            }
            break;