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