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