Bitcoin ABC 0.34.2
P2P Digital Currency
descriptor.cpp
Go to the documentation of this file.
1// Copyright (c) 2018 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <script/descriptor.h>
6
7#include <chainparams.h> // For Params()
8#include <common/args.h>
9#include <config.h>
10#include <key_io.h>
11#include <pubkey.h>
12#include <script/parsing.h>
13#include <script/solver.h>
14#include <span.h>
15#include <util/bip32.h>
16#include <util/strencodings.h>
17#include <util/vector.h>
18
19#include <memory>
20#include <string>
21
22using util::Split;
23
24namespace {
25
27// Checksum //
29
30// This section implements a checksum algorithm for descriptors with the
31// following properties:
32// * Mistakes in a descriptor string are measured in "symbol errors". The higher
33// the number of symbol errors, the harder it is to detect:
34// * An error substituting a character from 0123456789()[],'/*abcdefgh@:$%{}
35// for
36// another in that set always counts as 1 symbol error.
37// * Note that hex encoded keys are covered by these characters. Xprvs and
38// xpubs use other characters too, but already have their own checksum
39// mechanism.
40// * Function names like "multi()" use other characters, but mistakes in
41// these would generally result in an unparsable descriptor.
42// * A case error always counts as 1 symbol error.
43// * Any other 1 character substitution error counts as 1 or 2 symbol errors.
44// * Any 1 symbol error is always detected.
45// * Any 2 or 3 symbol error in a descriptor of up to 49154 characters is always
46// detected.
47// * Any 4 symbol error in a descriptor of up to 507 characters is always
48// detected.
49// * Any 5 symbol error in a descriptor of up to 77 characters is always
50// detected.
51// * Is optimized to minimize the chance a 5 symbol error in a descriptor up to
52// 387 characters is undetected
53// * Random errors have a chance of 1 in 2**40 of being undetected.
54//
55// These properties are achieved by expanding every group of 3 (non checksum)
56// characters into 4 GF(32) symbols, over which a cyclic code is defined.
57
58/*
59 * Interprets c as 8 groups of 5 bits which are the coefficients of a degree 8
60 * polynomial over GF(32), multiplies that polynomial by x, computes its
61 * remainder modulo a generator, and adds the constant term val.
62 *
63 * This generator is G(x) = x^8 + {30}x^7 + {23}x^6 + {15}x^5 + {14}x^4 +
64 * {10}x^3 + {6}x^2 + {12}x + {9}. It is chosen to define an cyclic error
65 * detecting code which is selected by:
66 * - Starting from all BCH codes over GF(32) of degree 8 and below, which by
67 * construction guarantee detecting 3 errors in windows up to 19000 symbols.
68 * - Taking all those generators, and for degree 7 ones, extend them to degree 8
69 * by adding all degree-1 factors.
70 * - Selecting just the set of generators that guarantee detecting 4 errors in a
71 * window of length 512.
72 * - Selecting one of those with best worst-case behavior for 5 errors in
73 * windows of length up to 512.
74 *
75 * The generator and the constants to implement it can be verified using this
76 * Sage code: B = GF(2) # Binary field BP.<b> = B[] # Polynomials over the
77 * binary field F_mod = b**5 + b**3 + 1 F.<f> = GF(32, modulus=F_mod,
78 * repr='int') # GF(32) definition FP.<x> = F[] # Polynomials over GF(32) E_mod
79 * = x**3 + x + F.fetch_int(8) E.<e> = F.extension(E_mod) # Extension field
80 * definition alpha = e**2743 # Choice of an element in extension field for p in
81 * divisors(E.order() - 1): # Verify alpha has order 32767. assert((alpha**p ==
82 * 1) == (p % 32767 == 0)) G = lcm([(alpha**i).minpoly() for i in
83 * [1056,1057,1058]] + [x + 1]) print(G) # Print out the generator for i in
84 * [1,2,4,8,16]: # Print out {1,2,4,8,16}*(G mod x^8), packed in hex integers.
85 * v = 0
86 * for coef in reversed((F.fetch_int(i)*(G %
87 * x**8)).coefficients(sparse=True)): v = v*32 + coef.integer_representation()
88 * print("0x%x" % v)
89 */
90uint64_t PolyMod(uint64_t c, int val) {
91 uint8_t c0 = c >> 35;
92 c = ((c & 0x7ffffffff) << 5) ^ val;
93 if (c0 & 1) {
94 c ^= 0xf5dee51989;
95 }
96 if (c0 & 2) {
97 c ^= 0xa9fdca3312;
98 }
99 if (c0 & 4) {
100 c ^= 0x1bab10e32d;
101 }
102 if (c0 & 8) {
103 c ^= 0x3706b1677a;
104 }
105 if (c0 & 16) {
106 c ^= 0x644d626ffd;
107 }
108 return c;
109}
110
111std::string DescriptorChecksum(const Span<const char> &span) {
129 static const std::string INPUT_CHARSET =
130 "0123456789()[],'/*abcdefgh@:$%{}"
131 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
132 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
133
135 static const std::string CHECKSUM_CHARSET =
136 "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
137
138 uint64_t c = 1;
139 int cls = 0;
140 int clscount = 0;
141 for (auto ch : span) {
142 auto pos = INPUT_CHARSET.find(ch);
143 if (pos == std::string::npos) {
144 return "";
145 }
146 // Emit a symbol for the position inside the group, for every character.
147 c = PolyMod(c, pos & 31);
148 // Accumulate the group numbers
149 cls = cls * 3 + (pos >> 5);
150 if (++clscount == 3) {
151 // Emit an extra symbol representing the group numbers, for every 3
152 // characters.
153 c = PolyMod(c, cls);
154 cls = 0;
155 clscount = 0;
156 }
157 }
158 if (clscount > 0) {
159 c = PolyMod(c, cls);
160 }
161 for (int j = 0; j < 8; ++j) {
162 // Shift further to determine the checksum.
163 c = PolyMod(c, 0);
164 }
165 // Prevent appending zeroes from not affecting the checksum.
166 c ^= 1;
167
168 std::string ret(8, ' ');
169 for (int j = 0; j < 8; ++j) {
170 ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
171 }
172 return ret;
173}
174
175std::string AddChecksum(const std::string &str) {
176 return str + "#" + DescriptorChecksum(str);
177}
178
180// Internal representation //
182
183typedef std::vector<uint32_t> KeyPath;
184
186struct PubkeyProvider {
187protected:
191 uint32_t m_expr_index;
192
193public:
194 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
195
196 virtual ~PubkeyProvider() = default;
197
205 virtual bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key,
206 KeyOriginInfo &info,
207 const DescriptorCache *read_cache = nullptr,
208 DescriptorCache *write_cache = nullptr) = 0;
209
211 virtual bool IsRange() const = 0;
212
214 virtual size_t GetSize() const = 0;
215
217 virtual std::string ToString() const = 0;
218
223 virtual bool ToPrivateString(const SigningProvider &arg,
224 std::string &out) const = 0;
225
227 virtual bool GetPrivKey(int pos, const SigningProvider &arg,
228 CKey &key) const = 0;
229};
230
231class OriginPubkeyProvider final : public PubkeyProvider {
232 KeyOriginInfo m_origin;
233 std::unique_ptr<PubkeyProvider> m_provider;
234
235 std::string OriginString() const {
236 return HexStr(m_origin.fingerprint) + FormatHDKeypath(m_origin.path);
237 }
238
239public:
240 OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info,
241 std::unique_ptr<PubkeyProvider> provider)
242 : PubkeyProvider(exp_index), m_origin(std::move(info)),
243 m_provider(std::move(provider)) {}
244 bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key,
245 KeyOriginInfo &info,
246 const DescriptorCache *read_cache = nullptr,
247 DescriptorCache *write_cache = nullptr) override {
248 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache,
249 write_cache)) {
250 return false;
251 }
252 std::copy(std::begin(m_origin.fingerprint),
253 std::end(m_origin.fingerprint), info.fingerprint);
254 info.path.insert(info.path.begin(), m_origin.path.begin(),
255 m_origin.path.end());
256 return true;
257 }
258 bool IsRange() const override { return m_provider->IsRange(); }
259 size_t GetSize() const override { return m_provider->GetSize(); }
260 std::string ToString() const override {
261 return "[" + OriginString() + "]" + m_provider->ToString();
262 }
263 bool ToPrivateString(const SigningProvider &arg,
264 std::string &ret) const override {
265 std::string sub;
266 if (!m_provider->ToPrivateString(arg, sub)) {
267 return false;
268 }
269 ret = "[" + OriginString() + "]" + std::move(sub);
270 return true;
271 }
272 bool GetPrivKey(int pos, const SigningProvider &arg,
273 CKey &key) const override {
274 return m_provider->GetPrivKey(pos, arg, key);
275 }
276};
277
279class ConstPubkeyProvider final : public PubkeyProvider {
280 CPubKey m_pubkey;
281
282public:
283 ConstPubkeyProvider(uint32_t exp_index, const CPubKey &pubkey)
284 : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
285 bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key,
286 KeyOriginInfo &info,
287 const DescriptorCache *read_cache = nullptr,
288 DescriptorCache *write_cache = nullptr) override {
289 key = m_pubkey;
290 info.path.clear();
291 CKeyID keyid = m_pubkey.GetID();
292 std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint),
293 info.fingerprint);
294 return true;
295 }
296 bool IsRange() const override { return false; }
297 size_t GetSize() const override { return m_pubkey.size(); }
298 std::string ToString() const override { return HexStr(m_pubkey); }
299 bool ToPrivateString(const SigningProvider &arg,
300 std::string &ret) const override {
301 CKey key;
302 if (!arg.GetKey(m_pubkey.GetID(), key)) {
303 return false;
304 }
305 ret = EncodeSecret(key);
306 return true;
307 }
308 bool GetPrivKey(int pos, const SigningProvider &arg,
309 CKey &key) const override {
310 return arg.GetKey(m_pubkey.GetID(), key);
311 }
312};
313
314enum class DeriveType {
315 NO,
316 UNHARDENED,
317 HARDENED,
318};
319
321class BIP32PubkeyProvider final : public PubkeyProvider {
322 // Root xpub, path, and final derivation step type being used, if any
323 CExtPubKey m_root_extkey;
324 KeyPath m_path;
325 DeriveType m_derive;
326 // Cache of the parent of the final derived pubkeys.
327 // Primarily useful for situations when no read_cache is provided
328 CExtPubKey m_cached_xpub;
329
330 bool GetExtKey(const SigningProvider &arg, CExtKey &ret) const {
331 CKey key;
332 if (!arg.GetKey(m_root_extkey.pubkey.GetID(), key)) {
333 return false;
334 }
335 ret.nDepth = m_root_extkey.nDepth;
336 std::copy(m_root_extkey.vchFingerprint,
337 m_root_extkey.vchFingerprint + sizeof(ret.vchFingerprint),
338 ret.vchFingerprint);
339 ret.nChild = m_root_extkey.nChild;
340 ret.chaincode = m_root_extkey.chaincode;
341 ret.key = key;
342 return true;
343 }
344
345 // Derives the last xprv
346 bool GetDerivedExtKey(const SigningProvider &arg, CExtKey &xprv) const {
347 if (!GetExtKey(arg, xprv)) {
348 return false;
349 }
350 for (auto entry : m_path) {
351 xprv.Derive(xprv, entry);
352 }
353 return true;
354 }
355
356 bool IsHardened() const {
357 if (m_derive == DeriveType::HARDENED) {
358 return true;
359 }
360 for (auto entry : m_path) {
361 if (entry >> 31) {
362 return true;
363 }
364 }
365 return false;
366 }
367
368public:
369 BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey &extkey,
370 KeyPath path, DeriveType derive)
371 : PubkeyProvider(exp_index), m_root_extkey(extkey),
372 m_path(std::move(path)), m_derive(derive) {}
373 bool IsRange() const override { return m_derive != DeriveType::NO; }
374 size_t GetSize() const override { return 33; }
375 bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key_out,
376 KeyOriginInfo &final_info_out,
377 const DescriptorCache *read_cache = nullptr,
378 DescriptorCache *write_cache = nullptr) override {
379 // Info of parent of the to be derived pubkey
380 KeyOriginInfo parent_info;
381 CKeyID keyid = m_root_extkey.pubkey.GetID();
382 std::copy(keyid.begin(),
383 keyid.begin() + sizeof(parent_info.fingerprint),
384 parent_info.fingerprint);
385 parent_info.path = m_path;
386
387 // Info of the derived key itself which is copied out upon successful
388 // completion
389 KeyOriginInfo final_info_out_tmp = parent_info;
390 if (m_derive == DeriveType::UNHARDENED) {
391 final_info_out_tmp.path.push_back((uint32_t)pos);
392 }
393 if (m_derive == DeriveType::HARDENED) {
394 final_info_out_tmp.path.push_back(((uint32_t)pos) | 0x80000000L);
395 }
396
397 // Derive keys or fetch them from cache
398 CExtPubKey final_extkey = m_root_extkey;
399 CExtPubKey parent_extkey = m_root_extkey;
400 bool der = true;
401 if (read_cache) {
402 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos,
403 final_extkey)) {
404 if (m_derive == DeriveType::HARDENED) {
405 return false;
406 }
407 // Try to get the derivation parent
408 if (!read_cache->GetCachedParentExtPubKey(m_expr_index,
409 parent_extkey)) {
410 return false;
411 }
412 final_extkey = parent_extkey;
413 if (m_derive == DeriveType::UNHARDENED) {
414 der = parent_extkey.Derive(final_extkey, pos);
415 }
416 }
417 } else if (m_cached_xpub.pubkey.IsValid() &&
418 m_derive != DeriveType::HARDENED) {
419 parent_extkey = final_extkey = m_cached_xpub;
420 if (m_derive == DeriveType::UNHARDENED) {
421 der = parent_extkey.Derive(final_extkey, pos);
422 }
423 } else if (IsHardened()) {
424 CExtKey xprv;
425 if (!GetDerivedExtKey(arg, xprv)) {
426 return false;
427 }
428 parent_extkey = xprv.Neuter();
429 if (m_derive == DeriveType::UNHARDENED) {
430 der = xprv.Derive(xprv, pos);
431 }
432 if (m_derive == DeriveType::HARDENED) {
433 der = xprv.Derive(xprv, pos | 0x80000000UL);
434 }
435 final_extkey = xprv.Neuter();
436 } else {
437 for (auto entry : m_path) {
438 der = parent_extkey.Derive(parent_extkey, entry);
439 assert(der);
440 }
441 final_extkey = parent_extkey;
442 if (m_derive == DeriveType::UNHARDENED) {
443 der = parent_extkey.Derive(final_extkey, pos);
444 }
445 assert(m_derive != DeriveType::HARDENED);
446 }
447 assert(der);
448
449 final_info_out = final_info_out_tmp;
450 key_out = final_extkey.pubkey;
451
452 // We rely on the consumer to check that m_derive isn't HARDENED as
453 // above But we can't have already cached something in case we read
454 // something from the cache and parent_extkey isn't actually the parent.
455 if (!m_cached_xpub.pubkey.IsValid()) {
456 m_cached_xpub = parent_extkey;
457 }
458
459 if (write_cache) {
460 // Only cache parent if there is any unhardened derivation
461 if (m_derive != DeriveType::HARDENED) {
462 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
463 } else if (final_info_out.path.size() > 0) {
464 write_cache->CacheDerivedExtPubKey(m_expr_index, pos,
465 final_extkey);
466 }
467 }
468
469 return true;
470 }
471 std::string ToString() const override {
472 std::string ret =
473 EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path);
474 if (IsRange()) {
475 ret += "/*";
476 if (m_derive == DeriveType::HARDENED) {
477 ret += '\'';
478 }
479 }
480 return ret;
481 }
482 bool ToPrivateString(const SigningProvider &arg,
483 std::string &out) const override {
484 CExtKey key;
485 if (!GetExtKey(arg, key)) {
486 return false;
487 }
488 out = EncodeExtKey(key) + FormatHDKeypath(m_path);
489 if (IsRange()) {
490 out += "/*";
491 if (m_derive == DeriveType::HARDENED) {
492 out += '\'';
493 }
494 }
495 return true;
496 }
497 bool GetPrivKey(int pos, const SigningProvider &arg,
498 CKey &key) const override {
499 CExtKey extkey;
500 if (!GetDerivedExtKey(arg, extkey)) {
501 return false;
502 }
503 if (m_derive == DeriveType::UNHARDENED) {
504 extkey.Derive(extkey, pos);
505 }
506 if (m_derive == DeriveType::HARDENED) {
507 extkey.Derive(extkey, pos | 0x80000000UL);
508 }
509 key = extkey.key;
510 return true;
511 }
512};
513
515class DescriptorImpl : public Descriptor {
518 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
520 const std::string m_name;
521
522protected:
526 const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
527
530 virtual std::string ToStringExtra() const { return ""; }
531
547 virtual std::vector<CScript>
548 MakeScripts(const std::vector<CPubKey> &pubkeys, const CScript *script,
549 FlatSigningProvider &out) const = 0;
550
551public:
552 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
553 std::unique_ptr<DescriptorImpl> script,
554 const std::string &name)
555 : m_pubkey_args(std::move(pubkeys)), m_name(name),
556 m_subdescriptor_arg(std::move(script)) {}
557
558 bool IsSolvable() const override {
559 if (m_subdescriptor_arg) {
560 if (!m_subdescriptor_arg->IsSolvable()) {
561 return false;
562 }
563 }
564 return true;
565 }
566
567 bool IsRange() const final {
568 for (const auto &pubkey : m_pubkey_args) {
569 if (pubkey->IsRange()) {
570 return true;
571 }
572 }
573 if (m_subdescriptor_arg) {
574 if (m_subdescriptor_arg->IsRange()) {
575 return true;
576 }
577 }
578 return false;
579 }
580
581 bool ToStringHelper(const SigningProvider *arg, std::string &out,
582 bool priv) const {
583 std::string extra = ToStringExtra();
584 size_t pos = extra.size() > 0 ? 1 : 0;
585 std::string ret = m_name + "(" + extra;
586 for (const auto &pubkey : m_pubkey_args) {
587 if (pos++) {
588 ret += ",";
589 }
590 std::string tmp;
591 if (priv) {
592 if (!pubkey->ToPrivateString(*arg, tmp)) {
593 return false;
594 }
595 } else {
596 tmp = pubkey->ToString();
597 }
598 ret += tmp;
599 }
600 if (m_subdescriptor_arg) {
601 if (pos++) {
602 ret += ",";
603 }
604 std::string tmp;
605 if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) {
606 return false;
607 }
608 ret += tmp;
609 }
610 out = std::move(ret) + ")";
611 return true;
612 }
613
614 std::string ToString() const final {
615 std::string ret;
616 ToStringHelper(nullptr, ret, false);
617 return AddChecksum(ret);
618 }
619
620 bool ToPrivateString(const SigningProvider &arg,
621 std::string &out) const final {
622 bool ret = ToStringHelper(&arg, out, true);
623 out = AddChecksum(out);
624 return ret;
625 }
626
627 bool ExpandHelper(int pos, const SigningProvider &arg,
628 const DescriptorCache *read_cache,
629 std::vector<CScript> &output_scripts,
631 DescriptorCache *write_cache) const {
632 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
633 entries.reserve(m_pubkey_args.size());
634
635 // Construct temporary data in `entries` and `subscripts`, to avoid
636 // producing output in case of failure.
637 for (const auto &p : m_pubkey_args) {
638 entries.emplace_back();
639 if (!p->GetPubKey(pos, arg, entries.back().first,
640 entries.back().second, read_cache, write_cache)) {
641 return false;
642 }
643 }
644 std::vector<CScript> subscripts;
645 if (m_subdescriptor_arg) {
646 FlatSigningProvider subprovider;
647 if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache,
648 subscripts, subprovider,
649 write_cache)) {
650 return false;
651 }
652 out = Merge(out, subprovider);
653 }
654
655 std::vector<CPubKey> pubkeys;
656 pubkeys.reserve(entries.size());
657 for (auto &entry : entries) {
658 pubkeys.push_back(entry.first);
659 out.origins.emplace(
660 entry.first.GetID(),
661 std::make_pair<CPubKey, KeyOriginInfo>(
662 CPubKey(entry.first), std::move(entry.second)));
663 }
664 if (m_subdescriptor_arg) {
665 for (const auto &subscript : subscripts) {
666 out.scripts.emplace(CScriptID(subscript), subscript);
667 std::vector<CScript> addscripts =
668 MakeScripts(pubkeys, &subscript, out);
669 for (auto &addscript : addscripts) {
670 output_scripts.push_back(std::move(addscript));
671 }
672 }
673 } else {
674 output_scripts = MakeScripts(pubkeys, nullptr, out);
675 }
676 return true;
677 }
678
679 bool Expand(int pos, const SigningProvider &provider,
680 std::vector<CScript> &output_scripts, FlatSigningProvider &out,
681 DescriptorCache *write_cache = nullptr) const final {
682 return ExpandHelper(pos, provider, nullptr, output_scripts, out,
683 write_cache);
684 }
685
686 bool ExpandFromCache(int pos, const DescriptorCache &read_cache,
687 std::vector<CScript> &output_scripts,
688 FlatSigningProvider &out) const final {
689 return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &read_cache,
690 output_scripts, out, nullptr);
691 }
692
693 void ExpandPrivate(int pos, const SigningProvider &provider,
694 FlatSigningProvider &out) const final {
695 for (const auto &p : m_pubkey_args) {
696 CKey key;
697 if (!p->GetPrivKey(pos, provider, key)) {
698 continue;
699 }
700 out.keys.emplace(key.GetPubKey().GetID(), key);
701 }
702 if (m_subdescriptor_arg) {
703 FlatSigningProvider subprovider;
704 m_subdescriptor_arg->ExpandPrivate(pos, provider, subprovider);
705 out = Merge(out, subprovider);
706 }
707 }
708
709 std::optional<OutputType> GetOutputType() const override {
710 return std::nullopt;
711 }
712};
713
715class AddressDescriptor final : public DescriptorImpl {
716 const CTxDestination m_destination;
717
718protected:
719 std::string ToStringExtra() const override {
720 return EncodeDestination(m_destination, GetConfig());
721 }
722 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &,
723 const CScript *,
724 FlatSigningProvider &) const override {
725 return Vector(GetScriptForDestination(m_destination));
726 }
727
728public:
729 AddressDescriptor(CTxDestination destination)
730 : DescriptorImpl({}, {}, "addr"),
731 m_destination(std::move(destination)) {}
732 bool IsSolvable() const final { return false; }
733
734 std::optional<OutputType> GetOutputType() const override {
735 switch (m_destination.index()) {
736 case 1 /* PKHash */:
737 case 2 /* ScriptHash */:
738 return OutputType::LEGACY;
739 case 0 /* CNoDestination */:
740 default:
741 return std::nullopt;
742 }
743 }
744 bool IsSingleType() const final { return true; }
745};
746
748class RawDescriptor final : public DescriptorImpl {
749 const CScript m_script;
750
751protected:
752 std::string ToStringExtra() const override { return HexStr(m_script); }
753 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &,
754 const CScript *,
755 FlatSigningProvider &) const override {
756 return Vector(m_script);
757 }
758
759public:
760 RawDescriptor(CScript script)
761 : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {}
762 bool IsSolvable() const final { return false; }
763
764 std::optional<OutputType> GetOutputType() const override {
765 CTxDestination dest;
766 ExtractDestination(m_script, dest);
767 switch (dest.index()) {
768 case 1 /* PKHash */:
769 case 2 /* ScriptHash */:
770 return OutputType::LEGACY;
771 case 0 /* CNoDestination */:
772 default:
773 return std::nullopt;
774 }
775 }
776 bool IsSingleType() const final { return true; }
777};
778
780class PKDescriptor final : public DescriptorImpl {
781protected:
782 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
783 const CScript *,
784 FlatSigningProvider &) const override {
785 return Vector(GetScriptForRawPubKey(keys[0]));
786 }
787
788public:
789 PKDescriptor(std::unique_ptr<PubkeyProvider> prov)
790 : DescriptorImpl(Vector(std::move(prov)), {}, "pk") {}
791 bool IsSingleType() const final { return true; }
792};
793
795class PKHDescriptor final : public DescriptorImpl {
796protected:
797 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
798 const CScript *,
799 FlatSigningProvider &out) const override {
800 CKeyID id = keys[0].GetID();
801 out.pubkeys.emplace(id, keys[0]);
803 }
804
805public:
806 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov)
807 : DescriptorImpl(Vector(std::move(prov)), {}, "pkh") {}
808 std::optional<OutputType> GetOutputType() const override {
809 return OutputType::LEGACY;
810 }
811 bool IsSingleType() const final { return true; }
812};
813
815class ComboDescriptor final : public DescriptorImpl {
816protected:
817 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
818 const CScript *,
819 FlatSigningProvider &out) const override {
820 std::vector<CScript> ret;
821 CKeyID id = keys[0].GetID();
822 out.pubkeys.emplace(id, keys[0]);
823 // P2PK
824 ret.emplace_back(GetScriptForRawPubKey(keys[0]));
825 // P2PKH
826 ret.emplace_back(GetScriptForDestination(PKHash(id)));
827 return ret;
828 }
829
830public:
831 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov)
832 : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {}
833 bool IsSingleType() const final { return false; }
834};
835
837class MultisigDescriptor final : public DescriptorImpl {
838 const int m_threshold;
839 const bool m_sorted;
840
841protected:
842 std::string ToStringExtra() const override {
843 return strprintf("%i", m_threshold);
844 }
845 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
846 const CScript *,
847 FlatSigningProvider &) const override {
848 if (m_sorted) {
849 std::vector<CPubKey> sorted_keys(keys);
850 std::sort(sorted_keys.begin(), sorted_keys.end());
851 return Vector(GetScriptForMultisig(m_threshold, sorted_keys));
852 }
853 return Vector(GetScriptForMultisig(m_threshold, keys));
854 }
855
856public:
857 MultisigDescriptor(int threshold,
858 std::vector<std::unique_ptr<PubkeyProvider>> providers,
859 bool sorted = false)
860 : DescriptorImpl(std::move(providers), {},
861 sorted ? "sortedmulti" : "multi"),
862 m_threshold(threshold), m_sorted(sorted) {}
863 bool IsSingleType() const final { return true; }
864};
865
867class SHDescriptor final : public DescriptorImpl {
868protected:
869 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &,
870 const CScript *script,
871 FlatSigningProvider &) const override {
873 }
874
875public:
876 SHDescriptor(std::unique_ptr<DescriptorImpl> desc)
877 : DescriptorImpl({}, std::move(desc), "sh") {}
878 std::optional<OutputType> GetOutputType() const override {
879 return OutputType::LEGACY;
880 }
881 bool IsSingleType() const final { return true; }
882};
883
885// Parser //
887
888enum class ParseScriptContext {
889 TOP,
890 P2SH,
891};
892
897[[nodiscard]] bool ParseKeyPath(const std::vector<Span<const char>> &split,
898 KeyPath &out, std::string &error) {
899 for (size_t i = 1; i < split.size(); ++i) {
900 Span<const char> elem = split[i];
901 bool hardened = false;
902 if (elem.size() > 0 &&
903 (elem[elem.size() - 1] == '\'' || elem[elem.size() - 1] == 'h')) {
904 elem = elem.first(elem.size() - 1);
905 hardened = true;
906 }
907 uint32_t p;
908 if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p)) {
909 error = strprintf("Key path value '%s' is not a valid uint32",
910 std::string(elem.begin(), elem.end()).c_str());
911 return false;
912 } else if (p > 0x7FFFFFFFUL) {
913 error = strprintf("Key path value %u is out of range", p);
914 return false;
915 }
916 out.push_back(p | (uint32_t(hardened) << 31));
917 }
918 return true;
919}
920
922std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
923 const Span<const char> &sp,
925 std::string &error) {
926 auto split = Split(sp, '/');
927 std::string str(split[0].begin(), split[0].end());
928 if (str.size() == 0) {
929 error = "No key provided";
930 return nullptr;
931 }
932 if (split.size() == 1) {
933 if (IsHex(str)) {
934 std::vector<uint8_t> data = ParseHex(str);
935 CPubKey pubkey(data);
936 if (pubkey.IsFullyValid()) {
937 return std::make_unique<ConstPubkeyProvider>(key_exp_index,
938 pubkey);
939 }
940 error = strprintf("Pubkey '%s' is invalid", str);
941 return nullptr;
942 }
943 CKey key = DecodeSecret(str);
944 if (key.IsValid()) {
945 CPubKey pubkey = key.GetPubKey();
946 out.keys.emplace(pubkey.GetID(), key);
947 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey);
948 }
949 }
950 CExtKey extkey = DecodeExtKey(str);
951 CExtPubKey extpubkey = DecodeExtPubKey(str);
952 if (!extkey.key.IsValid() && !extpubkey.pubkey.IsValid()) {
953 error = strprintf("key '%s' is not valid", str);
954 return nullptr;
955 }
956 KeyPath path;
957 DeriveType type = DeriveType::NO;
958 if (split.back() == Span{"*"}.first(1)) {
959 split.pop_back();
960 type = DeriveType::UNHARDENED;
961 } else if (split.back() == Span{"*'"}.first(2) ||
962 split.back() == Span{"*h"}.first(2)) {
963 split.pop_back();
964 type = DeriveType::HARDENED;
965 }
966 if (!ParseKeyPath(split, path, error)) {
967 return nullptr;
968 }
969 if (extkey.key.IsValid()) {
970 extpubkey = extkey.Neuter();
971 out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key);
972 }
973 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey,
974 std::move(path), type);
975}
976
978std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index,
979 const Span<const char> &sp,
981 std::string &error) {
982 auto origin_split = Split(sp, ']');
983 if (origin_split.size() > 2) {
984 error = "Multiple ']' characters found for a single pubkey";
985 return nullptr;
986 }
987 if (origin_split.size() == 1) {
988 return ParsePubkeyInner(key_exp_index, origin_split[0], out, error);
989 }
990 if (origin_split[0].empty() || origin_split[0][0] != '[') {
991 error = strprintf("Key origin start '[ character expected but not "
992 "found, got '%c' instead",
993 origin_split[0].empty()
994 ? ']'
995 : origin_split[0][0]);
996 return nullptr;
997 }
998 auto slash_split = Split(origin_split[0].subspan(1), '/');
999 if (slash_split[0].size() != 8) {
1000 error = strprintf("Fingerprint is not 4 bytes (%u characters instead "
1001 "of 8 characters)",
1002 slash_split[0].size());
1003 return nullptr;
1004 }
1005 std::string fpr_hex =
1006 std::string(slash_split[0].begin(), slash_split[0].end());
1007 if (!IsHex(fpr_hex)) {
1008 error = strprintf("Fingerprint '%s' is not hex", fpr_hex);
1009 return nullptr;
1010 }
1011 auto fpr_bytes = ParseHex(fpr_hex);
1012 KeyOriginInfo info;
1013 static_assert(sizeof(info.fingerprint) == 4, "Fingerprint must be 4 bytes");
1014 assert(fpr_bytes.size() == 4);
1015 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
1016 if (!ParseKeyPath(slash_split, info.path, error)) {
1017 return nullptr;
1018 }
1019 auto provider =
1020 ParsePubkeyInner(key_exp_index, origin_split[1], out, error);
1021 if (!provider) {
1022 return nullptr;
1023 }
1024 return std::make_unique<OriginPubkeyProvider>(
1025 key_exp_index, std::move(info), std::move(provider));
1026}
1027
1029std::unique_ptr<DescriptorImpl> ParseScript(uint32_t key_exp_index,
1030 Span<const char> &sp,
1031 ParseScriptContext ctx,
1033 std::string &error) {
1034 using namespace script;
1035
1036 auto expr = Expr(sp);
1037 bool sorted_multi = false;
1038 if (Func("pk", expr)) {
1039 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1040 if (!pubkey) {
1041 return nullptr;
1042 }
1043 return std::make_unique<PKDescriptor>(std::move(pubkey));
1044 }
1045 if (Func("pkh", expr)) {
1046 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1047 if (!pubkey) {
1048 return nullptr;
1049 }
1050 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1051 }
1052 if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
1053 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1054 if (!pubkey) {
1055 return nullptr;
1056 }
1057 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1058 } else if (ctx != ParseScriptContext::TOP && Func("combo", expr)) {
1059 error = "Cannot have combo in non-top level";
1060 return nullptr;
1061 }
1062 if ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr)) {
1063 auto threshold = Expr(expr);
1064 uint32_t thres;
1065 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1066 if (!ParseUInt32(std::string(threshold.begin(), threshold.end()),
1067 &thres)) {
1068 error = strprintf(
1069 "Multi threshold '%s' is not valid",
1070 std::string(threshold.begin(), threshold.end()).c_str());
1071 return nullptr;
1072 }
1073 size_t script_size = 0;
1074 while (expr.size()) {
1075 if (!Const(",", expr)) {
1076 error = strprintf("Multi: expected ',', got '%c'", expr[0]);
1077 return nullptr;
1078 }
1079 auto arg = Expr(expr);
1080 auto pk = ParsePubkey(key_exp_index, arg, out, error);
1081 if (!pk) {
1082 return nullptr;
1083 }
1084 script_size += pk->GetSize() + 1;
1085 providers.emplace_back(std::move(pk));
1086 key_exp_index++;
1087 }
1088 if (providers.empty() || providers.size() > 16) {
1089 error = strprintf("Cannot have %u keys in multisig; must have "
1090 "between 1 and 16 keys, inclusive",
1091 providers.size());
1092 return nullptr;
1093 } else if (thres < 1) {
1094 error = strprintf(
1095 "Multisig threshold cannot be %d, must be at least 1", thres);
1096 return nullptr;
1097 } else if (thres > providers.size()) {
1098 error =
1099 strprintf("Multisig threshold cannot be larger than the number "
1100 "of keys; threshold is %d but only %u keys specified",
1101 thres, providers.size());
1102 return nullptr;
1103 }
1104 if (ctx == ParseScriptContext::TOP) {
1105 if (providers.size() > 3) {
1106 error = strprintf("Cannot have %u pubkeys in bare multisig; "
1107 "only at most 3 pubkeys",
1108 providers.size());
1109 return nullptr;
1110 }
1111 }
1112 if (ctx == ParseScriptContext::P2SH) {
1113 if (script_size + 3 > MAX_SCRIPT_ELEMENT_SIZE) {
1114 error = strprintf("P2SH script is too large, %d bytes is "
1115 "larger than %d bytes",
1116 script_size + 3, MAX_SCRIPT_ELEMENT_SIZE);
1117 return nullptr;
1118 }
1119 }
1120 return std::make_unique<MultisigDescriptor>(thres, std::move(providers),
1121 sorted_multi);
1122 }
1123 if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
1124 auto desc = ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
1125 out, error);
1126 if (!desc || expr.size()) {
1127 return nullptr;
1128 }
1129 return std::make_unique<SHDescriptor>(std::move(desc));
1130 } else if (ctx != ParseScriptContext::TOP && Func("sh", expr)) {
1131 error = "Cannot have sh in non-top level";
1132 return nullptr;
1133 }
1134 if (ctx == ParseScriptContext::TOP && Func("addr", expr)) {
1135 CTxDestination dest =
1136 DecodeDestination(std::string(expr.begin(), expr.end()), Params());
1137 if (!IsValidDestination(dest)) {
1138 error = "Address is not valid";
1139 return nullptr;
1140 }
1141 return std::make_unique<AddressDescriptor>(std::move(dest));
1142 }
1143 if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
1144 std::string str(expr.begin(), expr.end());
1145 if (!IsHex(str)) {
1146 error = "Raw script is not hex";
1147 return nullptr;
1148 }
1149 auto bytes = ParseHex(str);
1150 return std::make_unique<RawDescriptor>(
1151 CScript(bytes.begin(), bytes.end()));
1152 }
1153 if (ctx == ParseScriptContext::P2SH) {
1154 error = "A function is needed within P2SH";
1155 return nullptr;
1156 }
1157 error = strprintf("%s is not a valid descriptor function",
1158 std::string(expr.begin(), expr.end()));
1159 return nullptr;
1160}
1161
1162std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey &pubkey,
1163 ParseScriptContext,
1164 const SigningProvider &provider) {
1165 std::unique_ptr<PubkeyProvider> key_provider =
1166 std::make_unique<ConstPubkeyProvider>(0, pubkey);
1167 KeyOriginInfo info;
1168 if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
1169 return std::make_unique<OriginPubkeyProvider>(0, std::move(info),
1170 std::move(key_provider));
1171 }
1172 return key_provider;
1173}
1174
1175std::unique_ptr<DescriptorImpl> InferScript(const CScript &script,
1176 ParseScriptContext ctx,
1177 const SigningProvider &provider) {
1178 std::vector<std::vector<uint8_t>> data;
1179 TxoutType txntype = Solver(script, data);
1180
1181 if (txntype == TxoutType::PUBKEY) {
1182 CPubKey pubkey(data[0]);
1183 if (pubkey.IsValid()) {
1184 return std::make_unique<PKDescriptor>(
1185 InferPubkey(pubkey, ctx, provider));
1186 }
1187 }
1188 if (txntype == TxoutType::PUBKEYHASH) {
1189 uint160 hash(data[0]);
1190 CKeyID keyid(hash);
1191 CPubKey pubkey;
1192 if (provider.GetPubKey(keyid, pubkey)) {
1193 return std::make_unique<PKHDescriptor>(
1194 InferPubkey(pubkey, ctx, provider));
1195 }
1196 }
1197 if (txntype == TxoutType::MULTISIG) {
1198 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1199 for (size_t i = 1; i + 1 < data.size(); ++i) {
1200 CPubKey pubkey(data[i]);
1201 providers.push_back(InferPubkey(pubkey, ctx, provider));
1202 }
1203 return std::make_unique<MultisigDescriptor>((int)data[0][0],
1204 std::move(providers));
1205 }
1206 if (txntype == TxoutType::SCRIPTHASH && ctx == ParseScriptContext::TOP) {
1207 uint160 hash(data[0]);
1208 CScriptID scriptid(hash);
1209 CScript subscript;
1210 if (provider.GetCScript(scriptid, subscript)) {
1211 auto sub =
1212 InferScript(subscript, ParseScriptContext::P2SH, provider);
1213 if (sub) {
1214 return std::make_unique<SHDescriptor>(std::move(sub));
1215 }
1216 }
1217 }
1218
1219 CTxDestination dest;
1220 if (ExtractDestination(script, dest)) {
1221 if (GetScriptForDestination(dest) == script) {
1222 return std::make_unique<AddressDescriptor>(std::move(dest));
1223 }
1224 }
1225
1226 return std::make_unique<RawDescriptor>(script);
1227}
1228
1229} // namespace
1230
1234bool CheckChecksum(Span<const char> &sp, bool require_checksum,
1235 std::string &error, std::string *out_checksum = nullptr) {
1236 auto check_split = Split(sp, '#');
1237 if (check_split.size() > 2) {
1238 error = "Multiple '#' symbols";
1239 return false;
1240 }
1241 if (check_split.size() == 1 && require_checksum) {
1242 error = "Missing checksum";
1243 return false;
1244 }
1245 if (check_split.size() == 2) {
1246 if (check_split[1].size() != 8) {
1247 error =
1248 strprintf("Expected 8 character checksum, not %u characters",
1249 check_split[1].size());
1250 return false;
1251 }
1252 }
1253 auto checksum = DescriptorChecksum(check_split[0]);
1254 if (checksum.empty()) {
1255 error = "Invalid characters in payload";
1256 return false;
1257 }
1258 if (check_split.size() == 2) {
1259 if (!std::equal(checksum.begin(), checksum.end(),
1260 check_split[1].begin())) {
1261 error = strprintf(
1262 "Provided checksum '%s' does not match computed checksum '%s'",
1263 std::string(check_split[1].begin(), check_split[1].end()),
1264 checksum);
1265 return false;
1266 }
1267 }
1268 if (out_checksum) {
1269 *out_checksum = std::move(checksum);
1270 }
1271 sp = check_split[0];
1272 return true;
1273}
1274
1275std::unique_ptr<Descriptor> Parse(const std::string &descriptor,
1276 FlatSigningProvider &out, std::string &error,
1277 bool require_checksum) {
1278 Span<const char> sp{descriptor};
1279 if (!CheckChecksum(sp, require_checksum, error)) {
1280 return nullptr;
1281 }
1282 auto ret = ParseScript(0, sp, ParseScriptContext::TOP, out, error);
1283 if (sp.size() == 0 && ret) {
1284 return std::unique_ptr<Descriptor>(std::move(ret));
1285 }
1286 return nullptr;
1287}
1288
1289std::string GetDescriptorChecksum(const std::string &descriptor) {
1290 std::string ret;
1291 std::string error;
1292 Span<const char> sp{descriptor};
1293 if (!CheckChecksum(sp, false, error, &ret)) {
1294 return "";
1295 }
1296 return ret;
1297}
1298
1299std::unique_ptr<Descriptor> InferDescriptor(const CScript &script,
1300 const SigningProvider &provider) {
1301 return InferScript(script, ParseScriptContext::TOP, provider);
1302}
1303
1305 const CExtPubKey &xpub) {
1306 m_parent_xpubs[key_exp_pos] = xpub;
1307}
1308
1310 uint32_t der_index,
1311 const CExtPubKey &xpub) {
1312 auto &xpubs = m_derived_xpubs[key_exp_pos];
1313 xpubs[der_index] = xpub;
1314}
1315
1317 CExtPubKey &xpub) const {
1318 const auto &it = m_parent_xpubs.find(key_exp_pos);
1319 if (it == m_parent_xpubs.end()) {
1320 return false;
1321 }
1322 xpub = it->second;
1323 return true;
1324}
1325
1327 uint32_t der_index,
1328 CExtPubKey &xpub) const {
1329 const auto &key_exp_it = m_derived_xpubs.find(key_exp_pos);
1330 if (key_exp_it == m_derived_xpubs.end()) {
1331 return false;
1332 }
1333 const auto &der_it = key_exp_it->second.find(der_index);
1334 if (der_it == key_exp_it->second.end()) {
1335 return false;
1336 }
1337 xpub = der_it->second;
1338 return true;
1339}
1340
1342 return m_parent_xpubs;
1343}
1344
1345std::unordered_map<uint32_t, ExtPubKeyMap>
1347 return m_derived_xpubs;
1348}
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: addresstype.cpp:33
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: addresstype.h:54
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
Definition: bip32.cpp:55
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:21
An encapsulated secp256k1 private key.
Definition: key.h:28
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:97
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:209
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:22
An encapsulated public key.
Definition: pubkey.h:31
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:137
bool IsValid() const
Definition: pubkey.h:147
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:564
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.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent 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
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 GetPubKey(const CKeyID &address, CPubKey &pubkey) 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:94
constexpr std::size_t size() const noexcept
Definition: span.h:210
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
Definition: span.h:228
constexpr C * begin() const noexcept
Definition: span.h:200
constexpr C * end() const noexcept
Definition: span.h:201
constexpr uint8_t * begin()
Definition: uint256.h:122
160-bit opaque blob.
Definition: uint256.h:184
const Config & GetConfig()
Definition: config.cpp:40
CScript ParseScript(const std::string &s)
Definition: core_read.cpp:59
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
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.
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
Definition: descriptor.h:16
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:30
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
Definition: key_io.cpp:167
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:156
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:118
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:102
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:174
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:77
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:132
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:142
secp256k1_context * ctx
Definition: bench_impl.h:13
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
Definition: parsing.cpp:14
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:23
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
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:36
const char * name
Definition: rest.cpp:46
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:27
static std::string ToString(const CService &ip)
Definition: db.h:36
bool IsSolvable(const SigningProvider &provider, const CScript &script)
Check whether we know how to sign for an output like this, assuming we have all private keys.
Definition: sign.cpp:436
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
Definition: sign.cpp:65
const SigningProvider & DUMMY_SIGNING_PROVIDER
FlatSigningProvider Merge(const FlatSigningProvider &a, const FlatSigningProvider &b)
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: solver.cpp:148
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< uint8_t > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: solver.cpp:93
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: solver.cpp:143
TxoutType
Definition: solver.h:15
Definition: key.h:167
CExtPubKey Neuter() const
Definition: key.cpp:395
bool Derive(CExtKey &out, unsigned int nChild) const
Definition: key.cpp:373
uint8_t nDepth
Definition: key.h:168
CKey key
Definition: key.h:172
ChainCode chaincode
Definition: key.h:171
unsigned int nChild
Definition: key.h:170
uint8_t vchFingerprint[4]
Definition: key.h:169
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:332
CPubKey pubkey
Definition: pubkey.h:198
Interface for parsed descriptor objects.
Definition: descriptor.h:89
virtual std::string ToString() 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 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::vector< uint32_t > path
Definition: keyorigin.h:14
uint8_t fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
Definition: keyorigin.h:13
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1203
template std::vector< std::byte > ParseHex(std::string_view)
bool IsHex(std::string_view str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
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