Bitcoin ABC 0.30.7
P2P Digital Currency
psbt.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2018 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>
8#include <node/psbt.h>
9#include <policy/policy.h>
10#include <policy/settings.h>
11#include <tinyformat.h>
12
13#include <numeric>
14
15namespace node {
17 // Go through each input and build status
18 PSBTAnalysis result;
19
20 bool calc_fee = true;
21
22 Amount in_amt{Amount::zero()};
23
24 result.inputs.resize(psbtx.tx->vin.size());
25
26 for (size_t i = 0; i < psbtx.tx->vin.size(); ++i) {
27 PSBTInput &input = psbtx.inputs[i];
28 PSBTInputAnalysis &input_analysis = result.inputs[i];
29
30 // We set next role here and ratchet backwards as required
31 input_analysis.next = PSBTRole::EXTRACTOR;
32
33 // Check for a UTXO
34 CTxOut utxo;
35 if (psbtx.GetInputUTXO(utxo, i)) {
36 if (!MoneyRange(utxo.nValue) || !MoneyRange(in_amt + utxo.nValue)) {
37 result.SetInvalid(strprintf(
38 "PSBT is not valid. Input %u has invalid value", i));
39 return result;
40 }
41 in_amt += utxo.nValue;
42 input_analysis.has_utxo = true;
43 } else {
44 input_analysis.has_utxo = false;
45 input_analysis.is_final = false;
46 input_analysis.next = PSBTRole::UPDATER;
47 calc_fee = false;
48 }
49
50 if (!utxo.IsNull() && utxo.scriptPubKey.IsUnspendable()) {
51 result.SetInvalid(strprintf(
52 "PSBT is not valid. Input %u spends unspendable output", i));
53 return result;
54 }
55
56 // Check if it is final
57 if (!utxo.IsNull() && !PSBTInputSigned(input)) {
58 input_analysis.is_final = false;
59
60 // Figure out what is missing
61 SignatureData outdata;
62 bool complete = SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i,
63 SigHashType().withForkId(), &outdata);
64
65 // Things are missing
66 if (!complete) {
67 input_analysis.missing_pubkeys = outdata.missing_pubkeys;
68 input_analysis.missing_redeem_script =
70 input_analysis.missing_sigs = outdata.missing_sigs;
71
72 // If we are only missing signatures and nothing else, then next
73 // is signer
74 if (outdata.missing_pubkeys.empty() &&
75 outdata.missing_redeem_script.IsNull() &&
76 !outdata.missing_sigs.empty()) {
77 input_analysis.next = PSBTRole::SIGNER;
78 } else {
79 input_analysis.next = PSBTRole::UPDATER;
80 }
81 } else {
82 input_analysis.next = PSBTRole::FINALIZER;
83 }
84 } else if (!utxo.IsNull()) {
85 input_analysis.is_final = true;
86 }
87 }
88
89 // Calculate next role for PSBT by grabbing "minumum" PSBTInput next role
91 for (size_t i = 0; i < psbtx.tx->vin.size(); ++i) {
92 PSBTInputAnalysis &input_analysis = result.inputs[i];
93 result.next = std::min(result.next, input_analysis.next);
94 }
96
97 if (calc_fee) {
98 // Get the output amount
99 Amount out_amt =
100 std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(),
101 Amount::zero(), [](Amount a, const CTxOut &b) {
102 if (!MoneyRange(a) || !MoneyRange(b.nValue) ||
103 !MoneyRange(a + b.nValue)) {
104 return -1 * SATOSHI;
105 }
106 return a += b.nValue;
107 });
108 if (!MoneyRange(out_amt)) {
109 result.SetInvalid(
110 strprintf("PSBT is not valid. Output amount invalid"));
111 return result;
112 }
113
114 // Get the fee
115 Amount 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 (size_t i = 0; i < psbtx.tx->vin.size(); ++i) {
125 PSBTInput &input = psbtx.inputs[i];
126 CTxOut newUtxo;
127
129 SigHashType().withForkId(), nullptr, true) ||
130 !psbtx.GetInputUTXO(newUtxo, i)) {
131 success = false;
132 break;
133 } else {
134 mtx.vin[i].scriptSig = input.final_script_sig;
135 view.AddCoin(psbtx.tx->vin[i].prevout, Coin(newUtxo, 1, false),
136 true);
137 }
138 }
139
140 if (success) {
142 size_t size = ctx.GetTotalSize();
143 result.estimated_vsize = size;
144 // Estimate fee rate
145 CFeeRate feerate(fee, size);
146 result.estimated_feerate = feerate;
147 }
148 }
149
150 return result;
151}
152} // namespace node
bool MoneyRange(const Amount nValue)
Definition: amount.h:166
secp256k1_context * ctx
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:221
void AddCoin(const COutPoint &outpoint, Coin coin, bool possible_overwrite)
Add a coin.
Definition: coins.cpp:104
Abstract view on the open txout dataset.
Definition: coins.h:163
Fee rate in satoshis per kilobyte: Amount / kB.
Definition: feerate.h:21
A mutable version of CTransaction.
Definition: transaction.h:274
std::vector< CTxIn > vin
Definition: transaction.h:276
bool IsUnspendable() const
Returns whether the script is guaranteed to fail at execution, regardless of the initial stack.
Definition: script.h:541
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:192
An output of a transaction.
Definition: transaction.h:128
CScript scriptPubKey
Definition: transaction.h:131
Amount nValue
Definition: transaction.h:130
bool IsNull() const
Definition: transaction.h:145
A UTXO entry.
Definition: coins.h:28
Signature hash type wrapper class.
Definition: sighashtype.h:37
bool IsNull() const
Definition: uint256.h:32
Definition: init.h:28
PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
Provides helpful miscellaneous information about where a PSBT is in the signing workflow.
Definition: psbt.cpp:16
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed.
Definition: psbt.cpp:160
bool SignPSBTInput(const SigningProvider &provider, PartiallySignedTransaction &psbt, int index, SigHashType sighash, SignatureData *out_sigdata, bool use_dummy)
Signs a PSBTInput, verifying that all provided data matches what is being signed.
Definition: psbt.cpp:186
const SigningProvider & DUMMY_SIGNING_PROVIDER
Definition: amount.h:19
static constexpr Amount zero() noexcept
Definition: amount.h:32
A structure for PSBTs which contain per-input information.
Definition: psbt.h:44
CScript final_script_sig
Definition: psbt.h:47
A version of CTransaction with the PSBT format.
Definition: psbt.h:334
bool GetInputUTXO(CTxOut &utxo, int input_index) const
Finds the UTXO for a given input index.
Definition: psbt.cpp:57
std::vector< PSBTInput > inputs
Definition: psbt.h:336
std::optional< CMutableTransaction > tx
Definition: psbt.h:335
uint160 missing_redeem_script
ScriptID of the missing redeemScript (if any)
Definition: sign.h:83
std::vector< CKeyID > missing_sigs
KeyIDs of pubkeys for signatures which could not be found.
Definition: sign.h:81
std::vector< CKeyID > missing_pubkeys
KeyIDs of pubkeys which could not be found.
Definition: sign.h:79
Holds the results of AnalyzePSBT (miscellaneous information about a PSBT)
Definition: psbt.h:35
std::vector< PSBTInputAnalysis > inputs
More information about the individual inputs of the transaction.
Definition: psbt.h:43
void SetInvalid(std::string err_msg)
Definition: psbt.h:49
std::optional< Amount > fee
Amount of fee being paid by the transaction.
Definition: psbt.h:41
std::optional< size_t > estimated_vsize
Estimated weight of the transaction.
Definition: psbt.h:37
std::optional< CFeeRate > estimated_feerate
Estimated feerate (fee / weight) of the transaction.
Definition: psbt.h:39
PSBTRole next
Which of the BIP 174 roles needs to handle the transaction next.
Definition: psbt.h:45
Holds an analysis of one input from a PSBT.
Definition: psbt.h:16
std::vector< CKeyID > missing_sigs
Pubkeys whose signatures are missing.
Definition: psbt.h:27
bool has_utxo
Whether we have UTXO information for this input.
Definition: psbt.h:18
PSBTRole next
Which of the BIP 174 roles needs to handle this input next.
Definition: psbt.h:22
std::vector< CKeyID > missing_pubkeys
Pubkeys whose BIP32 derivation path is missing.
Definition: psbt.h:25
uint160 missing_redeem_script
Hash160 of redeem script, if missing.
Definition: psbt.h:29
bool is_final
Whether the input has all required information including signatures.
Definition: psbt.h:20
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
assert(!tx.IsCoinBase())