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