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 16 : PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx) 16 : { 17 : // Go through each input and build status 18 16 : PSBTAnalysis result; 19 : 20 52 : bool calc_fee = true; 21 : 22 42 : CAmount in_amt = 0; 23 : 24 16 : result.inputs.resize(psbtx.tx->vin.size()); 25 : 26 32 : 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 : } 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 : } 47 2 : input_analysis.has_utxo = false; 48 2 : input_analysis.is_final = false; 49 2 : input_analysis.next = PSBTRole::UPDATER; 50 : calc_fee = false; 51 : } 52 : 53 12 : 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 : } 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 : } 79 : } else { 80 2 : input_analysis.next = PSBTRole::FINALIZER; 81 : } 82 10 : } else if (!utxo.IsNull()){ 83 2 : input_analysis.is_final = true; 84 2 : } 85 16 : } 86 : 87 : // Calculate next role for PSBT by grabbing "minimum" PSBTInput next role 88 10 : 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 0 : } 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 : } 102 8 : return a += b.nValue; 103 12 : } 104 : ); 105 8 : if (!MoneyRange(out_amt)) { 106 2 : result.SetInvalid(strprintf("PSBT is not valid. Output amount invalid")); 107 2 : return result; 108 : } 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 18 : 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 : success = false; 126 0 : break; 127 : } 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 : } 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 8 : } 145 : 146 8 : return result; 147 16 : }