/ src / test / fuzz / psbt.cpp
psbt.cpp
  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      PartiallySignedTransaction psbt_mut;
 29      std::string error;
 30      auto str = fuzzed_data_provider.ConsumeRandomLengthString();
 31      if (!DecodeRawPSBT(psbt_mut, MakeByteSpan(str), error)) {
 32          return;
 33      }
 34      const PartiallySignedTransaction psbt = psbt_mut;
 35  
 36      // A PSBT must roundtrip.
 37      PartiallySignedTransaction psbt_roundtrip;
 38      std::vector<uint8_t> psbt_ser;
 39      VectorWriter{psbt_ser, 0, psbt};
 40      SpanReader{psbt_ser} >> psbt_roundtrip;
 41  
 42      // And be stable across roundtrips.
 43      std::vector<uint8_t> roundtrip_ser;
 44      VectorWriter{roundtrip_ser, 0, psbt_roundtrip};
 45      Assert(psbt_ser == roundtrip_ser);
 46  
 47      const PSBTAnalysis analysis = AnalyzePSBT(psbt);
 48      (void)PSBTRoleName(analysis.next);
 49      for (const PSBTInputAnalysis& input_analysis : analysis.inputs) {
 50          (void)PSBTRoleName(input_analysis.next);
 51      }
 52  
 53      (void)psbt.IsNull();
 54  
 55      std::optional<CMutableTransaction> tx = psbt.tx;
 56      if (tx) {
 57          const CMutableTransaction& mtx = *tx;
 58          const PartiallySignedTransaction psbt_from_tx{mtx};
 59      }
 60  
 61      for (const PSBTInput& input : psbt.inputs) {
 62          (void)PSBTInputSigned(input);
 63          (void)input.IsNull();
 64      }
 65      (void)CountPSBTUnsignedInputs(psbt);
 66  
 67      for (const PSBTOutput& output : psbt.outputs) {
 68          (void)output.IsNull();
 69      }
 70  
 71      for (size_t i = 0; i < psbt.tx->vin.size(); ++i) {
 72          CTxOut tx_out;
 73          if (psbt.GetInputUTXO(tx_out, i)) {
 74              (void)tx_out.IsNull();
 75              (void)tx_out.ToString();
 76          }
 77      }
 78  
 79      psbt_mut = psbt;
 80      (void)FinalizePSBT(psbt_mut);
 81  
 82      psbt_mut = psbt;
 83      CMutableTransaction result;
 84      if (FinalizeAndExtractPSBT(psbt_mut, result)) {
 85          const PartiallySignedTransaction psbt_from_tx{result};
 86      }
 87  
 88      PartiallySignedTransaction psbt_merge;
 89      str = fuzzed_data_provider.ConsumeRandomLengthString();
 90      if (!DecodeRawPSBT(psbt_merge, MakeByteSpan(str), error)) {
 91          psbt_merge = psbt;
 92      }
 93      psbt_mut = psbt;
 94      (void)psbt_mut.Merge(psbt_merge);
 95      psbt_mut = psbt;
 96      (void)CombinePSBTs(psbt_mut, {psbt_mut, psbt_merge});
 97      psbt_mut = psbt;
 98      for (unsigned int i = 0; i < psbt_merge.tx->vin.size(); ++i) {
 99          (void)psbt_mut.AddInput(psbt_merge.tx->vin[i], psbt_merge.inputs[i]);
100      }
101      for (unsigned int i = 0; i < psbt_merge.tx->vout.size(); ++i) {
102          Assert(psbt_mut.AddOutput(psbt_merge.tx->vout[i], psbt_merge.outputs[i]));
103      }
104      psbt_mut.unknown.insert(psbt_merge.unknown.begin(), psbt_merge.unknown.end());
105  }