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