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