Bitcoin Core 31.99.0
P2P Digital Currency
psbt_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2022 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or https://www.opensource.org/licenses/mit-license.php.
4
5#include <addresstype.h>
6#include <key.h>
7#include <psbt.h>
8#include <script/descriptor.h>
9#include <script/script.h>
11#include <script/solver.h>
13#include <util/strencodings.h>
14#include <util/string.h>
15
16#include <boost/test/unit_test.hpp>
17
18#include <string>
19#include <vector>
20
22
23static PSBTProprietary MakeProprietary(uint64_t subtype, uint8_t key_data, uint8_t value)
24{
25 return PSBTProprietary{
26 .subtype = subtype,
27 .identifier = {'p', 's', 'b', 't'},
28 .key = {key_data},
29 .value = {value},
30 };
31}
32
33void CheckTimeLock(const std::string& base64_psbt, std::optional<uint32_t> timelock)
34{
36 BOOST_CHECK(psbt);
37
38 std::optional<uint32_t> computed_timelock = psbt->ComputeTimeLock();
39 std::optional<CMutableTransaction> tx = psbt->GetUnsignedTx();
40 if (timelock) {
41 BOOST_CHECK(computed_timelock);
42 BOOST_CHECK_EQUAL(*computed_timelock, *timelock);
43 BOOST_CHECK(tx);
44 BOOST_CHECK_EQUAL(tx->nLockTime, *timelock);
45 } else {
46 BOOST_CHECK(!computed_timelock);
47 BOOST_CHECK(!tx);
48 }
49}
50
51BOOST_AUTO_TEST_CASE(psbt2_timelock_test)
52{
53 CheckTimeLock("cHNidP8BAgQCAAAAAQQBAQEFAQIB+wQCAAAAAAEOIAsK2SFBnByHGXNdctxzn56p4GONH+TB7vD5lECEgV/IAQ8EAAAAAAABAwgACK8vAAAAAAEEFgAUxDD2TEdW2jENvRoIVXLvKZkmJywAAQMIi73rCwAAAAABBBYAFE3Rk6yWSlasG54cyoRU/i9HT4UTAA==", 0);
54 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAAAAQ4gOhs7PIN9ZInqejHY5sfdUDwAG+8+BpWOdXSAjWjKeKUBDwQAAAAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 0);
55 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 10000);
56 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAESBCgjAAAAAQMIT5M1dwAAAAABBBYAFAsTUsrNA89qobfzyNY4hnGzSl4RAA==", 10000);
57 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIBEgQoIwAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 10000);
58 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiARIEECcAAAABDiA6Gzs8g31kiep6Mdjmx91QPAAb7z4GlY51dICNaMp4pQEPBAAAAAABEQSMjcRiARIEKCMAAAABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 10000);
59 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIBEgQoIwAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 1657048460);
60 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiARIEECcAAAABDiA6Gzs8g31kiep6Mdjmx91QPAAb7z4GlY51dICNaMp4pQEPBAAAAAABEQSMjcRiAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 1657048460);
61 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAAAAQ4gOhs7PIN9ZInqejHY5sfdUDwAG+8+BpWOdXSAjWjKeKUBDwQAAAAAAREEjI3EYgABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 1657048460);
62 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIAAQMIT5M1dwAAAAABBBYAFAsTUsrNA89qobfzyNY4hnGzSl4RAA==", std::nullopt);
63}
64
65BOOST_AUTO_TEST_CASE(psbt2_addinput)
66{
67 FastRandomContext rng(/*fDeterministic=*/true);
68
70 PartiallySignedTransaction psbt(mtx, /*version=*/2);
71 psbt.m_tx_modifiable.emplace();
72 psbt.m_tx_modifiable->set(0, true);
73 BOOST_CHECK_EQUAL(psbt.inputs.size(), 0);
74
75 // Same PSBT version is required
76 uint256 txid;
78 PSBTInput psbtin_v0(/*psbt_version=*/0, Txid::FromUint256(txid), /*prev_out=*/0);
79 BOOST_CHECK(!psbt.AddInput(psbtin_v0));
80 BOOST_CHECK_EQUAL(psbt.inputs.size(), 0);
82 PSBTInput psbtin(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
83 BOOST_CHECK(psbt.AddInput(psbtin));
84 BOOST_CHECK_EQUAL(psbt.inputs.size(), 1);
85
86 // Duplicates are not allowed
87 BOOST_CHECK(!psbt.AddInput(psbtin));
88 BOOST_CHECK_EQUAL(psbt.inputs.size(), 1);
89
90 // Input with a unique txid is allowed
92 PSBTInput psbtin2(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
93 BOOST_CHECK(psbt.AddInput(psbtin2));
94 BOOST_CHECK_EQUAL(psbt.inputs.size(), 2);
95
96 // Disabling inputs modifiable flag prevents adding new inputs
97 psbt.m_tx_modifiable->set(0, false);
99 PSBTInput psbtin3(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
100 BOOST_CHECK(!psbt.AddInput(psbtin3));
101 BOOST_CHECK_EQUAL(psbt.inputs.size(), 2);
102 psbt.m_tx_modifiable->set(0, true);
103
104 // Make sure that timelock compatibility checks are working
105 // No previous required timelocks, new input with both height and time timelocks is allowed
107 PSBTInput psbtin4(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
109 psbtin4.height_locktime = 100;
110 BOOST_CHECK(psbt.AddInput(psbtin4));
111 BOOST_CHECK_EQUAL(psbt.inputs.size(), 3);
112
113 // Input with only a time timelock is allowed
115 PSBTInput psbtin5(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
116 psbtin5.time_locktime = LOCKTIME_THRESHOLD + 1;
117 BOOST_CHECK(psbt.AddInput(psbtin5));
118 BOOST_CHECK_EQUAL(psbt.inputs.size(), 4);
119
120 // Input with only a height timelock is not allowed because of previous
122 PSBTInput psbtin6(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
123 psbtin6.height_locktime = 100;
124 BOOST_CHECK(!psbt.AddInput(psbtin6));
125 BOOST_CHECK_EQUAL(psbt.inputs.size(), 4);
126
127 // Adding an input that already has a signature is allowed
129 PSBTInput psbtin7(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
130 psbtin7.final_script_sig << OP_1;
131 BOOST_CHECK(psbt.AddInput(psbtin7));
132 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
133
134 // Same thing, but with other things that have signatures
135 psbtin7.final_script_sig.clear();
136 psbtin7.final_script_witness.stack.emplace_back();
137 BOOST_CHECK(!psbt.AddInput(psbtin7));
138 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
140 psbtin7.partial_sigs.emplace();
141 BOOST_CHECK(!psbt.AddInput(psbtin7));
142 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
143 psbtin7.partial_sigs.clear();
144 psbtin7.m_tap_key_sig.push_back(0);
145 BOOST_CHECK(!psbt.AddInput(psbtin7));
146 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
147 psbtin7.m_tap_key_sig.clear();
148 psbtin7.m_tap_script_sigs.emplace();
149 BOOST_CHECK(!psbt.AddInput(psbtin7));
150 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
151 psbtin7.m_tap_script_sigs.clear();
152 psbtin7.m_musig2_partial_sigs.emplace();
153 BOOST_CHECK(!psbt.AddInput(psbtin7));
154 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
155
156 // Adding an input that changes the timelock is no longer allowed
158 PSBTInput psbtin8(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
159 psbtin8.time_locktime = LOCKTIME_THRESHOLD + 2;
160 BOOST_CHECK(!psbt.AddInput(psbtin8));
161 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
162}
163
164BOOST_AUTO_TEST_CASE(psbt2_addoutput)
165{
167 PartiallySignedTransaction psbt(mtx, /*version=*/2);
168 psbt.m_tx_modifiable.emplace();
169 psbt.m_tx_modifiable->set(1, true);
170 BOOST_CHECK_EQUAL(psbt.outputs.size(), 0);
171
172 // Same PSBT version is required
173 PSBTOutput psbtout_v0(/*psbt_version=*/0, /*amount=*/1, CScript());
174 BOOST_CHECK(!psbt.AddOutput(psbtout_v0));
175 BOOST_CHECK_EQUAL(psbt.outputs.size(), 0);
176 PSBTOutput psbtout(/*psbt_version=*/2, /*amount=*/1, CScript());
177 BOOST_CHECK(psbt.AddOutput(psbtout));
178 BOOST_CHECK_EQUAL(psbt.outputs.size(), 1);
179
180 // Disabling outputs modifiable flag prevents adding new outputs
181 psbt.m_tx_modifiable->set(1, false);
182 PSBTOutput psbtout2(/*psbt_version=*/2, /*amount=*/1, CScript());
183 BOOST_CHECK(!psbt.AddOutput(psbtout2));
184 BOOST_CHECK_EQUAL(psbt.outputs.size(), 1);
185 psbt.m_tx_modifiable->set(1, true);
186 PSBTOutput psbtout3(/*psbt_version=*/2, /*amount=*/1, CScript());
187 BOOST_CHECK(psbt.AddOutput(psbtout3));
188 BOOST_CHECK_EQUAL(psbt.outputs.size(), 2);
189}
190
191BOOST_AUTO_TEST_CASE(merge_proprietary_fields)
192{
194 tx.vin.emplace_back(COutPoint{});
195 tx.vout.emplace_back(0, CScript{});
196
199
200 const auto left_prop = MakeProprietary(/*subtype=*/1, /*key_data=*/0x01, /*value=*/0xaa);
201 const auto right_prop = MakeProprietary(/*subtype=*/2, /*key_data=*/0x02, /*value=*/0xbb);
202
203 left.m_proprietary.insert(left_prop);
204 left.inputs[0].m_proprietary.insert(left_prop);
205 left.outputs[0].m_proprietary.insert(left_prop);
206
207 right.m_proprietary.insert(right_prop);
208 right.inputs[0].m_proprietary.insert(right_prop);
209 right.outputs[0].m_proprietary.insert(right_prop);
210
211 BOOST_REQUIRE(left.Merge(right));
212
213 BOOST_REQUIRE_EQUAL(left.m_proprietary.size(), 2U);
214 BOOST_REQUIRE_EQUAL(left.inputs[0].m_proprietary.size(), 2U);
215 BOOST_REQUIRE_EQUAL(left.outputs[0].m_proprietary.size(), 2U);
216
217 const auto global_it = left.m_proprietary.find(right_prop);
218 BOOST_REQUIRE(global_it != left.m_proprietary.end());
219 BOOST_CHECK(global_it->value == right_prop.value);
220
221 const auto input_it = left.inputs[0].m_proprietary.find(right_prop);
222 BOOST_REQUIRE(input_it != left.inputs[0].m_proprietary.end());
223 BOOST_CHECK(input_it->value == right_prop.value);
224
225 const auto output_it = left.outputs[0].m_proprietary.find(right_prop);
226 BOOST_REQUIRE(output_it != left.outputs[0].m_proprietary.end());
227 BOOST_CHECK(output_it->value == right_prop.value);
228}
229
234
235 explicit PSBTOutputTest(std::string descriptor)
236 {
237 CKey key{GenerateRandomKey()};
238 pubkey = key.GetPubKey();
239 provider.keys.emplace(pubkey.GetID(), key);
240
241 util::ReplaceAll(descriptor, "<KEY>", HexStr(pubkey));
242 std::string error;
243 auto descriptors{Parse(descriptor, provider, error, /*require_checksum=*/false)};
244 BOOST_REQUIRE_MESSAGE(!descriptors.empty(), error);
245 std::vector<CScript> output_scripts;
246 BOOST_REQUIRE(descriptors[0]->Expand(/*pos=*/0, provider, output_scripts, provider));
247 BOOST_REQUIRE_EQUAL(output_scripts.size(), 1);
248 script_pubkey = output_scripts[0];
249 }
250
251 PSBTOutput UpdateOutput(bool has_input) const
252 {
254 if (has_input) tx.vin.emplace_back();
255 tx.vout.emplace_back(0, script_pubkey);
257 UpdatePSBTOutput(provider, psbt, 0);
258 return psbt.outputs[0];
259 }
260};
261
262BOOST_AUTO_TEST_CASE(update_psbt_output_keypaths)
263{
264 for (bool has_input : {false, true}) {
265 for (const auto& descriptor : {"pkh(<KEY>)", "wpkh(<KEY>)"}) {
266 PSBTOutputTest test{descriptor};
267 auto out{test.UpdateOutput(has_input)};
268 BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
269 BOOST_CHECK(out.redeem_script.empty());
270 BOOST_CHECK(out.witness_script.empty());
271 }
272 }
273}
274
275BOOST_AUTO_TEST_CASE(update_psbt_output_redeem_script)
276{
277 for (bool has_input : {false, true}) {
278 PSBTOutputTest test{"sh(wpkh(<KEY>))"};
279 auto out{test.UpdateOutput(has_input)};
280 BOOST_CHECK(out.redeem_script == GetScriptForDestination(WitnessV0KeyHash{test.pubkey}));
281 BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
282 }
283}
284
285BOOST_AUTO_TEST_CASE(update_psbt_output_witness_script)
286{
287 for (bool has_input : {false, true}) {
288 PSBTOutputTest test{"wsh(pk(<KEY>))"};
289 auto out{test.UpdateOutput(has_input)};
290 BOOST_CHECK(out.witness_script == GetScriptForRawPubKey(test.pubkey));
291 BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
292 }
293}
294
295BOOST_AUTO_TEST_CASE(update_psbt_output_miniscript_timelock)
296{
297 for (bool has_input : {false, true}) {
298 PSBTOutputTest test{"wsh(and_v(v:pk(<KEY>),older(144)))"};
299 auto out{test.UpdateOutput(has_input)};
300 BOOST_CHECK(GetScriptForDestination(WitnessV0ScriptHash{out.witness_script}) == test.script_pubkey);
301 BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
302 }
303}
304
305BOOST_AUTO_TEST_CASE(update_psbt_output_taproot)
306{
307 for (bool has_input : {false, true}) {
308 PSBTOutputTest test{"rawtr(<KEY>)"};
309 auto out{test.UpdateOutput(has_input)};
310 BOOST_CHECK(out.m_tap_bip32_paths.contains(XOnlyPubKey{test.pubkey}));
311 BOOST_CHECK(out.hd_keypaths.empty());
312 }
313}
314
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
An encapsulated private key.
Definition: key.h:40
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
An encapsulated public key.
Definition: pubkey.h:40
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:166
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:406
void clear()
Definition: script.h:569
Fast randomness source.
Definition: random.h:386
void fillrand(std::span< std::byte > output) noexcept
Fill a byte span with random bytes.
Definition: random.cpp:626
A structure for PSBTs which contain per-input information.
Definition: psbt.h:282
std::vector< unsigned char > m_tap_key_sig
Definition: psbt.h:307
CScriptWitness final_script_witness
Definition: psbt.h:292
std::map< CKeyID, SigPair > partial_sigs
Definition: psbt.h:294
std::map< std::pair< XOnlyPubKey, uint256 >, std::vector< unsigned char > > m_tap_script_sigs
Definition: psbt.h:308
std::optional< uint32_t > time_locktime
Definition: psbt.h:303
std::map< std::pair< CPubKey, uint256 >, std::map< CPubKey, uint256 > > m_musig2_partial_sigs
Definition: psbt.h:319
CScript final_script_sig
Definition: psbt.h:291
std::optional< uint32_t > height_locktime
Definition: psbt.h:304
A structure for PSBTs which contains per output information.
Definition: psbt.h:939
A version of CTransaction with the PSBT format.
Definition: psbt.h:1239
std::optional< std::bitset< 8 > > m_tx_modifiable
Definition: psbt.h:1247
bool Merge(const PartiallySignedTransaction &psbt)
Merge psbt into this.
Definition: psbt.cpp:36
std::vector< PSBTInput > inputs
Definition: psbt.h:1248
std::vector< PSBTOutput > outputs
Definition: psbt.h:1249
std::set< PSBTProprietary > m_proprietary
Definition: psbt.h:1251
bool AddOutput(const PSBTOutput &psbtout)
Definition: psbt.cpp:247
bool AddInput(const PSBTInput &psbtin)
Definition: psbt.cpp:164
static transaction_identifier FromUint256(const uint256 &id)
256-bit opaque blob.
Definition: uint256.h:196
static UniValue Parse(std::string_view raw, ParamFormat format=ParamFormat::JSON)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:405
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:30
BOOST_CHECK_EQUAL(headers.FindFirst("key"), "value")
CKey GenerateRandomKey(bool compressed) noexcept
Definition: key.cpp:354
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
Definition: string.cpp:14
#define BOOST_CHECK(expr)
Definition: object.cpp:16
void UpdatePSBTOutput(const SigningProvider &provider, PartiallySignedTransaction &psbt, int index)
Updates a PSBTOutput with information from provider.
Definition: psbt.cpp:593
util::Result< PartiallySignedTransaction > DecodeBase64PSBT(const std::string &base64_tx)
Decode a base64ed PSBT into a PartiallySignedTransaction.
Definition: psbt.cpp:858
BOOST_AUTO_TEST_CASE(psbt2_timelock_test)
Definition: psbt_tests.cpp:51
static PSBTProprietary MakeProprietary(uint64_t subtype, uint8_t key_data, uint8_t value)
Definition: psbt_tests.cpp:23
void CheckTimeLock(const std::string &base64_psbt, std::optional< uint32_t > timelock)
Definition: psbt_tests.cpp:33
@ OP_1
Definition: script.h:84
constexpr unsigned int LOCKTIME_THRESHOLD
Definition: script.h:48
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: solver.cpp:213
auto MakeWritableByteSpan(V &&v) noexcept
Definition: span.h:89
Basic testing setup.
Definition: setup_common.h:58
A mutable version of CTransaction.
Definition: transaction.h:358
std::vector< CTxOut > vout
Definition: transaction.h:360
std::vector< CTxIn > vin
Definition: transaction.h:359
std::vector< std::vector< unsigned char > > stack
Definition: script.h:581
void SetNull()
Definition: script.h:588
std::map< CKeyID, CKey > keys
PSBTOutput UpdateOutput(bool has_input) const
Definition: psbt_tests.cpp:251
FlatSigningProvider provider
Definition: psbt_tests.cpp:232
PSBTOutputTest(std::string descriptor)
Definition: psbt_tests.cpp:235
CScript script_pubkey
Definition: psbt_tests.cpp:233
A structure for PSBT proprietary types.
Definition: psbt.h:101
uint64_t subtype
Definition: psbt.h:102
FastRandomContext rng
Definition: dbwrapper.cpp:413