rpc: add coinbase_tx field to getblock #34512

pull Sjors wants to merge 1 commits into bitcoin:master from Sjors:2026/02/getblockfields changing 3 files +61 −0
  1. Sjors commented at 11:54 am on February 5, 2026: member

    This adds a coinbase_tx field to the getblock RPC result, starting at verbosity level 1. It contains only fields guaranteed to be small, i.e. not the outputs.

    Initial motivation for this was to more efficiently scan for BIP54 compliance. Without this change, it requires verbosity level 2 to get the coinbase, which makes such scan very slow. See https://github.com/bitcoin-inquisition/bitcoin/pull/99#issuecomment-3852370506.

    Adding these fields should be useful in general though and hardly makes the verbosity 1 result longer.

     0bitcoin rpc help getblock
     1
     2getblock "blockhash" ( verbosity )
     3
     4If verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.
     5If verbosity is 1, returns an Object with information about block <hash>.
     6If verbosity is 2, returns an Object with information about block <hash> and information about each transaction.
     7...
     8Result (for verbosity = 1):
     9{                                 (json object)
    10  "hash" : "hex",                 (string) the block hash (same as provided)
    11  "confirmations" : n,            (numeric) The number of confirmations, or -1 if the block is not on the main chain
    12  "size" : n,                     (numeric) The block size
    13  "strippedsize" : n,             (numeric) The block size excluding witness data
    14  "weight" : n,                   (numeric) The block weight as defined in BIP 141
    15  "coinbase_tx" : {               (json object) Coinbase transaction metadata
    16    "version" : n,                (numeric) The coinbase transaction version
    17    "locktime" : n,               (numeric) The coinbase transaction's locktime (nLockTime)
    18    "sequence" : n,               (numeric) The coinbase input's sequence number (nSequence)
    19    "coinbase" : "hex",         (string) The coinbase input's script
    20    "witness" : "hex"             (string, optional) The coinbase input's first (and only) witness stack element, if present
    21  },
    22  "height" : n,                   (numeric) The block height or index
    23  "version" : n,                  (numeric) The block version
    24...
    
    0bitcoin rpc getblock 000000000000000000013c986f9aebe800a78454c835ccd07ecae2650bfad3f6 1
    
     0{
     1  "hash": "000000000000000000013c986f9aebe800a78454c835ccd07ecae2650bfad3f6",
     2  "confirmations": 2,
     3  "height": 935113,
     4  "version": 561807360,
     5  "...": "...",
     6  "weight": 3993624,
     7  "coinbase_tx": {
     8    "version": 2,
     9    "locktime": 0,
    10    "sequence": 4294967295,
    11    "coinbase": "03c9440e04307c84692f466f756e6472792055534120506f6f6c202364726f70676f6c642ffabe6d6d9a8624235259d3680c972b0dd42fa3fe1c45c5e5ae5a96fe10c182bda17080e70100000000000000184b17d3f138020000000000",
    12    "witness": "0000000000000000000000000000000000000000000000000000000000000000"
    13  },
    14  "tx": [
    15    "70eb053340c7978c5aa1b34d75e1ba9f9d1879c09896317f306f30c243536b62",
    16    "5bcf8ed2900cb70721e808b8977898e47f2c9001fcee83c3ccd29e51c7775dcd",
    17    "3f1991771aef846d7bb379d2931cccc04e8421a630ec9f52d22449d028d2e7f4",
    18    "..."
    19  ]
    20}
    
  2. DrahtBot added the label RPC/REST/ZMQ on Feb 5, 2026
  3. DrahtBot commented at 11:54 am on February 5, 2026: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK ajtowns, darosior
    Concept ACK 0xB10C

    If your review is incorrectly listed, please copy-paste <!–meta-tag:bot-skip–> into the comment that the bot should ignore.

  4. Sjors commented at 11:55 am on February 5, 2026: member
  5. in src/rpc/blockchain.cpp:198 in 07d5dcdcf5 outdated
    193+    coinbase_tx_obj.pushKV("is_final", vin_0.nSequence == CTxIn::SEQUENCE_FINAL);
    194+    coinbase_tx_obj.pushKV("script_sig", HexStr(vin_0.scriptSig));
    195+    const auto& witness_stack{vin_0.scriptWitness.stack};
    196+    if (!witness_stack.empty()) {
    197+        CHECK_NONFATAL(witness_stack.size() == 1);
    198+        coinbase_tx_obj.pushKV("witness", HexStr(witness_stack[0]));
    


    Sjors commented at 11:58 am on February 5, 2026:
    Fun fact: block 485919 was the first to use a non-default coinbase transaction witness ([P2Pool][P2Pool][P2Pool][P2Pool]).
  6. in src/rpc/blockchain.cpp:193 in 07d5dcdcf5
    188+    const CTxIn& vin_0{coinbase_tx.vin[0]};
    189+    UniValue coinbase_tx_obj(UniValue::VOBJ);
    190+    coinbase_tx_obj.pushKV("version", coinbase_tx.version);
    191+    coinbase_tx_obj.pushKV("locktime", (int64_t)coinbase_tx.nLockTime);
    192+    coinbase_tx_obj.pushKV("sequence", (int64_t)vin_0.nSequence);
    193+    coinbase_tx_obj.pushKV("is_final", vin_0.nSequence == CTxIn::SEQUENCE_FINAL);
    


    Sjors commented at 12:02 pm on February 5, 2026:

    This is redunandant with sequence, but convenient in light of checking for BIP54 compliance.

    analyzepsbt has this field as well, fwiw.


    Sjors commented at 2:00 pm on February 9, 2026:
    (dropped, since it’s trivial for a user to check a specific value)
  7. in src/rpc/blockchain.cpp:192 in 07d5dcdcf5
    187+    CHECK_NONFATAL(!coinbase_tx.vin.empty());
    188+    const CTxIn& vin_0{coinbase_tx.vin[0]};
    189+    UniValue coinbase_tx_obj(UniValue::VOBJ);
    190+    coinbase_tx_obj.pushKV("version", coinbase_tx.version);
    191+    coinbase_tx_obj.pushKV("locktime", (int64_t)coinbase_tx.nLockTime);
    192+    coinbase_tx_obj.pushKV("sequence", (int64_t)vin_0.nSequence);
    


    maflcko commented at 12:10 pm on February 5, 2026:
    please no c-style casts. Also they are wrong and confusing? Why are you casting an unsigned to signed?

    Sjors commented at 12:18 pm on February 5, 2026:
    I lazily copied it from TxToUniv. I could add a commit that refactors that one as well.

    maflcko commented at 12:28 pm on February 6, 2026:

    I lazily copied it from TxToUniv. I could add a commit that refactors that one as well.

    I had the impression that I removed all of them, but apparently I used the wrong regex in git grep --extended-regexp back then.

    Fixed in https://github.com/bitcoin/bitcoin/pull/34524


    Sjors commented at 2:00 pm on February 9, 2026:
    I dropped the cast.
  8. 0xB10C commented at 12:31 pm on February 5, 2026: contributor

    Concept ACK. Something like this would have been useful when looking at coinbase scripts_sigs for e.g. pool identification. I usually fetch the whole block for this.

    Having the coinbase outputs is usually helpful. If adding these to the coinbase_tx output makes it to big, how about having the serialized coinbase in there as hex?

    The mainnet-observer project shows some stats on blocks where the coinbase locktime is set (https://mainnet.observer/charts/transactions-coinbase-locktime/) and where it matches BIP-54 (none yet, https://mainnet.observer/charts/transactions-coinbase-locktime-bip54/). Since the tool needs the full block with all prevouts anyway (getblock verbosity 3), this won’t be helpful there though.

  9. in src/rpc/blockchain.cpp:212 in 07d5dcdcf5 outdated
    207     result.pushKV("strippedsize", ::GetSerializeSize(TX_NO_WITNESS(block)));
    208     result.pushKV("size", ::GetSerializeSize(TX_WITH_WITNESS(block)));
    209     result.pushKV("weight", ::GetBlockWeight(block));
    210+
    211+    CHECK_NONFATAL(!block.vtx.empty());
    212+    result.pushKV("coinbase_tx", coinbaseTxToJSON(*block.vtx[0]));
    


    0xB10C commented at 12:32 pm on February 5, 2026:

    nit: could be just coinbase instead of coinbase_tx?

    0    result.pushKV("coinbase", coinbaseTxToJSON(*block.vtx[0]));
    

    Sjors commented at 12:50 pm on February 5, 2026:
    The coinbase is the scriptSig of the coinbase transaction. And in src/ipc/capnp/mining.capnp we also use CoinbaseTx.
  10. Sjors commented at 12:52 pm on February 5, 2026: member

    If adding these to the coinbase_tx output makes it too big, how about having the serialized coinbase in there as hex?

    I don’t think it does, because it’s dwarfed by the transaction id list. Note that coinbase_tx intentionally doesn’t include the outputs, because there could be thousands. For the same reason we should avoid hex because it could be 4 MB.

  11. in src/rpc/blockchain.cpp:791 in 07d5dcdcf5
    782@@ -760,6 +783,15 @@ static RPCHelpMan getblock()
    783                     {RPCResult::Type::NUM, "size", "The block size"},
    784                     {RPCResult::Type::NUM, "strippedsize", "The block size excluding witness data"},
    785                     {RPCResult::Type::NUM, "weight", "The block weight as defined in BIP 141"},
    786+                    {RPCResult::Type::OBJ, "coinbase_tx", "Coinbase transaction metadata",
    787+                    {
    788+                        {RPCResult::Type::NUM, "version", "The coinbase transaction version"},
    789+                        {RPCResult::Type::NUM, "locktime", "The coinbase transaction's locktime (nLockTime)"},
    790+                        {RPCResult::Type::NUM, "sequence", "The coinbase input's sequence number (nSequence)"},
    791+                        {RPCResult::Type::BOOL, "is_final", "Whether the coinbase input's nSequence equals 0xffffffff (SEQUENCE_FINAL)"},
    


    luke-jr commented at 4:39 pm on February 5, 2026:
    Seems redundant?

    Sjors commented at 11:45 am on February 6, 2026:
    It is, let’s discuss in #34512 (review)

    Sjors commented at 2:00 pm on February 9, 2026:
    I dropped it.
  12. in src/rpc/blockchain.cpp:792 in 07d5dcdcf5
    787+                    {
    788+                        {RPCResult::Type::NUM, "version", "The coinbase transaction version"},
    789+                        {RPCResult::Type::NUM, "locktime", "The coinbase transaction's locktime (nLockTime)"},
    790+                        {RPCResult::Type::NUM, "sequence", "The coinbase input's sequence number (nSequence)"},
    791+                        {RPCResult::Type::BOOL, "is_final", "Whether the coinbase input's nSequence equals 0xffffffff (SEQUENCE_FINAL)"},
    792+                        {RPCResult::Type::STR_HEX, "script_sig", "The coinbase input's scriptSig"},
    


    luke-jr commented at 4:40 pm on February 5, 2026:
    The generation tx has a coinbase instead of a scriptSig, so this field name is especially confusing. It literally is the coinbase…

    Sjors commented at 11:45 am on February 6, 2026:
    I could rename this to coinbase.

    darosior commented at 4:56 pm on February 6, 2026:
    @luke-jr i’m curious where this understanding of the coinbase transaction’s scriptSig as the “coinbase” comes from. I’ve checked early versions of the code and all mentions of coinbase i can find are used to (loosely) refer to the coinbase transaction, not its scriptSig in particular. Even without previous mention i see how the “base of the coin” could be the coinbase transaction’s input, but i’m not sure to understand why it would be the scriptSig in particular. @Sjors i think renaming this field to coinbase would be confusing. I don’t have a great suggestion, maybe input_script?

    darosior commented at 5:08 pm on February 6, 2026:
    Looking more into this i figured maybe we had some existing fields in the RPC interface named "coinbase" and referring specifically to the coinbase transaction’s scriptSig. Turns out we do, but we also use the very same name to refer to the value of the subsidy and for a boolean indicating whether a transaction is a coinbase transaction…

    Sjors commented at 2:20 pm on February 9, 2026:
    For now I switched to “coinbase” for consistency with existing methods.

    darosior commented at 2:39 pm on February 9, 2026:
    Sorry to nit on a field name, but i don’t think “coinbase” is consistent and i think it is quite confusing. I think scriptSig is less confusing as it refers to the technical transaction field, whether we nickname it coinbase or not.

    Sjors commented at 6:02 pm on February 9, 2026:

    don’t think “coinbase” is consistent

    It’s literally what TxToUniv does:

    0if (tx.IsCoinBase()) {
    1    in.pushKV("coinbase", HexStr(txin.scriptSig));
    2} else {
    3    ...
    4    UniValue o(UniValue::VOBJ);
    5    o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
    6    o.pushKV("hex", HexStr(txin.scriptSig));
    7    in.pushKV("scriptSig", std::move(o));
    8}
    

    And this is rendered by getblock at verbosity 2 and up.

    I think scriptSig is less confusing as it refers to the technical transaction field

    I tend to agree.


    darosior commented at 7:29 pm on February 9, 2026:
    My previous comments explained how we are already being inconsistent. Anyways, i don’t mean to hold this off any longer, debating the name of this RPC response field is a pretty low value use of our time. I withdraw my suggestion, feel free to close the thread.
  13. luke-jr changes_requested
  14. Sjors force-pushed on Feb 9, 2026
  15. Sjors commented at 2:19 pm on February 9, 2026: member

    I dropped is_final and the unnecessary int64_t casts.

    In DecodeTxDoc we use “coinbase” instead of “scriptSig” in the coinbase transaction, so I switched to that convention. But see #34512 (review)

  16. Sjors force-pushed on Feb 9, 2026
  17. rpc: add coinbase_tx field to getblock
    This adds a "coinbase_tx" field to the getblock RPC result, starting
    at verbosity level 1. It contains only fields guaranteed to be small,
    i.e. not the outputs.
    09cbb598ae
  18. Sjors force-pushed on Feb 9, 2026
  19. DrahtBot added the label CI failed on Feb 9, 2026
  20. in doc/release-notes-34512.md:8 in 09cbb598ae
    0@@ -0,0 +1,8 @@
    1+Updated RPCs
    2+------------
    3+
    4+- The `getblock` RPC now returns a `coinbase_tx` object at verbosity levels 1, 2,
    5+  and 3. It contains `version`, `locktime`, `sequence`, `coinbase` and
    6+  `witness`. This allows for efficiently querying coinbase
    7+  transaction properties without fetching the full transaction data at
    8+  verbosity 2+. (#xxxxx)
    


    ajtowns commented at 11:53 pm on February 9, 2026:
    The PR number is in the release-notes file name…

    Sjors commented at 9:17 am on February 10, 2026:
    I renamed the file but forgot to rename the PR number. Will fix if I need to touch anything else.
  21. ajtowns commented at 11:57 pm on February 9, 2026: contributor
    utACK 09cbb598aefcd47bd64a1fd3b6adf9ce4d61b4ce – at first glance the CI failures seem to be due to github exploding earlier today
  22. DrahtBot requested review from 0xB10C on Feb 9, 2026
  23. alswaryaldwly-wq commented at 0:03 am on February 10, 2026: none

    Please contact me via WhatsApp +967782452027

    في الثلاثاء، ١٠ فبراير ٢٠٢٦, ٣:٠٢ ص Anthony Towns @.***> كتب:

    ajtowns left a comment (bitcoin/bitcoin#34512) https://github.com/bitcoin/bitcoin/pull/34512#issuecomment-3874523429

    utACK 09cbb59 https://github.com/bitcoin/bitcoin/commit/09cbb598aefcd47bd64a1fd3b6adf9ce4d61b4ce – at first glance the CI failures seem to be due to github exploding earlier today

    — Reply to this email directly, view it on GitHub https://github.com/bitcoin/bitcoin/pull/34512#issuecomment-3874523429, or unsubscribe https://github.com/notifications/unsubscribe-auth/B3ABZXJQB4UCN56QZMI7U3T4LENZ7AVCNFSM6AAAAACUCVP4QGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTQNZUGUZDGNBSHE . You are receiving this because you are subscribed to this thread.Message ID: @.***>

  24. DrahtBot removed the label CI failed on Feb 10, 2026
  25. in src/rpc/blockchain.cpp:193 in 09cbb598ae
    188+    const CTxIn& vin_0{coinbase_tx.vin[0]};
    189+    UniValue coinbase_tx_obj(UniValue::VOBJ);
    190+    coinbase_tx_obj.pushKV("version", coinbase_tx.version);
    191+    coinbase_tx_obj.pushKV("locktime", coinbase_tx.nLockTime);
    192+    coinbase_tx_obj.pushKV("sequence", vin_0.nSequence);
    193+    coinbase_tx_obj.pushKV("coinbase", HexStr(vin_0.scriptSig));
    


    darosior commented at 7:22 pm on February 13, 2026:
    I still think it is unnecessarily confusing to refer to this field by its obscure, undocumented, nickname rather by its technical name like for the other fields included in the output. But hey, not a blocker i guess.

    Sjors commented at 8:28 am on February 14, 2026:

    Since you brought it up again, the getblock RPC docs for v31 says:

     0getblock "blockhash" ( verbosity )
     1
     2...
     3
     4Arguments:
     51. blockhash    (string, required) The block hash
     62. verbosity    (numeric, optional, default=1) 0 for hex-encoded data, 1 for a JSON object, 2 for JSON object with transaction data, and 3 for JSON object with transaction data including prevout information for inputs
     7
     8Result (for verbosity = 0):
     9"hex"    (string) A string that is serialized, hex-encoded data for block 'hash'
    10
    11Result (for verbosity = 1):
    12{                                 (json object)
    13  "hash" : "hex",                 (string) the block hash (same as provided)
    14...
    15}
    16
    17Result (for verbosity = 2):
    18{                   (json object)
    19  ...,              Same output as verbosity = 1
    20  "tx" : [          (json array)
    21    {               (json object)
    22      ...,          The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 "tx" result
    23    },
    24    ...
    25  ]
    26}
    

    So the doc for verbosity level 2 refers to getrawtransaction for how transactions are serialized, which says:

     0Result (if verbosity is set to 1):
     1{                                    (json object)
     2...
     3  "time" : n,                        (numeric, optional) Same as "blocktime"
     4...
     5  "version" : n,                     (numeric) The version
     6  "locktime" : xxx,                  (numeric) The lock time
     7  "vin" : [                          (json array)
     8    {                                (json object)
     9      "coinbase" : "hex",            (string, optional) The coinbase value (only if coinbase transaction)
    10...
    11      "scriptSig" : {                (json object, optional) The script (if not coinbase transaction)
    12        "asm" : "str",               (string) Disassembly of the signature script
    13        "hex" : "hex"                (string) The raw signature script bytes, hex-encoded
    14      },
    15...
    16      "sequence" : n                 (numeric) The script sequence number
    17    },
    

    So although I don’t have a very strong preference here, it makese sense to me to use the same name for the same thing in the same RPC call.

    You mentioned above: #34512 (review)

    but we also use the very same name to refer to the value of the subsidy and for a boolean indicating whether a transaction is a coinbase transaction

    It’s true that the term is overloaded. If https://github.com/murchandamus/bips/pull/1 actually picked an “official” name for the thing (and it got merged), my preference would switch to using it. That would overcome my above objection of having two different names for the same field in the same RPC call (which we have occasionally done IIRC).


    ajtowns commented at 10:14 pm on February 14, 2026:
    “coinbase” has been how this has been summarised since getrawtransaction was introduced in #1456 (looks to me mostly as a way of avoiding reporting irrelevant data for coinbase vin[0]). No discussion in the PR that I can see, maybe there was some on IRC or similar.
  26. darosior approved
  27. darosior commented at 7:22 pm on February 13, 2026: member
    utACK 09cbb598aefcd47bd64a1fd3b6adf9ce4d61b4ce

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-02-17 06:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me