LCOV - code coverage report
Current view: top level - src - psbt.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 209 240 87.1 %
Date: 2026-06-25 07:23:43 Functions: 25 29 86.2 %

          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             : #include <coins.h>
       6             : #include <consensus/tx_verify.h>
       7             : #include <policy/policy.h>
       8             : #include <policy/settings.h>
       9             : #include <psbt.h>
      10             : #include <tinyformat.h>
      11             : #include <util/check.h>
      12             : #include <util/strencodings.h>
      13             : 
      14             : #include <numeric>
      15             : 
      16         996 : PartiallySignedTransaction::PartiallySignedTransaction(const CMutableTransaction& tx) : tx(tx)
      17         498 : {
      18         498 :     inputs.resize(tx.vin.size());
      19         498 :     outputs.resize(tx.vout.size());
      20         996 : }
      21             : 
      22           0 : bool PartiallySignedTransaction::IsNull() const
      23             : {
      24           0 :     return !tx && inputs.empty() && outputs.empty() && unknown.empty();
      25             : }
      26             : 
      27          22 : bool PartiallySignedTransaction::Merge(const PartiallySignedTransaction& psbt)
      28             : {
      29             :     // Prohibited to merge two PSBTs over different transactions
      30          22 :     if (tx->GetHash() != psbt.tx->GetHash()) {
      31           4 :         return false;
      32             :     }
      33             : 
      34          44 :     for (unsigned int i = 0; i < inputs.size(); ++i) {
      35          26 :         inputs[i].Merge(psbt.inputs[i]);
      36          26 :     }
      37          42 :     for (unsigned int i = 0; i < outputs.size(); ++i) {
      38          24 :         outputs[i].Merge(psbt.outputs[i]);
      39          24 :     }
      40          18 :     for (auto& xpub_pair : psbt.m_xpubs) {
      41           0 :         if (m_xpubs.count(xpub_pair.first) == 0) {
      42           0 :             m_xpubs[xpub_pair.first] = xpub_pair.second;
      43           0 :         } else {
      44           0 :             m_xpubs[xpub_pair.first].insert(xpub_pair.second.begin(), xpub_pair.second.end());
      45             :         }
      46             :     }
      47          18 :     unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
      48             : 
      49          18 :     return true;
      50          22 : }
      51             : 
      52          24 : bool PartiallySignedTransaction::AddInput(const CTxIn& txin, PSBTInput& psbtin)
      53             : {
      54          24 :     if (std::find(tx->vin.begin(), tx->vin.end(), txin) != tx->vin.end()) {
      55           4 :         return false;
      56             :     }
      57          20 :     tx->vin.push_back(txin);
      58          20 :     psbtin.partial_sigs.clear();
      59          20 :     psbtin.final_script_sig.clear();
      60          20 :     inputs.push_back(psbtin);
      61          20 :     return true;
      62          24 : }
      63             : 
      64          12 : bool PartiallySignedTransaction::AddOutput(const CTxOut& txout, const PSBTOutput& psbtout)
      65             : {
      66          12 :     tx->vout.push_back(txout);
      67          12 :     outputs.push_back(psbtout);
      68          12 :     return true;
      69             : }
      70             : 
      71        2493 : bool PartiallySignedTransaction::GetInputUTXO(CTxOut& utxo, int input_index) const
      72             : {
      73        2493 :     const PSBTInput& input = inputs[input_index];
      74        2493 :     uint32_t prevout_index = tx->vin[input_index].prevout.n;
      75        2493 :     if (input.non_witness_utxo) {
      76        1457 :         if (prevout_index >= input.non_witness_utxo->vout.size()) {
      77          13 :             return false;
      78             :         }
      79        1444 :         if (input.non_witness_utxo->GetHash() != tx->vin[input_index].prevout.hash) {
      80           0 :             return false;
      81             :         }
      82        1444 :         utxo = input.non_witness_utxo->vout[prevout_index];
      83        1444 :     } else {
      84        1036 :         return false;
      85             :     }
      86        1444 :     return true;
      87        2493 : }
      88             : 
      89           0 : bool PSBTInput::IsNull() const
      90             : {
      91           0 :     return !non_witness_utxo && partial_sigs.empty() && unknown.empty() && hd_keypaths.empty() && redeem_script.empty();
      92             : }
      93             : 
      94        2969 : void PSBTInput::FillSignatureData(SignatureData& sigdata) const
      95             : {
      96        2969 :     if (!final_script_sig.empty()) {
      97           0 :         sigdata.scriptSig = final_script_sig;
      98           0 :         sigdata.complete = true;
      99           0 :     }
     100        2969 :     if (sigdata.complete) {
     101           0 :         return;
     102             :     }
     103             : 
     104        2969 :     sigdata.signatures.insert(partial_sigs.begin(), partial_sigs.end());
     105        2969 :     if (!redeem_script.empty()) {
     106         128 :         sigdata.redeem_script = redeem_script;
     107         128 :     }
     108        4772 :     for (const auto& key_pair : hd_keypaths) {
     109        1803 :         sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
     110             :     }
     111        2969 : }
     112             : 
     113        2953 : void PSBTInput::FromSignatureData(const SignatureData& sigdata)
     114             : {
     115        2953 :     if (sigdata.complete) {
     116         653 :         partial_sigs.clear();
     117         653 :         hd_keypaths.clear();
     118         653 :         redeem_script.clear();
     119             : 
     120         653 :         if (!sigdata.scriptSig.empty()) {
     121         653 :             final_script_sig = sigdata.scriptSig;
     122         653 :         }
     123         653 :         return;
     124             :     }
     125             : 
     126        2300 :     partial_sigs.insert(sigdata.signatures.begin(), sigdata.signatures.end());
     127        2300 :     if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
     128          22 :         redeem_script = sigdata.redeem_script;
     129          22 :     }
     130        4317 :     for (const auto& entry : sigdata.misc_pubkeys) {
     131        2017 :         hd_keypaths.emplace(entry.second);
     132             :     }
     133        2953 : }
     134             : 
     135          26 : void PSBTInput::Merge(const PSBTInput& input)
     136             : {
     137          26 :     if (!non_witness_utxo && input.non_witness_utxo) non_witness_utxo = input.non_witness_utxo;
     138             : 
     139          26 :     partial_sigs.insert(input.partial_sigs.begin(), input.partial_sigs.end());
     140          26 :     ripemd160_preimages.insert(input.ripemd160_preimages.begin(), input.ripemd160_preimages.end());
     141          26 :     sha256_preimages.insert(input.sha256_preimages.begin(), input.sha256_preimages.end());
     142          26 :     hash160_preimages.insert(input.hash160_preimages.begin(), input.hash160_preimages.end());
     143          26 :     hash256_preimages.insert(input.hash256_preimages.begin(), input.hash256_preimages.end());
     144          26 :     hd_keypaths.insert(input.hd_keypaths.begin(), input.hd_keypaths.end());
     145          26 :     unknown.insert(input.unknown.begin(), input.unknown.end());
     146             : 
     147          26 :     if (redeem_script.empty() && !input.redeem_script.empty()) redeem_script = input.redeem_script;
     148          26 :     if (final_script_sig.empty() && !input.final_script_sig.empty()) final_script_sig = input.final_script_sig;
     149          26 : }
     150             : 
     151        1261 : void PSBTOutput::FillSignatureData(SignatureData& sigdata) const
     152             : {
     153        1261 :     if (!redeem_script.empty()) {
     154           0 :         sigdata.redeem_script = redeem_script;
     155           0 :     }
     156        1592 :     for (const auto& key_pair : hd_keypaths) {
     157         331 :         sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
     158             :     }
     159        1261 : }
     160             : 
     161        1261 : void PSBTOutput::FromSignatureData(const SignatureData& sigdata)
     162             : {
     163        1261 :     if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
     164           4 :         redeem_script = sigdata.redeem_script;
     165           4 :     }
     166        2118 :     for (const auto& entry : sigdata.misc_pubkeys) {
     167         857 :         hd_keypaths.emplace(entry.second);
     168             :     }
     169        1261 : }
     170             : 
     171           0 : bool PSBTOutput::IsNull() const
     172             : {
     173           0 :     return redeem_script.empty() && hd_keypaths.empty() && unknown.empty();
     174             : }
     175             : 
     176          24 : void PSBTOutput::Merge(const PSBTOutput& output)
     177             : {
     178          24 :     hd_keypaths.insert(output.hd_keypaths.begin(), output.hd_keypaths.end());
     179          24 :     unknown.insert(output.unknown.begin(), output.unknown.end());
     180             : 
     181          24 :     if (redeem_script.empty() && !output.redeem_script.empty()) redeem_script = output.redeem_script;
     182          24 : }
     183             : 
     184           0 : size_t CountPSBTUnsignedInputs(const PartiallySignedTransaction& psbt) {
     185           0 :     size_t count = 0;
     186           0 :     for (const auto& input : psbt.inputs) {
     187           0 :         if (!PSBTInputSigned(input)) {
     188           0 :             count++;
     189           0 :         }
     190             :     }
     191             : 
     192           0 :     return count;
     193             : }
     194             : 
     195        1261 : void UpdatePSBTOutput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index)
     196             : {
     197        1261 :     CMutableTransaction& tx = *Assert(psbt.tx);
     198        1261 :     const CTxOut& out = tx.vout.at(index);
     199        1261 :     PSBTOutput& psbt_out = psbt.outputs.at(index);
     200             : 
     201             :     // Fill a SignatureData with output info
     202        1261 :     SignatureData sigdata;
     203        1261 :     psbt_out.FillSignatureData(sigdata);
     204             : 
     205             :     // Construct a would-be spend of this output, to update sigdata with.
     206             :     // Note that ProduceSignature is used to fill in metadata (not actual signatures),
     207             :     // so provider does not need to provide any private keys (it can be a HidingSigningProvider).
     208        1261 :     MutableTransactionSignatureCreator creator(tx, /*input_idx=*/0, out.nValue, SIGHASH_ALL);
     209        1261 :     ProduceSignature(provider, creator, out.scriptPubKey, sigdata);
     210             : 
     211             :     // Put redeem_script, key paths, into PSBTOutput.
     212        1261 :     psbt_out.FromSignatureData(sigdata);
     213        1261 : }
     214       13731 : bool PSBTInputSigned(const PSBTInput& input)
     215             : {
     216       13731 :     return !input.final_script_sig.empty();
     217             : }
     218             : 
     219        1346 : PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction& psbt)
     220             : {
     221        1346 :     const CMutableTransaction& tx = *psbt.tx;
     222        1346 :     bool have_all_spent_outputs = true;
     223        1346 :     std::vector<CTxOut> utxos(tx.vin.size());
     224        3795 :     for (size_t idx = 0; idx < tx.vin.size(); ++idx) {
     225        2449 :         if (!psbt.GetInputUTXO(utxos[idx], idx)) have_all_spent_outputs = false;
     226        2449 :     }
     227        1346 :     PrecomputedTransactionData txdata;
     228        1346 :     if (have_all_spent_outputs) {
     229         702 :         txdata.Init(tx, std::move(utxos), true);
     230         702 :     } else {
     231         644 :         txdata.Init(tx, {}, true);
     232             :     }
     233        1346 :     return txdata;
     234        1346 : }
     235             : 
     236        3598 : bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, int sighash,  SignatureData* out_sigdata, bool finalize)
     237             : {
     238        3598 :     PSBTInput& input = psbt.inputs.at(index);
     239        3598 :     const CMutableTransaction& tx = *psbt.tx;
     240             : 
     241        3598 :     if (PSBTInputSigned(input)) {
     242         629 :         return true;
     243             :     }
     244             : 
     245             :     // Fill SignatureData with input info
     246        2969 :     SignatureData sigdata;
     247        2969 :     input.FillSignatureData(sigdata);
     248             : 
     249             :     // Get UTXO
     250        2969 :     CTxOut utxo;
     251             : 
     252        2969 :     if (input.non_witness_utxo) {
     253             :         // If we're taking our information from a non-witness UTXO, verify that it matches the prevout.
     254        2953 :         COutPoint prevout = tx.vin[index].prevout;
     255        2953 :         if (prevout.n >= input.non_witness_utxo->vout.size()) {
     256           0 :             return false;
     257             :         }
     258        2953 :         if (input.non_witness_utxo->GetHash() != prevout.hash) {
     259           0 :             return false;
     260             :         }
     261        2953 :         utxo = input.non_witness_utxo->vout[prevout.n];
     262        2953 :     } else {
     263          16 :         return false;
     264             :     }
     265             : 
     266             :     bool sig_complete;
     267        2953 :     if (txdata == nullptr) {
     268           8 :         sig_complete = ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, utxo.scriptPubKey, sigdata);
     269           8 :     } else {
     270        2945 :         MutableTransactionSignatureCreator creator(tx, index, utxo.nValue, txdata, sighash);
     271        2945 :         sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);
     272        2945 :     }
     273             : 
     274             :     // If we are not finalizing, set sigdata.complete to false to not set the scriptSig
     275        2953 :     if (!finalize && sigdata.complete) sigdata.complete = false;
     276             : 
     277        2953 :     input.FromSignatureData(sigdata);
     278             : 
     279             :     // Fill in the missing info
     280        2953 :     if (out_sigdata) {
     281          12 :         out_sigdata->missing_pubkeys = sigdata.missing_pubkeys;
     282          12 :         out_sigdata->missing_sigs = sigdata.missing_sigs;
     283          12 :         out_sigdata->missing_redeem_script = sigdata.missing_redeem_script;
     284          12 :     }
     285             : 
     286        2953 :     return sig_complete;
     287        3598 : }
     288             : 
     289         959 : void RemoveUnnecessaryTransactions(PartiallySignedTransaction& /* psbtx */, const int& /* sighash_type */)
     290             : {
     291             :     // Dash does not support segwit, so there are no witness_utxos to consider.
     292             :     // In Bitcoin, this function drops non_witness_utxos when all inputs are
     293             :     // segwit v1+, which cannot occur in Dash.
     294         959 : }
     295             : 
     296         350 : bool FinalizePSBT(PartiallySignedTransaction& psbtx)
     297             : {
     298             :     // Finalize input signatures -- in case we have partial signatures that add up to a complete
     299             :     //   signature, but have not combined them yet (e.g. because the combiner that created this
     300             :     //   PartiallySignedTransaction did not understand them), this will combine them into a final
     301             :     //   script.
     302         350 :     bool complete = true;
     303         350 :     const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
     304        1019 :     for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
     305         669 :         complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, SIGHASH_ALL, nullptr, true);
     306         669 :     }
     307             : 
     308         350 :     return complete;
     309         350 : }
     310             : 
     311         346 : bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransaction& result)
     312             : {
     313             :     // It's not safe to extract a PSBT that isn't finalized, and there's no easy way to check
     314             :     //   whether a PSBT is finalized without finalizing it, so we just do this.
     315         346 :     if (!FinalizePSBT(psbtx)) {
     316          30 :         return false;
     317             :     }
     318             : 
     319         316 :     result = *psbtx.tx;
     320         935 :     for (unsigned int i = 0; i < result.vin.size(); ++i) {
     321         619 :         result.vin[i].scriptSig = psbtx.inputs[i].final_script_sig;
     322         619 :     }
     323         316 :     return true;
     324         346 : }
     325             : 
     326          22 : TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs)
     327             : {
     328          22 :     out = psbtxs[0]; // Copy the first one
     329             : 
     330             :     // Merge
     331          40 :     for (auto it = std::next(psbtxs.begin()); it != psbtxs.end(); ++it) {
     332          22 :         if (!out.Merge(*it)) {
     333           4 :             return TransactionError::PSBT_MISMATCH;
     334             :         }
     335          18 :     }
     336          18 :     return TransactionError::OK;
     337          22 : }
     338             : 
     339          48 : std::string PSBTRoleName(PSBTRole role) {
     340          48 :     switch (role) {
     341          16 :     case PSBTRole::CREATOR: return "creator";
     342          16 :     case PSBTRole::UPDATER: return "updater";
     343           8 :     case PSBTRole::SIGNER: return "signer";
     344           0 :     case PSBTRole::FINALIZER: return "finalizer";
     345           8 :     case PSBTRole::EXTRACTOR: return "extractor";
     346             :         // no default case, so the compiler can warn about missing cases
     347             :     }
     348           0 :     assert(false);
     349          48 : }
     350             : 
     351         650 : bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
     352             : {
     353         650 :     auto tx_data = DecodeBase64(base64_tx);
     354         650 :     if (!tx_data) {
     355          12 :         error = "invalid base64";
     356          12 :         return false;
     357             :     }
     358         638 :     return DecodeRawPSBT(psbt, MakeByteSpan(*tx_data), error);
     359         650 : }
     360             : 
     361         638 : bool DecodeRawPSBT(PartiallySignedTransaction& psbt, Span<const std::byte> tx_data, std::string& error)
     362             : {
     363         638 :     CDataStream ss_data(tx_data, SER_NETWORK, PROTOCOL_VERSION);
     364             :     try {
     365         638 :         ss_data >> psbt;
     366         534 :         if (!ss_data.empty()) {
     367           0 :             error = "extra data after PSBT";
     368           0 :             return false;
     369             :         }
     370         638 :     } catch (const std::exception& e) {
     371         104 :         error = e.what();
     372         104 :         return false;
     373         104 :     }
     374         534 :     return true;
     375         742 : }
     376             : 
     377         773 : uint32_t PartiallySignedTransaction::GetVersion() const
     378             : {
     379         773 :     if (m_version != std::nullopt) {
     380           0 :         return *m_version;
     381             :     }
     382         773 :     return 0;
     383         773 : }

Generated by: LCOV version 1.16