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 <psbt.h>
6
7#include <util/check.h>
8#include <util/strencodings.h>
9
11 const CMutableTransaction &txIn)
12 : tx(txIn) {
13 inputs.resize(txIn.vin.size());
14 outputs.resize(txIn.vout.size());
15}
16
18 return !tx && inputs.empty() && outputs.empty() && unknown.empty();
19}
20
22 // Prohibited to merge two PSBTs over different transactions
23 if (tx->GetId() != psbt.tx->GetId()) {
24 return false;
25 }
26
27 for (size_t i = 0; i < inputs.size(); ++i) {
28 inputs[i].Merge(psbt.inputs[i]);
29 }
30 for (size_t i = 0; i < outputs.size(); ++i) {
31 outputs[i].Merge(psbt.outputs[i]);
32 }
33 unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
34
35 return true;
36}
37
39 PSBTInput &psbtin) {
40 if (std::find(tx->vin.begin(), tx->vin.end(), txin) != tx->vin.end()) {
41 return false;
42 }
43 tx->vin.push_back(txin);
44 psbtin.partial_sigs.clear();
45 psbtin.final_script_sig.clear();
46 inputs.push_back(psbtin);
47 return true;
48}
49
51 const PSBTOutput &psbtout) {
52 tx->vout.push_back(txout);
53 outputs.push_back(psbtout);
54 return true;
55}
56
58 int input_index) const {
59 PSBTInput input = inputs[input_index];
60 if (!input.utxo.IsNull()) {
61 utxo = input.utxo;
62 } else {
63 return false;
64 }
65 return true;
66}
67
68bool PSBTInput::IsNull() const {
69 return utxo.IsNull() && partial_sigs.empty() && unknown.empty() &&
70 hd_keypaths.empty() && redeem_script.empty();
71}
72
74 if (!final_script_sig.empty()) {
76 sigdata.complete = true;
77 }
78 if (sigdata.complete) {
79 return;
80 }
81
82 sigdata.signatures.insert(partial_sigs.begin(), partial_sigs.end());
83 if (!redeem_script.empty()) {
85 }
86 for (const auto &key_pair : hd_keypaths) {
87 sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
88 }
89}
90
92 if (sigdata.complete) {
93 partial_sigs.clear();
94 hd_keypaths.clear();
96
97 if (!sigdata.scriptSig.empty()) {
99 }
100 return;
101 }
102
103 partial_sigs.insert(sigdata.signatures.begin(), sigdata.signatures.end());
104 if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
106 }
107 for (const auto &entry : sigdata.misc_pubkeys) {
108 hd_keypaths.emplace(entry.second);
109 }
110}
111
112void PSBTInput::Merge(const PSBTInput &input) {
113 if (utxo.IsNull() && !input.utxo.IsNull()) {
114 utxo = input.utxo;
115 }
116
117 partial_sigs.insert(input.partial_sigs.begin(), input.partial_sigs.end());
118 hd_keypaths.insert(input.hd_keypaths.begin(), input.hd_keypaths.end());
119 unknown.insert(input.unknown.begin(), input.unknown.end());
120
121 if (redeem_script.empty() && !input.redeem_script.empty()) {
123 }
124 if (final_script_sig.empty() && !input.final_script_sig.empty()) {
126 }
127}
128
130 if (!redeem_script.empty()) {
132 }
133 for (const auto &key_pair : hd_keypaths) {
134 sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
135 }
136}
137
139 if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
141 }
142 for (const auto &entry : sigdata.misc_pubkeys) {
143 hd_keypaths.emplace(entry.second);
144 }
145}
146
147bool PSBTOutput::IsNull() const {
148 return redeem_script.empty() && hd_keypaths.empty() && unknown.empty();
149}
150
151void PSBTOutput::Merge(const PSBTOutput &output) {
152 hd_keypaths.insert(output.hd_keypaths.begin(), output.hd_keypaths.end());
153 unknown.insert(output.unknown.begin(), output.unknown.end());
154
155 if (redeem_script.empty() && !output.redeem_script.empty()) {
157 }
158}
159
160bool PSBTInputSigned(const PSBTInput &input) {
161 return !input.final_script_sig.empty();
162}
163
165 PartiallySignedTransaction &psbt, int index) {
166 CMutableTransaction &tx = *Assert(psbt.tx);
167 const CTxOut &out = tx.vout.at(index);
168 PSBTOutput &psbt_out = psbt.outputs.at(index);
169
170 // Fill a SignatureData with output info
171 SignatureData sigdata;
172 psbt_out.FillSignatureData(sigdata);
173
174 // Construct a would-be spend of this output, to update sigdata with.
175 // Note that ProduceSignature is used to fill in metadata (not actual
176 // signatures), so provider does not need to provide any private keys (it
177 // can be a HidingSigningProvider).
178 MutableTransactionSignatureCreator creator(&tx, /* index */ 0, out.nValue,
179 SigHashType().withForkId());
180 ProduceSignature(provider, creator, out.scriptPubKey, sigdata);
181
182 // Put redeem_script and key paths, into PSBTOutput.
183 psbt_out.FromSignatureData(sigdata);
184}
185
186bool SignPSBTInput(const SigningProvider &provider,
187 PartiallySignedTransaction &psbt, int index,
188 SigHashType sighash, SignatureData *out_sigdata,
189 bool use_dummy) {
190 PSBTInput &input = psbt.inputs.at(index);
191 const CMutableTransaction &tx = *psbt.tx;
192
193 if (PSBTInputSigned(input)) {
194 return true;
195 }
196
197 // Fill SignatureData with input info
198 SignatureData sigdata;
199 input.FillSignatureData(sigdata);
200
201 // Get UTXO
202 CTxOut utxo;
203
204 if (input.utxo.IsNull()) {
205 return false;
206 }
207
208 utxo = input.utxo;
209
210 bool sig_complete{false};
211 if (use_dummy) {
212 sig_complete = ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR,
213 utxo.scriptPubKey, sigdata);
214 } else {
215 MutableTransactionSignatureCreator creator(&tx, index, utxo.nValue,
216 sighash);
217 sig_complete =
218 ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);
219 }
220 input.FromSignatureData(sigdata);
221
222 // Fill in the missing info
223 if (out_sigdata != nullptr) {
224 out_sigdata->missing_pubkeys = sigdata.missing_pubkeys;
225 out_sigdata->missing_sigs = sigdata.missing_sigs;
226 out_sigdata->missing_redeem_script = sigdata.missing_redeem_script;
227 }
228
229 return sig_complete;
230}
231
233 // Finalize input signatures -- in case we have partial signatures that add
234 // up to a complete
235 // signature, but have not combined them yet (e.g. because the combiner
236 // that created this PartiallySignedTransaction did not understand them),
237 // this will combine them into a final script.
238 bool complete = true;
239 for (size_t i = 0; i < psbtx.tx->vin.size(); ++i) {
240 complete &=
242 }
243
244 return complete;
245}
246
248 CMutableTransaction &result) {
249 // It's not safe to extract a PSBT that isn't finalized, and there's no easy
250 // way to check
251 // whether a PSBT is finalized without finalizing it, so we just do this.
252 if (!FinalizePSBT(psbtx)) {
253 return false;
254 }
255
256 result = *psbtx.tx;
257 for (size_t i = 0; i < result.vin.size(); ++i) {
258 result.vin[i].scriptSig = psbtx.inputs[i].final_script_sig;
259 }
260 return true;
261}
262
265 const std::vector<PartiallySignedTransaction> &psbtxs) {
266 // Copy the first one
267 out = psbtxs[0];
268
269 // Merge
270 for (auto it = std::next(psbtxs.begin()); it != psbtxs.end(); ++it) {
271 if (!out.Merge(*it)) {
273 }
274 }
275
277}
278
279std::string PSBTRoleName(const PSBTRole role) {
280 switch (role) {
282 return "creator";
284 return "updater";
285 case PSBTRole::SIGNER:
286 return "signer";
288 return "finalizer";
290 return "extractor";
291 // no default case, so the compiler can warn about missing cases
292 }
293 assert(false);
294}
295
297 const std::string &base64_tx, std::string &error) {
298 auto tx_data = DecodeBase64(base64_tx);
299 if (!tx_data) {
300 error = "invalid base64";
301 return false;
302 }
303 return DecodeRawPSBT(psbt, MakeByteSpan(*tx_data), error);
304}
305
307 Span<const std::byte> tx_data, std::string &error) {
308 CDataStream ss_data(tx_data, SER_NETWORK, PROTOCOL_VERSION);
309 try {
310 ss_data >> psbt;
311 if (!ss_data.empty()) {
312 error = "extra data after PSBT";
313 return false;
314 }
315 } catch (const std::exception &e) {
316 error = e.what();
317 return false;
318 }
319 return true;
320}
#define Assert(val)
Identity function.
Definition: check.h:84
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:177
bool empty() const
Definition: streams.h:224
A mutable version of CTransaction.
Definition: transaction.h:274
std::vector< CTxOut > vout
Definition: transaction.h:277
std::vector< CTxIn > vin
Definition: transaction.h:276
void clear()
Definition: script.h:546
An input of a transaction.
Definition: transaction.h:59
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 signature creator for transactions.
Definition: sign.h:38
Signature hash type wrapper class.
Definition: sighashtype.h:37
An interface to be implemented by keystores that support signing.
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:93
bool empty() const
Definition: prevector.h:396
TransactionError
Definition: error.h:22
bool error(const char *fmt, const Args &...args)
Definition: logging.h:263
bool DecodeBase64PSBT(PartiallySignedTransaction &psbt, const std::string &base64_tx, std::string &error)
Decode a base64ed PSBT into a PartiallySignedTransaction.
Definition: psbt.cpp:296
void UpdatePSBTOutput(const SigningProvider &provider, PartiallySignedTransaction &psbt, int index)
Updates a PSBTOutput with information from provider.
Definition: psbt.cpp:164
std::string PSBTRoleName(const PSBTRole role)
Definition: psbt.cpp:279
bool FinalizeAndExtractPSBT(PartiallySignedTransaction &psbtx, CMutableTransaction &result)
Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized.
Definition: psbt.cpp:247
bool DecodeRawPSBT(PartiallySignedTransaction &psbt, Span< const std::byte > tx_data, std::string &error)
Decode a raw (binary blob) PSBT into a PartiallySignedTransaction.
Definition: psbt.cpp:306
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed.
Definition: psbt.cpp:160
TransactionError CombinePSBTs(PartiallySignedTransaction &out, const std::vector< PartiallySignedTransaction > &psbtxs)
Combines PSBTs with the same underlying transaction, resulting in a single PSBT with all partial sign...
Definition: psbt.cpp:264
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
bool FinalizePSBT(PartiallySignedTransaction &psbtx)
Finalizes a PSBT if possible, combining partial signatures.
Definition: psbt.cpp:232
PSBTRole
Definition: psbt.h:506
@ SER_NETWORK
Definition: serialize.h:152
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
Definition: sign.cpp:198
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
Definition: sign.cpp:419
const SigningProvider & DUMMY_SIGNING_PROVIDER
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Definition: span.h:301
A structure for PSBTs which contain per-input information.
Definition: psbt.h:44
std::map< CPubKey, KeyOriginInfo > hd_keypaths
Definition: psbt.h:48
std::map< CKeyID, SigPair > partial_sigs
Definition: psbt.h:49
void FillSignatureData(SignatureData &sigdata) const
Definition: psbt.cpp:73
bool IsNull() const
Definition: psbt.cpp:68
void Merge(const PSBTInput &input)
Definition: psbt.cpp:112
std::map< std::vector< uint8_t >, std::vector< uint8_t > > unknown
Definition: psbt.h:50
CScript redeem_script
Definition: psbt.h:46
CScript final_script_sig
Definition: psbt.h:47
void FromSignatureData(const SignatureData &sigdata)
Definition: psbt.cpp:91
CTxOut utxo
Definition: psbt.h:45
A structure for PSBTs which contains per output information.
Definition: psbt.h:233
bool IsNull() const
Definition: psbt.cpp:147
void Merge(const PSBTOutput &output)
Definition: psbt.cpp:151
CScript redeem_script
Definition: psbt.h:234
std::map< CPubKey, KeyOriginInfo > hd_keypaths
Definition: psbt.h:235
std::map< std::vector< uint8_t >, std::vector< uint8_t > > unknown
Definition: psbt.h:236
void FillSignatureData(SignatureData &sigdata) const
Definition: psbt.cpp:129
void FromSignatureData(const SignatureData &sigdata)
Definition: psbt.cpp:138
A version of CTransaction with the PSBT format.
Definition: psbt.h:334
bool Merge(const PartiallySignedTransaction &psbt)
Merge psbt into this.
Definition: psbt.cpp:21
std::map< std::vector< uint8_t >, std::vector< uint8_t > > unknown
Definition: psbt.h:338
bool IsNull() const
Definition: psbt.cpp:17
bool GetInputUTXO(CTxOut &utxo, int input_index) const
Finds the UTXO for a given input index.
Definition: psbt.cpp:57
bool AddOutput(const CTxOut &txout, const PSBTOutput &psbtout)
Definition: psbt.cpp:50
std::vector< PSBTInput > inputs
Definition: psbt.h:336
std::optional< CMutableTransaction > tx
Definition: psbt.h:335
bool AddInput(const CTxIn &txin, PSBTInput &psbtin)
Definition: psbt.cpp:38
std::vector< PSBTOutput > outputs
Definition: psbt.h:337
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::map< CKeyID, SigPair > signatures
BIP 174 style partial signatures for the input.
Definition: sign.h:76
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > misc_pubkeys
Definition: sign.h:77
CScript scriptSig
The scriptSig of an input.
Definition: sign.h:71
CScript redeem_script
The redeemScript (if any) for the input.
Definition: sign.h:73
std::vector< CKeyID > missing_pubkeys
KeyIDs of pubkeys which could not be found.
Definition: sign.h:79
bool complete
Stores whether the scriptSig are complete.
Definition: sign.h:68
std::optional< std::vector< uint8_t > > DecodeBase64(std::string_view str)
assert(!tx.IsCoinBase())
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11