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 }