psbt.cpp raw

   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  FUZZ_TARGET(psbt)
  25  {
  26      SeedRandomStateForTest(SeedRand::ZEROS);
  27      FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
  28      auto str = fuzzed_data_provider.ConsumeRandomLengthString();
  29      util::Result<PartiallySignedTransaction> psbt_res = DecodeRawPSBT(MakeByteSpan(str));
  30      if (!psbt_res) {
  31          return;
  32      }
  33      PartiallySignedTransaction psbt_mut = *psbt_res;
  34      const PartiallySignedTransaction psbt = psbt_mut;
  35  
  36      // We are on purpose not forward compatible, and version 1 is disabled.
  37      const auto psbt_version{psbt.GetVersion()};
  38      Assert(psbt_version == 0 || psbt_version == 2);
  39  
  40      // A PSBT must roundtrip.
  41      std::vector<uint8_t> psbt_ser;
  42      VectorWriter{psbt_ser, 0, psbt};
  43      SpanReader reader{psbt_ser};
  44      PartiallySignedTransaction psbt_roundtrip(deserialize, reader);
  45  
  46      // And be stable across roundtrips.
  47      std::vector<uint8_t> roundtrip_ser;
  48      VectorWriter{roundtrip_ser, 0, psbt_roundtrip};
  49      Assert(psbt_ser == roundtrip_ser);
  50  
  51      const PSBTAnalysis analysis = AnalyzePSBT(psbt);
  52      (void)PSBTRoleName(analysis.next);
  53      for (const PSBTInputAnalysis& input_analysis : analysis.inputs) {
  54          (void)PSBTRoleName(input_analysis.next);
  55      }
  56  
  57      (void)psbt.IsNull();
  58      (void)psbt.GetUnsignedTx();
  59  
  60      for (const PSBTInput& input : psbt.inputs) {
  61          (void)PSBTInputSigned(input);
  62          (void)input.IsNull();
  63          PSBTInput input_mod = input;
  64          CTxOut tx_out;
  65          if (input.GetUTXO(tx_out)) {
  66              (void)tx_out.IsNull();
  67              (void)tx_out.ToString();
  68          }
  69          // A PSBT input must roundtrip to signature data.
  70          PSBTInput input_fill{psbt_version, input_mod.prev_txid, input_mod.prev_out, input_mod.sequence};
  71          SignatureData sig_data;
  72          input_mod.FillSignatureData(sig_data);
  73          input_fill.FromSignatureData(sig_data);
  74  
  75          // Only final_script_sig and final_script_witness are filled when sigdata is complete
  76          if (sig_data.complete) {
  77              Assert(input_mod.final_script_sig == input_fill.final_script_sig);
  78              Assert(input_mod.final_script_witness == input_fill.final_script_witness);
  79          } else {
  80              // UTXOs don't go into SignatureData
  81              input_mod.non_witness_utxo.reset();
  82              input_mod.witness_utxo.SetNull();
  83              // Sighash type doesn't go into SignatureData
  84              input_mod.sighash_type.reset();
  85              // Timelocks don't go into SignatureData
  86              input_mod.time_locktime.reset();
  87              input_mod.height_locktime.reset();
  88              // Proprietary fields are not included in SignatureData
  89              input_mod.m_proprietary.clear();
  90              // Unknown fields are not included in SignatureData
  91              input_mod.unknown.clear();
  92  
  93              Assert(input_mod == input_fill);
  94          }
  95      }
  96      (void)CountPSBTUnsignedInputs(psbt);
  97  
  98      for (const PSBTOutput& output : psbt.outputs) {
  99          (void)output.IsNull();
 100          PSBTOutput output_mod = output;
 101          // A PSBT output must roundtrip to signature data.
 102          PSBTOutput output_fill{psbt_version, output_mod.amount, output_mod.script};
 103          SignatureData sig_data;
 104          output_mod.FillSignatureData(sig_data);
 105          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          if (output_mod.m_tap_tree.empty() || !output_mod.m_tap_internal_key.IsFullyValid()) {
 110              output_mod.m_tap_tree.clear();
 111              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          std::sort(output_mod.m_tap_tree.begin(), output_mod.m_tap_tree.end());
 115          std::sort(output_fill.m_tap_tree.begin(), output_fill.m_tap_tree.end());
 116          // Proprietary fields are not included in SignatureData
 117          output_mod.m_proprietary.clear();
 118          // Unknown fields are not included in SignatureData
 119          output_mod.unknown.clear();
 120  
 121          Assert(output_mod.m_tap_internal_key == output_fill.m_tap_internal_key);
 122          Assert(output_mod == output_fill);
 123      }
 124  
 125      psbt_mut = psbt;
 126      (void)FinalizePSBT(psbt_mut);
 127  
 128      psbt_mut = psbt;
 129      CMutableTransaction result;
 130      if (FinalizeAndExtractPSBT(psbt_mut, result)) {
 131          const PartiallySignedTransaction psbt_from_tx{result};
 132      }
 133  
 134      PartiallySignedTransaction psbt_merge = psbt;
 135      str = fuzzed_data_provider.ConsumeRandomLengthString();
 136      util::Result<PartiallySignedTransaction> psbt_merge_res = DecodeRawPSBT(MakeByteSpan(str));
 137      if (psbt_merge_res) {
 138          psbt_merge = *psbt_merge_res;
 139      }
 140      psbt_mut = psbt;
 141      (void)psbt_mut.Merge(psbt_merge);
 142      psbt_mut = psbt;
 143      std::optional<PartiallySignedTransaction> comb_res = CombinePSBTs({psbt_mut, psbt_merge});
 144      if (comb_res) {
 145          psbt_mut = *comb_res;
 146      }
 147      for (const auto& psbt_in : psbt_merge.inputs) {
 148          (void)psbt_mut.AddInput(psbt_in);
 149      }
 150      for (const auto& psbt_out : psbt_merge.outputs) {
 151          (void)psbt_mut.AddOutput(psbt_out);
 152      }
 153      psbt_mut.unknown.insert(psbt_merge.unknown.begin(), psbt_merge.unknown.end());
 154  
 155      RemoveUnnecessaryTransactions(psbt_mut);
 156  }
 157