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