Bitcoin Core 28.99.0
P2P Digital Currency
descriptor.cpp
Go to the documentation of this file.
1// Copyright (c) 2018-2022 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 <script/descriptor.h>
6
7#include <hash.h>
8#include <key_io.h>
9#include <pubkey.h>
10#include <script/miniscript.h>
11#include <script/parsing.h>
12#include <script/script.h>
14#include <script/solver.h>
15#include <uint256.h>
16
17#include <common/args.h>
18#include <span.h>
19#include <util/bip32.h>
20#include <util/check.h>
21#include <util/strencodings.h>
22#include <util/vector.h>
23
24#include <algorithm>
25#include <memory>
26#include <numeric>
27#include <optional>
28#include <string>
29#include <vector>
30
31using util::Split;
32
33namespace {
34
36// Checksum //
38
39// This section implements a checksum algorithm for descriptors with the
40// following properties:
41// * Mistakes in a descriptor string are measured in "symbol errors". The higher
42// the number of symbol errors, the harder it is to detect:
43// * An error substituting a character from 0123456789()[],'/*abcdefgh@:$%{} for
44// another in that set always counts as 1 symbol error.
45// * Note that hex encoded keys are covered by these characters. Xprvs and
46// xpubs use other characters too, but already have their own checksum
47// mechanism.
48// * Function names like "multi()" use other characters, but mistakes in
49// these would generally result in an unparsable descriptor.
50// * A case error always counts as 1 symbol error.
51// * Any other 1 character substitution error counts as 1 or 2 symbol errors.
52// * Any 1 symbol error is always detected.
53// * Any 2 or 3 symbol error in a descriptor of up to 49154 characters is always detected.
54// * Any 4 symbol error in a descriptor of up to 507 characters is always detected.
55// * Any 5 symbol error in a descriptor of up to 77 characters is always detected.
56// * Is optimized to minimize the chance a 5 symbol error in a descriptor up to 387 characters is undetected
57// * Random errors have a chance of 1 in 2**40 of being undetected.
58//
59// These properties are achieved by expanding every group of 3 (non checksum) characters into
60// 4 GF(32) symbols, over which a cyclic code is defined.
61
62/*
63 * Interprets c as 8 groups of 5 bits which are the coefficients of a degree 8 polynomial over GF(32),
64 * multiplies that polynomial by x, computes its remainder modulo a generator, and adds the constant term val.
65 *
66 * This generator is G(x) = x^8 + {30}x^7 + {23}x^6 + {15}x^5 + {14}x^4 + {10}x^3 + {6}x^2 + {12}x + {9}.
67 * It is chosen to define an cyclic error detecting code which is selected by:
68 * - Starting from all BCH codes over GF(32) of degree 8 and below, which by construction guarantee detecting
69 * 3 errors in windows up to 19000 symbols.
70 * - Taking all those generators, and for degree 7 ones, extend them to degree 8 by adding all degree-1 factors.
71 * - Selecting just the set of generators that guarantee detecting 4 errors in a window of length 512.
72 * - Selecting one of those with best worst-case behavior for 5 errors in windows of length up to 512.
73 *
74 * The generator and the constants to implement it can be verified using this Sage code:
75 * B = GF(2) # Binary field
76 * BP.<b> = B[] # Polynomials over the binary field
77 * F_mod = b**5 + b**3 + 1
78 * F.<f> = GF(32, modulus=F_mod, repr='int') # GF(32) definition
79 * FP.<x> = F[] # Polynomials over GF(32)
80 * E_mod = x**3 + x + F.fetch_int(8)
81 * E.<e> = F.extension(E_mod) # Extension field definition
82 * alpha = e**2743 # Choice of an element in extension field
83 * for p in divisors(E.order() - 1): # Verify alpha has order 32767.
84 * assert((alpha**p == 1) == (p % 32767 == 0))
85 * G = lcm([(alpha**i).minpoly() for i in [1056,1057,1058]] + [x + 1])
86 * print(G) # Print out the generator
87 * for i in [1,2,4,8,16]: # Print out {1,2,4,8,16}*(G mod x^8), packed in hex integers.
88 * v = 0
89 * for coef in reversed((F.fetch_int(i)*(G % x**8)).coefficients(sparse=True)):
90 * v = v*32 + coef.integer_representation()
91 * print("0x%x" % v)
92 */
93uint64_t PolyMod(uint64_t c, int val)
94{
95 uint8_t c0 = c >> 35;
96 c = ((c & 0x7ffffffff) << 5) ^ val;
97 if (c0 & 1) c ^= 0xf5dee51989;
98 if (c0 & 2) c ^= 0xa9fdca3312;
99 if (c0 & 4) c ^= 0x1bab10e32d;
100 if (c0 & 8) c ^= 0x3706b1677a;
101 if (c0 & 16) c ^= 0x644d626ffd;
102 return c;
103}
104
105std::string DescriptorChecksum(const Span<const char>& span)
106{
120 static const std::string INPUT_CHARSET =
121 "0123456789()[],'/*abcdefgh@:$%{}"
122 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
123 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
124
126 static const std::string CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
127
128 uint64_t c = 1;
129 int cls = 0;
130 int clscount = 0;
131 for (auto ch : span) {
132 auto pos = INPUT_CHARSET.find(ch);
133 if (pos == std::string::npos) return "";
134 c = PolyMod(c, pos & 31); // Emit a symbol for the position inside the group, for every character.
135 cls = cls * 3 + (pos >> 5); // Accumulate the group numbers
136 if (++clscount == 3) {
137 // Emit an extra symbol representing the group numbers, for every 3 characters.
138 c = PolyMod(c, cls);
139 cls = 0;
140 clscount = 0;
141 }
142 }
143 if (clscount > 0) c = PolyMod(c, cls);
144 for (int j = 0; j < 8; ++j) c = PolyMod(c, 0); // Shift further to determine the checksum.
145 c ^= 1; // Prevent appending zeroes from not affecting the checksum.
146
147 std::string ret(8, ' ');
148 for (int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
149 return ret;
150}
151
152std::string AddChecksum(const std::string& str) { return str + "#" + DescriptorChecksum(str); }
153
155// Internal representation //
157
158typedef std::vector<uint32_t> KeyPath;
159
161struct PubkeyProvider
162{
163protected:
166 uint32_t m_expr_index;
167
168public:
169 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
170
171 virtual ~PubkeyProvider() = default;
172
176 bool operator<(PubkeyProvider& other) const {
177 CPubKey a, b;
178 SigningProvider dummy;
179 KeyOriginInfo dummy_info;
180
181 GetPubKey(0, dummy, a, dummy_info);
182 other.GetPubKey(0, dummy, b, dummy_info);
183
184 return a < b;
185 }
186
192 virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const = 0;
193
195 virtual bool IsRange() const = 0;
196
198 virtual size_t GetSize() const = 0;
199
200 enum class StringType {
201 PUBLIC,
202 COMPAT // string calculation that mustn't change over time to stay compatible with previous software versions
203 };
204
206 virtual std::string ToString(StringType type=StringType::PUBLIC) const = 0;
207
209 virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
210
214 virtual bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache = nullptr) const = 0;
215
217 virtual bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const = 0;
218
220 virtual std::optional<CPubKey> GetRootPubKey() const = 0;
222 virtual std::optional<CExtPubKey> GetRootExtPubKey() const = 0;
223
225 virtual std::unique_ptr<PubkeyProvider> Clone() const = 0;
226};
227
228class OriginPubkeyProvider final : public PubkeyProvider
229{
230 KeyOriginInfo m_origin;
231 std::unique_ptr<PubkeyProvider> m_provider;
232 bool m_apostrophe;
233
234 std::string OriginString(StringType type, bool normalized=false) const
235 {
236 // If StringType==COMPAT, always use the apostrophe to stay compatible with previous versions
237 bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
238 return HexStr(m_origin.fingerprint) + FormatHDKeypath(m_origin.path, use_apostrophe);
239 }
240
241public:
242 OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider, bool apostrophe) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)), m_apostrophe(apostrophe) {}
243 bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override
244 {
245 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache)) return false;
246 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.fingerprint);
247 info.path.insert(info.path.begin(), m_origin.path.begin(), m_origin.path.end());
248 return true;
249 }
250 bool IsRange() const override { return m_provider->IsRange(); }
251 size_t GetSize() const override { return m_provider->GetSize(); }
252 std::string ToString(StringType type) const override { return "[" + OriginString(type) + "]" + m_provider->ToString(type); }
253 bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
254 {
255 std::string sub;
256 if (!m_provider->ToPrivateString(arg, sub)) return false;
257 ret = "[" + OriginString(StringType::PUBLIC) + "]" + std::move(sub);
258 return true;
259 }
260 bool ToNormalizedString(const SigningProvider& arg, std::string& ret, const DescriptorCache* cache) const override
261 {
262 std::string sub;
263 if (!m_provider->ToNormalizedString(arg, sub, cache)) return false;
264 // If m_provider is a BIP32PubkeyProvider, we may get a string formatted like a OriginPubkeyProvider
265 // In that case, we need to strip out the leading square bracket and fingerprint from the substring,
266 // and append that to our own origin string.
267 if (sub[0] == '[') {
268 sub = sub.substr(9);
269 ret = "[" + OriginString(StringType::PUBLIC, /*normalized=*/true) + std::move(sub);
270 } else {
271 ret = "[" + OriginString(StringType::PUBLIC, /*normalized=*/true) + "]" + std::move(sub);
272 }
273 return true;
274 }
275 bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
276 {
277 return m_provider->GetPrivKey(pos, arg, key);
278 }
279 std::optional<CPubKey> GetRootPubKey() const override
280 {
281 return m_provider->GetRootPubKey();
282 }
283 std::optional<CExtPubKey> GetRootExtPubKey() const override
284 {
285 return m_provider->GetRootExtPubKey();
286 }
287 std::unique_ptr<PubkeyProvider> Clone() const override
288 {
289 return std::make_unique<OriginPubkeyProvider>(m_expr_index, m_origin, m_provider->Clone(), m_apostrophe);
290 }
291};
292
294class ConstPubkeyProvider final : public PubkeyProvider
295{
296 CPubKey m_pubkey;
297 bool m_xonly;
298
299public:
300 ConstPubkeyProvider(uint32_t exp_index, const CPubKey& pubkey, bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
301 bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override
302 {
303 key = m_pubkey;
304 info.path.clear();
305 CKeyID keyid = m_pubkey.GetID();
306 std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
307 return true;
308 }
309 bool IsRange() const override { return false; }
310 size_t GetSize() const override { return m_pubkey.size(); }
311 std::string ToString(StringType type) const override { return m_xonly ? HexStr(m_pubkey).substr(2) : HexStr(m_pubkey); }
312 bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
313 {
314 CKey key;
315 if (!GetPrivKey(/*pos=*/0, arg, key)) return false;
316 ret = EncodeSecret(key);
317 return true;
318 }
319 bool ToNormalizedString(const SigningProvider& arg, std::string& ret, const DescriptorCache* cache) const override
320 {
321 ret = ToString(StringType::PUBLIC);
322 return true;
323 }
324 bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
325 {
326 return m_xonly ? arg.GetKeyByXOnly(XOnlyPubKey(m_pubkey), key) :
327 arg.GetKey(m_pubkey.GetID(), key);
328 }
329 std::optional<CPubKey> GetRootPubKey() const override
330 {
331 return m_pubkey;
332 }
333 std::optional<CExtPubKey> GetRootExtPubKey() const override
334 {
335 return std::nullopt;
336 }
337 std::unique_ptr<PubkeyProvider> Clone() const override
338 {
339 return std::make_unique<ConstPubkeyProvider>(m_expr_index, m_pubkey, m_xonly);
340 }
341};
342
343enum class DeriveType {
344 NO,
345 UNHARDENED,
346 HARDENED,
347};
348
350class BIP32PubkeyProvider final : public PubkeyProvider
351{
352 // Root xpub, path, and final derivation step type being used, if any
353 CExtPubKey m_root_extkey;
354 KeyPath m_path;
355 DeriveType m_derive;
356 // Whether ' or h is used in harded derivation
357 bool m_apostrophe;
358
359 bool GetExtKey(const SigningProvider& arg, CExtKey& ret) const
360 {
361 CKey key;
362 if (!arg.GetKey(m_root_extkey.pubkey.GetID(), key)) return false;
363 ret.nDepth = m_root_extkey.nDepth;
364 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint + sizeof(ret.vchFingerprint), ret.vchFingerprint);
365 ret.nChild = m_root_extkey.nChild;
366 ret.chaincode = m_root_extkey.chaincode;
367 ret.key = key;
368 return true;
369 }
370
371 // Derives the last xprv
372 bool GetDerivedExtKey(const SigningProvider& arg, CExtKey& xprv, CExtKey& last_hardened) const
373 {
374 if (!GetExtKey(arg, xprv)) return false;
375 for (auto entry : m_path) {
376 if (!xprv.Derive(xprv, entry)) return false;
377 if (entry >> 31) {
378 last_hardened = xprv;
379 }
380 }
381 return true;
382 }
383
384 bool IsHardened() const
385 {
386 if (m_derive == DeriveType::HARDENED) return true;
387 for (auto entry : m_path) {
388 if (entry >> 31) return true;
389 }
390 return false;
391 }
392
393public:
394 BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive, bool apostrophe) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive), m_apostrophe(apostrophe) {}
395 bool IsRange() const override { return m_derive != DeriveType::NO; }
396 size_t GetSize() const override { return 33; }
397 bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key_out, KeyOriginInfo& final_info_out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override
398 {
399 // Info of parent of the to be derived pubkey
400 KeyOriginInfo parent_info;
401 CKeyID keyid = m_root_extkey.pubkey.GetID();
402 std::copy(keyid.begin(), keyid.begin() + sizeof(parent_info.fingerprint), parent_info.fingerprint);
403 parent_info.path = m_path;
404
405 // Info of the derived key itself which is copied out upon successful completion
406 KeyOriginInfo final_info_out_tmp = parent_info;
407 if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.path.push_back((uint32_t)pos);
408 if (m_derive == DeriveType::HARDENED) final_info_out_tmp.path.push_back(((uint32_t)pos) | 0x80000000L);
409
410 // Derive keys or fetch them from cache
411 CExtPubKey final_extkey = m_root_extkey;
412 CExtPubKey parent_extkey = m_root_extkey;
413 CExtPubKey last_hardened_extkey;
414 bool der = true;
415 if (read_cache) {
416 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
417 if (m_derive == DeriveType::HARDENED) return false;
418 // Try to get the derivation parent
419 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey)) return false;
420 final_extkey = parent_extkey;
421 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
422 }
423 } else if (IsHardened()) {
424 CExtKey xprv;
425 CExtKey lh_xprv;
426 if (!GetDerivedExtKey(arg, xprv, lh_xprv)) return false;
427 parent_extkey = xprv.Neuter();
428 if (m_derive == DeriveType::UNHARDENED) der = xprv.Derive(xprv, pos);
429 if (m_derive == DeriveType::HARDENED) der = xprv.Derive(xprv, pos | 0x80000000UL);
430 final_extkey = xprv.Neuter();
431 if (lh_xprv.key.IsValid()) {
432 last_hardened_extkey = lh_xprv.Neuter();
433 }
434 } else {
435 for (auto entry : m_path) {
436 if (!parent_extkey.Derive(parent_extkey, entry)) return false;
437 }
438 final_extkey = parent_extkey;
439 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
440 assert(m_derive != DeriveType::HARDENED);
441 }
442 if (!der) return false;
443
444 final_info_out = final_info_out_tmp;
445 key_out = final_extkey.pubkey;
446
447 if (write_cache) {
448 // Only cache parent if there is any unhardened derivation
449 if (m_derive != DeriveType::HARDENED) {
450 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
451 // Cache last hardened xpub if we have it
452 if (last_hardened_extkey.pubkey.IsValid()) {
453 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
454 }
455 } else if (final_info_out.path.size() > 0) {
456 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
457 }
458 }
459
460 return true;
461 }
462 std::string ToString(StringType type, bool normalized) const
463 {
464 // If StringType==COMPAT, always use the apostrophe to stay compatible with previous versions
465 const bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
466 std::string ret = EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path, /*apostrophe=*/use_apostrophe);
467 if (IsRange()) {
468 ret += "/*";
469 if (m_derive == DeriveType::HARDENED) ret += use_apostrophe ? '\'' : 'h';
470 }
471 return ret;
472 }
473 std::string ToString(StringType type=StringType::PUBLIC) const override
474 {
475 return ToString(type, /*normalized=*/false);
476 }
477 bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
478 {
479 CExtKey key;
480 if (!GetExtKey(arg, key)) return false;
481 out = EncodeExtKey(key) + FormatHDKeypath(m_path, /*apostrophe=*/m_apostrophe);
482 if (IsRange()) {
483 out += "/*";
484 if (m_derive == DeriveType::HARDENED) out += m_apostrophe ? '\'' : 'h';
485 }
486 return true;
487 }
488 bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache) const override
489 {
490 if (m_derive == DeriveType::HARDENED) {
491 out = ToString(StringType::PUBLIC, /*normalized=*/true);
492
493 return true;
494 }
495 // Step backwards to find the last hardened step in the path
496 int i = (int)m_path.size() - 1;
497 for (; i >= 0; --i) {
498 if (m_path.at(i) >> 31) {
499 break;
500 }
501 }
502 // Either no derivation or all unhardened derivation
503 if (i == -1) {
504 out = ToString();
505 return true;
506 }
507 // Get the path to the last hardened stup
508 KeyOriginInfo origin;
509 int k = 0;
510 for (; k <= i; ++k) {
511 // Add to the path
512 origin.path.push_back(m_path.at(k));
513 }
514 // Build the remaining path
515 KeyPath end_path;
516 for (; k < (int)m_path.size(); ++k) {
517 end_path.push_back(m_path.at(k));
518 }
519 // Get the fingerprint
520 CKeyID id = m_root_extkey.pubkey.GetID();
521 std::copy(id.begin(), id.begin() + 4, origin.fingerprint);
522
523 CExtPubKey xpub;
524 CExtKey lh_xprv;
525 // If we have the cache, just get the parent xpub
526 if (cache != nullptr) {
527 cache->GetCachedLastHardenedExtPubKey(m_expr_index, xpub);
528 }
529 if (!xpub.pubkey.IsValid()) {
530 // Cache miss, or nor cache, or need privkey
531 CExtKey xprv;
532 if (!GetDerivedExtKey(arg, xprv, lh_xprv)) return false;
533 xpub = lh_xprv.Neuter();
534 }
535 assert(xpub.pubkey.IsValid());
536
537 // Build the string
538 std::string origin_str = HexStr(origin.fingerprint) + FormatHDKeypath(origin.path);
539 out = "[" + origin_str + "]" + EncodeExtPubKey(xpub) + FormatHDKeypath(end_path);
540 if (IsRange()) {
541 out += "/*";
542 assert(m_derive == DeriveType::UNHARDENED);
543 }
544 return true;
545 }
546 bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
547 {
548 CExtKey extkey;
549 CExtKey dummy;
550 if (!GetDerivedExtKey(arg, extkey, dummy)) return false;
551 if (m_derive == DeriveType::UNHARDENED && !extkey.Derive(extkey, pos)) return false;
552 if (m_derive == DeriveType::HARDENED && !extkey.Derive(extkey, pos | 0x80000000UL)) return false;
553 key = extkey.key;
554 return true;
555 }
556 std::optional<CPubKey> GetRootPubKey() const override
557 {
558 return std::nullopt;
559 }
560 std::optional<CExtPubKey> GetRootExtPubKey() const override
561 {
562 return m_root_extkey;
563 }
564 std::unique_ptr<PubkeyProvider> Clone() const override
565 {
566 return std::make_unique<BIP32PubkeyProvider>(m_expr_index, m_root_extkey, m_path, m_derive, m_apostrophe);
567 }
568};
569
571class DescriptorImpl : public Descriptor
572{
573protected:
575 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
577 const std::string m_name;
578
583 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
584
586 virtual std::string ToStringExtra() const { return ""; }
587
598 virtual std::vector<CScript> MakeScripts(const std::vector<CPubKey>& pubkeys, Span<const CScript> scripts, FlatSigningProvider& out) const = 0;
599
600public:
601 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_name(name), m_subdescriptor_args() {}
602 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl> script, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_name(name), m_subdescriptor_args(Vector(std::move(script))) {}
603 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::vector<std::unique_ptr<DescriptorImpl>> scripts, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_name(name), m_subdescriptor_args(std::move(scripts)) {}
604
605 enum class StringType
606 {
607 PUBLIC,
608 PRIVATE,
609 NORMALIZED,
610 COMPAT, // string calculation that mustn't change over time to stay compatible with previous software versions
611 };
612
613 // NOLINTNEXTLINE(misc-no-recursion)
614 bool IsSolvable() const override
615 {
616 for (const auto& arg : m_subdescriptor_args) {
617 if (!arg->IsSolvable()) return false;
618 }
619 return true;
620 }
621
622 // NOLINTNEXTLINE(misc-no-recursion)
623 bool IsRange() const final
624 {
625 for (const auto& pubkey : m_pubkey_args) {
626 if (pubkey->IsRange()) return true;
627 }
628 for (const auto& arg : m_subdescriptor_args) {
629 if (arg->IsRange()) return true;
630 }
631 return false;
632 }
633
634 // NOLINTNEXTLINE(misc-no-recursion)
635 virtual bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type, const DescriptorCache* cache = nullptr) const
636 {
637 size_t pos = 0;
638 for (const auto& scriptarg : m_subdescriptor_args) {
639 if (pos++) ret += ",";
640 std::string tmp;
641 if (!scriptarg->ToStringHelper(arg, tmp, type, cache)) return false;
642 ret += tmp;
643 }
644 return true;
645 }
646
647 // NOLINTNEXTLINE(misc-no-recursion)
648 virtual bool ToStringHelper(const SigningProvider* arg, std::string& out, const StringType type, const DescriptorCache* cache = nullptr) const
649 {
650 std::string extra = ToStringExtra();
651 size_t pos = extra.size() > 0 ? 1 : 0;
652 std::string ret = m_name + "(" + extra;
653 for (const auto& pubkey : m_pubkey_args) {
654 if (pos++) ret += ",";
655 std::string tmp;
656 switch (type) {
657 case StringType::NORMALIZED:
658 if (!pubkey->ToNormalizedString(*arg, tmp, cache)) return false;
659 break;
660 case StringType::PRIVATE:
661 if (!pubkey->ToPrivateString(*arg, tmp)) return false;
662 break;
663 case StringType::PUBLIC:
664 tmp = pubkey->ToString();
665 break;
666 case StringType::COMPAT:
667 tmp = pubkey->ToString(PubkeyProvider::StringType::COMPAT);
668 break;
669 }
670 ret += tmp;
671 }
672 std::string subscript;
673 if (!ToStringSubScriptHelper(arg, subscript, type, cache)) return false;
674 if (pos && subscript.size()) ret += ',';
675 out = std::move(ret) + std::move(subscript) + ")";
676 return true;
677 }
678
679 std::string ToString(bool compat_format) const final
680 {
681 std::string ret;
682 ToStringHelper(nullptr, ret, compat_format ? StringType::COMPAT : StringType::PUBLIC);
683 return AddChecksum(ret);
684 }
685
686 bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
687 {
688 bool ret = ToStringHelper(&arg, out, StringType::PRIVATE);
689 out = AddChecksum(out);
690 return ret;
691 }
692
693 bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache) const override final
694 {
695 bool ret = ToStringHelper(&arg, out, StringType::NORMALIZED, cache);
696 out = AddChecksum(out);
697 return ret;
698 }
699
700 // NOLINTNEXTLINE(misc-no-recursion)
701 bool ExpandHelper(int pos, const SigningProvider& arg, const DescriptorCache* read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache) const
702 {
703 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
704 entries.reserve(m_pubkey_args.size());
705
706 // Construct temporary data in `entries`, `subscripts`, and `subprovider` to avoid producing output in case of failure.
707 for (const auto& p : m_pubkey_args) {
708 entries.emplace_back();
709 if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache)) return false;
710 }
711 std::vector<CScript> subscripts;
712 FlatSigningProvider subprovider;
713 for (const auto& subarg : m_subdescriptor_args) {
714 std::vector<CScript> outscripts;
715 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache)) return false;
716 assert(outscripts.size() == 1);
717 subscripts.emplace_back(std::move(outscripts[0]));
718 }
719 out.Merge(std::move(subprovider));
720
721 std::vector<CPubKey> pubkeys;
722 pubkeys.reserve(entries.size());
723 for (auto& entry : entries) {
724 pubkeys.push_back(entry.first);
725 out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(CPubKey(entry.first), std::move(entry.second)));
726 }
727
728 output_scripts = MakeScripts(pubkeys, Span{subscripts}, out);
729 return true;
730 }
731
732 bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache = nullptr) const final
733 {
734 return ExpandHelper(pos, provider, nullptr, output_scripts, out, write_cache);
735 }
736
737 bool ExpandFromCache(int pos, const DescriptorCache& read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const final
738 {
739 return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &read_cache, output_scripts, out, nullptr);
740 }
741
742 // NOLINTNEXTLINE(misc-no-recursion)
743 void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const final
744 {
745 for (const auto& p : m_pubkey_args) {
746 CKey key;
747 if (!p->GetPrivKey(pos, provider, key)) continue;
748 out.keys.emplace(key.GetPubKey().GetID(), key);
749 }
750 for (const auto& arg : m_subdescriptor_args) {
751 arg->ExpandPrivate(pos, provider, out);
752 }
753 }
754
755 std::optional<OutputType> GetOutputType() const override { return std::nullopt; }
756
757 std::optional<int64_t> ScriptSize() const override { return {}; }
758
764 virtual std::optional<int64_t> MaxSatSize(bool use_max_sig) const { return {}; }
765
766 std::optional<int64_t> MaxSatisfactionWeight(bool) const override { return {}; }
767
768 std::optional<int64_t> MaxSatisfactionElems() const override { return {}; }
769
770 // NOLINTNEXTLINE(misc-no-recursion)
771 void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs) const override
772 {
773 for (const auto& p : m_pubkey_args) {
774 std::optional<CPubKey> pub = p->GetRootPubKey();
775 if (pub) pubkeys.insert(*pub);
776 std::optional<CExtPubKey> ext_pub = p->GetRootExtPubKey();
777 if (ext_pub) ext_pubs.insert(*ext_pub);
778 }
779 for (const auto& arg : m_subdescriptor_args) {
780 arg->GetPubKeys(pubkeys, ext_pubs);
781 }
782 }
783
784 virtual std::unique_ptr<DescriptorImpl> Clone() const = 0;
785};
786
788class AddressDescriptor final : public DescriptorImpl
789{
790 const CTxDestination m_destination;
791protected:
792 std::string ToStringExtra() const override { return EncodeDestination(m_destination); }
793 std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, Span<const CScript>, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(m_destination)); }
794public:
795 AddressDescriptor(CTxDestination destination) : DescriptorImpl({}, "addr"), m_destination(std::move(destination)) {}
796 bool IsSolvable() const final { return false; }
797
798 std::optional<OutputType> GetOutputType() const override
799 {
800 return OutputTypeFromDestination(m_destination);
801 }
802 bool IsSingleType() const final { return true; }
803 bool ToPrivateString(const SigningProvider& arg, std::string& out) const final { return false; }
804
805 std::optional<int64_t> ScriptSize() const override { return GetScriptForDestination(m_destination).size(); }
806 std::unique_ptr<DescriptorImpl> Clone() const override
807 {
808 return std::make_unique<AddressDescriptor>(m_destination);
809 }
810};
811
813class RawDescriptor final : public DescriptorImpl
814{
815 const CScript m_script;
816protected:
817 std::string ToStringExtra() const override { return HexStr(m_script); }
818 std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, Span<const CScript>, FlatSigningProvider&) const override { return Vector(m_script); }
819public:
820 RawDescriptor(CScript script) : DescriptorImpl({}, "raw"), m_script(std::move(script)) {}
821 bool IsSolvable() const final { return false; }
822
823 std::optional<OutputType> GetOutputType() const override
824 {
825 CTxDestination dest;
826 ExtractDestination(m_script, dest);
827 return OutputTypeFromDestination(dest);
828 }
829 bool IsSingleType() const final { return true; }
830 bool ToPrivateString(const SigningProvider& arg, std::string& out) const final { return false; }
831
832 std::optional<int64_t> ScriptSize() const override { return m_script.size(); }
833
834 std::unique_ptr<DescriptorImpl> Clone() const override
835 {
836 return std::make_unique<RawDescriptor>(m_script);
837 }
838};
839
841class PKDescriptor final : public DescriptorImpl
842{
843private:
844 const bool m_xonly;
845protected:
846 std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider&) const override
847 {
848 if (m_xonly) {
850 return Vector(std::move(script));
851 } else {
852 return Vector(GetScriptForRawPubKey(keys[0]));
853 }
854 }
855public:
856 PKDescriptor(std::unique_ptr<PubkeyProvider> prov, bool xonly = false) : DescriptorImpl(Vector(std::move(prov)), "pk"), m_xonly(xonly) {}
857 bool IsSingleType() const final { return true; }
858
859 std::optional<int64_t> ScriptSize() const override {
860 return 1 + (m_xonly ? 32 : m_pubkey_args[0]->GetSize()) + 1;
861 }
862
863 std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {
864 const auto ecdsa_sig_size = use_max_sig ? 72 : 71;
865 return 1 + (m_xonly ? 65 : ecdsa_sig_size);
866 }
867
868 std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {
869 return *MaxSatSize(use_max_sig) * WITNESS_SCALE_FACTOR;
870 }
871
872 std::optional<int64_t> MaxSatisfactionElems() const override { return 1; }
873
874 std::unique_ptr<DescriptorImpl> Clone() const override
875 {
876 return std::make_unique<PKDescriptor>(m_pubkey_args.at(0)->Clone(), m_xonly);
877 }
878};
879
881class PKHDescriptor final : public DescriptorImpl
882{
883protected:
884 std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider& out) const override
885 {
886 CKeyID id = keys[0].GetID();
887 out.pubkeys.emplace(id, keys[0]);
889 }
890public:
891 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "pkh") {}
892 std::optional<OutputType> GetOutputType() const override { return OutputType::LEGACY; }
893 bool IsSingleType() const final { return true; }
894
895 std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 1 + 20 + 1 + 1; }
896
897 std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {
898 const auto sig_size = use_max_sig ? 72 : 71;
899 return 1 + sig_size + 1 + m_pubkey_args[0]->GetSize();
900 }
901
902 std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {
903 return *MaxSatSize(use_max_sig) * WITNESS_SCALE_FACTOR;
904 }
905
906 std::optional<int64_t> MaxSatisfactionElems() const override { return 2; }
907
908 std::unique_ptr<DescriptorImpl> Clone() const override
909 {
910 return std::make_unique<PKHDescriptor>(m_pubkey_args.at(0)->Clone());
911 }
912};
913
915class WPKHDescriptor final : public DescriptorImpl
916{
917protected:
918 std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider& out) const override
919 {
920 CKeyID id = keys[0].GetID();
921 out.pubkeys.emplace(id, keys[0]);
923 }
924public:
925 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "wpkh") {}
926 std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
927 bool IsSingleType() const final { return true; }
928
929 std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 20; }
930
931 std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {
932 const auto sig_size = use_max_sig ? 72 : 71;
933 return (1 + sig_size + 1 + 33);
934 }
935
936 std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {
937 return MaxSatSize(use_max_sig);
938 }
939
940 std::optional<int64_t> MaxSatisfactionElems() const override { return 2; }
941
942 std::unique_ptr<DescriptorImpl> Clone() const override
943 {
944 return std::make_unique<WPKHDescriptor>(m_pubkey_args.at(0)->Clone());
945 }
946};
947
949class ComboDescriptor final : public DescriptorImpl
950{
951protected:
952 std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider& out) const override
953 {
954 std::vector<CScript> ret;
955 CKeyID id = keys[0].GetID();
956 out.pubkeys.emplace(id, keys[0]);
957 ret.emplace_back(GetScriptForRawPubKey(keys[0])); // P2PK
958 ret.emplace_back(GetScriptForDestination(PKHash(id))); // P2PKH
959 if (keys[0].IsCompressed()) {
961 out.scripts.emplace(CScriptID(p2wpkh), p2wpkh);
962 ret.emplace_back(p2wpkh);
963 ret.emplace_back(GetScriptForDestination(ScriptHash(p2wpkh))); // P2SH-P2WPKH
964 }
965 return ret;
966 }
967public:
968 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "combo") {}
969 bool IsSingleType() const final { return false; }
970 std::unique_ptr<DescriptorImpl> Clone() const override
971 {
972 return std::make_unique<ComboDescriptor>(m_pubkey_args.at(0)->Clone());
973 }
974};
975
977class MultisigDescriptor final : public DescriptorImpl
978{
979 const int m_threshold;
980 const bool m_sorted;
981protected:
982 std::string ToStringExtra() const override { return strprintf("%i", m_threshold); }
983 std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider&) const override {
984 if (m_sorted) {
985 std::vector<CPubKey> sorted_keys(keys);
986 std::sort(sorted_keys.begin(), sorted_keys.end());
987 return Vector(GetScriptForMultisig(m_threshold, sorted_keys));
988 }
989 return Vector(GetScriptForMultisig(m_threshold, keys));
990 }
991public:
992 MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {}
993 bool IsSingleType() const final { return true; }
994
995 std::optional<int64_t> ScriptSize() const override {
996 const auto n_keys = m_pubkey_args.size();
997 auto op = [](int64_t acc, const std::unique_ptr<PubkeyProvider>& pk) { return acc + 1 + pk->GetSize();};
998 const auto pubkeys_size{std::accumulate(m_pubkey_args.begin(), m_pubkey_args.end(), int64_t{0}, op)};
999 return 1 + BuildScript(n_keys).size() + BuildScript(m_threshold).size() + pubkeys_size;
1000 }
1001
1002 std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {
1003 const auto sig_size = use_max_sig ? 72 : 71;
1004 return (1 + (1 + sig_size) * m_threshold);
1005 }
1006
1007 std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {
1008 return *MaxSatSize(use_max_sig) * WITNESS_SCALE_FACTOR;
1009 }
1010
1011 std::optional<int64_t> MaxSatisfactionElems() const override { return 1 + m_threshold; }
1012
1013 std::unique_ptr<DescriptorImpl> Clone() const override
1014 {
1015 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1016 providers.reserve(m_pubkey_args.size());
1017 std::transform(m_pubkey_args.begin(), m_pubkey_args.end(), providers.begin(), [](const std::unique_ptr<PubkeyProvider>& p) { return p->Clone(); });
1018 return std::make_unique<MultisigDescriptor>(m_threshold, std::move(providers), m_sorted);
1019 }
1020};
1021
1023class MultiADescriptor final : public DescriptorImpl
1024{
1025 const int m_threshold;
1026 const bool m_sorted;
1027protected:
1028 std::string ToStringExtra() const override { return strprintf("%i", m_threshold); }
1029 std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider&) const override {
1030 CScript ret;
1031 std::vector<XOnlyPubKey> xkeys;
1032 xkeys.reserve(keys.size());
1033 for (const auto& key : keys) xkeys.emplace_back(key);
1034 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
1035 ret << ToByteVector(xkeys[0]) << OP_CHECKSIG;
1036 for (size_t i = 1; i < keys.size(); ++i) {
1037 ret << ToByteVector(xkeys[i]) << OP_CHECKSIGADD;
1038 }
1039 ret << m_threshold << OP_NUMEQUAL;
1040 return Vector(std::move(ret));
1041 }
1042public:
1043 MultiADescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), sorted ? "sortedmulti_a" : "multi_a"), m_threshold(threshold), m_sorted(sorted) {}
1044 bool IsSingleType() const final { return true; }
1045
1046 std::optional<int64_t> ScriptSize() const override {
1047 const auto n_keys = m_pubkey_args.size();
1048 return (1 + 32 + 1) * n_keys + BuildScript(m_threshold).size() + 1;
1049 }
1050
1051 std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {
1052 return (1 + 65) * m_threshold + (m_pubkey_args.size() - m_threshold);
1053 }
1054
1055 std::optional<int64_t> MaxSatisfactionElems() const override { return m_pubkey_args.size(); }
1056
1057 std::unique_ptr<DescriptorImpl> Clone() const override
1058 {
1059 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1060 providers.reserve(m_pubkey_args.size());
1061 for (const auto& arg : m_pubkey_args) {
1062 providers.push_back(arg->Clone());
1063 }
1064 return std::make_unique<MultiADescriptor>(m_threshold, std::move(providers), m_sorted);
1065 }
1066};
1067
1069class SHDescriptor final : public DescriptorImpl
1070{
1071protected:
1072 std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, Span<const CScript> scripts, FlatSigningProvider& out) const override
1073 {
1074 auto ret = Vector(GetScriptForDestination(ScriptHash(scripts[0])));
1075 if (ret.size()) out.scripts.emplace(CScriptID(scripts[0]), scripts[0]);
1076 return ret;
1077 }
1078
1079 bool IsSegwit() const { return m_subdescriptor_args[0]->GetOutputType() == OutputType::BECH32; }
1080
1081public:
1082 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {}
1083
1084 std::optional<OutputType> GetOutputType() const override
1085 {
1086 assert(m_subdescriptor_args.size() == 1);
1087 if (IsSegwit()) return OutputType::P2SH_SEGWIT;
1088 return OutputType::LEGACY;
1089 }
1090 bool IsSingleType() const final { return true; }
1091
1092 std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 20 + 1; }
1093
1094 std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {
1095 if (const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1096 if (const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1097 // The subscript is never witness data.
1098 const auto subscript_weight = (1 + *subscript_size) * WITNESS_SCALE_FACTOR;
1099 // The weight depends on whether the inner descriptor is satisfied using the witness stack.
1100 if (IsSegwit()) return subscript_weight + *sat_size;
1101 return subscript_weight + *sat_size * WITNESS_SCALE_FACTOR;
1102 }
1103 }
1104 return {};
1105 }
1106
1107 std::optional<int64_t> MaxSatisfactionElems() const override {
1108 if (const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems()) return 1 + *sub_elems;
1109 return {};
1110 }
1111
1112 std::unique_ptr<DescriptorImpl> Clone() const override
1113 {
1114 return std::make_unique<SHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1115 }
1116};
1117
1119class WSHDescriptor final : public DescriptorImpl
1120{
1121protected:
1122 std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, Span<const CScript> scripts, FlatSigningProvider& out) const override
1123 {
1125 if (ret.size()) out.scripts.emplace(CScriptID(scripts[0]), scripts[0]);
1126 return ret;
1127 }
1128public:
1129 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {}
1130 std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
1131 bool IsSingleType() const final { return true; }
1132
1133 std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 32; }
1134
1135 std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {
1136 if (const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1137 if (const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1138 return GetSizeOfCompactSize(*subscript_size) + *subscript_size + *sat_size;
1139 }
1140 }
1141 return {};
1142 }
1143
1144 std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {
1145 return MaxSatSize(use_max_sig);
1146 }
1147
1148 std::optional<int64_t> MaxSatisfactionElems() const override {
1149 if (const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems()) return 1 + *sub_elems;
1150 return {};
1151 }
1152
1153 std::unique_ptr<DescriptorImpl> Clone() const override
1154 {
1155 return std::make_unique<WSHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1156 }
1157};
1158
1160class TRDescriptor final : public DescriptorImpl
1161{
1162 std::vector<int> m_depths;
1163protected:
1164 std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript> scripts, FlatSigningProvider& out) const override
1165 {
1166 TaprootBuilder builder;
1167 assert(m_depths.size() == scripts.size());
1168 for (size_t pos = 0; pos < m_depths.size(); ++pos) {
1169 builder.Add(m_depths[pos], scripts[pos], TAPROOT_LEAF_TAPSCRIPT);
1170 }
1171 if (!builder.IsComplete()) return {};
1172 assert(keys.size() == 1);
1173 XOnlyPubKey xpk(keys[0]);
1174 if (!xpk.IsFullyValid()) return {};
1175 builder.Finalize(xpk);
1176 WitnessV1Taproot output = builder.GetOutput();
1177 out.tr_trees[output] = builder;
1178 out.pubkeys.emplace(keys[0].GetID(), keys[0]);
1179 return Vector(GetScriptForDestination(output));
1180 }
1181 bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type, const DescriptorCache* cache = nullptr) const override
1182 {
1183 if (m_depths.empty()) return true;
1184 std::vector<bool> path;
1185 for (size_t pos = 0; pos < m_depths.size(); ++pos) {
1186 if (pos) ret += ',';
1187 while ((int)path.size() <= m_depths[pos]) {
1188 if (path.size()) ret += '{';
1189 path.push_back(false);
1190 }
1191 std::string tmp;
1192 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache)) return false;
1193 ret += tmp;
1194 while (!path.empty() && path.back()) {
1195 if (path.size() > 1) ret += '}';
1196 path.pop_back();
1197 }
1198 if (!path.empty()) path.back() = true;
1199 }
1200 return true;
1201 }
1202public:
1203 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
1204 DescriptorImpl(Vector(std::move(internal_key)), std::move(descs), "tr"), m_depths(std::move(depths))
1205 {
1206 assert(m_subdescriptor_args.size() == m_depths.size());
1207 }
1208 std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32M; }
1209 bool IsSingleType() const final { return true; }
1210
1211 std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 32; }
1212
1213 std::optional<int64_t> MaxSatisfactionWeight(bool) const override {
1214 // FIXME: We assume keypath spend, which can lead to very large underestimations.
1215 return 1 + 65;
1216 }
1217
1218 std::optional<int64_t> MaxSatisfactionElems() const override {
1219 // FIXME: See above, we assume keypath spend.
1220 return 1;
1221 }
1222
1223 std::unique_ptr<DescriptorImpl> Clone() const override
1224 {
1225 std::vector<std::unique_ptr<DescriptorImpl>> subdescs;
1226 subdescs.reserve(m_subdescriptor_args.size());
1227 std::transform(m_subdescriptor_args.begin(), m_subdescriptor_args.end(), subdescs.begin(), [](const std::unique_ptr<DescriptorImpl>& d) { return d->Clone(); });
1228 return std::make_unique<TRDescriptor>(m_pubkey_args.at(0)->Clone(), std::move(subdescs), m_depths);
1229 }
1230};
1231
1232/* We instantiate Miniscript here with a simple integer as key type.
1233 * The value of these key integers are an index in the
1234 * DescriptorImpl::m_pubkey_args vector.
1235 */
1236
1240class ScriptMaker {
1242 const std::vector<CPubKey>& m_keys;
1244 const miniscript::MiniscriptContext m_script_ctx;
1245
1249 uint160 GetHash160(uint32_t key) const {
1250 if (miniscript::IsTapscript(m_script_ctx)) {
1251 return Hash160(XOnlyPubKey{m_keys[key]});
1252 }
1253 return m_keys[key].GetID();
1254 }
1255
1256public:
1257 ScriptMaker(const std::vector<CPubKey>& keys LIFETIMEBOUND, const miniscript::MiniscriptContext script_ctx) : m_keys(keys), m_script_ctx{script_ctx} {}
1258
1259 std::vector<unsigned char> ToPKBytes(uint32_t key) const {
1260 // In Tapscript keys always serialize as x-only, whether an x-only key was used in the descriptor or not.
1261 if (!miniscript::IsTapscript(m_script_ctx)) {
1262 return {m_keys[key].begin(), m_keys[key].end()};
1263 }
1264 const XOnlyPubKey xonly_pubkey{m_keys[key]};
1265 return {xonly_pubkey.begin(), xonly_pubkey.end()};
1266 }
1267
1268 std::vector<unsigned char> ToPKHBytes(uint32_t key) const {
1269 auto id = GetHash160(key);
1270 return {id.begin(), id.end()};
1271 }
1272};
1273
1277class StringMaker {
1279 const SigningProvider* m_arg;
1281 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
1283 bool m_private;
1284
1285public:
1286 StringMaker(const SigningProvider* arg LIFETIMEBOUND, const std::vector<std::unique_ptr<PubkeyProvider>>& pubkeys LIFETIMEBOUND, bool priv)
1287 : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
1288
1289 std::optional<std::string> ToString(uint32_t key) const
1290 {
1291 std::string ret;
1292 if (m_private) {
1293 if (!m_pubkeys[key]->ToPrivateString(*m_arg, ret)) return {};
1294 } else {
1295 ret = m_pubkeys[key]->ToString();
1296 }
1297 return ret;
1298 }
1299};
1300
1301class MiniscriptDescriptor final : public DescriptorImpl
1302{
1303private:
1305
1306protected:
1307 std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript> scripts,
1308 FlatSigningProvider& provider) const override
1309 {
1310 const auto script_ctx{m_node->GetMsCtx()};
1311 for (const auto& key : keys) {
1312 if (miniscript::IsTapscript(script_ctx)) {
1313 provider.pubkeys.emplace(Hash160(XOnlyPubKey{key}), key);
1314 } else {
1315 provider.pubkeys.emplace(key.GetID(), key);
1316 }
1317 }
1318 return Vector(m_node->ToScript(ScriptMaker(keys, script_ctx)));
1319 }
1320
1321public:
1322 MiniscriptDescriptor(std::vector<std::unique_ptr<PubkeyProvider>> providers, miniscript::NodeRef<uint32_t> node)
1323 : DescriptorImpl(std::move(providers), "?"), m_node(std::move(node)) {}
1324
1325 bool ToStringHelper(const SigningProvider* arg, std::string& out, const StringType type,
1326 const DescriptorCache* cache = nullptr) const override
1327 {
1328 if (const auto res = m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
1329 out = *res;
1330 return true;
1331 }
1332 return false;
1333 }
1334
1335 bool IsSolvable() const override { return true; }
1336 bool IsSingleType() const final { return true; }
1337
1338 std::optional<int64_t> ScriptSize() const override { return m_node->ScriptSize(); }
1339
1340 std::optional<int64_t> MaxSatSize(bool) const override {
1341 // For Miniscript we always assume high-R ECDSA signatures.
1342 return m_node->GetWitnessSize();
1343 }
1344
1345 std::optional<int64_t> MaxSatisfactionElems() const override {
1346 return m_node->GetStackSize();
1347 }
1348
1349 std::unique_ptr<DescriptorImpl> Clone() const override
1350 {
1351 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1352 providers.reserve(m_pubkey_args.size());
1353 for (const auto& arg : m_pubkey_args) {
1354 providers.push_back(arg->Clone());
1355 }
1356 return std::make_unique<MiniscriptDescriptor>(std::move(providers), m_node->Clone());
1357 }
1358};
1359
1361class RawTRDescriptor final : public DescriptorImpl
1362{
1363protected:
1364 std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript> scripts, FlatSigningProvider& out) const override
1365 {
1366 assert(keys.size() == 1);
1367 XOnlyPubKey xpk(keys[0]);
1368 if (!xpk.IsFullyValid()) return {};
1369 WitnessV1Taproot output{xpk};
1370 return Vector(GetScriptForDestination(output));
1371 }
1372public:
1373 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(Vector(std::move(output_key)), "rawtr") {}
1374 std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32M; }
1375 bool IsSingleType() const final { return true; }
1376
1377 std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 32; }
1378
1379 std::optional<int64_t> MaxSatisfactionWeight(bool) const override {
1380 // We can't know whether there is a script path, so assume key path spend.
1381 return 1 + 65;
1382 }
1383
1384 std::optional<int64_t> MaxSatisfactionElems() const override {
1385 // See above, we assume keypath spend.
1386 return 1;
1387 }
1388
1389 std::unique_ptr<DescriptorImpl> Clone() const override
1390 {
1391 return std::make_unique<RawTRDescriptor>(m_pubkey_args.at(0)->Clone());
1392 }
1393};
1394
1396// Parser //
1398
1399enum class ParseScriptContext {
1400 TOP,
1401 P2SH,
1402 P2WPKH,
1403 P2WSH,
1404 P2TR,
1405};
1406
1407std::optional<uint32_t> ParseKeyPathNum(Span<const char> elem, bool& apostrophe, std::string& error)
1408{
1409 bool hardened = false;
1410 if (elem.size() > 0) {
1411 const char last = elem[elem.size() - 1];
1412 if (last == '\'' || last == 'h') {
1413 elem = elem.first(elem.size() - 1);
1414 hardened = true;
1415 apostrophe = last == '\'';
1416 }
1417 }
1418 uint32_t p;
1419 if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p)) {
1420 error = strprintf("Key path value '%s' is not a valid uint32", std::string(elem.begin(), elem.end()));
1421 return std::nullopt;
1422 } else if (p > 0x7FFFFFFFUL) {
1423 error = strprintf("Key path value %u is out of range", p);
1424 return std::nullopt;
1425 }
1426
1427 return std::make_optional<uint32_t>(p | (((uint32_t)hardened) << 31));
1428}
1429
1440[[nodiscard]] bool ParseKeyPath(const std::vector<Span<const char>>& split, std::vector<KeyPath>& out, bool& apostrophe, std::string& error, bool allow_multipath)
1441{
1442 KeyPath path;
1443 std::optional<size_t> multipath_segment_index;
1444 std::vector<uint32_t> multipath_values;
1445 std::unordered_set<uint32_t> seen_multipath;
1446
1447 for (size_t i = 1; i < split.size(); ++i) {
1448 const Span<const char>& elem = split[i];
1449
1450 // Check if element contain multipath specifier
1451 if (!elem.empty() && elem.front() == '<' && elem.back() == '>') {
1452 if (!allow_multipath) {
1453 error = strprintf("Key path value '%s' specifies multipath in a section where multipath is not allowed", std::string(elem.begin(), elem.end()));
1454 return false;
1455 }
1456 if (multipath_segment_index) {
1457 error = "Multiple multipath key path specifiers found";
1458 return false;
1459 }
1460
1461 // Parse each possible value
1462 std::vector<Span<const char>> nums = Split(Span(elem.begin()+1, elem.end()-1), ";");
1463 if (nums.size() < 2) {
1464 error = "Multipath key path specifiers must have at least two items";
1465 return false;
1466 }
1467
1468 for (const auto& num : nums) {
1469 const auto& op_num = ParseKeyPathNum(num, apostrophe, error);
1470 if (!op_num) return false;
1471 auto [_, inserted] = seen_multipath.insert(*op_num);
1472 if (!inserted) {
1473 error = strprintf("Duplicated key path value %u in multipath specifier", *op_num);
1474 return false;
1475 }
1476 multipath_values.emplace_back(*op_num);
1477 }
1478
1479 path.emplace_back(); // Placeholder for multipath segment
1480 multipath_segment_index = path.size()-1;
1481 } else {
1482 const auto& op_num = ParseKeyPathNum(elem, apostrophe, error);
1483 if (!op_num) return false;
1484 path.emplace_back(*op_num);
1485 }
1486 }
1487
1488 if (!multipath_segment_index) {
1489 out.emplace_back(std::move(path));
1490 } else {
1491 // Replace the multipath placeholder with each value while generating paths
1492 for (size_t i = 0; i < multipath_values.size(); i++) {
1493 KeyPath branch_path = path;
1494 branch_path[*multipath_segment_index] = multipath_values[i];
1495 out.emplace_back(std::move(branch_path));
1496 }
1497 }
1498 return true;
1499}
1500
1502std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkeyInner(uint32_t key_exp_index, const Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, bool& apostrophe, std::string& error)
1503{
1504 std::vector<std::unique_ptr<PubkeyProvider>> ret;
1505 bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
1506 auto split = Split(sp, '/');
1507 std::string str(split[0].begin(), split[0].end());
1508 if (str.size() == 0) {
1509 error = "No key provided";
1510 return {};
1511 }
1512 if (split.size() == 1) {
1513 if (IsHex(str)) {
1514 std::vector<unsigned char> data = ParseHex(str);
1515 CPubKey pubkey(data);
1516 if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) {
1517 error = "Hybrid public keys are not allowed";
1518 return {};
1519 }
1520 if (pubkey.IsFullyValid()) {
1521 if (permit_uncompressed || pubkey.IsCompressed()) {
1522 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, false));
1523 return ret;
1524 } else {
1525 error = "Uncompressed keys are not allowed";
1526 return {};
1527 }
1528 } else if (data.size() == 32 && ctx == ParseScriptContext::P2TR) {
1529 unsigned char fullkey[33] = {0x02};
1530 std::copy(data.begin(), data.end(), fullkey + 1);
1531 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1532 if (pubkey.IsFullyValid()) {
1533 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, true));
1534 return ret;
1535 }
1536 }
1537 error = strprintf("Pubkey '%s' is invalid", str);
1538 return {};
1539 }
1540 CKey key = DecodeSecret(str);
1541 if (key.IsValid()) {
1542 if (permit_uncompressed || key.IsCompressed()) {
1543 CPubKey pubkey = key.GetPubKey();
1544 out.keys.emplace(pubkey.GetID(), key);
1545 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, ctx == ParseScriptContext::P2TR));
1546 return ret;
1547 } else {
1548 error = "Uncompressed keys are not allowed";
1549 return {};
1550 }
1551 }
1552 }
1553 CExtKey extkey = DecodeExtKey(str);
1554 CExtPubKey extpubkey = DecodeExtPubKey(str);
1555 if (!extkey.key.IsValid() && !extpubkey.pubkey.IsValid()) {
1556 error = strprintf("key '%s' is not valid", str);
1557 return {};
1558 }
1559 std::vector<KeyPath> paths;
1560 DeriveType type = DeriveType::NO;
1561 if (std::ranges::equal(split.back(), Span{"*"}.first(1))) {
1562 split.pop_back();
1563 type = DeriveType::UNHARDENED;
1564 } else if (std::ranges::equal(split.back(), Span{"*'"}.first(2)) || std::ranges::equal(split.back(), Span{"*h"}.first(2))) {
1565 apostrophe = std::ranges::equal(split.back(), Span{"*'"}.first(2));
1566 split.pop_back();
1567 type = DeriveType::HARDENED;
1568 }
1569 if (!ParseKeyPath(split, paths, apostrophe, error, /*allow_multipath=*/true)) return {};
1570 if (extkey.key.IsValid()) {
1571 extpubkey = extkey.Neuter();
1572 out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key);
1573 }
1574 for (auto& path : paths) {
1575 ret.emplace_back(std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type, apostrophe));
1576 }
1577 return ret;
1578}
1579
1581std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkey(uint32_t key_exp_index, const Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
1582{
1583 std::vector<std::unique_ptr<PubkeyProvider>> ret;
1584 auto origin_split = Split(sp, ']');
1585 if (origin_split.size() > 2) {
1586 error = "Multiple ']' characters found for a single pubkey";
1587 return {};
1588 }
1589 // This is set if either the origin or path suffix contains a hardened derivation.
1590 bool apostrophe = false;
1591 if (origin_split.size() == 1) {
1592 return ParsePubkeyInner(key_exp_index, origin_split[0], ctx, out, apostrophe, error);
1593 }
1594 if (origin_split[0].empty() || origin_split[0][0] != '[') {
1595 error = strprintf("Key origin start '[ character expected but not found, got '%c' instead",
1596 origin_split[0].empty() ? ']' : origin_split[0][0]);
1597 return {};
1598 }
1599 auto slash_split = Split(origin_split[0].subspan(1), '/');
1600 if (slash_split[0].size() != 8) {
1601 error = strprintf("Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
1602 return {};
1603 }
1604 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
1605 if (!IsHex(fpr_hex)) {
1606 error = strprintf("Fingerprint '%s' is not hex", fpr_hex);
1607 return {};
1608 }
1609 auto fpr_bytes = ParseHex(fpr_hex);
1610 KeyOriginInfo info;
1611 static_assert(sizeof(info.fingerprint) == 4, "Fingerprint must be 4 bytes");
1612 assert(fpr_bytes.size() == 4);
1613 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
1614 std::vector<KeyPath> path;
1615 if (!ParseKeyPath(slash_split, path, apostrophe, error, /*allow_multipath=*/false)) return {};
1616 info.path = path.at(0);
1617 auto providers = ParsePubkeyInner(key_exp_index, origin_split[1], ctx, out, apostrophe, error);
1618 if (providers.empty()) return {};
1619 ret.reserve(providers.size());
1620 for (auto& prov : providers) {
1621 ret.emplace_back(std::make_unique<OriginPubkeyProvider>(key_exp_index, info, std::move(prov), apostrophe));
1622 }
1623 return ret;
1624}
1625
1626std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext ctx, const SigningProvider& provider)
1627{
1628 // Key cannot be hybrid
1629 if (!pubkey.IsValidNonHybrid()) {
1630 return nullptr;
1631 }
1632 // Uncompressed is only allowed in TOP and P2SH contexts
1633 if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.IsCompressed()) {
1634 return nullptr;
1635 }
1636 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, false);
1637 KeyOriginInfo info;
1638 if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
1639 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider), /*apostrophe=*/false);
1640 }
1641 return key_provider;
1642}
1643
1644std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(const XOnlyPubKey& xkey, ParseScriptContext ctx, const SigningProvider& provider)
1645{
1646 CPubKey pubkey{xkey.GetEvenCorrespondingCPubKey()};
1647 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, true);
1648 KeyOriginInfo info;
1649 if (provider.GetKeyOriginByXOnly(xkey, info)) {
1650 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider), /*apostrophe=*/false);
1651 }
1652 return key_provider;
1653}
1654
1658struct KeyParser {
1660 using Key = uint32_t;
1662 FlatSigningProvider* m_out;
1664 const SigningProvider* m_in;
1666 mutable std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> m_keys;
1668 mutable std::string m_key_parsing_error;
1670 const miniscript::MiniscriptContext m_script_ctx;
1672 uint32_t m_offset;
1673
1675 miniscript::MiniscriptContext ctx, uint32_t offset = 0)
1676 : m_out(out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}
1677
1678 bool KeyCompare(const Key& a, const Key& b) const {
1679 return *m_keys.at(a).at(0) < *m_keys.at(b).at(0);
1680 }
1681
1682 ParseScriptContext ParseContext() const {
1683 switch (m_script_ctx) {
1684 case miniscript::MiniscriptContext::P2WSH: return ParseScriptContext::P2WSH;
1685 case miniscript::MiniscriptContext::TAPSCRIPT: return ParseScriptContext::P2TR;
1686 }
1687 assert(false);
1688 }
1689
1690 template<typename I> std::optional<Key> FromString(I begin, I end) const
1691 {
1692 assert(m_out);
1693 Key key = m_keys.size();
1694 auto pk = ParsePubkey(m_offset + key, {&*begin, &*end}, ParseContext(), *m_out, m_key_parsing_error);
1695 if (pk.empty()) return {};
1696 m_keys.emplace_back(std::move(pk));
1697 return key;
1698 }
1699
1700 std::optional<std::string> ToString(const Key& key) const
1701 {
1702 return m_keys.at(key).at(0)->ToString();
1703 }
1704
1705 template<typename I> std::optional<Key> FromPKBytes(I begin, I end) const
1706 {
1707 assert(m_in);
1708 Key key = m_keys.size();
1709 if (miniscript::IsTapscript(m_script_ctx) && end - begin == 32) {
1710 XOnlyPubKey pubkey;
1711 std::copy(begin, end, pubkey.begin());
1712 if (auto pubkey_provider = InferXOnlyPubkey(pubkey, ParseContext(), *m_in)) {
1713 m_keys.emplace_back();
1714 m_keys.back().push_back(std::move(pubkey_provider));
1715 return key;
1716 }
1717 } else if (!miniscript::IsTapscript(m_script_ctx)) {
1718 CPubKey pubkey(begin, end);
1719 if (auto pubkey_provider = InferPubkey(pubkey, ParseContext(), *m_in)) {
1720 m_keys.emplace_back();
1721 m_keys.back().push_back(std::move(pubkey_provider));
1722 return key;
1723 }
1724 }
1725 return {};
1726 }
1727
1728 template<typename I> std::optional<Key> FromPKHBytes(I begin, I end) const
1729 {
1730 assert(end - begin == 20);
1731 assert(m_in);
1732 uint160 hash;
1733 std::copy(begin, end, hash.begin());
1734 CKeyID keyid(hash);
1735 CPubKey pubkey;
1736 if (m_in->GetPubKey(keyid, pubkey)) {
1737 if (auto pubkey_provider = InferPubkey(pubkey, ParseContext(), *m_in)) {
1738 Key key = m_keys.size();
1739 m_keys.emplace_back();
1740 m_keys.back().push_back(std::move(pubkey_provider));
1741 return key;
1742 }
1743 }
1744 return {};
1745 }
1746
1747 miniscript::MiniscriptContext MsContext() const {
1748 return m_script_ctx;
1749 }
1750};
1751
1753// NOLINTNEXTLINE(misc-no-recursion)
1754std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index, Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
1755{
1756 using namespace script;
1757 Assume(ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR);
1758 std::vector<std::unique_ptr<DescriptorImpl>> ret;
1759 auto expr = Expr(sp);
1760 if (Func("pk", expr)) {
1761 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx, out, error);
1762 if (pubkeys.empty()) {
1763 error = strprintf("pk(): %s", error);
1764 return {};
1765 }
1766 ++key_exp_index;
1767 for (auto& pubkey : pubkeys) {
1768 ret.emplace_back(std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR));
1769 }
1770 return ret;
1771 }
1772 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && Func("pkh", expr)) {
1773 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx, out, error);
1774 if (pubkeys.empty()) {
1775 error = strprintf("pkh(): %s", error);
1776 return {};
1777 }
1778 ++key_exp_index;
1779 for (auto& pubkey : pubkeys) {
1780 ret.emplace_back(std::make_unique<PKHDescriptor>(std::move(pubkey)));
1781 }
1782 return ret;
1783 }
1784 if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
1785 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx, out, error);
1786 if (pubkeys.empty()) {
1787 error = strprintf("combo(): %s", error);
1788 return {};
1789 }
1790 ++key_exp_index;
1791 for (auto& pubkey : pubkeys) {
1792 ret.emplace_back(std::make_unique<ComboDescriptor>(std::move(pubkey)));
1793 }
1794 return ret;
1795 } else if (Func("combo", expr)) {
1796 error = "Can only have combo() at top level";
1797 return {};
1798 }
1799 const bool multi = Func("multi", expr);
1800 const bool sortedmulti = !multi && Func("sortedmulti", expr);
1801 const bool multi_a = !(multi || sortedmulti) && Func("multi_a", expr);
1802 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) && Func("sortedmulti_a", expr);
1803 if (((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
1804 (ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
1805 auto threshold = Expr(expr);
1806 uint32_t thres;
1807 std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> providers; // List of multipath expanded pubkeys
1808 if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
1809 error = strprintf("Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
1810 return {};
1811 }
1812 size_t script_size = 0;
1813 size_t max_providers_len = 0;
1814 while (expr.size()) {
1815 if (!Const(",", expr)) {
1816 error = strprintf("Multi: expected ',', got '%c'", expr[0]);
1817 return {};
1818 }
1819 auto arg = Expr(expr);
1820 auto pks = ParsePubkey(key_exp_index, arg, ctx, out, error);
1821 if (pks.empty()) {
1822 error = strprintf("Multi: %s", error);
1823 return {};
1824 }
1825 script_size += pks.at(0)->GetSize() + 1;
1826 max_providers_len = std::max(max_providers_len, pks.size());
1827 providers.emplace_back(std::move(pks));
1828 key_exp_index++;
1829 }
1830 if ((multi || sortedmulti) && (providers.empty() || providers.size() > MAX_PUBKEYS_PER_MULTISIG)) {
1831 error = strprintf("Cannot have %u keys in multisig; must have between 1 and %d keys, inclusive", providers.size(), MAX_PUBKEYS_PER_MULTISIG);
1832 return {};
1833 } else if ((multi_a || sortedmulti_a) && (providers.empty() || providers.size() > MAX_PUBKEYS_PER_MULTI_A)) {
1834 error = strprintf("Cannot have %u keys in multi_a; must have between 1 and %d keys, inclusive", providers.size(), MAX_PUBKEYS_PER_MULTI_A);
1835 return {};
1836 } else if (thres < 1) {
1837 error = strprintf("Multisig threshold cannot be %d, must be at least 1", thres);
1838 return {};
1839 } else if (thres > providers.size()) {
1840 error = strprintf("Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
1841 return {};
1842 }
1843 if (ctx == ParseScriptContext::TOP) {
1844 if (providers.size() > 3) {
1845 error = strprintf("Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
1846 return {};
1847 }
1848 }
1849 if (ctx == ParseScriptContext::P2SH) {
1850 // This limits the maximum number of compressed pubkeys to 15.
1851 if (script_size + 3 > MAX_SCRIPT_ELEMENT_SIZE) {
1852 error = strprintf("P2SH script is too large, %d bytes is larger than %d bytes", script_size + 3, MAX_SCRIPT_ELEMENT_SIZE);
1853 return {};
1854 }
1855 }
1856
1857 // Make sure all vecs are of the same length, or exactly length 1
1858 // For length 1 vectors, clone key providers until vector is the same length
1859 for (auto& vec : providers) {
1860 if (vec.size() == 1) {
1861 for (size_t i = 1; i < max_providers_len; ++i) {
1862 vec.emplace_back(vec.at(0)->Clone());
1863 }
1864 } else if (vec.size() != max_providers_len) {
1865 error = strprintf("multi(): Multipath derivation paths have mismatched lengths");
1866 return {};
1867 }
1868 }
1869
1870 // Build the final descriptors vector
1871 for (size_t i = 0; i < max_providers_len; ++i) {
1872 // Build final pubkeys vectors by retrieving the i'th subscript for each vector in subscripts
1873 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
1874 pubs.reserve(providers.size());
1875 for (auto& pub : providers) {
1876 pubs.emplace_back(std::move(pub.at(i)));
1877 }
1878 if (multi || sortedmulti) {
1879 ret.emplace_back(std::make_unique<MultisigDescriptor>(thres, std::move(pubs), sortedmulti));
1880 } else {
1881 ret.emplace_back(std::make_unique<MultiADescriptor>(thres, std::move(pubs), sortedmulti_a));
1882 }
1883 }
1884 return ret;
1885 } else if (multi || sortedmulti) {
1886 error = "Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
1887 return {};
1888 } else if (multi_a || sortedmulti_a) {
1889 error = "Can only have multi_a/sortedmulti_a inside tr()";
1890 return {};
1891 }
1892 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) && Func("wpkh", expr)) {
1893 auto pubkeys = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH, out, error);
1894 if (pubkeys.empty()) {
1895 error = strprintf("wpkh(): %s", error);
1896 return {};
1897 }
1898 key_exp_index++;
1899 for (auto& pubkey : pubkeys) {
1900 ret.emplace_back(std::make_unique<WPKHDescriptor>(std::move(pubkey)));
1901 }
1902 return ret;
1903 } else if (Func("wpkh", expr)) {
1904 error = "Can only have wpkh() at top level or inside sh()";
1905 return {};
1906 }
1907 if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
1908 auto descs = ParseScript(key_exp_index, expr, ParseScriptContext::P2SH, out, error);
1909 if (descs.empty() || expr.size()) return {};
1910 std::vector<std::unique_ptr<DescriptorImpl>> ret;
1911 ret.reserve(descs.size());
1912 for (auto& desc : descs) {
1913 ret.push_back(std::make_unique<SHDescriptor>(std::move(desc)));
1914 }
1915 return ret;
1916 } else if (Func("sh", expr)) {
1917 error = "Can only have sh() at top level";
1918 return {};
1919 }
1920 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) && Func("wsh", expr)) {
1921 auto descs = ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH, out, error);
1922 if (descs.empty() || expr.size()) return {};
1923 for (auto& desc : descs) {
1924 ret.emplace_back(std::make_unique<WSHDescriptor>(std::move(desc)));
1925 }
1926 return ret;
1927 } else if (Func("wsh", expr)) {
1928 error = "Can only have wsh() at top level or inside sh()";
1929 return {};
1930 }
1931 if (ctx == ParseScriptContext::TOP && Func("addr", expr)) {
1932 CTxDestination dest = DecodeDestination(std::string(expr.begin(), expr.end()));
1933 if (!IsValidDestination(dest)) {
1934 error = "Address is not valid";
1935 return {};
1936 }
1937 ret.emplace_back(std::make_unique<AddressDescriptor>(std::move(dest)));
1938 return ret;
1939 } else if (Func("addr", expr)) {
1940 error = "Can only have addr() at top level";
1941 return {};
1942 }
1943 if (ctx == ParseScriptContext::TOP && Func("tr", expr)) {
1944 auto arg = Expr(expr);
1945 auto internal_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out, error);
1946 if (internal_keys.empty()) {
1947 error = strprintf("tr(): %s", error);
1948 return {};
1949 }
1950 size_t max_providers_len = internal_keys.size();
1951 ++key_exp_index;
1952 std::vector<std::vector<std::unique_ptr<DescriptorImpl>>> subscripts;
1953 std::vector<int> depths;
1954 if (expr.size()) {
1955 if (!Const(",", expr)) {
1956 error = strprintf("tr: expected ',', got '%c'", expr[0]);
1957 return {};
1958 }
1962 std::vector<bool> branches;
1963 // Loop over all provided scripts. In every iteration exactly one script will be processed.
1964 // Use a do-loop because inside this if-branch we expect at least one script.
1965 do {
1966 // First process all open braces.
1967 while (Const("{", expr)) {
1968 branches.push_back(false); // new left branch
1969 if (branches.size() > TAPROOT_CONTROL_MAX_NODE_COUNT) {
1970 error = strprintf("tr() supports at most %i nesting levels", TAPROOT_CONTROL_MAX_NODE_COUNT);
1971 return {};
1972 }
1973 }
1974 // Process the actual script expression.
1975 auto sarg = Expr(expr);
1976 subscripts.emplace_back(ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR, out, error));
1977 if (subscripts.back().empty()) return {};
1978 max_providers_len = std::max(max_providers_len, subscripts.back().size());
1979 depths.push_back(branches.size());
1980 // Process closing braces; one is expected for every right branch we were in.
1981 while (branches.size() && branches.back()) {
1982 if (!Const("}", expr)) {
1983 error = strprintf("tr(): expected '}' after script expression");
1984 return {};
1985 }
1986 branches.pop_back(); // move up one level after encountering '}'
1987 }
1988 // If after that, we're at the end of a left branch, expect a comma.
1989 if (branches.size() && !branches.back()) {
1990 if (!Const(",", expr)) {
1991 error = strprintf("tr(): expected ',' after script expression");
1992 return {};
1993 }
1994 branches.back() = true; // And now we're in a right branch.
1995 }
1996 } while (branches.size());
1997 // After we've explored a whole tree, we must be at the end of the expression.
1998 if (expr.size()) {
1999 error = strprintf("tr(): expected ')' after script expression");
2000 return {};
2001 }
2002 }
2004
2005 // Make sure all vecs are of the same length, or exactly length 1
2006 // For length 1 vectors, clone subdescs until vector is the same length
2007 for (auto& vec : subscripts) {
2008 if (vec.size() == 1) {
2009 for (size_t i = 1; i < max_providers_len; ++i) {
2010 vec.emplace_back(vec.at(0)->Clone());
2011 }
2012 } else if (vec.size() != max_providers_len) {
2013 error = strprintf("tr(): Multipath subscripts have mismatched lengths");
2014 return {};
2015 }
2016 }
2017
2018 if (internal_keys.size() > 1 && internal_keys.size() != max_providers_len) {
2019 error = strprintf("tr(): Multipath internal key mismatches multipath subscripts lengths");
2020 return {};
2021 }
2022
2023 while (internal_keys.size() < max_providers_len) {
2024 internal_keys.emplace_back(internal_keys.at(0)->Clone());
2025 }
2026
2027 // Build the final descriptors vector
2028 for (size_t i = 0; i < max_providers_len; ++i) {
2029 // Build final subscripts vectors by retrieving the i'th subscript for each vector in subscripts
2030 std::vector<std::unique_ptr<DescriptorImpl>> this_subs;
2031 this_subs.reserve(subscripts.size());
2032 for (auto& subs : subscripts) {
2033 this_subs.emplace_back(std::move(subs.at(i)));
2034 }
2035 ret.emplace_back(std::make_unique<TRDescriptor>(std::move(internal_keys.at(i)), std::move(this_subs), depths));
2036 }
2037 return ret;
2038
2039
2040 } else if (Func("tr", expr)) {
2041 error = "Can only have tr at top level";
2042 return {};
2043 }
2044 if (ctx == ParseScriptContext::TOP && Func("rawtr", expr)) {
2045 auto arg = Expr(expr);
2046 if (expr.size()) {
2047 error = strprintf("rawtr(): only one key expected.");
2048 return {};
2049 }
2050 auto output_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out, error);
2051 if (output_keys.empty()) {
2052 error = strprintf("rawtr(): %s", error);
2053 return {};
2054 }
2055 ++key_exp_index;
2056 for (auto& pubkey : output_keys) {
2057 ret.emplace_back(std::make_unique<RawTRDescriptor>(std::move(pubkey)));
2058 }
2059 return ret;
2060 } else if (Func("rawtr", expr)) {
2061 error = "Can only have rawtr at top level";
2062 return {};
2063 }
2064 if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
2065 std::string str(expr.begin(), expr.end());
2066 if (!IsHex(str)) {
2067 error = "Raw script is not hex";
2068 return {};
2069 }
2070 auto bytes = ParseHex(str);
2071 ret.emplace_back(std::make_unique<RawDescriptor>(CScript(bytes.begin(), bytes.end())));
2072 return ret;
2073 } else if (Func("raw", expr)) {
2074 error = "Can only have raw() at top level";
2075 return {};
2076 }
2077 // Process miniscript expressions.
2078 {
2079 const auto script_ctx{ctx == ParseScriptContext::P2WSH ? miniscript::MiniscriptContext::P2WSH : miniscript::MiniscriptContext::TAPSCRIPT};
2080 KeyParser parser(/*out = */&out, /* in = */nullptr, /* ctx = */script_ctx, key_exp_index);
2081 auto node = miniscript::FromString(std::string(expr.begin(), expr.end()), parser);
2082 if (parser.m_key_parsing_error != "") {
2083 error = std::move(parser.m_key_parsing_error);
2084 return {};
2085 }
2086 if (node) {
2087 if (ctx != ParseScriptContext::P2WSH && ctx != ParseScriptContext::P2TR) {
2088 error = "Miniscript expressions can only be used in wsh or tr.";
2089 return {};
2090 }
2091 if (!node->IsSane() || node->IsNotSatisfiable()) {
2092 // Try to find the first insane sub for better error reporting.
2093 auto insane_node = node.get();
2094 if (const auto sub = node->FindInsaneSub()) insane_node = sub;
2095 if (const auto str = insane_node->ToString(parser)) error = *str;
2096 if (!insane_node->IsValid()) {
2097 error += " is invalid";
2098 } else if (!node->IsSane()) {
2099 error += " is not sane";
2100 if (!insane_node->IsNonMalleable()) {
2101 error += ": malleable witnesses exist";
2102 } else if (insane_node == node.get() && !insane_node->NeedsSignature()) {
2103 error += ": witnesses without signature exist";
2104 } else if (!insane_node->CheckTimeLocksMix()) {
2105 error += ": contains mixes of timelocks expressed in blocks and seconds";
2106 } else if (!insane_node->CheckDuplicateKey()) {
2107 error += ": contains duplicate public keys";
2108 } else if (!insane_node->ValidSatisfactions()) {
2109 error += ": needs witnesses that may exceed resource limits";
2110 }
2111 } else {
2112 error += " is not satisfiable";
2113 }
2114 return {};
2115 }
2116 // A signature check is required for a miniscript to be sane. Therefore no sane miniscript
2117 // may have an empty list of public keys.
2118 CHECK_NONFATAL(!parser.m_keys.empty());
2119 key_exp_index += parser.m_keys.size();
2120 // Make sure all vecs are of the same length, or exactly length 1
2121 // For length 1 vectors, clone subdescs until vector is the same length
2122 size_t num_multipath = std::max_element(parser.m_keys.begin(), parser.m_keys.end(),
2123 [](const std::vector<std::unique_ptr<PubkeyProvider>>& a, const std::vector<std::unique_ptr<PubkeyProvider>>& b) {
2124 return a.size() < b.size();
2125 })->size();
2126
2127 for (auto& vec : parser.m_keys) {
2128 if (vec.size() == 1) {
2129 for (size_t i = 1; i < num_multipath; ++i) {
2130 vec.emplace_back(vec.at(0)->Clone());
2131 }
2132 } else if (vec.size() != num_multipath) {
2133 error = strprintf("Miniscript: Multipath derivation paths have mismatched lengths");
2134 return {};
2135 }
2136 }
2137
2138 // Build the final descriptors vector
2139 for (size_t i = 0; i < num_multipath; ++i) {
2140 // Build final pubkeys vectors by retrieving the i'th subscript for each vector in subscripts
2141 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
2142 pubs.reserve(parser.m_keys.size());
2143 for (auto& pub : parser.m_keys) {
2144 pubs.emplace_back(std::move(pub.at(i)));
2145 }
2146 ret.emplace_back(std::make_unique<MiniscriptDescriptor>(std::move(pubs), node->Clone()));
2147 }
2148 return ret;
2149 }
2150 }
2151 if (ctx == ParseScriptContext::P2SH) {
2152 error = "A function is needed within P2SH";
2153 return {};
2154 } else if (ctx == ParseScriptContext::P2WSH) {
2155 error = "A function is needed within P2WSH";
2156 return {};
2157 }
2158 error = strprintf("'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
2159 return {};
2160}
2161
2162std::unique_ptr<DescriptorImpl> InferMultiA(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
2163{
2164 auto match = MatchMultiA(script);
2165 if (!match) return {};
2166 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2167 keys.reserve(match->second.size());
2168 for (const auto keyspan : match->second) {
2169 if (keyspan.size() != 32) return {};
2170 auto key = InferXOnlyPubkey(XOnlyPubKey{keyspan}, ctx, provider);
2171 if (!key) return {};
2172 keys.push_back(std::move(key));
2173 }
2174 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
2175}
2176
2177// NOLINTNEXTLINE(misc-no-recursion)
2178std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
2179{
2180 if (ctx == ParseScriptContext::P2TR && script.size() == 34 && script[0] == 32 && script[33] == OP_CHECKSIG) {
2181 XOnlyPubKey key{Span{script}.subspan(1, 32)};
2182 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider), true);
2183 }
2184
2185 if (ctx == ParseScriptContext::P2TR) {
2186 auto ret = InferMultiA(script, ctx, provider);
2187 if (ret) return ret;
2188 }
2189
2190 std::vector<std::vector<unsigned char>> data;
2191 TxoutType txntype = Solver(script, data);
2192
2193 if (txntype == TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2194 CPubKey pubkey(data[0]);
2195 if (auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2196 return std::make_unique<PKDescriptor>(std::move(pubkey_provider));
2197 }
2198 }
2199 if (txntype == TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2200 uint160 hash(data[0]);
2201 CKeyID keyid(hash);
2202 CPubKey pubkey;
2203 if (provider.GetPubKey(keyid, pubkey)) {
2204 if (auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2205 return std::make_unique<PKHDescriptor>(std::move(pubkey_provider));
2206 }
2207 }
2208 }
2209 if (txntype == TxoutType::WITNESS_V0_KEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH)) {
2210 uint160 hash(data[0]);
2211 CKeyID keyid(hash);
2212 CPubKey pubkey;
2213 if (provider.GetPubKey(keyid, pubkey)) {
2214 if (auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) {
2215 return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider));
2216 }
2217 }
2218 }
2219 if (txntype == TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2220 bool ok = true;
2221 std::vector<std::unique_ptr<PubkeyProvider>> providers;
2222 for (size_t i = 1; i + 1 < data.size(); ++i) {
2223 CPubKey pubkey(data[i]);
2224 if (auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2225 providers.push_back(std::move(pubkey_provider));
2226 } else {
2227 ok = false;
2228 break;
2229 }
2230 }
2231 if (ok) return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers));
2232 }
2233 if (txntype == TxoutType::SCRIPTHASH && ctx == ParseScriptContext::TOP) {
2234 uint160 hash(data[0]);
2235 CScriptID scriptid(hash);
2236 CScript subscript;
2237 if (provider.GetCScript(scriptid, subscript)) {
2238 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
2239 if (sub) return std::make_unique<SHDescriptor>(std::move(sub));
2240 }
2241 }
2242 if (txntype == TxoutType::WITNESS_V0_SCRIPTHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH)) {
2243 CScriptID scriptid{RIPEMD160(data[0])};
2244 CScript subscript;
2245 if (provider.GetCScript(scriptid, subscript)) {
2246 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
2247 if (sub) return std::make_unique<WSHDescriptor>(std::move(sub));
2248 }
2249 }
2250 if (txntype == TxoutType::WITNESS_V1_TAPROOT && ctx == ParseScriptContext::TOP) {
2251 // Extract x-only pubkey from output.
2252 XOnlyPubKey pubkey;
2253 std::copy(data[0].begin(), data[0].end(), pubkey.begin());
2254 // Request spending data.
2255 TaprootSpendData tap;
2256 if (provider.GetTaprootSpendData(pubkey, tap)) {
2257 // If found, convert it back to tree form.
2258 auto tree = InferTaprootTree(tap, pubkey);
2259 if (tree) {
2260 // If that works, try to infer subdescriptors for all leaves.
2261 bool ok = true;
2262 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
2263 std::vector<int> depths;
2264 for (const auto& [depth, script, leaf_ver] : *tree) {
2265 std::unique_ptr<DescriptorImpl> subdesc;
2266 if (leaf_ver == TAPROOT_LEAF_TAPSCRIPT) {
2267 subdesc = InferScript(CScript(script.begin(), script.end()), ParseScriptContext::P2TR, provider);
2268 }
2269 if (!subdesc) {
2270 ok = false;
2271 break;
2272 } else {
2273 subscripts.push_back(std::move(subdesc));
2274 depths.push_back(depth);
2275 }
2276 }
2277 if (ok) {
2278 auto key = InferXOnlyPubkey(tap.internal_key, ParseScriptContext::P2TR, provider);
2279 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
2280 }
2281 }
2282 }
2283 // If the above doesn't work, construct a rawtr() descriptor with just the encoded x-only pubkey.
2284 if (pubkey.IsFullyValid()) {
2285 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
2286 if (key) {
2287 return std::make_unique<RawTRDescriptor>(std::move(key));
2288 }
2289 }
2290 }
2291
2292 if (ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR) {
2293 const auto script_ctx{ctx == ParseScriptContext::P2WSH ? miniscript::MiniscriptContext::P2WSH : miniscript::MiniscriptContext::TAPSCRIPT};
2294 KeyParser parser(/* out = */nullptr, /* in = */&provider, /* ctx = */script_ctx);
2295 auto node = miniscript::FromScript(script, parser);
2296 if (node && node->IsSane()) {
2297 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2298 keys.reserve(parser.m_keys.size());
2299 for (auto& key : parser.m_keys) {
2300 keys.emplace_back(std::move(key.at(0)));
2301 }
2302 return std::make_unique<MiniscriptDescriptor>(std::move(keys), std::move(node));
2303 }
2304 }
2305
2306 // The following descriptors are all top-level only descriptors.
2307 // So if we are not at the top level, return early.
2308 if (ctx != ParseScriptContext::TOP) return nullptr;
2309
2310 CTxDestination dest;
2311 if (ExtractDestination(script, dest)) {
2312 if (GetScriptForDestination(dest) == script) {
2313 return std::make_unique<AddressDescriptor>(std::move(dest));
2314 }
2315 }
2316
2317 return std::make_unique<RawDescriptor>(script);
2318}
2319
2320
2321} // namespace
2322
2324bool CheckChecksum(Span<const char>& sp, bool require_checksum, std::string& error, std::string* out_checksum = nullptr)
2325{
2326 auto check_split = Split(sp, '#');
2327 if (check_split.size() > 2) {
2328 error = "Multiple '#' symbols";
2329 return false;
2330 }
2331 if (check_split.size() == 1 && require_checksum){
2332 error = "Missing checksum";
2333 return false;
2334 }
2335 if (check_split.size() == 2) {
2336 if (check_split[1].size() != 8) {
2337 error = strprintf("Expected 8 character checksum, not %u characters", check_split[1].size());
2338 return false;
2339 }
2340 }
2341 auto checksum = DescriptorChecksum(check_split[0]);
2342 if (checksum.empty()) {
2343 error = "Invalid characters in payload";
2344 return false;
2345 }
2346 if (check_split.size() == 2) {
2347 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
2348 error = strprintf("Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
2349 return false;
2350 }
2351 }
2352 if (out_checksum) *out_checksum = std::move(checksum);
2353 sp = check_split[0];
2354 return true;
2355}
2356
2357std::vector<std::unique_ptr<Descriptor>> Parse(const std::string& descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum)
2358{
2359 Span<const char> sp{descriptor};
2360 if (!CheckChecksum(sp, require_checksum, error)) return {};
2361 uint32_t key_exp_index = 0;
2362 auto ret = ParseScript(key_exp_index, sp, ParseScriptContext::TOP, out, error);
2363 if (sp.size() == 0 && !ret.empty()) {
2364 std::vector<std::unique_ptr<Descriptor>> descs;
2365 descs.reserve(ret.size());
2366 for (auto& r : ret) {
2367 descs.emplace_back(std::unique_ptr<Descriptor>(std::move(r)));
2368 }
2369 return descs;
2370 }
2371 return {};
2372}
2373
2374std::string GetDescriptorChecksum(const std::string& descriptor)
2375{
2376 std::string ret;
2377 std::string error;
2378 Span<const char> sp{descriptor};
2379 if (!CheckChecksum(sp, false, error, &ret)) return "";
2380 return ret;
2381}
2382
2383std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider)
2384{
2385 return InferScript(script, ParseScriptContext::TOP, provider);
2386}
2387
2389{
2390 std::string desc_str = desc.ToString(/*compat_format=*/true);
2391 uint256 id;
2392 CSHA256().Write((unsigned char*)desc_str.data(), desc_str.size()).Finalize(id.begin());
2393 return id;
2394}
2395
2396void DescriptorCache::CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub)
2397{
2398 m_parent_xpubs[key_exp_pos] = xpub;
2399}
2400
2401void DescriptorCache::CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey& xpub)
2402{
2403 auto& xpubs = m_derived_xpubs[key_exp_pos];
2404 xpubs[der_index] = xpub;
2405}
2406
2407void DescriptorCache::CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub)
2408{
2409 m_last_hardened_xpubs[key_exp_pos] = xpub;
2410}
2411
2412bool DescriptorCache::GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const
2413{
2414 const auto& it = m_parent_xpubs.find(key_exp_pos);
2415 if (it == m_parent_xpubs.end()) return false;
2416 xpub = it->second;
2417 return true;
2418}
2419
2420bool DescriptorCache::GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey& xpub) const
2421{
2422 const auto& key_exp_it = m_derived_xpubs.find(key_exp_pos);
2423 if (key_exp_it == m_derived_xpubs.end()) return false;
2424 const auto& der_it = key_exp_it->second.find(der_index);
2425 if (der_it == key_exp_it->second.end()) return false;
2426 xpub = der_it->second;
2427 return true;
2428}
2429
2431{
2432 const auto& it = m_last_hardened_xpubs.find(key_exp_pos);
2433 if (it == m_last_hardened_xpubs.end()) return false;
2434 xpub = it->second;
2435 return true;
2436}
2437
2439{
2440 DescriptorCache diff;
2441 for (const auto& parent_xpub_pair : other.GetCachedParentExtPubKeys()) {
2442 CExtPubKey xpub;
2443 if (GetCachedParentExtPubKey(parent_xpub_pair.first, xpub)) {
2444 if (xpub != parent_xpub_pair.second) {
2445 throw std::runtime_error(std::string(__func__) + ": New cached parent xpub does not match already cached parent xpub");
2446 }
2447 continue;
2448 }
2449 CacheParentExtPubKey(parent_xpub_pair.first, parent_xpub_pair.second);
2450 diff.CacheParentExtPubKey(parent_xpub_pair.first, parent_xpub_pair.second);
2451 }
2452 for (const auto& derived_xpub_map_pair : other.GetCachedDerivedExtPubKeys()) {
2453 for (const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
2454 CExtPubKey xpub;
2455 if (GetCachedDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, xpub)) {
2456 if (xpub != derived_xpub_pair.second) {
2457 throw std::runtime_error(std::string(__func__) + ": New cached derived xpub does not match already cached derived xpub");
2458 }
2459 continue;
2460 }
2461 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2462 diff.CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2463 }
2464 }
2465 for (const auto& lh_xpub_pair : other.GetCachedLastHardenedExtPubKeys()) {
2466 CExtPubKey xpub;
2467 if (GetCachedLastHardenedExtPubKey(lh_xpub_pair.first, xpub)) {
2468 if (xpub != lh_xpub_pair.second) {
2469 throw std::runtime_error(std::string(__func__) + ": New cached last hardened xpub does not match already cached last hardened xpub");
2470 }
2471 continue;
2472 }
2473 CacheLastHardenedExtPubKey(lh_xpub_pair.first, lh_xpub_pair.second);
2474 diff.CacheLastHardenedExtPubKey(lh_xpub_pair.first, lh_xpub_pair.second);
2475 }
2476 return diff;
2477}
2478
2480{
2481 return m_parent_xpubs;
2482}
2483
2484std::unordered_map<uint32_t, ExtPubKeyMap> DescriptorCache::GetCachedDerivedExtPubKeys() const
2485{
2486 return m_derived_xpubs;
2487}
2488
2490{
2491 return m_last_hardened_xpubs;
2492}
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
Definition: addresstype.cpp:49
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:140
#define LIFETIMEBOUND
Definition: attributes.h:16
std::string FormatHDKeypath(const std::vector< uint32_t > &path, bool apostrophe)
Definition: bip32.cpp:54
int ret
node::NodeContext m_node
Definition: bitcoin-gui.cpp:42
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:81
#define Assume(val)
Assume is the identity function.
Definition: check.h:97
An encapsulated private key.
Definition: key.h:35
unsigned int size() const
Simple read-only vector-like interface.
Definition: key.h:117
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:123
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:126
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:182
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:24
An encapsulated public key.
Definition: pubkey.h:34
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:204
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:164
bool IsValid() const
Definition: pubkey.h:189
bool IsValidNonHybrid() const noexcept
Check if a public key is a syntactically valid compressed or uncompressed key.
Definition: pubkey.h:195
A hasher class for SHA-256.
Definition: sha256.h:14
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha256.cpp:727
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:701
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:415
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:602
Cache for single descriptor's derived extended pubkeys.
Definition: descriptor.h:19
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
ExtPubKeyMap m_last_hardened_xpubs
Map key expression index -> last hardened xpub.
Definition: descriptor.h:26
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
DescriptorCache MergeAndDiff(const DescriptorCache &other)
Combine another DescriptorCache into this one.
ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a last hardened xpub.
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
std::unordered_map< uint32_t, ExtPubKeyMap > m_derived_xpubs
Map key expression index -> map of (key derivation index -> xpub)
Definition: descriptor.h:22
bool GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached last hardened xpub.
ExtPubKeyMap m_parent_xpubs
Map key expression index -> parent xpub.
Definition: descriptor.h:24
An interface to be implemented by keystores that support signing.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
virtual bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const
bool GetKeyByXOnly(const XOnlyPubKey &pubkey, CKey &key) const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
bool GetKeyOriginByXOnly(const XOnlyPubKey &pubkey, KeyOriginInfo &info) const
virtual bool GetKey(const CKeyID &address, CKey &key) const
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:98
CONSTEXPR_IF_NOT_DEBUG C & back() const noexcept
Definition: span.h:182
constexpr std::size_t size() const noexcept
Definition: span.h:187
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
Definition: span.h:205
constexpr C * begin() const noexcept
Definition: span.h:175
constexpr bool empty() const noexcept
Definition: span.h:189
constexpr C * end() const noexcept
Definition: span.h:176
CONSTEXPR_IF_NOT_DEBUG C & front() const noexcept
Definition: span.h:177
Utility class to construct Taproot outputs from internal key and script tree.
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
bool IsComplete() const
Return whether there were either no leaves, or the leaves form a Huffman tree.
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
TaprootBuilder & Add(int depth, Span< const unsigned char > script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
const unsigned char * begin() const
Definition: pubkey.h:295
static constexpr size_t size()
Definition: pubkey.h:293
CPubKey GetEvenCorrespondingCPubKey() const
Definition: pubkey.cpp:217
bool IsFullyValid() const
Determine if this pubkey is fully valid.
Definition: pubkey.cpp:224
constexpr unsigned char * begin()
Definition: uint256.h:115
size_type size() const
Definition: prevector.h:294
160-bit opaque blob.
Definition: uint256.h:189
256-bit opaque blob.
Definition: uint256.h:201
static const int WITNESS_SCALE_FACTOR
Definition: consensus.h:21
CScript ParseScript(const std::string &s)
Definition: core_read.cpp:63
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
Definition: hash.h:92
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
Definition: hash.h:222
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:29
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
Definition: interpreter.h:232
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT
Definition: interpreter.h:235
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:283
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:244
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:299
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:231
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:294
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:213
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:257
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:267
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
Definition: miniscript.h:2640
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
Definition: miniscript.h:245
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
Definition: miniscript.h:2645
std::unique_ptr< const Node< Key > > NodeRef
Definition: miniscript.h:192
Definition: messages.h:20
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
Definition: parsing.cpp:15
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
Definition: parsing.cpp:33
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
Definition: parsing.cpp:24
static std::vector< std::string > split(const std::string &str, const std::string &delims=" \t")
Definition: subprocess.h:303
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:233
std::vector< T > Split(const Span< const char > &sp, std::string_view separators)
Split a string on any char found in separators, returning a vector.
Definition: string.h:107
static OutputType GetOutputType(TxoutType type, bool is_from_p2sh)
Definition: spend.cpp:248
static bool IsSegwit(const Descriptor &desc)
Whether the descriptor represents, directly or not, a witness program.
Definition: spend.cpp:47
bool operator<(const CNetAddr &a, const CNetAddr &b)
Definition: netaddress.cpp:612
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
Definition: outputtype.cpp:110
const char * name
Definition: rest.cpp:49
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
bool CheckChecksum(Span< const char > &sp, bool require_checksum, std::string &error, std::string *out_checksum=nullptr)
Check a descriptor checksum, and update desc to be the checksum-less part.
uint256 DescriptorID(const Descriptor &desc)
Unique identifier that may not change over time, unless explicitly marked as not backwards compatible...
std::vector< std::unique_ptr< Descriptor > > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
Definition: descriptor.h:16
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:28
@ OP_CHECKSIG
Definition: script.h:190
@ OP_NUMEQUAL
Definition: script.h:171
@ OP_CHECKSIGADD
Definition: script.h:210
static constexpr unsigned int MAX_PUBKEYS_PER_MULTI_A
The limit of keys in OP_CHECKSIGADD-based scripts.
Definition: script.h:37
CScript BuildScript(Ts &&... inputs)
Build a script by concatenating other scripts, or any argument accepted by CScript::operator<<.
Definition: script.h:616
static const int MAX_PUBKEYS_PER_MULTISIG
Definition: script.h:34
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:67
constexpr unsigned int GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 byt...
Definition: serialize.h:297
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
Definition: sign.cpp:109
std::optional< std::vector< std::tuple< int, std::vector< unsigned char >, int > > > InferTaprootTree(const TaprootSpendData &spenddata, const XOnlyPubKey &output)
Given a TaprootSpendData and the output key, reconstruct its script tree.
const SigningProvider & DUMMY_SIGNING_PROVIDER
void PolyMod(const std::vector< typename F::Elem > &mod, std::vector< typename F::Elem > &val, const F &field)
Compute the remainder of a polynomial division of val by mod, putting the result in mod.
Definition: sketch_impl.h:18
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: solver.cpp:141
std::optional< std::pair< int, std::vector< Span< const unsigned char > > > > MatchMultiA(const CScript &script)
Definition: solver.cpp:107
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: solver.cpp:218
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: solver.cpp:213
TxoutType
Definition: solver.h:22
@ WITNESS_V1_TAPROOT
@ WITNESS_V0_SCRIPTHASH
@ WITNESS_V0_KEYHASH
Span(T *, EndOrSize) -> Span< T >
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
Definition: strencodings.h:68
Definition: key.h:227
CExtPubKey Neuter() const
Definition: key.cpp:380
bool Derive(CExtKey &out, unsigned int nChild) const
Definition: key.cpp:359
CKey key
Definition: key.h:232
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:406
CPubKey pubkey
Definition: pubkey.h:348
Interface for parsed descriptor objects.
Definition: descriptor.h:98
virtual std::optional< int64_t > MaxSatisfactionElems() const =0
Get the maximum size number of stack elements for satisfying this descriptor.
virtual void GetPubKeys(std::set< CPubKey > &pubkeys, std::set< CExtPubKey > &ext_pubs) const =0
Return all (extended) public keys for this descriptor, including any from subdescriptors.
virtual bool ToNormalizedString(const SigningProvider &provider, std::string &out, const DescriptorCache *cache=nullptr) const =0
Convert the descriptor to a normalized string.
virtual std::optional< int64_t > MaxSatisfactionWeight(bool use_max_sig) const =0
Get the maximum size of a satisfaction for this descriptor, in weight units.
virtual std::string ToString(bool compat_format=false) const =0
Convert the descriptor back to a string, undoing parsing.
virtual std::optional< OutputType > GetOutputType() const =0
virtual bool Expand(int pos, const SigningProvider &provider, std::vector< CScript > &output_scripts, FlatSigningProvider &out, DescriptorCache *write_cache=nullptr) const =0
Expand a descriptor at a specified position.
virtual bool IsRange() const =0
Whether the expansion of this descriptor depends on the position.
virtual std::optional< int64_t > ScriptSize() const =0
Get the size of the scriptPubKey for this descriptor.
virtual bool IsSolvable() const =0
Whether this descriptor has all information about signing ignoring lack of private keys.
virtual void ExpandPrivate(int pos, const SigningProvider &provider, FlatSigningProvider &out) const =0
Expand the private key for a descriptor at a specified position, if possible.
virtual bool ToPrivateString(const SigningProvider &provider, std::string &out) const =0
Convert the descriptor to a private string.
virtual bool ExpandFromCache(int pos, const DescriptorCache &read_cache, std::vector< CScript > &output_scripts, FlatSigningProvider &out) const =0
Expand a descriptor at a specified position using cached expansion data.
std::map< CKeyID, CPubKey > pubkeys
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
Definition: keyorigin.h:13
std::vector< uint32_t > path
Definition: keyorigin.h:14
XOnlyPubKey internal_key
The BIP341 internal key.
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
consteval auto _(util::TranslatedLiteral str)
Definition: translation.h:79
bool IsHex(std::string_view str)
bool ParseUInt32(std::string_view str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
assert(!tx.IsCoinBase())
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
Definition: vector.h:23