LCOV - code coverage report
Current view: top level - src - psbt.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 264 311 84.9 %
Date: 2022-04-21 14:51:19 Functions: 22 26 84.6 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 138 192 71.9 %

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

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a