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