Bitcoin ABC 0.32.12
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/standard.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 std::string INPUT_CHARSET = "0123456789()[],'/*abcdefgh@:$%{}"
130 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
131 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
132
134 static std::string CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
135
136 uint64_t c = 1;
137 int cls = 0;
138 int clscount = 0;
139 for (auto ch : span) {
140 auto pos = INPUT_CHARSET.find(ch);
141 if (pos == std::string::npos) {
142 return "";
143 }
144 // Emit a symbol for the position inside the group, for every character.
145 c = PolyMod(c, pos & 31);
146 // Accumulate the group numbers
147 cls = cls * 3 + (pos >> 5);
148 if (++clscount == 3) {
149 // Emit an extra symbol representing the group numbers, for every 3
150 // characters.
151 c = PolyMod(c, cls);
152 cls = 0;
153 clscount = 0;
154 }
155 }
156 if (clscount > 0) {
157 c = PolyMod(c, cls);
158 }
159 for (int j = 0; j < 8; ++j) {
160 // Shift further to determine the checksum.
161 c = PolyMod(c, 0);
162 }
163 // Prevent appending zeroes from not affecting the checksum.
164 c ^= 1;
165
166 std::string ret(8, ' ');
167 for (int j = 0; j < 8; ++j) {
168 ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
169 }
170 return ret;
171}
172
173std::string AddChecksum(const std::string &str) {
174 return str + "#" + DescriptorChecksum(str);
175}
176
178// Internal representation //
180
181typedef std::vector<uint32_t> KeyPath;
182
184struct PubkeyProvider {
185protected:
189 uint32_t m_expr_index;
190
191public:
192 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
193
194 virtual ~PubkeyProvider() = default;
195
203 virtual bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key,
204 KeyOriginInfo &info,
205 const DescriptorCache *read_cache = nullptr,
206 DescriptorCache *write_cache = nullptr) = 0;
207
209 virtual bool IsRange() const = 0;
210
212 virtual size_t GetSize() const = 0;
213
215 virtual std::string ToString() const = 0;
216
221 virtual bool ToPrivateString(const SigningProvider &arg,
222 std::string &out) const = 0;
223
225 virtual bool GetPrivKey(int pos, const SigningProvider &arg,
226 CKey &key) const = 0;
227};
228
229class OriginPubkeyProvider final : public PubkeyProvider {
230 KeyOriginInfo m_origin;
231 std::unique_ptr<PubkeyProvider> m_provider;
232
233 std::string OriginString() const {
234 return HexStr(m_origin.fingerprint) + FormatHDKeypath(m_origin.path);
235 }
236
237public:
238 OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info,
239 std::unique_ptr<PubkeyProvider> provider)
240 : PubkeyProvider(exp_index), m_origin(std::move(info)),
241 m_provider(std::move(provider)) {}
242 bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key,
243 KeyOriginInfo &info,
244 const DescriptorCache *read_cache = nullptr,
245 DescriptorCache *write_cache = nullptr) override {
246 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache,
247 write_cache)) {
248 return false;
249 }
250 std::copy(std::begin(m_origin.fingerprint),
251 std::end(m_origin.fingerprint), info.fingerprint);
252 info.path.insert(info.path.begin(), m_origin.path.begin(),
253 m_origin.path.end());
254 return true;
255 }
256 bool IsRange() const override { return m_provider->IsRange(); }
257 size_t GetSize() const override { return m_provider->GetSize(); }
258 std::string ToString() const override {
259 return "[" + OriginString() + "]" + m_provider->ToString();
260 }
261 bool ToPrivateString(const SigningProvider &arg,
262 std::string &ret) const override {
263 std::string sub;
264 if (!m_provider->ToPrivateString(arg, sub)) {
265 return false;
266 }
267 ret = "[" + OriginString() + "]" + std::move(sub);
268 return true;
269 }
270 bool GetPrivKey(int pos, const SigningProvider &arg,
271 CKey &key) const override {
272 return m_provider->GetPrivKey(pos, arg, key);
273 }
274};
275
277class ConstPubkeyProvider final : public PubkeyProvider {
278 CPubKey m_pubkey;
279
280public:
281 ConstPubkeyProvider(uint32_t exp_index, const CPubKey &pubkey)
282 : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
283 bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key,
284 KeyOriginInfo &info,
285 const DescriptorCache *read_cache = nullptr,
286 DescriptorCache *write_cache = nullptr) override {
287 key = m_pubkey;
288 info.path.clear();
289 CKeyID keyid = m_pubkey.GetID();
290 std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint),
291 info.fingerprint);
292 return true;
293 }
294 bool IsRange() const override { return false; }
295 size_t GetSize() const override { return m_pubkey.size(); }
296 std::string ToString() const override { return HexStr(m_pubkey); }
297 bool ToPrivateString(const SigningProvider &arg,
298 std::string &ret) const override {
299 CKey key;
300 if (!arg.GetKey(m_pubkey.GetID(), key)) {
301 return false;
302 }
303 ret = EncodeSecret(key);
304 return true;
305 }
306 bool GetPrivKey(int pos, const SigningProvider &arg,
307 CKey &key) const override {
308 return arg.GetKey(m_pubkey.GetID(), key);
309 }
310};
311
312enum class DeriveType {
313 NO,
314 UNHARDENED,
315 HARDENED,
316};
317
319class BIP32PubkeyProvider final : public PubkeyProvider {
320 // Root xpub, path, and final derivation step type being used, if any
321 CExtPubKey m_root_extkey;
322 KeyPath m_path;
323 DeriveType m_derive;
324 // Cache of the parent of the final derived pubkeys.
325 // Primarily useful for situations when no read_cache is provided
326 CExtPubKey m_cached_xpub;
327
328 bool GetExtKey(const SigningProvider &arg, CExtKey &ret) const {
329 CKey key;
330 if (!arg.GetKey(m_root_extkey.pubkey.GetID(), key)) {
331 return false;
332 }
333 ret.nDepth = m_root_extkey.nDepth;
334 std::copy(m_root_extkey.vchFingerprint,
335 m_root_extkey.vchFingerprint + sizeof(ret.vchFingerprint),
336 ret.vchFingerprint);
337 ret.nChild = m_root_extkey.nChild;
338 ret.chaincode = m_root_extkey.chaincode;
339 ret.key = key;
340 return true;
341 }
342
343 // Derives the last xprv
344 bool GetDerivedExtKey(const SigningProvider &arg, CExtKey &xprv) const {
345 if (!GetExtKey(arg, xprv)) {
346 return false;
347 }
348 for (auto entry : m_path) {
349 xprv.Derive(xprv, entry);
350 }
351 return true;
352 }
353
354 bool IsHardened() const {
355 if (m_derive == DeriveType::HARDENED) {
356 return true;
357 }
358 for (auto entry : m_path) {
359 if (entry >> 31) {
360 return true;
361 }
362 }
363 return false;
364 }
365
366public:
367 BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey &extkey,
368 KeyPath path, DeriveType derive)
369 : PubkeyProvider(exp_index), m_root_extkey(extkey),
370 m_path(std::move(path)), m_derive(derive) {}
371 bool IsRange() const override { return m_derive != DeriveType::NO; }
372 size_t GetSize() const override { return 33; }
373 bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key_out,
374 KeyOriginInfo &final_info_out,
375 const DescriptorCache *read_cache = nullptr,
376 DescriptorCache *write_cache = nullptr) override {
377 // Info of parent of the to be derived pubkey
378 KeyOriginInfo parent_info;
379 CKeyID keyid = m_root_extkey.pubkey.GetID();
380 std::copy(keyid.begin(),
381 keyid.begin() + sizeof(parent_info.fingerprint),
382 parent_info.fingerprint);
383 parent_info.path = m_path;
384
385 // Info of the derived key itself which is copied out upon successful
386 // completion
387 KeyOriginInfo final_info_out_tmp = parent_info;
388 if (m_derive == DeriveType::UNHARDENED) {
389 final_info_out_tmp.path.push_back((uint32_t)pos);
390 }
391 if (m_derive == DeriveType::HARDENED) {
392 final_info_out_tmp.path.push_back(((uint32_t)pos) | 0x80000000L);
393 }
394
395 // Derive keys or fetch them from cache
396 CExtPubKey final_extkey = m_root_extkey;
397 CExtPubKey parent_extkey = m_root_extkey;
398 bool der = true;
399 if (read_cache) {
400 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos,
401 final_extkey)) {
402 if (m_derive == DeriveType::HARDENED) {
403 return false;
404 }
405 // Try to get the derivation parent
406 if (!read_cache->GetCachedParentExtPubKey(m_expr_index,
407 parent_extkey)) {
408 return false;
409 }
410 final_extkey = parent_extkey;
411 if (m_derive == DeriveType::UNHARDENED) {
412 der = parent_extkey.Derive(final_extkey, pos);
413 }
414 }
415 } else if (m_cached_xpub.pubkey.IsValid() &&
416 m_derive != DeriveType::HARDENED) {
417 parent_extkey = final_extkey = m_cached_xpub;
418 if (m_derive == DeriveType::UNHARDENED) {
419 der = parent_extkey.Derive(final_extkey, pos);
420 }
421 } else if (IsHardened()) {
422 CExtKey xprv;
423 if (!GetDerivedExtKey(arg, xprv)) {
424 return false;
425 }
426 parent_extkey = xprv.Neuter();
427 if (m_derive == DeriveType::UNHARDENED) {
428 der = xprv.Derive(xprv, pos);
429 }
430 if (m_derive == DeriveType::HARDENED) {
431 der = xprv.Derive(xprv, pos | 0x80000000UL);
432 }
433 final_extkey = xprv.Neuter();
434 } else {
435 for (auto entry : m_path) {
436 der = parent_extkey.Derive(parent_extkey, entry);
437 assert(der);
438 }
439 final_extkey = parent_extkey;
440 if (m_derive == DeriveType::UNHARDENED) {
441 der = parent_extkey.Derive(final_extkey, pos);
442 }
443 assert(m_derive != DeriveType::HARDENED);
444 }
445 assert(der);
446
447 final_info_out = final_info_out_tmp;
448 key_out = final_extkey.pubkey;
449
450 // We rely on the consumer to check that m_derive isn't HARDENED as
451 // above But we can't have already cached something in case we read
452 // something from the cache and parent_extkey isn't actually the parent.
453 if (!m_cached_xpub.pubkey.IsValid()) {
454 m_cached_xpub = parent_extkey;
455 }
456
457 if (write_cache) {
458 // Only cache parent if there is any unhardened derivation
459 if (m_derive != DeriveType::HARDENED) {
460 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
461 } else if (final_info_out.path.size() > 0) {
462 write_cache->CacheDerivedExtPubKey(m_expr_index, pos,
463 final_extkey);
464 }
465 }
466
467 return true;
468 }
469 std::string ToString() const override {
470 std::string ret =
471 EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path);
472 if (IsRange()) {
473 ret += "/*";
474 if (m_derive == DeriveType::HARDENED) {
475 ret += '\'';
476 }
477 }
478 return ret;
479 }
480 bool ToPrivateString(const SigningProvider &arg,
481 std::string &out) const override {
482 CExtKey key;
483 if (!GetExtKey(arg, key)) {
484 return false;
485 }
486 out = EncodeExtKey(key) + FormatHDKeypath(m_path);
487 if (IsRange()) {
488 out += "/*";
489 if (m_derive == DeriveType::HARDENED) {
490 out += '\'';
491 }
492 }
493 return true;
494 }
495 bool GetPrivKey(int pos, const SigningProvider &arg,
496 CKey &key) const override {
497 CExtKey extkey;
498 if (!GetDerivedExtKey(arg, extkey)) {
499 return false;
500 }
501 if (m_derive == DeriveType::UNHARDENED) {
502 extkey.Derive(extkey, pos);
503 }
504 if (m_derive == DeriveType::HARDENED) {
505 extkey.Derive(extkey, pos | 0x80000000UL);
506 }
507 key = extkey.key;
508 return true;
509 }
510};
511
513class DescriptorImpl : public Descriptor {
516 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
518 const std::string m_name;
519
520protected:
524 const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
525
528 virtual std::string ToStringExtra() const { return ""; }
529
545 virtual std::vector<CScript>
546 MakeScripts(const std::vector<CPubKey> &pubkeys, const CScript *script,
547 FlatSigningProvider &out) const = 0;
548
549public:
550 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
551 std::unique_ptr<DescriptorImpl> script,
552 const std::string &name)
553 : m_pubkey_args(std::move(pubkeys)), m_name(name),
554 m_subdescriptor_arg(std::move(script)) {}
555
556 bool IsSolvable() const override {
557 if (m_subdescriptor_arg) {
558 if (!m_subdescriptor_arg->IsSolvable()) {
559 return false;
560 }
561 }
562 return true;
563 }
564
565 bool IsRange() const final {
566 for (const auto &pubkey : m_pubkey_args) {
567 if (pubkey->IsRange()) {
568 return true;
569 }
570 }
571 if (m_subdescriptor_arg) {
572 if (m_subdescriptor_arg->IsRange()) {
573 return true;
574 }
575 }
576 return false;
577 }
578
579 bool ToStringHelper(const SigningProvider *arg, std::string &out,
580 bool priv) const {
581 std::string extra = ToStringExtra();
582 size_t pos = extra.size() > 0 ? 1 : 0;
583 std::string ret = m_name + "(" + extra;
584 for (const auto &pubkey : m_pubkey_args) {
585 if (pos++) {
586 ret += ",";
587 }
588 std::string tmp;
589 if (priv) {
590 if (!pubkey->ToPrivateString(*arg, tmp)) {
591 return false;
592 }
593 } else {
594 tmp = pubkey->ToString();
595 }
596 ret += tmp;
597 }
598 if (m_subdescriptor_arg) {
599 if (pos++) {
600 ret += ",";
601 }
602 std::string tmp;
603 if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) {
604 return false;
605 }
606 ret += tmp;
607 }
608 out = std::move(ret) + ")";
609 return true;
610 }
611
612 std::string ToString() const final {
613 std::string ret;
614 ToStringHelper(nullptr, ret, false);
615 return AddChecksum(ret);
616 }
617
618 bool ToPrivateString(const SigningProvider &arg,
619 std::string &out) const final {
620 bool ret = ToStringHelper(&arg, out, true);
621 out = AddChecksum(out);
622 return ret;
623 }
624
625 bool ExpandHelper(int pos, const SigningProvider &arg,
626 const DescriptorCache *read_cache,
627 std::vector<CScript> &output_scripts,
629 DescriptorCache *write_cache) const {
630 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
631 entries.reserve(m_pubkey_args.size());
632
633 // Construct temporary data in `entries` and `subscripts`, to avoid
634 // producing output in case of failure.
635 for (const auto &p : m_pubkey_args) {
636 entries.emplace_back();
637 if (!p->GetPubKey(pos, arg, entries.back().first,
638 entries.back().second, read_cache, write_cache)) {
639 return false;
640 }
641 }
642 std::vector<CScript> subscripts;
643 if (m_subdescriptor_arg) {
644 FlatSigningProvider subprovider;
645 if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache,
646 subscripts, subprovider,
647 write_cache)) {
648 return false;
649 }
650 out = Merge(out, subprovider);
651 }
652
653 std::vector<CPubKey> pubkeys;
654 pubkeys.reserve(entries.size());
655 for (auto &entry : entries) {
656 pubkeys.push_back(entry.first);
657 out.origins.emplace(
658 entry.first.GetID(),
659 std::make_pair<CPubKey, KeyOriginInfo>(
660 CPubKey(entry.first), std::move(entry.second)));
661 }
662 if (m_subdescriptor_arg) {
663 for (const auto &subscript : subscripts) {
664 out.scripts.emplace(CScriptID(subscript), subscript);
665 std::vector<CScript> addscripts =
666 MakeScripts(pubkeys, &subscript, out);
667 for (auto &addscript : addscripts) {
668 output_scripts.push_back(std::move(addscript));
669 }
670 }
671 } else {
672 output_scripts = MakeScripts(pubkeys, nullptr, out);
673 }
674 return true;
675 }
676
677 bool Expand(int pos, const SigningProvider &provider,
678 std::vector<CScript> &output_scripts, FlatSigningProvider &out,
679 DescriptorCache *write_cache = nullptr) const final {
680 return ExpandHelper(pos, provider, nullptr, output_scripts, out,
681 write_cache);
682 }
683
684 bool ExpandFromCache(int pos, const DescriptorCache &read_cache,
685 std::vector<CScript> &output_scripts,
686 FlatSigningProvider &out) const final {
687 return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &read_cache,
688 output_scripts, out, nullptr);
689 }
690
691 void ExpandPrivate(int pos, const SigningProvider &provider,
692 FlatSigningProvider &out) const final {
693 for (const auto &p : m_pubkey_args) {
694 CKey key;
695 if (!p->GetPrivKey(pos, provider, key)) {
696 continue;
697 }
698 out.keys.emplace(key.GetPubKey().GetID(), key);
699 }
700 if (m_subdescriptor_arg) {
701 FlatSigningProvider subprovider;
702 m_subdescriptor_arg->ExpandPrivate(pos, provider, subprovider);
703 out = Merge(out, subprovider);
704 }
705 }
706
707 std::optional<OutputType> GetOutputType() const override {
708 return std::nullopt;
709 }
710};
711
713class AddressDescriptor final : public DescriptorImpl {
714 const CTxDestination m_destination;
715
716protected:
717 std::string ToStringExtra() const override {
718 return EncodeDestination(m_destination, GetConfig());
719 }
720 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &,
721 const CScript *,
722 FlatSigningProvider &) const override {
723 return Vector(GetScriptForDestination(m_destination));
724 }
725
726public:
727 AddressDescriptor(CTxDestination destination)
728 : DescriptorImpl({}, {}, "addr"),
729 m_destination(std::move(destination)) {}
730 bool IsSolvable() const final { return false; }
731
732 std::optional<OutputType> GetOutputType() const override {
733 switch (m_destination.index()) {
734 case 1 /* PKHash */:
735 case 2 /* ScriptHash */:
736 return OutputType::LEGACY;
737 case 0 /* CNoDestination */:
738 default:
739 return std::nullopt;
740 }
741 }
742 bool IsSingleType() const final { return true; }
743};
744
746class RawDescriptor final : public DescriptorImpl {
747 const CScript m_script;
748
749protected:
750 std::string ToStringExtra() const override { return HexStr(m_script); }
751 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &,
752 const CScript *,
753 FlatSigningProvider &) const override {
754 return Vector(m_script);
755 }
756
757public:
758 RawDescriptor(CScript script)
759 : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {}
760 bool IsSolvable() const final { return false; }
761
762 std::optional<OutputType> GetOutputType() const override {
763 CTxDestination dest;
764 ExtractDestination(m_script, dest);
765 switch (dest.index()) {
766 case 1 /* PKHash */:
767 case 2 /* ScriptHash */:
768 return OutputType::LEGACY;
769 case 0 /* CNoDestination */:
770 default:
771 return std::nullopt;
772 }
773 }
774 bool IsSingleType() const final { return true; }
775};
776
778class PKDescriptor final : public DescriptorImpl {
779protected:
780 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
781 const CScript *,
782 FlatSigningProvider &) const override {
783 return Vector(GetScriptForRawPubKey(keys[0]));
784 }
785
786public:
787 PKDescriptor(std::unique_ptr<PubkeyProvider> prov)
788 : DescriptorImpl(Vector(std::move(prov)), {}, "pk") {}
789 bool IsSingleType() const final { return true; }
790};
791
793class PKHDescriptor final : public DescriptorImpl {
794protected:
795 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
796 const CScript *,
797 FlatSigningProvider &out) const override {
798 CKeyID id = keys[0].GetID();
799 out.pubkeys.emplace(id, keys[0]);
801 }
802
803public:
804 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov)
805 : DescriptorImpl(Vector(std::move(prov)), {}, "pkh") {}
806 std::optional<OutputType> GetOutputType() const override {
807 return OutputType::LEGACY;
808 }
809 bool IsSingleType() const final { return true; }
810};
811
813class ComboDescriptor final : public DescriptorImpl {
814protected:
815 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
816 const CScript *,
817 FlatSigningProvider &out) const override {
818 std::vector<CScript> ret;
819 CKeyID id = keys[0].GetID();
820 out.pubkeys.emplace(id, keys[0]);
821 // P2PK
822 ret.emplace_back(GetScriptForRawPubKey(keys[0]));
823 // P2PKH
824 ret.emplace_back(GetScriptForDestination(PKHash(id)));
825 return ret;
826 }
827
828public:
829 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov)
830 : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {}
831 bool IsSingleType() const final { return false; }
832};
833
835class MultisigDescriptor final : public DescriptorImpl {
836 const int m_threshold;
837 const bool m_sorted;
838
839protected:
840 std::string ToStringExtra() const override {
841 return strprintf("%i", m_threshold);
842 }
843 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
844 const CScript *,
845 FlatSigningProvider &) const override {
846 if (m_sorted) {
847 std::vector<CPubKey> sorted_keys(keys);
848 std::sort(sorted_keys.begin(), sorted_keys.end());
849 return Vector(GetScriptForMultisig(m_threshold, sorted_keys));
850 }
851 return Vector(GetScriptForMultisig(m_threshold, keys));
852 }
853
854public:
855 MultisigDescriptor(int threshold,
856 std::vector<std::unique_ptr<PubkeyProvider>> providers,
857 bool sorted = false)
858 : DescriptorImpl(std::move(providers), {},
859 sorted ? "sortedmulti" : "multi"),
860 m_threshold(threshold), m_sorted(sorted) {}
861 bool IsSingleType() const final { return true; }
862};
863
865class SHDescriptor final : public DescriptorImpl {
866protected:
867 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &,
868 const CScript *script,
869 FlatSigningProvider &) const override {
871 }
872
873public:
874 SHDescriptor(std::unique_ptr<DescriptorImpl> desc)
875 : DescriptorImpl({}, std::move(desc), "sh") {}
876 std::optional<OutputType> GetOutputType() const override {
877 return OutputType::LEGACY;
878 }
879 bool IsSingleType() const final { return true; }
880};
881
883// Parser //
885
886enum class ParseScriptContext {
887 TOP,
888 P2SH,
889};
890
895[[nodiscard]] bool ParseKeyPath(const std::vector<Span<const char>> &split,
896 KeyPath &out, std::string &error) {
897 for (size_t i = 1; i < split.size(); ++i) {
898 Span<const char> elem = split[i];
899 bool hardened = false;
900 if (elem.size() > 0 &&
901 (elem[elem.size() - 1] == '\'' || elem[elem.size() - 1] == 'h')) {
902 elem = elem.first(elem.size() - 1);
903 hardened = true;
904 }
905 uint32_t p;
906 if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p)) {
907 error = strprintf("Key path value '%s' is not a valid uint32",
908 std::string(elem.begin(), elem.end()).c_str());
909 return false;
910 } else if (p > 0x7FFFFFFFUL) {
911 error = strprintf("Key path value %u is out of range", p);
912 return false;
913 }
914 out.push_back(p | (uint32_t(hardened) << 31));
915 }
916 return true;
917}
918
920std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
921 const Span<const char> &sp,
923 std::string &error) {
924 auto split = Split(sp, '/');
925 std::string str(split[0].begin(), split[0].end());
926 if (str.size() == 0) {
927 error = "No key provided";
928 return nullptr;
929 }
930 if (split.size() == 1) {
931 if (IsHex(str)) {
932 std::vector<uint8_t> data = ParseHex(str);
933 CPubKey pubkey(data);
934 if (pubkey.IsFullyValid()) {
935 return std::make_unique<ConstPubkeyProvider>(key_exp_index,
936 pubkey);
937 }
938 error = strprintf("Pubkey '%s' is invalid", str);
939 return nullptr;
940 }
941 CKey key = DecodeSecret(str);
942 if (key.IsValid()) {
943 CPubKey pubkey = key.GetPubKey();
944 out.keys.emplace(pubkey.GetID(), key);
945 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey);
946 }
947 }
948 CExtKey extkey = DecodeExtKey(str);
949 CExtPubKey extpubkey = DecodeExtPubKey(str);
950 if (!extkey.key.IsValid() && !extpubkey.pubkey.IsValid()) {
951 error = strprintf("key '%s' is not valid", str);
952 return nullptr;
953 }
954 KeyPath path;
955 DeriveType type = DeriveType::NO;
956 if (split.back() == Span{"*"}.first(1)) {
957 split.pop_back();
958 type = DeriveType::UNHARDENED;
959 } else if (split.back() == Span{"*'"}.first(2) ||
960 split.back() == Span{"*h"}.first(2)) {
961 split.pop_back();
962 type = DeriveType::HARDENED;
963 }
964 if (!ParseKeyPath(split, path, error)) {
965 return nullptr;
966 }
967 if (extkey.key.IsValid()) {
968 extpubkey = extkey.Neuter();
969 out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key);
970 }
971 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey,
972 std::move(path), type);
973}
974
976std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index,
977 const Span<const char> &sp,
979 std::string &error) {
980 auto origin_split = Split(sp, ']');
981 if (origin_split.size() > 2) {
982 error = "Multiple ']' characters found for a single pubkey";
983 return nullptr;
984 }
985 if (origin_split.size() == 1) {
986 return ParsePubkeyInner(key_exp_index, origin_split[0], out, error);
987 }
988 if (origin_split[0].empty() || origin_split[0][0] != '[') {
989 error = strprintf("Key origin start '[ character expected but not "
990 "found, got '%c' instead",
991 origin_split[0].empty()
992 ? ']'
993 : origin_split[0][0]);
994 return nullptr;
995 }
996 auto slash_split = Split(origin_split[0].subspan(1), '/');
997 if (slash_split[0].size() != 8) {
998 error = strprintf("Fingerprint is not 4 bytes (%u characters instead "
999 "of 8 characters)",
1000 slash_split[0].size());
1001 return nullptr;
1002 }
1003 std::string fpr_hex =
1004 std::string(slash_split[0].begin(), slash_split[0].end());
1005 if (!IsHex(fpr_hex)) {
1006 error = strprintf("Fingerprint '%s' is not hex", fpr_hex);
1007 return nullptr;
1008 }
1009 auto fpr_bytes = ParseHex(fpr_hex);
1010 KeyOriginInfo info;
1011 static_assert(sizeof(info.fingerprint) == 4, "Fingerprint must be 4 bytes");
1012 assert(fpr_bytes.size() == 4);
1013 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
1014 if (!ParseKeyPath(slash_split, info.path, error)) {
1015 return nullptr;
1016 }
1017 auto provider =
1018 ParsePubkeyInner(key_exp_index, origin_split[1], out, error);
1019 if (!provider) {
1020 return nullptr;
1021 }
1022 return std::make_unique<OriginPubkeyProvider>(
1023 key_exp_index, std::move(info), std::move(provider));
1024}
1025
1027std::unique_ptr<DescriptorImpl> ParseScript(uint32_t key_exp_index,
1028 Span<const char> &sp,
1029 ParseScriptContext ctx,
1031 std::string &error) {
1032 using namespace script;
1033
1034 auto expr = Expr(sp);
1035 bool sorted_multi = false;
1036 if (Func("pk", expr)) {
1037 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1038 if (!pubkey) {
1039 return nullptr;
1040 }
1041 return std::make_unique<PKDescriptor>(std::move(pubkey));
1042 }
1043 if (Func("pkh", expr)) {
1044 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1045 if (!pubkey) {
1046 return nullptr;
1047 }
1048 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1049 }
1050 if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
1051 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1052 if (!pubkey) {
1053 return nullptr;
1054 }
1055 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1056 } else if (ctx != ParseScriptContext::TOP && Func("combo", expr)) {
1057 error = "Cannot have combo in non-top level";
1058 return nullptr;
1059 }
1060 if ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr)) {
1061 auto threshold = Expr(expr);
1062 uint32_t thres;
1063 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1064 if (!ParseUInt32(std::string(threshold.begin(), threshold.end()),
1065 &thres)) {
1066 error = strprintf(
1067 "Multi threshold '%s' is not valid",
1068 std::string(threshold.begin(), threshold.end()).c_str());
1069 return nullptr;
1070 }
1071 size_t script_size = 0;
1072 while (expr.size()) {
1073 if (!Const(",", expr)) {
1074 error = strprintf("Multi: expected ',', got '%c'", expr[0]);
1075 return nullptr;
1076 }
1077 auto arg = Expr(expr);
1078 auto pk = ParsePubkey(key_exp_index, arg, out, error);
1079 if (!pk) {
1080 return nullptr;
1081 }
1082 script_size += pk->GetSize() + 1;
1083 providers.emplace_back(std::move(pk));
1084 key_exp_index++;
1085 }
1086 if (providers.empty() || providers.size() > 16) {
1087 error = strprintf("Cannot have %u keys in multisig; must have "
1088 "between 1 and 16 keys, inclusive",
1089 providers.size());
1090 return nullptr;
1091 } else if (thres < 1) {
1092 error = strprintf(
1093 "Multisig threshold cannot be %d, must be at least 1", thres);
1094 return nullptr;
1095 } else if (thres > providers.size()) {
1096 error =
1097 strprintf("Multisig threshold cannot be larger than the number "
1098 "of keys; threshold is %d but only %u keys specified",
1099 thres, providers.size());
1100 return nullptr;
1101 }
1102 if (ctx == ParseScriptContext::TOP) {
1103 if (providers.size() > 3) {
1104 error = strprintf("Cannot have %u pubkeys in bare multisig; "
1105 "only at most 3 pubkeys",
1106 providers.size());
1107 return nullptr;
1108 }
1109 }
1110 if (ctx == ParseScriptContext::P2SH) {
1111 if (script_size + 3 > MAX_SCRIPT_ELEMENT_SIZE) {
1112 error = strprintf("P2SH script is too large, %d bytes is "
1113 "larger than %d bytes",
1114 script_size + 3, MAX_SCRIPT_ELEMENT_SIZE);
1115 return nullptr;
1116 }
1117 }
1118 return std::make_unique<MultisigDescriptor>(thres, std::move(providers),
1119 sorted_multi);
1120 }
1121 if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
1122 auto desc = ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
1123 out, error);
1124 if (!desc || expr.size()) {
1125 return nullptr;
1126 }
1127 return std::make_unique<SHDescriptor>(std::move(desc));
1128 } else if (ctx != ParseScriptContext::TOP && Func("sh", expr)) {
1129 error = "Cannot have sh in non-top level";
1130 return nullptr;
1131 }
1132 if (ctx == ParseScriptContext::TOP && Func("addr", expr)) {
1133 CTxDestination dest =
1134 DecodeDestination(std::string(expr.begin(), expr.end()), Params());
1135 if (!IsValidDestination(dest)) {
1136 error = "Address is not valid";
1137 return nullptr;
1138 }
1139 return std::make_unique<AddressDescriptor>(std::move(dest));
1140 }
1141 if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
1142 std::string str(expr.begin(), expr.end());
1143 if (!IsHex(str)) {
1144 error = "Raw script is not hex";
1145 return nullptr;
1146 }
1147 auto bytes = ParseHex(str);
1148 return std::make_unique<RawDescriptor>(
1149 CScript(bytes.begin(), bytes.end()));
1150 }
1151 if (ctx == ParseScriptContext::P2SH) {
1152 error = "A function is needed within P2SH";
1153 return nullptr;
1154 }
1155 error = strprintf("%s is not a valid descriptor function",
1156 std::string(expr.begin(), expr.end()));
1157 return nullptr;
1158}
1159
1160std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey &pubkey,
1161 ParseScriptContext,
1162 const SigningProvider &provider) {
1163 std::unique_ptr<PubkeyProvider> key_provider =
1164 std::make_unique<ConstPubkeyProvider>(0, pubkey);
1165 KeyOriginInfo info;
1166 if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
1167 return std::make_unique<OriginPubkeyProvider>(0, std::move(info),
1168 std::move(key_provider));
1169 }
1170 return key_provider;
1171}
1172
1173std::unique_ptr<DescriptorImpl> InferScript(const CScript &script,
1174 ParseScriptContext ctx,
1175 const SigningProvider &provider) {
1176 std::vector<std::vector<uint8_t>> data;
1177 TxoutType txntype = Solver(script, data);
1178
1179 if (txntype == TxoutType::PUBKEY) {
1180 CPubKey pubkey(data[0]);
1181 if (pubkey.IsValid()) {
1182 return std::make_unique<PKDescriptor>(
1183 InferPubkey(pubkey, ctx, provider));
1184 }
1185 }
1186 if (txntype == TxoutType::PUBKEYHASH) {
1187 uint160 hash(data[0]);
1188 CKeyID keyid(hash);
1189 CPubKey pubkey;
1190 if (provider.GetPubKey(keyid, pubkey)) {
1191 return std::make_unique<PKHDescriptor>(
1192 InferPubkey(pubkey, ctx, provider));
1193 }
1194 }
1195 if (txntype == TxoutType::MULTISIG) {
1196 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1197 for (size_t i = 1; i + 1 < data.size(); ++i) {
1198 CPubKey pubkey(data[i]);
1199 providers.push_back(InferPubkey(pubkey, ctx, provider));
1200 }
1201 return std::make_unique<MultisigDescriptor>((int)data[0][0],
1202 std::move(providers));
1203 }
1204 if (txntype == TxoutType::SCRIPTHASH && ctx == ParseScriptContext::TOP) {
1205 uint160 hash(data[0]);
1206 CScriptID scriptid(hash);
1207 CScript subscript;
1208 if (provider.GetCScript(scriptid, subscript)) {
1209 auto sub =
1210 InferScript(subscript, ParseScriptContext::P2SH, provider);
1211 if (sub) {
1212 return std::make_unique<SHDescriptor>(std::move(sub));
1213 }
1214 }
1215 }
1216
1217 CTxDestination dest;
1218 if (ExtractDestination(script, dest)) {
1219 if (GetScriptForDestination(dest) == script) {
1220 return std::make_unique<AddressDescriptor>(std::move(dest));
1221 }
1222 }
1223
1224 return std::make_unique<RawDescriptor>(script);
1225}
1226
1227} // namespace
1228
1232bool CheckChecksum(Span<const char> &sp, bool require_checksum,
1233 std::string &error, std::string *out_checksum = nullptr) {
1234 auto check_split = Split(sp, '#');
1235 if (check_split.size() > 2) {
1236 error = "Multiple '#' symbols";
1237 return false;
1238 }
1239 if (check_split.size() == 1 && require_checksum) {
1240 error = "Missing checksum";
1241 return false;
1242 }
1243 if (check_split.size() == 2) {
1244 if (check_split[1].size() != 8) {
1245 error =
1246 strprintf("Expected 8 character checksum, not %u characters",
1247 check_split[1].size());
1248 return false;
1249 }
1250 }
1251 auto checksum = DescriptorChecksum(check_split[0]);
1252 if (checksum.empty()) {
1253 error = "Invalid characters in payload";
1254 return false;
1255 }
1256 if (check_split.size() == 2) {
1257 if (!std::equal(checksum.begin(), checksum.end(),
1258 check_split[1].begin())) {
1259 error = strprintf(
1260 "Provided checksum '%s' does not match computed checksum '%s'",
1261 std::string(check_split[1].begin(), check_split[1].end()),
1262 checksum);
1263 return false;
1264 }
1265 }
1266 if (out_checksum) {
1267 *out_checksum = std::move(checksum);
1268 }
1269 sp = check_split[0];
1270 return true;
1271}
1272
1273std::unique_ptr<Descriptor> Parse(const std::string &descriptor,
1274 FlatSigningProvider &out, std::string &error,
1275 bool require_checksum) {
1276 Span<const char> sp{descriptor};
1277 if (!CheckChecksum(sp, require_checksum, error)) {
1278 return nullptr;
1279 }
1280 auto ret = ParseScript(0, sp, ParseScriptContext::TOP, out, error);
1281 if (sp.size() == 0 && ret) {
1282 return std::unique_ptr<Descriptor>(std::move(ret));
1283 }
1284 return nullptr;
1285}
1286
1287std::string GetDescriptorChecksum(const std::string &descriptor) {
1288 std::string ret;
1289 std::string error;
1290 Span<const char> sp{descriptor};
1291 if (!CheckChecksum(sp, false, error, &ret)) {
1292 return "";
1293 }
1294 return ret;
1295}
1296
1297std::unique_ptr<Descriptor> InferDescriptor(const CScript &script,
1298 const SigningProvider &provider) {
1299 return InferScript(script, ParseScriptContext::TOP, provider);
1300}
1301
1303 const CExtPubKey &xpub) {
1304 m_parent_xpubs[key_exp_pos] = xpub;
1305}
1306
1308 uint32_t der_index,
1309 const CExtPubKey &xpub) {
1310 auto &xpubs = m_derived_xpubs[key_exp_pos];
1311 xpubs[der_index] = xpub;
1312}
1313
1315 CExtPubKey &xpub) const {
1316 const auto &it = m_parent_xpubs.find(key_exp_pos);
1317 if (it == m_parent_xpubs.end()) {
1318 return false;
1319 }
1320 xpub = it->second;
1321 return true;
1322}
1323
1325 uint32_t der_index,
1326 CExtPubKey &xpub) const {
1327 const auto &key_exp_it = m_derived_xpubs.find(key_exp_pos);
1328 if (key_exp_it == m_derived_xpubs.end()) {
1329 return false;
1330 }
1331 const auto &der_it = key_exp_it->second.find(der_index);
1332 if (der_it == key_exp_it->second.end()) {
1333 return false;
1334 }
1335 xpub = der_it->second;
1336 return true;
1337}
1338
1340 return m_parent_xpubs;
1341}
1342
1343std::unordered_map<uint32_t, ExtPubKeyMap>
1345 return m_derived_xpubs;
1346}
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 (see script.h)
Definition: standard.h:24
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
uint8_t * begin()
Definition: uint256.h:85
160-bit opaque blob.
Definition: uint256.h:117
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:32
const char * name
Definition: rest.cpp:47
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:25
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:424
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
Definition: sign.cpp:55
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: standard.cpp:249
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< uint8_t > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: standard.cpp:108
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:244
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:260
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:240
TxoutType
Definition: standard.h:38
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:85
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::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
std::map< CKeyID, CPubKey > pubkeys
std::map< CKeyID, CKey > keys
std::map< CScriptID, CScript > scripts
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:1202
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