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