LCOV - code coverage report
Current view: top level - src - psbt.h (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 140 380 36.8 %
Date: 2026-06-25 07:23:51 Functions: 33 56 58.9 %

          Line data    Source code
       1             : // Copyright (c) 2009-2021 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             : #ifndef BITCOIN_PSBT_H
       6             : #define BITCOIN_PSBT_H
       7             : 
       8             : #include <node/transaction.h>
       9             : #include <policy/feerate.h>
      10             : #include <primitives/transaction.h>
      11             : #include <pubkey.h>
      12             : #include <script/keyorigin.h>
      13             : #include <script/sign.h>
      14             : #include <script/signingprovider.h>
      15             : #include <span.h>
      16             : #include <streams.h>
      17             : 
      18             : #include <optional>
      19             : 
      20             : // Magic bytes
      21             : static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff};
      22             : 
      23             : // Global types
      24             : static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00;
      25             : static constexpr uint8_t PSBT_GLOBAL_XPUB = 0x01;
      26             : static constexpr uint8_t PSBT_GLOBAL_VERSION = 0xFB;
      27             : static constexpr uint8_t PSBT_GLOBAL_PROPRIETARY = 0xFC;
      28             : 
      29             : // Input types
      30             : static constexpr uint8_t PSBT_IN_NON_WITNESS_UTXO = 0x00;
      31             : static constexpr uint8_t PSBT_IN_PARTIAL_SIG = 0x02;
      32             : static constexpr uint8_t PSBT_IN_SIGHASH = 0x03;
      33             : static constexpr uint8_t PSBT_IN_REDEEMSCRIPT = 0x04;
      34             : static constexpr uint8_t PSBT_IN_BIP32_DERIVATION = 0x06;
      35             : static constexpr uint8_t PSBT_IN_SCRIPTSIG = 0x07;
      36             : static constexpr uint8_t PSBT_IN_RIPEMD160 = 0x0A;
      37             : static constexpr uint8_t PSBT_IN_SHA256 = 0x0B;
      38             : static constexpr uint8_t PSBT_IN_HASH160 = 0x0C;
      39             : static constexpr uint8_t PSBT_IN_HASH256 = 0x0D;
      40             : static constexpr uint8_t PSBT_IN_PROPRIETARY = 0xFC;
      41             : 
      42             : // Output types
      43             : static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00;
      44             : static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
      45             : static constexpr uint8_t PSBT_OUT_PROPRIETARY = 0xFC;
      46             : 
      47             : // The separator is 0x00. Reading this in means that the unserializer can interpret it
      48             : // as a 0 length key which indicates that this is the separator. The separator has no value.
      49             : static constexpr uint8_t PSBT_SEPARATOR = 0x00;
      50             : 
      51             : // BIP 174 does not specify a maximum file size, but we set a limit anyway
      52             : // to prevent reading a stream indefinitely and running out of memory.
      53             : const std::streamsize MAX_FILE_SIZE_PSBT = 100000000; // 100 MB
      54             : 
      55             : // PSBT version number
      56             : static constexpr uint32_t PSBT_HIGHEST_VERSION = 0;
      57             : 
      58             : /** A structure for PSBT proprietary types */
      59           0 : struct PSBTProprietary
      60             : {
      61             :     uint64_t subtype;
      62             :     std::vector<unsigned char> identifier;
      63             :     std::vector<unsigned char> key;
      64             :     std::vector<unsigned char> value;
      65             : 
      66           0 :     bool operator<(const PSBTProprietary &b) const {
      67           0 :         return key < b.key;
      68             :     }
      69             :     bool operator==(const PSBTProprietary &b) const {
      70             :         return key == b.key;
      71             :     }
      72             : };
      73             : 
      74             : // Takes a stream and multiple arguments and serializes them as if first serialized into a vector and then into the stream
      75             : // The resulting output into the stream has the total serialized length of all of the objects followed by all objects concatenated with each other.
      76             : template<typename Stream, typename... X>
      77           7 : void SerializeToVector(Stream& s, const X&... args)
      78             : {
      79           7 :     WriteCompactSize(s, GetSerializeSizeMany(s.GetVersion(), args...));
      80           7 :     SerializeMany(s, args...);
      81           7 : }
      82             : 
      83             : // Takes a stream and multiple arguments and unserializes them first as a vector then each object individually in the order provided in the arguments
      84             : template<typename Stream, typename... X>
      85           1 : void UnserializeFromVector(Stream& s, X&... args)
      86             : {
      87           1 :     size_t expected_size = ReadCompactSize(s);
      88           1 :     size_t remaining_before = s.size();
      89           1 :     UnserializeMany(s, args...);
      90           1 :     size_t remaining_after = s.size();
      91           1 :     if (remaining_after + expected_size != remaining_before) {
      92           0 :         throw std::ios_base::failure("Size of value was not the stated size");
      93             :     }
      94           1 : }
      95             : 
      96             : // Deserialize an individual HD keypath to a stream
      97             : template<typename Stream>
      98           0 : void DeserializeHDKeypath(Stream& s, KeyOriginInfo& hd_keypath)
      99             : {
     100             :     // Read in key path
     101           0 :     uint64_t value_len = ReadCompactSize(s);
     102           0 :     if (value_len % 4 || value_len == 0) {
     103           0 :         throw std::ios_base::failure("Invalid length for HD key path");
     104             :     }
     105             : 
     106           0 :     s >> hd_keypath.fingerprint;
     107           0 :     for (unsigned int i = 4; i < value_len; i += sizeof(uint32_t)) {
     108             :         uint32_t index;
     109           0 :         s >> index;
     110           0 :         hd_keypath.path.push_back(index);
     111           0 :     }
     112           0 : }
     113             : 
     114             : // Deserialize HD keypaths into a map
     115             : template<typename Stream>
     116           0 : void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std::map<CPubKey, KeyOriginInfo>& hd_keypaths)
     117             : {
     118             :     // Make sure that the key is the size of pubkey + 1
     119           0 :     if (key.size() != CPubKey::SIZE + 1 && key.size() != CPubKey::COMPRESSED_SIZE + 1) {
     120           0 :         throw std::ios_base::failure("Size of key was not the expected size for the type BIP32 keypath");
     121             :     }
     122             :     // Read in the pubkey from key
     123           0 :     CPubKey pubkey(key.begin() + 1, key.end());
     124           0 :     if (!pubkey.IsFullyValid()) {
     125           0 :        throw std::ios_base::failure("Invalid pubkey");
     126             :     }
     127           0 :     if (hd_keypaths.count(pubkey) > 0) {
     128           0 :         throw std::ios_base::failure("Duplicate Key, pubkey derivation path already provided");
     129             :     }
     130             : 
     131           0 :     KeyOriginInfo keypath;
     132           0 :     DeserializeHDKeypath(s, keypath);
     133             : 
     134             :     // Add to map
     135           0 :     hd_keypaths.emplace(pubkey, std::move(keypath));
     136           0 : }
     137             : 
     138             : // Serialize an individual HD keypath to a stream
     139             : template<typename Stream>
     140           2 : void SerializeHDKeypath(Stream& s, KeyOriginInfo hd_keypath)
     141             : {
     142           2 :     WriteCompactSize(s, (hd_keypath.path.size() + 1) * sizeof(uint32_t));
     143           2 :     s << hd_keypath.fingerprint;
     144           8 :     for (const auto& path : hd_keypath.path) {
     145           6 :         s << path;
     146             :     }
     147           2 : }
     148             : 
     149             : // Serialize HD keypaths to a stream from a map
     150             : template<typename Stream>
     151           4 : void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, KeyOriginInfo>& hd_keypaths, CompactSizeWriter type)
     152             : {
     153           6 :     for (const auto& keypath_pair : hd_keypaths) {
     154           2 :         if (!keypath_pair.first.IsValid()) {
     155           0 :             throw std::ios_base::failure("Invalid CPubKey being serialized");
     156             :         }
     157           2 :         SerializeToVector(s, type, Span{keypath_pair.first});
     158           2 :         SerializeHDKeypath(s, keypath_pair.second);
     159             :     }
     160           4 : }
     161             : 
     162             : /** A structure for PSBTs which contain per-input information */
     163           2 : struct PSBTInput
     164             : {
     165             :     CTransactionRef non_witness_utxo;
     166             :     CScript redeem_script;
     167             :     CScript final_script_sig;
     168             :     std::map<CPubKey, KeyOriginInfo> hd_keypaths;
     169             :     std::map<CKeyID, SigPair> partial_sigs;
     170             :     std::map<uint160, std::vector<unsigned char>> ripemd160_preimages;
     171             :     std::map<uint256, std::vector<unsigned char>> sha256_preimages;
     172             :     std::map<uint160, std::vector<unsigned char>> hash160_preimages;
     173             :     std::map<uint256, std::vector<unsigned char>> hash256_preimages;
     174             :     std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
     175             :     std::set<PSBTProprietary> m_proprietary;
     176             :     std::optional<int> sighash_type;
     177             : 
     178             :     bool IsNull() const;
     179             :     void FillSignatureData(SignatureData& sigdata) const;
     180             :     void FromSignatureData(const SignatureData& sigdata);
     181             :     void Merge(const PSBTInput& input);
     182           4 :     PSBTInput() {}
     183             : 
     184             :     template <typename Stream>
     185           2 :     inline void Serialize(Stream& s) const {
     186             :         // Write the utxo
     187           2 :         if (non_witness_utxo) {
     188           1 :             SerializeToVector(s, CompactSizeWriter(PSBT_IN_NON_WITNESS_UTXO));
     189           1 :             SerializeToVector(s, non_witness_utxo);
     190           1 :         }
     191             : 
     192           2 :         if (final_script_sig.empty()) {
     193             :             // Write any partial signatures
     194           2 :             for (const auto& sig_pair : partial_sigs) {
     195           0 :                 SerializeToVector(s, CompactSizeWriter(PSBT_IN_PARTIAL_SIG), Span{sig_pair.second.first});
     196           0 :                 s << sig_pair.second.second;
     197             :             }
     198             : 
     199             :             // Write the sighash type
     200           2 :             if (sighash_type != std::nullopt) {
     201           0 :                 SerializeToVector(s, CompactSizeWriter(PSBT_IN_SIGHASH));
     202           0 :                 SerializeToVector(s, *sighash_type);
     203           0 :             }
     204             : 
     205             :             // Write the redeem script
     206           2 :             if (!redeem_script.empty()) {
     207           1 :                 SerializeToVector(s, CompactSizeWriter(PSBT_IN_REDEEMSCRIPT));
     208           1 :                 s << redeem_script;
     209           1 :             }
     210             : 
     211             :             // Write any hd keypaths
     212           2 :             SerializeHDKeypaths(s, hd_keypaths, CompactSizeWriter(PSBT_IN_BIP32_DERIVATION));
     213             : 
     214             :             // Write any ripemd160 preimage
     215           2 :             for (const auto& [hash, preimage] : ripemd160_preimages) {
     216           0 :                 SerializeToVector(s, CompactSizeWriter(PSBT_IN_RIPEMD160), Span{hash});
     217           0 :                 s << preimage;
     218             :             }
     219             : 
     220             :             // Write any sha256 preimage
     221           2 :             for (const auto& [hash, preimage] : sha256_preimages) {
     222           0 :                 SerializeToVector(s, CompactSizeWriter(PSBT_IN_SHA256), Span{hash});
     223           0 :                 s << preimage;
     224             :             }
     225             : 
     226             :             // Write any hash160 preimage
     227           2 :             for (const auto& [hash, preimage] : hash160_preimages) {
     228           0 :                 SerializeToVector(s, CompactSizeWriter(PSBT_IN_HASH160), Span{hash});
     229           0 :                 s << preimage;
     230             :             }
     231             : 
     232             :             // Write any hash256 preimage
     233           2 :             for (const auto& [hash, preimage] : hash256_preimages) {
     234           0 :                 SerializeToVector(s, CompactSizeWriter(PSBT_IN_HASH256), Span{hash});
     235           0 :                 s << preimage;
     236             :             }
     237           2 :         }
     238             : 
     239             :         // Write script sig
     240           2 :         if (!final_script_sig.empty()) {
     241           0 :             SerializeToVector(s, CompactSizeWriter(PSBT_IN_SCRIPTSIG));
     242           0 :             s << final_script_sig;
     243           0 :         }
     244             : 
     245             :         // Write proprietary things
     246           2 :         for (const auto& entry : m_proprietary) {
     247           0 :             s << entry.key;
     248           0 :             s << entry.value;
     249             :         }
     250             : 
     251             :         // Write unknown things
     252           2 :         for (auto& entry : unknown) {
     253           0 :             s << entry.first;
     254           0 :             s << entry.second;
     255             :         }
     256             : 
     257           2 :         s << PSBT_SEPARATOR;
     258           2 :     }
     259             : 
     260             : 
     261             :     template <typename Stream>
     262           2 :     inline void Unserialize(Stream& s) {
     263             :         // Used for duplicate key detection
     264           2 :         std::set<std::vector<unsigned char>> key_lookup;
     265             : 
     266             :         // Read loop
     267           2 :         bool found_sep = false;
     268           2 :         while(!s.empty()) {
     269             :             // Read
     270           2 :             std::vector<unsigned char> key;
     271           2 :             s >> key;
     272             : 
     273             :             // the key is empty if that was actually a separator byte
     274             :             // This is a special case for key lengths 0 as those are not allowed (except for separator)
     275           2 :             if (key.empty()) {
     276           2 :                 found_sep = true;
     277           2 :                 break;
     278             :             }
     279             : 
     280             :             // Type is compact size uint at beginning of key
     281           0 :             SpanReader skey(s.GetType(), s.GetVersion(), key);
     282           0 :             uint64_t type = ReadCompactSize(skey);
     283             : 
     284             :             // Do stuff based on type
     285           0 :             switch(type) {
     286             :                 case PSBT_IN_NON_WITNESS_UTXO:
     287           0 :                     if (!key_lookup.emplace(key).second) {
     288           0 :                         throw std::ios_base::failure("Duplicate Key, input non-witness utxo already provided");
     289           0 :                     } else if (key.size() != 1) {
     290           0 :                         throw std::ios_base::failure("Non-witness utxo key is more than one byte type");
     291             :                     }
     292           0 :                     UnserializeFromVector(s, non_witness_utxo);
     293           0 :                     break;
     294             :                 case PSBT_IN_PARTIAL_SIG:
     295             :                 {
     296             :                     // Make sure that the key is the size of pubkey + 1
     297           0 :                     if (key.size() != CPubKey::SIZE + 1 && key.size() != CPubKey::COMPRESSED_SIZE + 1) {
     298           0 :                         throw std::ios_base::failure("Size of key was not the expected size for the type partial signature pubkey");
     299             :                     }
     300             :                     // Read in the pubkey from key
     301           0 :                     CPubKey pubkey(key.begin() + 1, key.end());
     302           0 :                     if (!pubkey.IsFullyValid()) {
     303           0 :                        throw std::ios_base::failure("Invalid pubkey");
     304             :                     }
     305           0 :                     if (partial_sigs.count(pubkey.GetID()) > 0) {
     306           0 :                         throw std::ios_base::failure("Duplicate Key, input partial signature for pubkey already provided");
     307             :                     }
     308             : 
     309             :                     // Read in the signature from value
     310           0 :                     std::vector<unsigned char> sig;
     311           0 :                     s >> sig;
     312             : 
     313             :                     // Add to list
     314           0 :                     partial_sigs.emplace(pubkey.GetID(), SigPair(pubkey, std::move(sig)));
     315             :                     break;
     316           0 :                 }
     317             :                 case PSBT_IN_SIGHASH:
     318           0 :                     if (!key_lookup.emplace(key).second) {
     319           0 :                         throw std::ios_base::failure("Duplicate Key, input sighash type already provided");
     320           0 :                     } else if (key.size() != 1) {
     321           0 :                         throw std::ios_base::failure("Sighash type key is more than one byte type");
     322             :                     }
     323             :                     int sighash;
     324           0 :                     UnserializeFromVector(s, sighash);
     325           0 :                     sighash_type = sighash;
     326           0 :                     break;
     327             :                 case PSBT_IN_REDEEMSCRIPT:
     328             :                 {
     329           0 :                     if (!key_lookup.emplace(key).second) {
     330           0 :                         throw std::ios_base::failure("Duplicate Key, input redeemScript already provided");
     331           0 :                     } else if (key.size() != 1) {
     332           0 :                         throw std::ios_base::failure("Input redeemScript key is more than one byte type");
     333             :                     }
     334           0 :                     s >> redeem_script;
     335           0 :                     break;
     336             :                 }
     337             :                 case PSBT_IN_BIP32_DERIVATION:
     338             :                 {
     339           0 :                     DeserializeHDKeypaths(s, key, hd_keypaths);
     340           0 :                     break;
     341             :                 }
     342             :                 case PSBT_IN_SCRIPTSIG:
     343             :                 {
     344           0 :                     if (!key_lookup.emplace(key).second) {
     345           0 :                         throw std::ios_base::failure("Duplicate Key, input final scriptSig already provided");
     346           0 :                     } else if (key.size() != 1) {
     347           0 :                         throw std::ios_base::failure("Final scriptSig key is more than one byte type");
     348             :                     }
     349           0 :                     s >> final_script_sig;
     350           0 :                     break;
     351             :                 }
     352             :                 case PSBT_IN_RIPEMD160:
     353             :                 {
     354             :                     // Make sure that the key is the size of a ripemd160 hash + 1
     355           0 :                     if (key.size() != CRIPEMD160::OUTPUT_SIZE + 1) {
     356           0 :                         throw std::ios_base::failure("Size of key was not the expected size for the type ripemd160 preimage");
     357             :                     }
     358             :                     // Read in the hash from key
     359           0 :                     std::vector<unsigned char> hash_vec(key.begin() + 1, key.end());
     360           0 :                     uint160 hash(hash_vec);
     361           0 :                     if (ripemd160_preimages.count(hash) > 0) {
     362           0 :                         throw std::ios_base::failure("Duplicate Key, input ripemd160 preimage already provided");
     363             :                     }
     364             : 
     365             :                     // Read in the preimage from value
     366           0 :                     std::vector<unsigned char> preimage;
     367           0 :                     s >> preimage;
     368             : 
     369             :                     // Add to preimages list
     370           0 :                     ripemd160_preimages.emplace(hash, std::move(preimage));
     371             :                     break;
     372           0 :                 }
     373             :                 case PSBT_IN_SHA256:
     374             :                 {
     375             :                     // Make sure that the key is the size of a sha256 hash + 1
     376           0 :                     if (key.size() != CSHA256::OUTPUT_SIZE + 1) {
     377           0 :                         throw std::ios_base::failure("Size of key was not the expected size for the type sha256 preimage");
     378             :                     }
     379             :                     // Read in the hash from key
     380           0 :                     std::vector<unsigned char> hash_vec(key.begin() + 1, key.end());
     381           0 :                     uint256 hash(hash_vec);
     382           0 :                     if (sha256_preimages.count(hash) > 0) {
     383           0 :                         throw std::ios_base::failure("Duplicate Key, input sha256 preimage already provided");
     384             :                     }
     385             : 
     386             :                     // Read in the preimage from value
     387           0 :                     std::vector<unsigned char> preimage;
     388           0 :                     s >> preimage;
     389             : 
     390             :                     // Add to preimages list
     391           0 :                     sha256_preimages.emplace(hash, std::move(preimage));
     392             :                     break;
     393           0 :                 }
     394             :                 case PSBT_IN_HASH160:
     395             :                 {
     396             :                     // Make sure that the key is the size of a hash160 hash + 1
     397           0 :                     if (key.size() != CHash160::OUTPUT_SIZE + 1) {
     398           0 :                         throw std::ios_base::failure("Size of key was not the expected size for the type hash160 preimage");
     399             :                     }
     400             :                     // Read in the hash from key
     401           0 :                     std::vector<unsigned char> hash_vec(key.begin() + 1, key.end());
     402           0 :                     uint160 hash(hash_vec);
     403           0 :                     if (hash160_preimages.count(hash) > 0) {
     404           0 :                         throw std::ios_base::failure("Duplicate Key, input hash160 preimage already provided");
     405             :                     }
     406             : 
     407             :                     // Read in the preimage from value
     408           0 :                     std::vector<unsigned char> preimage;
     409           0 :                     s >> preimage;
     410             : 
     411             :                     // Add to preimages list
     412           0 :                     hash160_preimages.emplace(hash, std::move(preimage));
     413             :                     break;
     414           0 :                 }
     415             :                 case PSBT_IN_HASH256:
     416             :                 {
     417             :                     // Make sure that the key is the size of a hash256 hash + 1
     418           0 :                     if (key.size() != CHash256::OUTPUT_SIZE + 1) {
     419           0 :                         throw std::ios_base::failure("Size of key was not the expected size for the type hash256 preimage");
     420             :                     }
     421             :                     // Read in the hash from key
     422           0 :                     std::vector<unsigned char> hash_vec(key.begin() + 1, key.end());
     423           0 :                     uint256 hash(hash_vec);
     424           0 :                     if (hash256_preimages.count(hash) > 0) {
     425           0 :                         throw std::ios_base::failure("Duplicate Key, input hash256 preimage already provided");
     426             :                     }
     427             : 
     428             :                     // Read in the preimage from value
     429           0 :                     std::vector<unsigned char> preimage;
     430           0 :                     s >> preimage;
     431             : 
     432             :                     // Add to preimages list
     433           0 :                     hash256_preimages.emplace(hash, std::move(preimage));
     434             :                     break;
     435           0 :                 }
     436             :                 case PSBT_IN_PROPRIETARY:
     437             :                 {
     438           0 :                     PSBTProprietary this_prop;
     439           0 :                     skey >> this_prop.identifier;
     440           0 :                     this_prop.subtype = ReadCompactSize(skey);
     441           0 :                     this_prop.key = key;
     442             : 
     443           0 :                     if (m_proprietary.count(this_prop) > 0) {
     444           0 :                         throw std::ios_base::failure("Duplicate Key, proprietary key already found");
     445             :                     }
     446           0 :                     s >> this_prop.value;
     447           0 :                     m_proprietary.insert(this_prop);
     448             :                     break;
     449           0 :                 }
     450             :                 // Unknown stuff
     451             :                 default:
     452           0 :                     if (unknown.count(key) > 0) {
     453           0 :                         throw std::ios_base::failure("Duplicate Key, key for unknown value already provided");
     454             :                     }
     455             :                     // Read in the value
     456           0 :                     std::vector<unsigned char> val_bytes;
     457           0 :                     s >> val_bytes;
     458           0 :                     unknown.emplace(std::move(key), std::move(val_bytes));
     459             :                     break;
     460           0 :             }
     461           2 :         }
     462             : 
     463           2 :         if (!found_sep) {
     464           0 :             throw std::ios_base::failure("Separator is missing at the end of an input map");
     465             :         }
     466           2 :     }
     467             : 
     468             :     template <typename Stream>
     469             :     PSBTInput(deserialize_type, Stream& s) {
     470             :         Unserialize(s);
     471             :     }
     472             : };
     473             : 
     474             : /** A structure for PSBTs which contains per output information */
     475           2 : struct PSBTOutput
     476             : {
     477             :     CScript redeem_script;
     478             :     std::map<CPubKey, KeyOriginInfo> hd_keypaths;
     479             :     std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
     480             :     std::set<PSBTProprietary> m_proprietary;
     481             : 
     482             :     bool IsNull() const;
     483             :     void FillSignatureData(SignatureData& sigdata) const;
     484             :     void FromSignatureData(const SignatureData& sigdata);
     485             :     void Merge(const PSBTOutput& output);
     486           4 :     PSBTOutput() {}
     487             : 
     488             :     template <typename Stream>
     489           2 :     inline void Serialize(Stream& s) const {
     490             :         // Write the redeem script
     491           2 :         if (!redeem_script.empty()) {
     492           0 :             SerializeToVector(s, CompactSizeWriter(PSBT_OUT_REDEEMSCRIPT));
     493           0 :             s << redeem_script;
     494           0 :         }
     495             : 
     496             :         // Write any hd keypaths
     497           2 :         SerializeHDKeypaths(s, hd_keypaths, CompactSizeWriter(PSBT_OUT_BIP32_DERIVATION));
     498             : 
     499             :         // Write proprietary things
     500           2 :         for (const auto& entry : m_proprietary) {
     501           0 :             s << entry.key;
     502           0 :             s << entry.value;
     503             :         }
     504             : 
     505             :         // Write unknown things
     506           2 :         for (auto& entry : unknown) {
     507           0 :             s << entry.first;
     508           0 :             s << entry.second;
     509             :         }
     510             : 
     511           2 :         s << PSBT_SEPARATOR;
     512           2 :     }
     513             : 
     514             : 
     515             :     template <typename Stream>
     516           2 :     inline void Unserialize(Stream& s) {
     517             :         // Used for duplicate key detection
     518           2 :         std::set<std::vector<unsigned char>> key_lookup;
     519             : 
     520             :         // Read loop
     521           2 :         bool found_sep = false;
     522           2 :         while(!s.empty()) {
     523             :             // Read
     524           2 :             std::vector<unsigned char> key;
     525           2 :             s >> key;
     526             : 
     527             :             // the key is empty if that was actually a separator byte
     528             :             // This is a special case for key lengths 0 as those are not allowed (except for separator)
     529           2 :             if (key.empty()) {
     530           2 :                 found_sep = true;
     531           2 :                 break;
     532             :             }
     533             : 
     534             :             // Type is compact size uint at beginning of key
     535           0 :             SpanReader skey(s.GetType(), s.GetVersion(), key);
     536           0 :             uint64_t type = ReadCompactSize(skey);
     537             : 
     538             :             // Do stuff based on type
     539           0 :             switch(type) {
     540             :                 case PSBT_OUT_REDEEMSCRIPT:
     541             :                 {
     542           0 :                     if (!key_lookup.emplace(key).second) {
     543           0 :                         throw std::ios_base::failure("Duplicate Key, output redeemScript already provided");
     544           0 :                     } else if (key.size() != 1) {
     545           0 :                         throw std::ios_base::failure("Output redeemScript key is more than one byte type");
     546             :                     }
     547           0 :                     s >> redeem_script;
     548           0 :                     break;
     549             :                 }
     550             :                 case PSBT_OUT_BIP32_DERIVATION:
     551             :                 {
     552           0 :                     DeserializeHDKeypaths(s, key, hd_keypaths);
     553           0 :                     break;
     554             :                 }
     555             :                 case PSBT_OUT_PROPRIETARY:
     556             :                 {
     557           0 :                     PSBTProprietary this_prop;
     558           0 :                     skey >> this_prop.identifier;
     559           0 :                     this_prop.subtype = ReadCompactSize(skey);
     560           0 :                     this_prop.key = key;
     561             : 
     562           0 :                     if (m_proprietary.count(this_prop) > 0) {
     563           0 :                         throw std::ios_base::failure("Duplicate Key, proprietary key already found");
     564             :                     }
     565           0 :                     s >> this_prop.value;
     566           0 :                     m_proprietary.insert(this_prop);
     567             :                     break;
     568           0 :                 }
     569             :                 // Unknown stuff
     570             :                 default: {
     571           0 :                     if (unknown.count(key) > 0) {
     572           0 :                         throw std::ios_base::failure("Duplicate Key, key for unknown value already provided");
     573             :                     }
     574             :                     // Read in the value
     575           0 :                     std::vector<unsigned char> val_bytes;
     576           0 :                     s >> val_bytes;
     577           0 :                     unknown.emplace(std::move(key), std::move(val_bytes));
     578             :                     break;
     579           0 :                 }
     580             :             }
     581           2 :         }
     582             : 
     583           2 :         if (!found_sep) {
     584           0 :             throw std::ios_base::failure("Separator is missing at the end of an output map");
     585             :         }
     586           2 :     }
     587             : 
     588             :     template <typename Stream>
     589             :     PSBTOutput(deserialize_type, Stream& s) {
     590             :         Unserialize(s);
     591             :     }
     592             : };
     593             : 
     594             : /** A version of CTransaction with the PSBT format*/
     595           0 : struct PartiallySignedTransaction
     596             : {
     597             :     std::optional<CMutableTransaction> tx;
     598             :     // We use a vector of CExtPubKey in the event that there happens to be the same KeyOriginInfos for different CExtPubKeys
     599             :     // Note that this map swaps the key and values from the serialization
     600             :     std::map<KeyOriginInfo, std::set<CExtPubKey>> m_xpubs;
     601             :     std::vector<PSBTInput> inputs;
     602             :     std::vector<PSBTOutput> outputs;
     603             :     std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
     604             :     std::optional<uint32_t> m_version;
     605             :     std::set<PSBTProprietary> m_proprietary;
     606             : 
     607             :     bool IsNull() const;
     608             :     uint32_t GetVersion() const;
     609             : 
     610             :     /** Merge psbt into this. The two psbts must have the same underlying CTransaction (i.e. the
     611             :       * same actual Bitcoin transaction.) Returns true if the merge succeeded, false otherwise. */
     612             :     [[nodiscard]] bool Merge(const PartiallySignedTransaction& psbt);
     613             :     bool AddInput(const CTxIn& txin, PSBTInput& psbtin);
     614             :     bool AddOutput(const CTxOut& txout, const PSBTOutput& psbtout);
     615           2 :     PartiallySignedTransaction() {}
     616             :     explicit PartiallySignedTransaction(const CMutableTransaction& tx);
     617             : 
     618             :     /**
     619             :      * Finds the UTXO for a given input index
     620             :      *
     621             :      * @param[out] utxo The UTXO of the input if found
     622             :      * @param[in] input_index Index of the input to retrieve the UTXO of
     623             :      * @return Whether the UTXO for the specified input was found
     624             :      */
     625             :     bool GetInputUTXO(CTxOut& utxo, int input_index) const;
     626             : 
     627             :     template <typename Stream>
     628           1 :     inline void Serialize(Stream& s) const {
     629             : 
     630             :         // magic bytes
     631           1 :         s << PSBT_MAGIC_BYTES;
     632             : 
     633             :         // unsigned tx flag
     634           1 :         SerializeToVector(s, CompactSizeWriter(PSBT_GLOBAL_UNSIGNED_TX));
     635             : 
     636             :         // Write serialized tx to a stream
     637           1 :         SerializeToVector(s, *tx);
     638             : 
     639             :         // Write xpubs
     640           1 :         for (const auto& xpub_pair : m_xpubs) {
     641           0 :             for (const auto& xpub : xpub_pair.second) {
     642             :                 unsigned char ser_xpub[BIP32_EXTKEY_WITH_VERSION_SIZE];
     643           0 :                 xpub.EncodeWithVersion(ser_xpub);
     644             :                 // Note that the serialization swaps the key and value
     645             :                 // The xpub is the key (for uniqueness) while the path is the value
     646           0 :                 SerializeToVector(s, PSBT_GLOBAL_XPUB, ser_xpub);
     647           0 :                 SerializeHDKeypath(s, xpub_pair.first);
     648             :             }
     649             :         }
     650             : 
     651             :         // PSBT version
     652           1 :         if (GetVersion() > 0) {
     653           0 :             SerializeToVector(s, CompactSizeWriter(PSBT_GLOBAL_VERSION));
     654           0 :             SerializeToVector(s, *m_version);
     655           0 :         }
     656             : 
     657             :         // Write proprietary things
     658           1 :         for (const auto& entry : m_proprietary) {
     659           0 :             s << entry.key;
     660           0 :             s << entry.value;
     661             :         }
     662             : 
     663             :         // Write the unknown things
     664           1 :         for (auto& entry : unknown) {
     665           0 :             s << entry.first;
     666           0 :             s << entry.second;
     667             :         }
     668             : 
     669             :         // Separator
     670           1 :         s << PSBT_SEPARATOR;
     671             : 
     672             :         // Write inputs
     673           3 :         for (const PSBTInput& input : inputs) {
     674           2 :             s << input;
     675             :         }
     676             :         // Write outputs
     677           3 :         for (const PSBTOutput& output : outputs) {
     678           2 :             s << output;
     679             :         }
     680           1 :     }
     681             : 
     682             : 
     683             :     template <typename Stream>
     684           1 :     inline void Unserialize(Stream& s) {
     685             :         // Read the magic bytes
     686             :         uint8_t magic[5];
     687           1 :         s >> magic;
     688           1 :         if (!std::equal(magic, magic + 5, PSBT_MAGIC_BYTES)) {
     689           0 :             throw std::ios_base::failure("Invalid PSBT magic bytes");
     690             :         }
     691             : 
     692             :         // Used for duplicate key detection
     693           1 :         std::set<std::vector<unsigned char>> key_lookup;
     694             : 
     695             :         // Track the global xpubs we have already seen. Just for sanity checking
     696           1 :         std::set<CExtPubKey> global_xpubs;
     697             : 
     698             :         // Read global data
     699           1 :         bool found_sep = false;
     700           2 :         while(!s.empty()) {
     701             :             // Read
     702           2 :             std::vector<unsigned char> key;
     703           2 :             s >> key;
     704             : 
     705             :             // the key is empty if that was actually a separator byte
     706             :             // This is a special case for key lengths 0 as those are not allowed (except for separator)
     707           2 :             if (key.empty()) {
     708           1 :                 found_sep = true;
     709           1 :                 break;
     710             :             }
     711             : 
     712             :             // Type is compact size uint at beginning of key
     713           1 :             SpanReader skey(s.GetType(), s.GetVersion(), key);
     714           1 :             uint64_t type = ReadCompactSize(skey);
     715             : 
     716             :             // Do stuff based on type
     717           1 :             switch(type) {
     718             :                 case PSBT_GLOBAL_UNSIGNED_TX:
     719             :                 {
     720           1 :                     if (!key_lookup.emplace(key).second) {
     721           0 :                         throw std::ios_base::failure("Duplicate Key, unsigned tx already provided");
     722           1 :                     } else if (key.size() != 1) {
     723           0 :                         throw std::ios_base::failure("Global unsigned tx key is more than one byte type");
     724             :                     }
     725           1 :                     CMutableTransaction mtx;
     726           1 :                     UnserializeFromVector(s, mtx);
     727           1 :                     tx = std::move(mtx);
     728             :                     // Make sure that all scriptSigs are empty
     729           3 :                     for (const CTxIn& txin : tx->vin) {
     730           2 :                         if (!txin.scriptSig.empty()) {
     731           0 :                             throw std::ios_base::failure("Unsigned tx does not have empty scriptSigs.");
     732             :                         }
     733             :                     }
     734             :                     break;
     735           1 :                 }
     736             :                 case PSBT_GLOBAL_XPUB:
     737             :                 {
     738           0 :                     if (key.size() != BIP32_EXTKEY_WITH_VERSION_SIZE + 1) {
     739           0 :                         throw std::ios_base::failure("Size of key was not the expected size for the type global xpub");
     740             :                     }
     741             :                     // Read in the xpub from key
     742           0 :                     CExtPubKey xpub;
     743           0 :                     xpub.DecodeWithVersion(&key.data()[1]);
     744           0 :                     if (!xpub.pubkey.IsFullyValid()) {
     745           0 :                        throw std::ios_base::failure("Invalid pubkey");
     746             :                     }
     747           0 :                     if (global_xpubs.count(xpub) > 0) {
     748           0 :                        throw std::ios_base::failure("Duplicate key, global xpub already provided");
     749             :                     }
     750           0 :                     global_xpubs.insert(xpub);
     751             :                     // Read in the keypath from stream
     752           0 :                     KeyOriginInfo keypath;
     753           0 :                     DeserializeHDKeypath(s, keypath);
     754             : 
     755             :                     // Note that we store these swapped to make searches faster.
     756             :                     // Serialization uses xpub -> keypath to enqure key uniqueness
     757           0 :                     if (m_xpubs.count(keypath) == 0) {
     758             :                         // Make a new set to put the xpub in
     759           0 :                         m_xpubs[keypath] = {xpub};
     760           0 :                     } else {
     761             :                         // Insert xpub into existing set
     762           0 :                         m_xpubs[keypath].insert(xpub);
     763             :                     }
     764             :                     break;
     765           0 :                 }
     766             :                 case PSBT_GLOBAL_VERSION:
     767             :                 {
     768           0 :                     if (m_version) {
     769           0 :                         throw std::ios_base::failure("Duplicate Key, version already provided");
     770           0 :                     } else if (key.size() != 1) {
     771           0 :                         throw std::ios_base::failure("Global version key is more than one byte type");
     772             :                     }
     773             :                     uint32_t v;
     774           0 :                     UnserializeFromVector(s, v);
     775           0 :                     m_version = v;
     776           0 :                     if (*m_version > PSBT_HIGHEST_VERSION) {
     777           0 :                         throw std::ios_base::failure("Unsupported version number");
     778             :                     }
     779           0 :                     break;
     780             :                 }
     781             :                 case PSBT_GLOBAL_PROPRIETARY:
     782             :                 {
     783           0 :                     PSBTProprietary this_prop;
     784           0 :                     skey >> this_prop.identifier;
     785           0 :                     this_prop.subtype = ReadCompactSize(skey);
     786           0 :                     this_prop.key = key;
     787             : 
     788           0 :                     if (m_proprietary.count(this_prop) > 0) {
     789           0 :                         throw std::ios_base::failure("Duplicate Key, proprietary key already found");
     790             :                     }
     791           0 :                     s >> this_prop.value;
     792           0 :                     m_proprietary.insert(this_prop);
     793             :                     break;
     794           0 :                 }
     795             :                 // Unknown stuff
     796             :                 default: {
     797           0 :                     if (unknown.count(key) > 0) {
     798           0 :                         throw std::ios_base::failure("Duplicate Key, key for unknown value already provided");
     799             :                     }
     800             :                     // Read in the value
     801           0 :                     std::vector<unsigned char> val_bytes;
     802           0 :                     s >> val_bytes;
     803           0 :                     unknown.emplace(std::move(key), std::move(val_bytes));
     804           0 :                 }
     805           0 :             }
     806           2 :         }
     807             : 
     808           1 :         if (!found_sep) {
     809           0 :             throw std::ios_base::failure("Separator is missing at the end of the global map");
     810             :         }
     811             : 
     812             :         // Make sure that we got an unsigned tx
     813           1 :         if (!tx) {
     814           0 :             throw std::ios_base::failure("No unsigned transaction was provided");
     815             :         }
     816             : 
     817             :         // Read input data
     818           1 :         unsigned int i = 0;
     819           3 :         while (!s.empty() && i < tx->vin.size()) {
     820           2 :             PSBTInput input;
     821           2 :             s >> input;
     822           2 :             inputs.push_back(input);
     823             : 
     824             :             // Make sure the non-witness utxo matches the outpoint
     825           2 :             if (input.non_witness_utxo && input.non_witness_utxo->GetHash() != tx->vin[i].prevout.hash) {
     826           0 :                 throw std::ios_base::failure("Non-witness UTXO does not match outpoint hash");
     827             :             }
     828           2 :             ++i;
     829           2 :         }
     830             :         // Make sure that the number of inputs matches the number of inputs in the transaction
     831           1 :         if (inputs.size() != tx->vin.size()) {
     832           0 :             throw std::ios_base::failure("Inputs provided does not match the number of inputs in transaction.");
     833             :         }
     834             : 
     835             :         // Read output data
     836           1 :         i = 0;
     837           3 :         while (!s.empty() && i < tx->vout.size()) {
     838           2 :             PSBTOutput output;
     839           2 :             s >> output;
     840           2 :             outputs.push_back(output);
     841           2 :             ++i;
     842           2 :         }
     843             :         // Make sure that the number of outputs matches the number of outputs in the transaction
     844           1 :         if (outputs.size() != tx->vout.size()) {
     845           0 :             throw std::ios_base::failure("Outputs provided does not match the number of outputs in transaction.");
     846             :         }
     847           1 :     }
     848             : 
     849             :     template <typename Stream>
     850             :     PartiallySignedTransaction(deserialize_type, Stream& s) {
     851             :         Unserialize(s);
     852             :     }
     853             : };
     854             : 
     855             : enum class PSBTRole {
     856             :     CREATOR,
     857             :     UPDATER,
     858             :     SIGNER,
     859             :     FINALIZER,
     860             :     EXTRACTOR
     861             : };
     862             : 
     863             : std::string PSBTRoleName(PSBTRole role);
     864             : 
     865             : /** Compute a PrecomputedTransactionData object from a psbt. */
     866             : PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction& psbt);
     867             : 
     868             : /** Checks whether a PSBTInput is already signed. */
     869             : bool PSBTInputSigned(const PSBTInput& input);
     870             : 
     871             : /** Signs a PSBTInput, verifying that all provided data matches what is being signed.
     872             :  *
     873             :  * txdata should be the output of PrecomputePSBTData (which can be shared across
     874             :  * multiple SignPSBTInput calls). If it is nullptr, a dummy signature will be created.
     875             :  **/
     876             : bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, int sighash = SIGHASH_ALL, SignatureData* out_sigdata = nullptr, bool finalize = true);
     877             : 
     878             : /**  Reduces the size of the PSBT by dropping unnecessary `non_witness_utxos` (i.e. complete previous transactions) from a psbt when all inputs are segwit v1. */
     879             : void RemoveUnnecessaryTransactions(PartiallySignedTransaction& psbtx, const int& sighash_type);
     880             : 
     881             : /** Counts the unsigned inputs of a PSBT. */
     882             : size_t CountPSBTUnsignedInputs(const PartiallySignedTransaction& psbt);
     883             : 
     884             : /** Updates a PSBTOutput with information from provider.
     885             :  *
     886             :  * This fills in the redeem_script, and hd_keypaths where possible.
     887             :  */
     888             : void UpdatePSBTOutput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index);
     889             : 
     890             : /**
     891             :  * Finalizes a PSBT if possible, combining partial signatures.
     892             :  *
     893             :  * @param[in,out] psbtx PartiallySignedTransaction to finalize
     894             :  * return True if the PSBT is now complete, false otherwise
     895             :  */
     896             : bool FinalizePSBT(PartiallySignedTransaction& psbtx);
     897             : 
     898             : /**
     899             :  * Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized.
     900             :  *
     901             :  * @param[in]  psbtx PartiallySignedTransaction
     902             :  * @param[out] result CMutableTransaction representing the complete transaction, if successful
     903             :  * @return True if we successfully extracted the transaction, false otherwise
     904             :  */
     905             : bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransaction& result);
     906             : 
     907             : /**
     908             :  * Combines PSBTs with the same underlying transaction, resulting in a single PSBT with all partial signatures from each input.
     909             :  *
     910             :  * @param[out] out   the combined PSBT, if successful
     911             :  * @param[in]  psbtxs the PSBTs to combine
     912             :  * @return error (OK if we successfully combined the transactions, other error if they were not compatible)
     913             :  */
     914             : [[nodiscard]] TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs);
     915             : 
     916             : //! Decode a base64ed PSBT into a PartiallySignedTransaction
     917             : [[nodiscard]] bool DecodeBase64PSBT(PartiallySignedTransaction& decoded_psbt, const std::string& base64_psbt, std::string& error);
     918             : //! Decode a raw (binary blob) PSBT into a PartiallySignedTransaction
     919             : [[nodiscard]] bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, Span<const std::byte> raw_psbt, std::string& error);
     920             : 
     921             : #endif // BITCOIN_PSBT_H

Generated by: LCOV version 1.16