LCOV - code coverage report
Current view: top level - src/test/fuzz - psbt.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 100.0 % 91 91
Test Date: 2026-05-13 07:36:37 Functions: 100.0 % 2 2
Branches: 58.6 % 152 89

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2019-present The Bitcoin Core developers
       2                 :             : // Distributed under the MIT software license, see the accompanying
       3                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4                 :             : 
       5                 :             : #include <node/psbt.h>
       6                 :             : #include <psbt.h>
       7                 :             : #include <pubkey.h>
       8                 :             : #include <script/script.h>
       9                 :             : #include <streams.h>
      10                 :             : #include <test/fuzz/FuzzedDataProvider.h>
      11                 :             : #include <test/fuzz/fuzz.h>
      12                 :             : #include <test/util/random.h>
      13                 :             : #include <util/check.h>
      14                 :             : 
      15                 :             : #include <cstdint>
      16                 :             : #include <optional>
      17                 :             : #include <string>
      18                 :             : #include <vector>
      19                 :             : 
      20                 :             : using node::AnalyzePSBT;
      21                 :             : using node::PSBTAnalysis;
      22                 :             : using node::PSBTInputAnalysis;
      23                 :             : 
      24         [ +  - ]:        6594 : FUZZ_TARGET(psbt)
      25                 :             : {
      26                 :        6134 :     SeedRandomStateForTest(SeedRand::ZEROS);
      27                 :        6134 :     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
      28                 :        6134 :     auto str = fuzzed_data_provider.ConsumeRandomLengthString();
      29         [ +  - ]:        6134 :     util::Result<PartiallySignedTransaction> psbt_res = DecodeRawPSBT(MakeByteSpan(str));
      30         [ +  + ]:        6134 :     if (!psbt_res) {
      31                 :        1649 :         return;
      32                 :             :     }
      33         [ +  - ]:        4485 :     PartiallySignedTransaction psbt_mut = *psbt_res;
      34         [ +  - ]:        4485 :     const PartiallySignedTransaction psbt = psbt_mut;
      35                 :             : 
      36                 :             :     // We are on purpose not forward compatible, and version 1 is disabled.
      37         [ +  - ]:        4485 :     const auto psbt_version{psbt.GetVersion()};
      38         [ -  + ]:        4485 :     Assert(psbt_version == 0 || psbt_version == 2);
      39                 :             : 
      40                 :             :     // A PSBT must roundtrip.
      41                 :        4485 :     std::vector<uint8_t> psbt_ser;
      42         [ +  - ]:        4485 :     VectorWriter{psbt_ser, 0, psbt};
      43         [ -  + ]:        4485 :     SpanReader reader{psbt_ser};
      44         [ +  - ]:        4485 :     PartiallySignedTransaction psbt_roundtrip(deserialize, reader);
      45                 :             : 
      46                 :             :     // And be stable across roundtrips.
      47                 :        4485 :     std::vector<uint8_t> roundtrip_ser;
      48         [ +  - ]:        4485 :     VectorWriter{roundtrip_ser, 0, psbt_roundtrip};
      49         [ -  + ]:        4485 :     Assert(psbt_ser == roundtrip_ser);
      50                 :             : 
      51   [ +  -  +  - ]:        4485 :     const PSBTAnalysis analysis = AnalyzePSBT(psbt);
      52         [ +  - ]:        4485 :     (void)PSBTRoleName(analysis.next);
      53         [ +  + ]:        9450 :     for (const PSBTInputAnalysis& input_analysis : analysis.inputs) {
      54         [ +  - ]:        9930 :         (void)PSBTRoleName(input_analysis.next);
      55                 :             :     }
      56                 :             : 
      57         [ +  - ]:        4485 :     (void)psbt.IsNull();
      58         [ +  - ]:        4485 :     (void)psbt.GetUnsignedTx();
      59                 :             : 
      60         [ +  + ]:       11674 :     for (const PSBTInput& input : psbt.inputs) {
      61         [ +  - ]:        7189 :         (void)PSBTInputSigned(input);
      62         [ +  - ]:        7189 :         (void)input.IsNull();
      63         [ +  - ]:        7189 :         PSBTInput input_mod = input;
      64                 :        7189 :         CTxOut tx_out;
      65   [ +  -  +  + ]:        7189 :         if (input.GetUTXO(tx_out)) {
      66                 :        4942 :             (void)tx_out.IsNull();
      67         [ +  - ]:        9884 :             (void)tx_out.ToString();
      68                 :             :         }
      69                 :             :         // A PSBT input must roundtrip to signature data.
      70                 :        7189 :         PSBTInput input_fill{psbt_version, input_mod.prev_txid, input_mod.prev_out, input_mod.sequence};
      71                 :        7189 :         SignatureData sig_data;
      72         [ +  - ]:        7189 :         input_mod.FillSignatureData(sig_data);
      73         [ +  - ]:        7189 :         input_fill.FromSignatureData(sig_data);
      74                 :             : 
      75                 :             :         // Only final_script_sig and final_script_witness are filled when sigdata is complete
      76         [ +  + ]:        7189 :         if (sig_data.complete) {
      77         [ -  + ]:        1808 :             Assert(input_mod.final_script_sig == input_fill.final_script_sig);
      78         [ -  + ]:        3616 :             Assert(input_mod.final_script_witness == input_fill.final_script_witness);
      79                 :             :         } else {
      80                 :             :             // UTXOs don't go into SignatureData
      81                 :        5381 :             input_mod.non_witness_utxo.reset();
      82                 :        5381 :             input_mod.witness_utxo.SetNull();
      83                 :             :             // Sighash type doesn't go into SignatureData
      84         [ +  + ]:        5381 :             input_mod.sighash_type.reset();
      85                 :             :             // Timelocks don't go into SignatureData
      86         [ -  + ]:        5381 :             input_mod.time_locktime.reset();
      87         [ -  + ]:        5381 :             input_mod.height_locktime.reset();
      88                 :             :             // Proprietary fields are not included in SignatureData
      89                 :        5381 :             input_mod.m_proprietary.clear();
      90                 :             :             // Unknown fields are not included in SignatureData
      91                 :        5381 :             input_mod.unknown.clear();
      92                 :             : 
      93         [ -  + ]:        5381 :             Assert(input_mod == input_fill);
      94                 :             :         }
      95                 :        7189 :     }
      96         [ +  - ]:        4485 :     (void)CountPSBTUnsignedInputs(psbt);
      97                 :             : 
      98         [ +  + ]:       10581 :     for (const PSBTOutput& output : psbt.outputs) {
      99         [ +  - ]:        6096 :         (void)output.IsNull();
     100         [ +  - ]:        6096 :         PSBTOutput output_mod = output;
     101                 :             :         // A PSBT output must roundtrip to signature data.
     102                 :        6096 :         PSBTOutput output_fill{psbt_version, output_mod.amount, output_mod.script};
     103                 :        6096 :         SignatureData sig_data;
     104         [ +  - ]:        6096 :         output_mod.FillSignatureData(sig_data);
     105         [ +  - ]:        6096 :         output_fill.FromSignatureData(sig_data);
     106                 :             : 
     107                 :             :         // FillSignatureData will not fill tap tree or internal key if the tree is empty or
     108                 :             :         // the key is not fully valid. These need to be cleared before checking for equivalence
     109   [ +  +  +  -  :        6096 :         if (output_mod.m_tap_tree.empty() || !output_mod.m_tap_internal_key.IsFullyValid()) {
                   +  + ]
     110                 :        6058 :             output_mod.m_tap_tree.clear();
     111                 :        6058 :             std::fill(output_mod.m_tap_internal_key.begin(), output_mod.m_tap_internal_key.end(), 0);
     112                 :             :         }
     113                 :             :         // Sort m_tap_tree to ensure the vectors match
     114                 :        6096 :         std::sort(output_mod.m_tap_tree.begin(), output_mod.m_tap_tree.end());
     115                 :        6096 :         std::sort(output_fill.m_tap_tree.begin(), output_fill.m_tap_tree.end());
     116                 :             :         // Proprietary fields are not included in SignatureData
     117                 :        6096 :         output_mod.m_proprietary.clear();
     118                 :             :         // Unknown fields are not included in SignatureData
     119                 :        6096 :         output_mod.unknown.clear();
     120                 :             : 
     121         [ -  + ]:        6096 :         Assert(output_mod.m_tap_internal_key == output_fill.m_tap_internal_key);
     122         [ -  + ]:        6096 :         Assert(output_mod == output_fill);
     123                 :        6096 :     }
     124                 :             : 
     125         [ +  - ]:        4485 :     psbt_mut = psbt;
     126         [ +  - ]:        4485 :     (void)FinalizePSBT(psbt_mut);
     127                 :             : 
     128         [ +  - ]:        4485 :     psbt_mut = psbt;
     129         [ +  - ]:        4485 :     CMutableTransaction result;
     130   [ +  -  +  + ]:        4485 :     if (FinalizeAndExtractPSBT(psbt_mut, result)) {
     131         [ +  - ]:         607 :         const PartiallySignedTransaction psbt_from_tx{result};
     132                 :         607 :     }
     133                 :             : 
     134         [ +  - ]:        4485 :     PartiallySignedTransaction psbt_merge = psbt;
     135         [ +  - ]:        4485 :     str = fuzzed_data_provider.ConsumeRandomLengthString();
     136         [ +  - ]:        4485 :     util::Result<PartiallySignedTransaction> psbt_merge_res = DecodeRawPSBT(MakeByteSpan(str));
     137         [ +  + ]:        4485 :     if (psbt_merge_res) {
     138         [ +  - ]:         331 :         psbt_merge = *psbt_merge_res;
     139                 :             :     }
     140         [ +  - ]:        4485 :     psbt_mut = psbt;
     141         [ +  - ]:        4485 :     (void)psbt_mut.Merge(psbt_merge);
     142         [ +  - ]:        4485 :     psbt_mut = psbt;
     143   [ +  -  +  -  :       13455 :     std::optional<PartiallySignedTransaction> comb_res = CombinePSBTs({psbt_mut, psbt_merge});
             +  +  -  - ]
     144         [ +  + ]:        4485 :     if (comb_res) {
     145         [ +  - ]:        4370 :         psbt_mut = *comb_res;
     146                 :             :     }
     147         [ +  + ]:       11756 :     for (const auto& psbt_in : psbt_merge.inputs) {
     148         [ +  - ]:        7271 :         (void)psbt_mut.AddInput(psbt_in);
     149                 :             :     }
     150         [ +  + ]:       10889 :     for (const auto& psbt_out : psbt_merge.outputs) {
     151         [ +  - ]:        6404 :         (void)psbt_mut.AddOutput(psbt_out);
     152                 :             :     }
     153         [ +  - ]:        4485 :     psbt_mut.unknown.insert(psbt_merge.unknown.begin(), psbt_merge.unknown.end());
     154                 :             : 
     155         [ +  - ]:        4485 :     RemoveUnnecessaryTransactions(psbt_mut);
     156   [ +  -  +  -  :       19589 : }
                   -  - ]
        

Generated by: LCOV version 2.0-1