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