test: check `PSBT_GLOBAL_VERSION` validation on decode #36626

pull nebula-21 wants to merge 1 commits into bitcoin:master from nebula-21:test-psbt-version-field changing 1 files +16 −0
  1. nebula-21 commented at 4:06 PM on October 23, 2026: contributor

    This PR adds coverage for the global PSBT version field validation on decode.

    test_psbt_unsupported_version_field checks that the PSBT has supported version number into the PSBT_GLOBAL_VERSION field. The test can be triggered with this diff:

    <details> <summary>Diff</summary>

    diff --git a/src/psbt.h b/src/psbt.h
    index 5eb5e81428..d90528e01d 100644
    --- a/src/psbt.h
    +++ b/src/psbt.h
    @@ -94,7 +94,7 @@ inline constexpr uint8_t PSBT_SEPARATOR = 0x00;
     inline constexpr std::streamsize MAX_FILE_SIZE_PSBT{100'000'000}; // 100 MB
     
     // PSBT version number
    -inline constexpr uint32_t PSBT_HIGHEST_VERSION = 2;
    +inline constexpr uint32_t PSBT_HIGHEST_VERSION = 4;
     
     /** A structure for PSBT proprietary types */
     struct PSBTProprietary
    

    </details>

    test_psbt_missing_version_field checks that a PSBT without the PSBT_GLOBAL_VERSION field is interpreted as a v0. I've created a v2 and removed the field to check the correct behavior (fails beacuse it was originally a v2 and now is misinterpreted as a v0). The test can be triggered with this diff:

    <details> <summary>Diff</summary>

    diff --git a/src/psbt.h b/src/psbt.h
    index 5eb5e81428..ea11267e0f 100644
    --- a/src/psbt.h
    +++ b/src/psbt.h
    @@ -1515,7 +1515,7 @@ public:
             if (psbt_ver == 0) {
                 // Make sure that we got an unsigned tx for PSBTv0
                 if (!tx) {
    -                throw std::ios_base::failure("No unsigned transaction was provided");
    +                //throw std::ios_base::failure("No unsigned transaction was provided");
                 }
                 // Make sure no PSBTv2 fields are present
                 if (found_tx_version) {
    

    </details>

    Prior to this PR, no test would be triggered with this diffs.

  2. test: check `PSBT_GLOBAL_VERSION` validation on decode eeb4782bda
  3. DrahtBot added the label Tests on Oct 23, 2026
  4. DrahtBot commented at 4:06 PM on October 23, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    External sites

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    Concept ACK Bicaru20

    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:

    • #36343 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/36343.svg"></sub> (psbt: verify final scripts in FinalizePSBT by Bruce039)

    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-->

  5. in test/functional/rpc_psbt.py:845 in eeb4782bda
     838 | @@ -839,6 +839,20 @@ def test_psbt_version(self):
     839 |          assert_raises_rpc_error(-8, "The PSBT version can only be 2 or 0", self.nodes[0].converttopsbt, hexstring=rawtx, psbt_version=1)
     840 |          assert_raises_rpc_error(-8, "The PSBT version can only be 2 or 0", self.nodes[0].psbtbumpfee, txid=tobump, psbt_version=1)
     841 |  
     842 | +    def test_psbt_unsupported_version_field(self):
     843 | +        self.log.info("Test that the global PSBT version is supported on decode")
     844 | +
     845 | +        psbt = PSBT.from_base64(self.nodes[0].createpsbt([{"txid": "00" * 32, "vout": 0}], [{"data": "00"}]))
    


    Bicaru20 commented at 10:13 AM on October 27, 2026:

    nit: Since the test is for PSBTv2, I think it's better to explicity add the psbt version in case the default it is ever changed.

            psbt = PSBT.from_base64(self.nodes[0].createpsbt([{"txid": "00" * 32, "vout": 0}], [{"data": "00"}], psbt_version=2))
    
  6. in test/functional/rpc_psbt.py:852 in eeb4782bda
     847 | +        assert_raises_rpc_error(-22, "TX decode failed Unsupported version number", self.nodes[0].decodepsbt, psbt.to_base64())
     848 | +
     849 | +    def test_psbt_missing_version_field(self):
     850 | +        self.log.info("Test that a PSBT without the global version is interpreted as v0")
     851 | +
     852 | +        psbt = PSBT.from_base64(self.nodes[0].createpsbt([{"txid": "00" * 32, "vout": 0}], [{"data": "00"}]))
    


    Bicaru20 commented at 10:14 AM on October 27, 2026:

    nit: Same as before

            psbt = PSBT.from_base64(self.nodes[0].createpsbt([{"txid": "00" * 32, "vout": 0}], [{"data": "00"}], psbt_version=2))
    
  7. Bicaru20 commented at 11:00 AM on October 27, 2026: contributor

    Concept ACK. Left a couple of nits. I beleive it is good to separate the test into functions, but in this case I think we could do it with one function that covers both cases, that way we can reuse the PSBT.

    --- a/test/functional/rpc_psbt.py
    +++ b/test/functional/rpc_psbt.py
    @@ -839,17 +839,15 @@ class PSBTTest(BitcoinTestFramework):
             assert_raises_rpc_error(-8, "The PSBT version can only be 2 or 0", self.nodes[0].converttopsbt, hexstring=rawtx, psbt_version=1)
             assert_raises_rpc_error(-8, "The PSBT version can only be 2 or 0", self.nodes[0].psbtbumpfee, txid=tobump, psbt_version=1)
     
    -    def test_psbt_unsupported_version_field(self):
    +    def test_psbt_version_field(self):
             self.log.info("Test that the global PSBT version is supported on decode")
     
    -        psbt = PSBT.from_base64(self.nodes[0].createpsbt([{"txid": "00" * 32, "vout": 0}], [{"data": "00"}]))
    +        psbt = PSBT.from_base64(self.nodes[0].createpsbt([{"txid": "00" * 32, "vout": 0}], [{"data": "00"}], psbt_version=2))
             psbt.g.map[PSBT_GLOBAL_VERSION] = (3).to_bytes(4, "little")
             assert_raises_rpc_error(-22, "TX decode failed Unsupported version number", self.nodes[0].decodepsbt, psbt.to_base64())
     
    -    def test_psbt_missing_version_field(self):
             self.log.info("Test that a PSBT without the global version is interpreted as v0")
     
    -        psbt = PSBT.from_base64(self.nodes[0].createpsbt([{"txid": "00" * 32, "vout": 0}], [{"data": "00"}]))
             del psbt.g.map[PSBT_GLOBAL_VERSION]
             assert_raises_rpc_error(-22, "TX decode failed No unsigned transaction was provided", self.nodes[0].decodepsbt, psbt.to_base64())
     
    @@ -1836,8 +1834,7 @@ class PSBTTest(BitcoinTestFramework):
             self.test_psbt_named_parameter_handling()
             self.test_psbt_roundtrip()
             self.test_psbt_version()
    -        self.test_psbt_unsupported_version_field()
    -        self.test_psbt_missing_version_field()
    +        self.test_psbt_version_field()
             self.test_psbt_with_invalid_signature()
             self.test_musig2_untrusted_derivation()
    
    
  8. Bicaru20 commented at 8:57 AM on October 29, 2026: contributor

    After digging a little bit more into the test, I've noticed that regarding PSBT_GLOBAL_VERSION there is a case that is not coverd and we could add to this test:

          psbt.g.map[PSBT_GLOBAL_VERSION] = (1).to_bytes(4, "little")
          assert_raises_rpc_error(-22, "TX decode failed There is no PSBT version 1", self.nodes[0].decodepsbt, psbt.to_base64())
    

    This is the line where the error is thrown in psbt.h: https://github.com/bitcoin/bitcoin/blob/9bf4815b94b9eaf8807f4e569091778da6c338d5/src/psbt.h#L1539

Labels

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-10-30 09:40 UTC