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