rpc: add wtxid lookup support to getrawtransaction #34829

pull chriszeng1010 wants to merge 2 commits into bitcoin:master from chriszeng1010:rpc-getrawtransaction-wtxid changing 7 files +89 −5
  1. chriszeng1010 commented at 6:43 am on March 16, 2026: none

    getrawtransaction() now accepts a wtxid in addition to a txid. If the initial txid lookup fails, the hash is retried as a wtxid against the mempool. Wtxid lookup is mempool-only since the txindex indexes by txid.

    Use case

    If you have a wtxid and want to look up the transaction, there’s currently no way to do it without scanning the whole mempool. To find a transaction by wtxid, you’d have to call getrawmempool true and iterate through every result to match it. There’s no direct lookup.

    This adds wtxid lookup support to getrawtransaction.

    Closes #34013

  2. DrahtBot added the label RPC/REST/ZMQ on Mar 16, 2026
  3. DrahtBot commented at 6:43 am on March 16, 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. A summary of reviews will appear here.

  4. chriszeng1010 force-pushed on Mar 16, 2026
  5. DrahtBot added the label CI failed on Mar 16, 2026
  6. in src/rpc/rawtransaction.cpp:231 in c5f2fec5c3 outdated
    227@@ -228,7 +228,7 @@ static RPCHelpMan getrawtransaction()
    228                 "If verbosity is 1, returns a JSON Object with information about the transaction.\n"
    229                 "If verbosity is 2, returns a JSON Object with information about the transaction, including fee and prevout information.",
    230                 {
    231-                    {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
    232+                    {"txid|wtxid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (txid or wtxid)"},
    


    stickies-v commented at 1:12 pm on March 16, 2026:

    I think stuffing two types into one field makes the RPC worse. Do we have a good rationale to do so, instead of adding wtxid as an additional parameter?

    The main benefit I see is probably that it keeps the positional cli interface simpler, but I’m not sure that tradeoff is worth it, when cli supports named args, and it doesn’t seem like this has bothered human/ad-hoc users so far?


    chriszeng1010 commented at 6:05 pm on March 16, 2026:

    I kept the signature the same to ensure minimal changes where possible for consistency.

    A single parameter is simpler for the caller — they just pass a hash and it resolves. Adding a separate parameter forces the caller to know upfront which type they have.


    chriszeng1010 commented at 4:08 am on March 17, 2026:
    I see the argument for a separate parameter — happy to refactor if you feel strongly about it.
  7. maflcko commented at 1:27 pm on March 16, 2026: member

    The lint CI fails. Also, it would be good to add a use-case to the pull description, so that it is self-contained.

    Wtxid lookup is mempool-only since the txindex indexes by txid.

    I don’t think this is true. blockhash lookup is possible too

  8. chriszeng1010 commented at 4:07 am on March 17, 2026: none

    The lint CI fails. Also, it would be good to add a use-case to the pull description, so that it is self-contained.

    Wtxid lookup is mempool-only since the txindex indexes by txid.

    I don’t think this is true. blockhash lookup is possible too

    Would you prefer I add blockhash support here or is a follow-up PR acceptable?

  9. chriszeng1010 force-pushed on Mar 17, 2026
  10. maflcko commented at 2:29 pm on March 18, 2026: member
  11. chriszeng1010 force-pushed on Mar 19, 2026
  12. luke-jr commented at 1:03 pm on March 19, 2026: member
    Why can’t the peer give you a txid?
  13. Sjors commented at 3:31 pm on March 19, 2026: member
    Maybe it’s better to add an optional (named) boolean argument that specifies whether you’re searching by witness id.
  14. chriszeng1010 commented at 5:30 pm on March 19, 2026: none

    Why can’t the peer give you a txid?

    0const auto inv = peer.m_wtxid_relay ?
    1                     CInv{MSG_WTX, wtxid.ToUint256()} :
    2                     CInv{MSG_TX, txid.ToUint256()};
    

    When a peer supports wtxid relay, it only sends MSG_WTX.

  15. maflcko commented at 7:18 pm on March 19, 2026: member

    This may be a useful feature, but it is clear that this is a low-effort LLM generated pull request, where the author obviously doesn’t understand any of it, so I think this should be closed.

    Then, an issue or pull request can be opened with a properly explained use-case and properly explained rationale.

  16. chriszeng1010 commented at 7:45 pm on March 19, 2026: none

    This may be a useful feature, but it is clear that this is a low-effort LLM generated pull request, where the author obviously doesn’t understand any of it, so I think this should be closed.

    Then, an issue or pull request can be opened with a properly explained use-case and properly explained rationale.

    I appreciate the feedback here. I’m researching the answers to the questions as they come in. This is my first contribution in this area, I’m reworking the PR with the suggested changes. If I’m not showing enough understanding, please be patient and tell me what I’m missing so I can fix it.

  17. maflcko commented at 5:49 am on March 20, 2026: member

    If I’m not showing enough understanding, please be patient and tell me what I’m missing so I can fix it.

    I am happy to answer specific questions, but the burden to understand and explain the pull request is on the author. Seeing every single review comment getting a copy-pasted and erroneous reply from an LLM shows the opposite. If you genuinely want to understand and be able to explain the changes yourself, there is an easy answer: Don’t use an LLM.

  18. Sjors commented at 12:06 pm on March 20, 2026: member

    Another approach could be to keep using this branch yourself in your local setup as you work on / with that wallet. Consider also changing the wallet code, so you can contrast both approaches.

    Then in the mean time try reviewing other RPC related pull requests here, to increase familiarity. Eventually you might find that you don’t need this change at all, or you still want it, and can try again with more confidence in the change.

  19. chriszeng1010 commented at 1:57 am on March 22, 2026: none

    If I’m not showing enough understanding, please be patient and tell me what I’m missing so I can fix it.

    I am happy to answer specific questions, but the burden to understand and explain the pull request is on the author. Seeing every single review comment getting a copy-pasted and erroneous reply from an LLM shows the opposite. If you genuinely want to understand and be able to explain the changes yourself, there is an easy answer: Don’t use an LLM.

    I’m using tools to learn and navigate the code base. But the knowledge is mine and I understood the code that I wrote. Please correct me if I’m saying anything incorrect here and I will dig deeper.

    Txid is the legacy transaction hash while wtxid hashes the transaction along with the witness data. Modern nodes uses Wtxid, while old nodes uses Txid. When a transaction is published to the P2P network, the node sends the Wtxid. This feature would be useful to anyone or any tools that wants to get the transaction data using Wtxid.

    I reproduced the issue on master branch and validated the PR-fix by running the regtest bitcoind node. I verified that every transaction contain both txid and wtxid but the current getrawtransaction only supports txid lookup, and saw error returned when I passed in a wtxid. Once the fix was applied, the same call using Wtxid returns the transaction data.

    I’m also working on addressing the design feedback from @Sjors and @stickies-v.

  20. optout21 commented at 9:56 am on March 23, 2026: contributor

    Txid is the legacy transaction hash while wtxid hashes the transaction along with the witness data. …

    I think your above comment contains several mis-stated or misunderstood points. E.g.:

    • “Modern nodes uses Wtxid, while old nodes uses Txid” – nodes use both
    • “When a transaction is published to the P2P network, the node sends the Wtxid” – no, they send the TX itself (content, not the ID, that can be derived)

    Such miscommunication makes if quite difficult to argue about the merits of the PR.

  21. DrahtBot commented at 6:17 am on March 25, 2026: contributor
    Could turn into draft while CI is failing?
  22. sipa commented at 11:32 am on March 25, 2026: member

    "When a transaction is published to the P2P network, the node sends the Wtxid" – no, they send the TX itself (content, not the ID, that can be derived)

    Transaction announcements use the wtxid between nodes that support BIP339, and the txid between older nodes. The full transaction data is only sent if the receiver requests it through a getdata message.

  23. chriszeng1010 commented at 6:48 pm on March 25, 2026: none

    After considering the design suggestions from @Sjors and @stickies-v to implement either a boolean or separate wtxid into a different field completely. I think the original design of having implicit wtxid as fall back is more elegant.

    Adding wtxid as a separate field explicitly adds complexity with no real benefits (wtxid and txid are cryptographically impossible to collide). While and a Boolean field requires -name calling convention otherwise it adds positional awkwardness, for example:

    bitcoin-cli -named getrawtransaction txid=<wtxid> use_wtxid=true requires bitcoin-cli getrawtransaction <wtxid> 0 "" true

    Using the original implicit fallback approach is safe (no possibility of collision). Plus it’s backwards compatible, adds no change to client side, and keeps API simple.

    Please let me know if there are additional suggestions or areas of improvements.

    Thanks.

  24. chriszeng1010 force-pushed on Mar 25, 2026
  25. chriszeng1010 commented at 9:49 pm on March 28, 2026: none

    Gentle ping here.

    The commits are squashed. Could a maintainer help approve the CI workflow? Also happy to continue the design discussion on explicit fall back if necessary.

    Thanks.

  26. DrahtBot removed the label CI failed on Mar 28, 2026
  27. in src/rpc/rawtransaction.cpp:288 in e8364e27e9
    283@@ -284,7 +284,8 @@ static RPCHelpMan getrawtransaction()
    284     const NodeContext& node = EnsureAnyNodeContext(request.context);
    285     ChainstateManager& chainman = EnsureChainman(node);
    286 
    287-    auto txid{Txid::FromUint256(ParseHashV(request.params[0], "parameter 1"))};
    288+    const uint256 hash{ParseHashV(request.params[0], "parameter 1")};
    289+    const Txid txid{Txid::FromUint256(hash)};
    


    Sjors commented at 7:35 am on March 30, 2026:
    e8364e27e987ed312e4c3f492db7e25d6b02dfdd: if your goal is to first try as Txid and then later as Wtxid, then I would defer this cast until you need it for the GetTransaction calls.

    chriszeng1010 commented at 2:51 am on April 1, 2026:
    I will fix this.
  28. in src/rpc/rawtransaction.cpp:317 in e8364e27e9 outdated
    310@@ -310,7 +311,13 @@ static RPCHelpMan getrawtransaction()
    311     }
    312 
    313     uint256 hash_block;
    314-    const CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), txid, chainman.m_blockman, hash_block);
    315+    CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), txid, chainman.m_blockman, hash_block);
    316+    if (!tx && node.mempool && !blockindex) {
    317+        LOCK(node.mempool->cs);
    318+        if (const auto it{node.mempool->GetIter(Wtxid::FromUint256(hash))}) {
    


    Sjors commented at 7:38 am on March 30, 2026:
    e8364e2: the first commit of #34020 introduces a helper that can do this.

    chriszeng1010 commented at 2:19 am on March 31, 2026:
    Got it. Thanks. If you merge it first I will rebase it.

    Sjors commented at 6:50 am on March 31, 2026:
    That might take a while, so I suggest either marking this PR as draft or cherry-picking it.

    chriszeng1010 commented at 2:28 am on April 1, 2026:
    Sure i will cherry pick the commit
  29. in src/rpc/rawtransaction.cpp:315 in e8364e27e9 outdated
    310@@ -310,7 +311,13 @@ static RPCHelpMan getrawtransaction()
    311     }
    312 
    313     uint256 hash_block;
    314-    const CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), txid, chainman.m_blockman, hash_block);
    315+    CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), txid, chainman.m_blockman, hash_block);
    316+    if (!tx && node.mempool && !blockindex) {
    


    Sjors commented at 7:41 am on March 30, 2026:
    e8364e2: IIUC this skips mempool lookup by witness if there’s a block index?

    chriszeng1010 commented at 3:15 am on March 31, 2026:

    Yes initially my understand was that blocks have no knowledge of wtxid, and that every transaction is referenced with a txid. Passing in wtxid and blockhash is incorrect because from user’s perspective they are saying “find this transaction using wtxid from this block”, which should fail.

    After looking deeper, I did see that CTransaction in Blocks can be identified with both ID. So technically we can take the blockhash, get the blockID and iterate through each transaction to match with Wtxid.

    I will fix it.

  30. Sjors commented at 7:47 am on March 30, 2026: member

    I still prefer either a boolean or whole new RPC method. The caller knows whether it’s a txid or wtxid so it shouldn’t have a problem setting the correct boolean.

    with no real benefits (wtxid and txid are cryptographically impossible to collide)

    I haven’t measured this, but this potentially slows the RPC call down, because now there’s three lookups: mempool by txid, mempool by wtxid and then the index.

    If we ever add a -wtxindex that adds a fourth lookup, and in the worst case those two index lookups use the disk.

    I would also still like to know which application actually needs this, though I understand how a theoretical application would use this.

  31. chriszeng1010 force-pushed on Apr 1, 2026
  32. mempool: add lookup by witness hash
    Add a simple test for both the Txid and Wtxid variants of GetTransaction().
    9c590d86b7
  33. rpc: add wtxid lookup support to getrawtransaction 0b5504d085
  34. chriszeng1010 force-pushed on Apr 1, 2026
  35. chriszeng1010 commented at 4:10 am on April 1, 2026: none

    I still prefer either a boolean or whole new RPC method. The caller knows whether it’s a txid or wtxid so it shouldn’t have a problem setting the correct boolean.

    with no real benefits (wtxid and txid are cryptographically impossible to collide)

    I haven’t measured this, but this potentially slows the RPC call down, because now there’s three lookups: mempool by txid, mempool by wtxid and then the index.

    If we ever add a -wtxindex that adds a fourth lookup, and in the worst case those two index lookups use the disk.

    Adding a Boolean field adds positional awkwardness as mentioned above, for example:

    bitcoin-cli -named getrawtransaction txid=<wtxid> use_wtxid=true requires bitcoin-cli getrawtransaction <wtxid> 0 "" true

    I think adding a new RPC call for getrawtransactionbywtxid and abstract commonality into a helper function is a more elegant approach.


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-04-12 03:13 UTC

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