LCOV - code coverage report
Current view: top level - src/node - psbt.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 99 101 98.0 %
Date: 2022-04-21 14:51:19 Functions: 2 2 100.0 %
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: 47 56 83.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 <coins.h>
#       6                 :            : #include <consensus/amount.h>
#       7                 :            : #include <consensus/tx_verify.h>
#       8                 :            : #include <node/psbt.h>
#       9                 :            : #include <policy/policy.h>
#      10                 :            : #include <policy/settings.h>
#      11                 :            : #include <tinyformat.h>
#      12                 :            : 
#      13                 :            : #include <numeric>
#      14                 :            : 
#      15                 :            : namespace node {
#      16                 :            : PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
#      17                 :         16 : {
#      18                 :            :     // Go through each input and build status
#      19                 :         16 :     PSBTAnalysis result;
#      20                 :            : 
#      21                 :         16 :     bool calc_fee = true;
#      22                 :            : 
#      23                 :         16 :     CAmount in_amt = 0;
#      24                 :            : 
#      25                 :         16 :     result.inputs.resize(psbtx.tx->vin.size());
#      26                 :            : 
#      27                 :         16 :     const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
#      28                 :            : 
#      29         [ +  + ]:         26 :     for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
#      30                 :         16 :         PSBTInput& input = psbtx.inputs[i];
#      31                 :         16 :         PSBTInputAnalysis& input_analysis = result.inputs[i];
#      32                 :            : 
#      33                 :            :         // We set next role here and ratchet backwards as required
#      34                 :         16 :         input_analysis.next = PSBTRole::EXTRACTOR;
#      35                 :            : 
#      36                 :            :         // Check for a UTXO
#      37                 :         16 :         CTxOut utxo;
#      38         [ +  + ]:         16 :         if (psbtx.GetInputUTXO(utxo, i)) {
#      39 [ +  + ][ +  + ]:         12 :             if (!MoneyRange(utxo.nValue) || !MoneyRange(in_amt + utxo.nValue)) {
#                 [ -  + ]
#      40                 :          2 :                 result.SetInvalid(strprintf("PSBT is not valid. Input %u has invalid value", i));
#      41                 :          2 :                 return result;
#      42                 :          2 :             }
#      43                 :         10 :             in_amt += utxo.nValue;
#      44                 :         10 :             input_analysis.has_utxo = true;
#      45                 :         10 :         } else {
#      46 [ +  + ][ +  - ]:          4 :             if (input.non_witness_utxo && psbtx.tx->vin[i].prevout.n >= input.non_witness_utxo->vout.size()) {
#      47                 :          2 :                 result.SetInvalid(strprintf("PSBT is not valid. Input %u specifies invalid prevout", i));
#      48                 :          2 :                 return result;
#      49                 :          2 :             }
#      50                 :          2 :             input_analysis.has_utxo = false;
#      51                 :          2 :             input_analysis.is_final = false;
#      52                 :          2 :             input_analysis.next = PSBTRole::UPDATER;
#      53                 :          2 :             calc_fee = false;
#      54                 :          2 :         }
#      55                 :            : 
#      56 [ +  + ][ +  + ]:         12 :         if (!utxo.IsNull() && utxo.scriptPubKey.IsUnspendable()) {
#      57                 :          2 :             result.SetInvalid(strprintf("PSBT is not valid. Input %u spends unspendable output", i));
#      58                 :          2 :             return result;
#      59                 :          2 :         }
#      60                 :            : 
#      61                 :            :         // Check if it is final
#      62 [ +  + ][ +  + ]:         10 :         if (!utxo.IsNull() && !PSBTInputSigned(input)) {
#      63                 :          6 :             input_analysis.is_final = false;
#      64                 :            : 
#      65                 :            :             // Figure out what is missing
#      66                 :          6 :             SignatureData outdata;
#      67                 :          6 :             bool complete = SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, 1, &outdata);
#      68                 :            : 
#      69                 :            :             // Things are missing
#      70         [ +  + ]:          6 :             if (!complete) {
#      71                 :          4 :                 input_analysis.missing_pubkeys = outdata.missing_pubkeys;
#      72                 :          4 :                 input_analysis.missing_redeem_script = outdata.missing_redeem_script;
#      73                 :          4 :                 input_analysis.missing_witness_script = outdata.missing_witness_script;
#      74                 :          4 :                 input_analysis.missing_sigs = outdata.missing_sigs;
#      75                 :            : 
#      76                 :            :                 // If we are only missing signatures and nothing else, then next is signer
#      77 [ +  + ][ +  - ]:          4 :                 if (outdata.missing_pubkeys.empty() && outdata.missing_redeem_script.IsNull() && outdata.missing_witness_script.IsNull() && !outdata.missing_sigs.empty()) {
#         [ +  - ][ +  - ]
#      78                 :          2 :                     input_analysis.next = PSBTRole::SIGNER;
#      79                 :          2 :                 } else {
#      80                 :          2 :                     input_analysis.next = PSBTRole::UPDATER;
#      81                 :          2 :                 }
#      82                 :          4 :             } else {
#      83                 :          2 :                 input_analysis.next = PSBTRole::FINALIZER;
#      84                 :          2 :             }
#      85         [ +  + ]:          6 :         } else if (!utxo.IsNull()){
#      86                 :          2 :             input_analysis.is_final = true;
#      87                 :          2 :         }
#      88                 :         10 :     }
#      89                 :            : 
#      90                 :            :     // Calculate next role for PSBT by grabbing "minimum" PSBTInput next role
#      91                 :         10 :     result.next = PSBTRole::EXTRACTOR;
#      92         [ +  + ]:         20 :     for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
#      93                 :         10 :         PSBTInputAnalysis& input_analysis = result.inputs[i];
#      94                 :         10 :         result.next = std::min(result.next, input_analysis.next);
#      95                 :         10 :     }
#      96                 :         10 :     assert(result.next > PSBTRole::CREATOR);
#      97                 :            : 
#      98         [ +  + ]:         10 :     if (calc_fee) {
#      99                 :            :         // Get the output amount
#     100                 :          8 :         CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmount(0),
#     101                 :         12 :             [](CAmount a, const CTxOut& b) {
#     102 [ +  + ][ +  + ]:         12 :                 if (!MoneyRange(a) || !MoneyRange(b.nValue) || !MoneyRange(a + b.nValue)) {
#         [ +  + ][ -  + ]
#     103                 :          4 :                     return CAmount(-1);
#     104                 :          4 :                 }
#     105                 :          8 :                 return a += b.nValue;
#     106                 :         12 :             }
#     107                 :          8 :         );
#     108         [ +  + ]:          8 :         if (!MoneyRange(out_amt)) {
#     109                 :          2 :             result.SetInvalid("PSBT is not valid. Output amount invalid");
#     110                 :          2 :             return result;
#     111                 :          2 :         }
#     112                 :            : 
#     113                 :            :         // Get the fee
#     114                 :          6 :         CAmount fee = in_amt - out_amt;
#     115                 :          6 :         result.fee = fee;
#     116                 :            : 
#     117                 :            :         // Estimate the size
#     118                 :          6 :         CMutableTransaction mtx(*psbtx.tx);
#     119                 :          6 :         CCoinsView view_dummy;
#     120                 :          6 :         CCoinsViewCache view(&view_dummy);
#     121                 :          6 :         bool success = true;
#     122                 :            : 
#     123         [ +  + ]:         12 :         for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
#     124                 :          6 :             PSBTInput& input = psbtx.inputs[i];
#     125                 :          6 :             Coin newcoin;
#     126                 :            : 
#     127 [ -  + ][ -  + ]:          6 :             if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, nullptr, 1) || !psbtx.GetInputUTXO(newcoin.out, i)) {
#     128                 :          0 :                 success = false;
#     129                 :          0 :                 break;
#     130                 :          6 :             } else {
#     131                 :          6 :                 mtx.vin[i].scriptSig = input.final_script_sig;
#     132                 :          6 :                 mtx.vin[i].scriptWitness = input.final_script_witness;
#     133                 :          6 :                 newcoin.nHeight = 1;
#     134                 :          6 :                 view.AddCoin(psbtx.tx->vin[i].prevout, std::move(newcoin), true);
#     135                 :          6 :             }
#     136                 :          6 :         }
#     137                 :            : 
#     138         [ +  - ]:          6 :         if (success) {
#     139                 :          6 :             CTransaction ctx = CTransaction(mtx);
#     140                 :          6 :             size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
#     141                 :          6 :             result.estimated_vsize = size;
#     142                 :            :             // Estimate fee rate
#     143                 :          6 :             CFeeRate feerate(fee, size);
#     144                 :          6 :             result.estimated_feerate = feerate;
#     145                 :          6 :         }
#     146                 :            : 
#     147                 :          6 :     }
#     148                 :            : 
#     149                 :          8 :     return result;
#     150                 :         10 : }
#     151                 :            : } // namespace node

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