rpc: print P2WSH and P2SH redem Script in getrawtransaction and getblock #31252

pull polespinasa wants to merge 3 commits into bitcoin:master from polespinasa:p2wsh_redeem changing 6 files +156 −3
  1. polespinasa commented at 8:39 PM on November 7, 2024: member

    This PR is motivated by #27391. And inspired by a previous PR #8849 that proposed something similar.

    This is an example with a real mainnet transaction (3-5 multisig) and using getrawtransaction 'txid' 2 and getblock. It also affects the endpoint rest/getblock

    Verbosity must be set to 2 or higher if possible.

    $ bitcoin-cli getrawtransaction 44f5ab666cb9dccef69120fe5b51757a647c1f96882931a9faa0b2b5781ddfd2 2 000000000000000000018fa64b5e32335f7d3ac14b9e5553db20f2909c902c34
    {
      "in_active_chain": true,
      "txid": "44f5ab666cb9dccef69120fe5b51757a647c1f96882931a9faa0b2b5781ddfd2",
      "hash": "53836d2a4fb1e14356eac69fe1dad8be5dfd9a1b8101bc8aeb04ea2a320aa398",
      "version": 1,
      "size": 382,
      "vsize": 192,
      "weight": 766,
      "locktime": 0,
      "vin": [
        {
          "txid": "d15236206fbe06d6f38505656a2006a9a5a1ddf189a2647750091fd218d59581",
          "vout": 2,
          "scriptSig": {
            "asm": "",
            "hex": ""
          },
          "txinwitness": [
            "",
            "304402204d91eb67d798d071278ea0570973f3488d60c3ec98a611856f6a813b2e35df3202200bb36403ebd2dcc96b236efaf07db4f1da26b1031fc854548634ff44a340dc6601",
            "3044022046abaa75082c2d1cdef57f8ef59a0046729220eabe2c2a229d1d592b89ccf1b0022028954703f13d836b1b77acd1eb72639a7a918d756fdd3ddef1d42a28567403ed01",
            "522102f69779f4bb466a8c0aa7d6bf2a2dde34e44bae29d5186ee0c3bed4d903d57fa7210333c337637453164d5fd0dc31787a614a74d2acca5c08710937b9b831bd41b11f2103be7c86e40ad380b33f9abd653c6d04b95b818abd5653b63402678fcc45a017e753ae"
          ],
          "witnessScript": {
            "asm": "2 02f69779f4bb466a8c0aa7d6bf2a2dde34e44bae29d5186ee0c3bed4d903d57fa7 0333c337637453164d5fd0dc31787a614a74d2acca5c08710937b9b831bd41b11f 03be7c86e40ad380b33f9abd653c6d04b95b818abd5653b63402678fcc45a017e7 3 OP_CHECKMULTISIG",
            "desc": "multi(2,02f69779f4bb466a8c0aa7d6bf2a2dde34e44bae29d5186ee0c3bed4d903d57fa7,0333c337637453164d5fd0dc31787a614a74d2acca5c08710937b9b831bd41b11f,03be7c86e40ad380b33f9abd653c6d04b95b818abd5653b63402678fcc45a017e7)#sll5t8hh",
            "type": "multisig"
          },
          "prevout": {
            ... bla bla bla prev output info ...
            }
          },
          "sequence": 4294967293
        }
      ],
      "vout": [ ... bla bla bla outputs ...  ],
      "fee": 0.00000594,
      "hex": "010000000001018195d518d21f09507764a289f1dda1a5a906206a650585f3d606be6f203652d10200000000fdffffff025b730500000000001976a914381d46badae879d1c6037a03da52074e3914812c88ac38088000000000002200205ab691555ede8432ed7765585edb1c9b285532daf639e3e5ccd4843ff3b04cdf040047304402204d91eb67d798d071278ea0570973f3488d60c3ec98a611856f6a813b2e35df3202200bb36403ebd2dcc96b236efaf07db4f1da26b1031fc854548634ff44a340dc6601473044022046abaa75082c2d1cdef57f8ef59a0046729220eabe2c2a229d1d592b89ccf1b0022028954703f13d836b1b77acd1eb72639a7a918d756fdd3ddef1d42a28567403ed0169522102f69779f4bb466a8c0aa7d6bf2a2dde34e44bae29d5186ee0c3bed4d903d57fa7210333c337637453164d5fd0dc31787a614a74d2acca5c08710937b9b831bd41b11f2103be7c86e40ad380b33f9abd653c6d04b95b818abd5653b63402678fcc45a017e753ae00000000",
      "blockhash": "000000000000000000018fa64b5e32335f7d3ac14b9e5553db20f2909c902c34",
      "confirmations": 1,
      "time": 1746727602,
      "blocktime": 1746727602
    }
    
    
  2. DrahtBot commented at 8:39 PM on November 7, 2024: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31252.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK murchandamus, sedited

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35569 (Encapsulation for CTransaction by purpleKarrot)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible places where named args for integral literals may be used (e.g. func(x, /*named_arg=*/0) in C++, and func(x, named_arg=0) in Python):

    • [ScriptToUniv(script.first, dScript, false, true)] in src/core_io.cpp

    <sup>2026-06-20 06:19:00</sup>

  3. DrahtBot added the label RPC/REST/ZMQ on Nov 7, 2024
  4. polespinasa renamed this:
    rpc: print P2WSH redeemScript in getrawtransaction
    rpc: print P2WSH witScript in getrawtransaction
    on Nov 7, 2024
  5. polespinasa marked this as a draft on Nov 7, 2024
  6. DrahtBot added the label CI failed on Nov 7, 2024
  7. DrahtBot removed the label CI failed on Nov 8, 2024
  8. polespinasa marked this as ready for review on Nov 8, 2024
  9. in src/core_write.cpp:None in 66ea8941de outdated
     206 | @@ -207,6 +207,14 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry
     207 |                  txinwitness.push_back(HexStr(item));
     208 |              }
     209 |              in.pushKV("txinwitness", std::move(txinwitness));
     210 | +            CPubKey pubkey(tx.vin[i].scriptWitness.stack.back());
     211 | +            if (!pubkey.IsFullyValid()){
     212 | +                CScript witnessScript(tx.vin[i].scriptWitness.stack.back().begin(), tx.vin[i].scriptWitness.stack.back().end());
     213 | +                UniValue witScript(UniValue::VOBJ);
     214 | +                ScriptToUniv(witnessScript, witScript, false, true);
     215 | +                in.pushKV("witScript", std::move(witScript));
    


    kevkevinpal commented at 3:10 AM on November 13, 2024:

    I think it might make more sense to name it "witnessScript" instead of "witScript", It might be confusing to some if it is abbreviated

                    in.pushKV("witnessScript", std::move(witScript));
    

    polespinasa commented at 11:36 AM on November 13, 2024:

    I agree, it needs to be changed in one more place apart from this line but yes I will apply it. Thanks!

  10. kevkevinpal commented at 3:12 AM on November 13, 2024: contributor

    can we squash 66ea8941de3dfd498319c6390655a165f6a5a92b and 84fb299de72ca9e08fe5029380a779d57d302347 to a single commit

  11. polespinasa force-pushed on Nov 13, 2024
  12. polespinasa requested review from kevkevinpal on Nov 13, 2024
  13. in src/core_write.cpp:None in 4e128d4f9b outdated
     206 | @@ -207,6 +207,14 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry
     207 |                  txinwitness.push_back(HexStr(item));
     208 |              }
     209 |              in.pushKV("txinwitness", std::move(txinwitness));
     210 | +            CPubKey pubkey(tx.vin[i].scriptWitness.stack.back());
     211 | +            if (!pubkey.IsFullyValid()){
    


    luke-jr commented at 11:51 PM on November 20, 2024:

    This isn't an indicator of p2wsh... Maybe use d1f0ff0e1fed2c4124d0d81f18daf7b76a770dda or similar?


    polespinasa commented at 6:29 PM on November 22, 2024:

    code rewritten based on this comment

  14. polespinasa force-pushed on Nov 22, 2024
  15. polespinasa force-pushed on Nov 22, 2024
  16. polespinasa force-pushed on Nov 22, 2024
  17. polespinasa requested review from luke-jr on Nov 26, 2024
  18. naiyoma commented at 12:36 PM on January 11, 2025: contributor

    I've tested https://github.com/bitcoin/bitcoin/pull/31252/commits/43dbc696b9e9bb5472b01708d33e022042b5ce3b on regtest, and both (P2SH redeemScript and P2WSH witnessScript )are only being decompiled when calling getblock … 2. I think you should consider editing the PR description to indicate exactly what is working so far.

  19. polespinasa renamed this:
    rpc: print P2WSH witScript in getrawtransaction
    rpc: print P2WSH and P2SH redem Script in getrawtransaction
    on Jan 27, 2025
  20. polespinasa commented at 9:42 AM on January 27, 2025: member

    I've tested 43dbc69 on regtest, and both (P2SH redeemScript and P2WSH witnessScript )are only being decompiled when calling getblock … 2. I think you should consider editing the PR description to indicate exactly what is working so far.

    Thanks for the review and testing! Yes, the description was outdated to the first implementation of it. Updated 🫡

  21. in src/core_write.cpp:None in 43dbc696b9 outdated
     215 |              const Coin& prev_coin = txundo->vprevout[i];
     216 |              const CTxOut& prev_txout = prev_coin.out;
     217 |  
     218 |              amt_total_in += prev_txout.nValue;
     219 |  
     220 | +            std::pair<CScript, int> script = GetScriptForTransactionInput(prev_txout.scriptPubKey, txin);
    


    naiyoma commented at 8:50 PM on February 11, 2025:

    the value of have_undo is always going to be 0 when calling getrawtransaction hence the reason why this only works for getblock..2


    naiyoma commented at 8:59 AM on February 12, 2025:

    This is not a suggestion to replace your current approach, but rather an alternative way. I have an implementation here ->https://github.com/naiyoma/bitcoin/pull/1/commits/ff82e551404e55c75b1950e01e4f4626f5ad452e that shows how to decompile outside of if(have_undo) . While it needs more testing, it successfully works for both getrawtransaction and getblock..2. You might find some ideas there for handlinggetrawtransaction.


    polespinasa commented at 4:24 PM on May 8, 2025:

    Sorry for the delay, got this PR a bit abandoned, re-taking it now :).

    Thanks for the suggestion! The problem is that I don't see the way to detect the type without the previous transaction. Your patch is similar to my first approach. If you test with a P2SH-P2WPKH, the decoding is done wrong.

  22. in src/core_write.cpp:None in 43dbc696b9 outdated
     219 |  
     220 | +            std::pair<CScript, int> script = GetScriptForTransactionInput(prev_txout.scriptPubKey, txin);
     221 | +            UniValue redeemScript(UniValue::VOBJ);
     222 | +            ScriptToUniv(script.first, redeemScript, false, true);
     223 | +            if (script.second != -2) {
     224 | +                in.pushKV("redeemScript", std::move(redeemScript));
    


    naiyoma commented at 8:12 AM on February 12, 2025:

    this outputs redeemScript for both P2SH and P2WSH, but it should be P2SH redeemScript and P2WSH witnessScript


    polespinasa commented at 4:21 PM on May 8, 2025:

    done

  23. DrahtBot commented at 4:53 PM on March 21, 2025: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Debug: https://github.com/bitcoin/bitcoin/runs/33403307702</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  24. DrahtBot added the label CI failed on Mar 21, 2025
  25. DrahtBot commented at 2:18 PM on April 1, 2025: contributor

    Are you still working on this?

  26. DrahtBot marked this as a draft on Apr 11, 2025
  27. polespinasa force-pushed on May 8, 2025
  28. polespinasa marked this as ready for review on May 8, 2025
  29. polespinasa force-pushed on May 8, 2025
  30. polespinasa force-pushed on May 8, 2025
  31. polespinasa force-pushed on May 8, 2025
  32. polespinasa force-pushed on May 8, 2025
  33. polespinasa force-pushed on May 8, 2025
  34. polespinasa force-pushed on May 8, 2025
  35. polespinasa commented at 5:29 PM on May 8, 2025: member

    Rebased on top of master 58ac220e857da32401a7291f77b4b8a864e80ebb @Sjors maybe you would like to review this

  36. polespinasa requested review from naiyoma on May 8, 2025
  37. DrahtBot removed the label CI failed on May 8, 2025
  38. DrahtBot added the label CI failed on May 17, 2025
  39. DrahtBot removed the label CI failed on May 18, 2025
  40. in src/script/script.cpp:None in 58ac220e85 outdated
     406 | +    int witnessversion = 0;
     407 | +    std::vector<unsigned char> witnessprogram;
     408 | +    if (!prevScript.IsWitnessProgram(witnessversion, witnessprogram)) {
     409 | +        // For P2SH, scriptSig is always push-only, so the actual script is only the last stack item
     410 | +        // For non-P2SH, prevScript is likely the real script, but not part of this transaction, and scriptSig could very well be executable, so return the latter instead
     411 | +        return std::make_pair(p2sh ? prevScript : txin.scriptSig, -1);
    


    naiyoma commented at 8:37 PM on August 26, 2025:

    For a non-P2SH transaction, returning -1 will result in a redeemScript field being added. I tested this using a P2PKH transaction, and this was the output: "redeemScript": { "asm": "304402...7981", "type": "nonstandard" }"


    polespinasa commented at 6:22 PM on September 15, 2025:

    Nice catch! You're right, solved in 18c513f8babf65ea73ea9c785fba90446ef947db. Now non-P2SH and non-segwit inputs return -2 and don't show any script as it's out the scope of the PR.

  41. polespinasa force-pushed on Sep 15, 2025
  42. polespinasa force-pushed on Sep 15, 2025
  43. polespinasa force-pushed on Sep 16, 2025
  44. murchandamus commented at 1:07 PM on November 3, 2025: member

    Concept ACK

  45. DrahtBot added the label Needs rebase on Nov 11, 2025
  46. polespinasa force-pushed on Jan 13, 2026
  47. polespinasa commented at 8:33 AM on January 13, 2026: member

    Rebased to resolve conflicts with #32517, only moved DecodeTxDoc from rawtransaction.cpp to rawtransaction_util.cpp

  48. polespinasa renamed this:
    rpc: print P2WSH and P2SH redem Script in getrawtransaction
    rpc: print P2WSH and P2SH redem Script in (get/decode)rawtransaction
    on Jan 13, 2026
  49. DrahtBot removed the label Needs rebase on Jan 13, 2026
  50. DrahtBot added the label Needs rebase on Jan 19, 2026
  51. polespinasa force-pushed on Jan 20, 2026
  52. DrahtBot removed the label Needs rebase on Jan 20, 2026
  53. sedited removed review request from kevkevinpal on Mar 19, 2026
  54. sedited requested review from stickies-v on Mar 19, 2026
  55. sedited requested review from kevkevinpal on May 22, 2026
  56. in src/script/script.h:576 in 2aa405a80e outdated
     572 | @@ -573,6 +573,9 @@ class CScript : public CScriptBase
     573 |      }
     574 |  };
     575 |  
     576 | +class CTxIn;
    


    sedited commented at 11:33 AM on June 19, 2026:

    We usually put forward declarations at the top of the headers.


    polespinasa commented at 4:02 PM on June 19, 2026:

    done

  57. in src/core_io.cpp:479 in 2aa405a80e outdated
     475 | @@ -476,6 +476,15 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry
     476 |  
     477 |              amt_total_in += prev_txout.nValue;
     478 |  
     479 | +            std::pair<CScript, int> script = GetScriptForTransactionInput(prev_txout.scriptPubKey, txin);
    


    sedited commented at 11:40 AM on June 19, 2026:

    TxToUniv is used by a few other callers besides the rawtransaction rpcs. Are they effected by this change too?


    polespinasa commented at 4:33 PM on June 19, 2026:

    ~Yes, all of them if I am not wrong.~ Will update the PR description.

    Update: Only getblock is affected and the /rest/block endpoint.

    decodepsbt calls TxToUniv() with the default txundo=nullptr. gettransaction explicitly passes txundo=nullptr.

    So they are not affected as without txundo the data is not available.

  58. in src/script/script.cpp:13 in 2aa405a80e outdated
       9 | @@ -10,6 +10,7 @@
      10 |  #include <hash.h>
      11 |  #include <uint256.h>
      12 |  #include <util/hash_type.h>
      13 | +#include<script/interpreter.h>
    


    sedited commented at 12:00 PM on June 19, 2026:

    I think it would be good to avoid including the interpreter here. Looking at the existing contents of this file, I also don't think this extractor really fits in here. Could we teak script/sign.cpp's DataFromTransaction to return the required SignatureData from the transactions instead?


    polespinasa commented at 4:14 PM on June 19, 2026:

    Could we teak script/sign.cpp's DataFromTransaction to return the required SignatureData from the transactions instead?

    Didn't check how to do it but, should we?

    // Extracts signatures and scripts from incomplete scriptSigs. Please do not extend this, use PSBT instead
    SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout)
    {
    

    polespinasa commented at 7:54 PM on June 19, 2026:

    I moved the function from script.cpp to solver.cpp I am not sure if it is where it should be, but moved it to avoid a recursive inclusion.

  59. sedited commented at 12:34 PM on June 19, 2026: contributor

    Concept ACK

    Is returning the descriptor of the redeem script useful for anything? There have been a few changes in some of the rpc code, can you do a rebase for them? This also still needs a release note.

  60. polespinasa commented at 3:58 PM on June 19, 2026: member

    Is returning the descriptor of the redeem script useful for anything?

    I am not sure, I added it as "free" extra information in case it is useful for something I am not aware of.

    Added the field following sjors idea from the original issue :)

    I think adding fields is fine, unless determining their values is slow for some reason.

    Jokes a side, I am happy dropping it if we don't want it.

  61. polespinasa force-pushed on Jun 19, 2026
  62. polespinasa force-pushed on Jun 19, 2026
  63. DrahtBot added the label CI failed on Jun 19, 2026
  64. DrahtBot commented at 4:36 PM on June 19, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task iwyu: https://github.com/bitcoin/bitcoin/actions/runs/27836133550/job/82384476200</sub> <sub>LLM reason (✨ experimental): IWYU include-check failed (forced by “Failure generated from IWYU” while fixing includes in src/script/script.cpp).</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  65. polespinasa renamed this:
    rpc: print P2WSH and P2SH redem Script in (get/decode)rawtransaction
    rpc: print P2WSH and P2SH redem Script in (get/decode)rawtransaction and getblock
    on Jun 19, 2026
  66. polespinasa renamed this:
    rpc: print P2WSH and P2SH redem Script in (get/decode)rawtransaction and getblock
    rpc: print P2WSH and P2SH redem Script in getrawtransaction and getblock
    on Jun 19, 2026
  67. polespinasa force-pushed on Jun 19, 2026
  68. polespinasa force-pushed on Jun 19, 2026
  69. polespinasa force-pushed on Jun 19, 2026
  70. polespinasa force-pushed on Jun 19, 2026
  71. polespinasa force-pushed on Jun 19, 2026
  72. DrahtBot added the label Needs rebase on Jun 20, 2026
  73. rpc: Decode P2(W)SH scripts if data from prev tx is available and verbose is 2 f88e1fc39c
  74. test: test that getrawtransaction with verbosity 2 returns the redeem and witness script f9b7019527
  75. add release note fa0267b7fb
  76. polespinasa force-pushed on Jun 20, 2026
  77. DrahtBot removed the label CI failed on Jun 20, 2026
  78. DrahtBot removed the label Needs rebase on Jun 20, 2026

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-07-04 02:51 UTC

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