Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
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/standard.h>
13#include <span.h>
14#include <util/bip32.h>
15#include <util/spanparsing.h>
16#include <util/strencodings.h>
17#include <util/vector.h>
18
19#include <memory>
20#include <string>
21
22namespace {
23
25// Checksum //
27
28// This section implements a checksum algorithm for descriptors with the
29// following properties:
30// * Mistakes in a descriptor string are measured in "symbol errors". The higher
31// the number of symbol errors, the harder it is to detect:
32// * An error substituting a character from 0123456789()[],'/*abcdefgh@:$%{}
33// for
34// another in that set always counts as 1 symbol error.
35// * Note that hex encoded keys are covered by these characters. Xprvs and
36// xpubs use other characters too, but already have their own checksum
37// mechanism.
38// * Function names like "multi()" use other characters, but mistakes in
39// these would generally result in an unparsable descriptor.
40// * A case error always counts as 1 symbol error.
41// * Any other 1 character substitution error counts as 1 or 2 symbol errors.
42// * Any 1 symbol error is always detected.
43// * Any 2 or 3 symbol error in a descriptor of up to 49154 characters is always
44// detected.
45// * Any 4 symbol error in a descriptor of up to 507 characters is always
46// detected.
47// * Any 5 symbol error in a descriptor of up to 77 characters is always
48// detected.
49// * Is optimized to minimize the chance a 5 symbol error in a descriptor up to
50// 387 characters is undetected
51// * Random errors have a chance of 1 in 2**40 of being undetected.
52//
53// These properties are achieved by expanding every group of 3 (non checksum)
54// characters into 4 GF(32) symbols, over which a cyclic code is defined.
55
56/*
57 * Interprets c as 8 groups of 5 bits which are the coefficients of a degree 8
58 * polynomial over GF(32), multiplies that polynomial by x, computes its
59 * remainder modulo a generator, and adds the constant term val.
60 *
61 * This generator is G(x) = x^8 + {30}x^7 + {23}x^6 + {15}x^5 + {14}x^4 +
62 * {10}x^3 + {6}x^2 + {12}x + {9}. It is chosen to define an cyclic error
63 * detecting code which is selected by:
64 * - Starting from all BCH codes over GF(32) of degree 8 and below, which by
65 * construction guarantee detecting 3 errors in windows up to 19000 symbols.
66 * - Taking all those generators, and for degree 7 ones, extend them to degree 8
67 * by adding all degree-1 factors.
68 * - Selecting just the set of generators that guarantee detecting 4 errors in a
69 * window of length 512.
70 * - Selecting one of those with best worst-case behavior for 5 errors in
71 * windows of length up to 512.
72 *
73 * The generator and the constants to implement it can be verified using this
74 * Sage code: B = GF(2) # Binary field BP.<b> = B[] # Polynomials over the
75 * binary field F_mod = b**5 + b**3 + 1 F.<f> = GF(32, modulus=F_mod,
76 * repr='int') # GF(32) definition FP.<x> = F[] # Polynomials over GF(32) E_mod
77 * = x**3 + x + F.fetch_int(8) E.<e> = F.extension(E_mod) # Extension field
78 * definition alpha = e**2743 # Choice of an element in extension field for p in
79 * divisors(E.order() - 1): # Verify alpha has order 32767. assert((alpha**p ==
80 * 1) == (p % 32767 == 0)) G = lcm([(alpha**i).minpoly() for i in
81 * [1056,1057,1058]] + [x + 1]) print(G) # Print out the generator for i in
82 * [1,2,4,8,16]: # Print out {1,2,4,8,16}*(G mod x^8), packed in hex integers.
83 * v = 0
84 * for coef in reversed((F.fetch_int(i)*(G %
85 * x**8)).coefficients(sparse=True)): v = v*32 + coef.integer_representation()
86 * print("0x%x" % v)
87 */
88uint64_t PolyMod(uint64_t c, int val) {
89 uint8_t c0 = c >> 35;
90 c = ((c & 0x7ffffffff) << 5) ^ val;
91 if (c0 & 1) {
92 c ^= 0xf5dee51989;
93 }
94 if (c0 & 2) {
95 c ^= 0xa9fdca3312;
96 }
97 if (c0 & 4) {
98 c ^= 0x1bab10e32d;
99 }
100 if (c0 & 8) {
101 c ^= 0x3706b1677a;
102 }
103 if (c0 & 16) {
104 c ^= 0x644d626ffd;
105 }
106 return c;
107}
108
109std::string DescriptorChecksum(const Span<const char> &span) {
127 static std::string INPUT_CHARSET = "0123456789()[],'/*abcdefgh@:$%{}"
128 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
129 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
130
132 static std::string CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
133
134 uint64_t c = 1;
135 int cls = 0;
136 int clscount = 0;
137 for (auto ch : span) {
138 auto pos = INPUT_CHARSET.find(ch);
139 if (pos == std::string::npos) {
140 return "";
141 }
142 // Emit a symbol for the position inside the group, for every character.
143 c = PolyMod(c, pos & 31);
144 // Accumulate the group numbers
145 cls = cls * 3 + (pos >> 5);
146 if (++clscount == 3) {
147 // Emit an extra symbol representing the group numbers, for every 3
148 // characters.
149 c = PolyMod(c, cls);
150 cls = 0;
151 clscount = 0;
152 }
153 }
154 if (clscount > 0) {
155 c = PolyMod(c, cls);
156 }
157 for (int j = 0; j < 8; ++j) {
158 // Shift further to determine the checksum.
159 c = PolyMod(c, 0);
160 }
161 // Prevent appending zeroes from not affecting the checksum.
162 c ^= 1;
163
164 std::string ret(8, ' ');
165 for (int j = 0; j < 8; ++j) {
166 ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
167 }
168 return ret;
169}
170
171std::string AddChecksum(const std::string &str) {
172 return str + "#" + DescriptorChecksum(str);
173}
174
176// Internal representation //
178
179typedef std::vector<uint32_t> KeyPath;
180
182struct PubkeyProvider {
183protected:
187 uint32_t m_expr_index;
188
189public:
190 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
191
192 virtual ~PubkeyProvider() = default;
193
201 virtual bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key,
202 KeyOriginInfo &info,
203 const DescriptorCache *read_cache = nullptr,
204 DescriptorCache *write_cache = nullptr) = 0;
205
207 virtual bool IsRange() const = 0;
208
210 virtual size_t GetSize() const = 0;
211
213 virtual std::string ToString() const = 0;
214
219 virtual bool ToPrivateString(const SigningProvider &arg,
220 std::string &out) const = 0;
221
223 virtual bool GetPrivKey(int pos, const SigningProvider &arg,
224 CKey &key) const = 0;
225};
226
227class OriginPubkeyProvider final : public PubkeyProvider {
228 KeyOriginInfo m_origin;
229 std::unique_ptr<PubkeyProvider> m_provider;
230
231 std::string OriginString() const {
232 return HexStr(m_origin.fingerprint) + FormatHDKeypath(m_origin.path);
233 }
234
235public:
236 OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info,
237 std::unique_ptr<PubkeyProvider> provider)
238 : PubkeyProvider(exp_index), m_origin(std::move(info)),
239 m_provider(std::move(provider)) {}
240 bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key,
241 KeyOriginInfo &info,
242 const DescriptorCache *read_cache = nullptr,
243 DescriptorCache *write_cache = nullptr) override {
244 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache,
245 write_cache)) {
246 return false;
247 }
248 std::copy(std::begin(m_origin.fingerprint),
249 std::end(m_origin.fingerprint), info.fingerprint);
250 info.path.insert(info.path.begin(), m_origin.path.begin(),
251 m_origin.path.end());
252 return true;
253 }
254 bool IsRange() const override { return m_provider->IsRange(); }
255 size_t GetSize() const override { return m_provider->GetSize(); }
256 std::string ToString() const override {
257 return "[" + OriginString() + "]" + m_provider->ToString();
258 }
259 bool ToPrivateString(const SigningProvider &arg,
260 std::string &ret) const override {
261 std::string sub;
262 if (!m_provider->ToPrivateString(arg, sub)) {
263 return false;
264 }
265 ret = "[" + OriginString() + "]" + std::move(sub);
266 return true;
267 }
268 bool GetPrivKey(int pos, const SigningProvider &arg,
269 CKey &key) const override {
270 return m_provider->GetPrivKey(pos, arg, key);
271 }
272};
273
275class ConstPubkeyProvider final : public PubkeyProvider {
276 CPubKey m_pubkey;
277
278public:
279 ConstPubkeyProvider(uint32_t exp_index, const CPubKey &pubkey)
280 : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
281 bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key,
282 KeyOriginInfo &info,
283 const DescriptorCache *read_cache = nullptr,
284 DescriptorCache *write_cache = nullptr) override {
285 key = m_pubkey;
286 info.path.clear();
287 CKeyID keyid = m_pubkey.GetID();
288 std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint),
289 info.fingerprint);
290 return true;
291 }
292 bool IsRange() const override { return false; }
293 size_t GetSize() const override { return m_pubkey.size(); }
294 std::string ToString() const override { return HexStr(m_pubkey); }
295 bool ToPrivateString(const SigningProvider &arg,
296 std::string &ret) const override {
297 CKey key;
298 if (!arg.GetKey(m_pubkey.GetID(), key)) {
299 return false;
300 }
301 ret = EncodeSecret(key);
302 return true;
303 }
304 bool GetPrivKey(int pos, const SigningProvider &arg,
305 CKey &key) const override {
306 return arg.GetKey(m_pubkey.GetID(), key);
307 }
308};
309
310enum class DeriveType {
311 NO,
312 UNHARDENED,
313 HARDENED,
314};
315
317class BIP32PubkeyProvider final : public PubkeyProvider {
318 // Root xpub, path, and final derivation step type being used, if any
319 CExtPubKey m_root_extkey;
320 KeyPath m_path;
321 DeriveType m_derive;
322 // Cache of the parent of the final derived pubkeys.
323 // Primarily useful for situations when no read_cache is provided
324 CExtPubKey m_cached_xpub;
325
326 bool GetExtKey(const SigningProvider &arg, CExtKey &ret) const {
327 CKey key;
328 if (!arg.GetKey(m_root_extkey.pubkey.GetID(), key)) {
329 return false;
330 }
331 ret.nDepth = m_root_extkey.nDepth;
332 std::copy(m_root_extkey.vchFingerprint,
333 m_root_extkey.vchFingerprint + sizeof(ret.vchFingerprint),
334 ret.vchFingerprint);
335 ret.nChild = m_root_extkey.nChild;
336 ret.chaincode = m_root_extkey.chaincode;
337 ret.key = key;
338 return true;
339 }
340
341 // Derives the last xprv
342 bool GetDerivedExtKey(const SigningProvider &arg, CExtKey &xprv) const {
343 if (!GetExtKey(arg, xprv)) {
344 return false;
345 }
346 for (auto entry : m_path) {
347 xprv.Derive(xprv, entry);
348 }
349 return true;
350 }
351
352 bool IsHardened() const {
353 if (m_derive == DeriveType::HARDENED) {
354 return true;
355 }
356 for (auto entry : m_path) {
357 if (entry >> 31) {
358 return true;
359 }
360 }
361 return false;
362 }
363
364public:
365 BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey &extkey,
366 KeyPath path, DeriveType derive)
367 : PubkeyProvider(exp_index), m_root_extkey(extkey),
368 m_path(std::move(path)), m_derive(derive) {}
369 bool IsRange() const override { return m_derive != DeriveType::NO; }
370 size_t GetSize() const override { return 33; }
371 bool GetPubKey(int pos, const SigningProvider &arg, CPubKey &key_out,
373 const DescriptorCache *read_cache = nullptr,
374 DescriptorCache *write_cache = nullptr) override {
375 // Info of parent of the to be derived pubkey
377 CKeyID keyid = m_root_extkey.pubkey.GetID();
378 std::copy(keyid.begin(),
379 keyid.begin() + sizeof(parent_info.fingerprint),
380 parent_info.fingerprint);
381 parent_info.path = m_path;
382
383 // Info of the derived key itself which is copied out upon successful
384 // completion
386 if (m_derive == DeriveType::UNHARDENED) {
387 final_info_out_tmp.path.push_back((uint32_t)pos);
388 }
389 if (m_derive == DeriveType::HARDENED) {
390 final_info_out_tmp.path.push_back(((uint32_t)pos) | 0x80000000L);
391 }
392
393 // Derive keys or fetch them from cache
394 CExtPubKey final_extkey = m_root_extkey;
395 CExtPubKey parent_extkey = m_root_extkey;
396 bool der = true;
397 if (read_cache) {
398 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos,
399 final_extkey)) {
400 if (m_derive == DeriveType::HARDENED) {
401 return false;
402 }
403 // Try to get the derivation parent
404 if (!read_cache->GetCachedParentExtPubKey(m_expr_index,
405 parent_extkey)) {
406 return false;
407 }
409 if (m_derive == DeriveType::UNHARDENED) {
411 }
412 }
413 } else if (m_cached_xpub.pubkey.IsValid() &&
414 m_derive != DeriveType::HARDENED) {
415 parent_extkey = final_extkey = m_cached_xpub;
416 if (m_derive == DeriveType::UNHARDENED) {
418 }
419 } else if (IsHardened()) {
421 if (!GetDerivedExtKey(arg, xprv)) {
422 return false;
423 }
425 if (m_derive == DeriveType::UNHARDENED) {
426 der = xprv.Derive(xprv, pos);
427 }
428 if (m_derive == DeriveType::HARDENED) {
429 der = xprv.Derive(xprv, pos | 0x80000000UL);
430 }
431 final_extkey = xprv.Neuter();
432 } else {
433 for (auto entry : m_path) {
434 der = parent_extkey.Derive(parent_extkey, entry);
435 assert(der);
436 }
438 if (m_derive == DeriveType::UNHARDENED) {
439 der = parent_extkey.Derive(final_extkey, pos);
440 }
441 assert(m_derive != DeriveType::HARDENED);
442 }
443 assert(der);
444
446 key_out = final_extkey.pubkey;
447
448 // We rely on the consumer to check that m_derive isn't HARDENED as
449 // above But we can't have already cached something in case we read
450 // something from the cache and parent_extkey isn't actually the parent.
451 if (!m_cached_xpub.pubkey.IsValid()) {
452 m_cached_xpub = parent_extkey;
453 }
454
455 if (write_cache) {
456 // Only cache parent if there is any unhardened derivation
457 if (m_derive != DeriveType::HARDENED) {
458 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
459 } else if (final_info_out.path.size() > 0) {
460 write_cache->CacheDerivedExtPubKey(m_expr_index, pos,
462 }
463 }
464
465 return true;
466 }
467 std::string ToString() const override {
468 std::string ret =
469 EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path);
470 if (IsRange()) {
471 ret += "/*";
472 if (m_derive == DeriveType::HARDENED) {
473 ret += '\'';
474 }
475 }
476 return ret;
477 }
478 bool ToPrivateString(const SigningProvider &arg,
479 std::string &out) const override {
480 CExtKey key;
481 if (!GetExtKey(arg, key)) {
482 return false;
483 }
484 out = EncodeExtKey(key) + FormatHDKeypath(m_path);
485 if (IsRange()) {
486 out += "/*";
487 if (m_derive == DeriveType::HARDENED) {
488 out += '\'';
489 }
490 }
491 return true;
492 }
493 bool GetPrivKey(int pos, const SigningProvider &arg,
494 CKey &key) const override {
496 if (!GetDerivedExtKey(arg, extkey)) {
497 return false;
498 }
499 if (m_derive == DeriveType::UNHARDENED) {
500 extkey.Derive(extkey, pos);
501 }
502 if (m_derive == DeriveType::HARDENED) {
503 extkey.Derive(extkey, pos | 0x80000000UL);
504 }
505 key = extkey.key;
506 return true;
507 }
508};
509
511class DescriptorImpl : public Descriptor {
514 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
516 const std::string m_name;
517
518protected:
522 const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
523
526 virtual std::string ToStringExtra() const { return ""; }
527
543 virtual std::vector<CScript>
544 MakeScripts(const std::vector<CPubKey> &pubkeys, const CScript *script,
545 FlatSigningProvider &out) const = 0;
546
547public:
548 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
549 std::unique_ptr<DescriptorImpl> script,
550 const std::string &name)
551 : m_pubkey_args(std::move(pubkeys)), m_name(name),
552 m_subdescriptor_arg(std::move(script)) {}
553
554 bool IsSolvable() const override {
555 if (m_subdescriptor_arg) {
556 if (!m_subdescriptor_arg->IsSolvable()) {
557 return false;
558 }
559 }
560 return true;
561 }
562
563 bool IsRange() const final {
564 for (const auto &pubkey : m_pubkey_args) {
565 if (pubkey->IsRange()) {
566 return true;
567 }
568 }
569 if (m_subdescriptor_arg) {
570 if (m_subdescriptor_arg->IsRange()) {
571 return true;
572 }
573 }
574 return false;
575 }
576
577 bool ToStringHelper(const SigningProvider *arg, std::string &out,
578 bool priv) const {
579 std::string extra = ToStringExtra();
580 size_t pos = extra.size() > 0 ? 1 : 0;
581 std::string ret = m_name + "(" + extra;
582 for (const auto &pubkey : m_pubkey_args) {
583 if (pos++) {
584 ret += ",";
585 }
586 std::string tmp;
587 if (priv) {
588 if (!pubkey->ToPrivateString(*arg, tmp)) {
589 return false;
590 }
591 } else {
592 tmp = pubkey->ToString();
593 }
594 ret += tmp;
595 }
596 if (m_subdescriptor_arg) {
597 if (pos++) {
598 ret += ",";
599 }
600 std::string tmp;
601 if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) {
602 return false;
603 }
604 ret += tmp;
605 }
606 out = std::move(ret) + ")";
607 return true;
608 }
609
610 std::string ToString() const final {
611 std::string ret;
612 ToStringHelper(nullptr, ret, false);
613 return AddChecksum(ret);
614 }
615
617 std::string &out) const final {
618 bool ret = ToStringHelper(&arg, out, true);
619 out = AddChecksum(out);
620 return ret;
621 }
622
623 bool ExpandHelper(int pos, const SigningProvider &arg,
625 std::vector<CScript> &output_scripts,
628 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
629 entries.reserve(m_pubkey_args.size());
630
631 // Construct temporary data in `entries` and `subscripts`, to avoid
632 // producing output in case of failure.
633 for (const auto &p : m_pubkey_args) {
634 entries.emplace_back();
635 if (!p->GetPubKey(pos, arg, entries.back().first,
636 entries.back().second, read_cache, write_cache)) {
637 return false;
638 }
639 }
640 std::vector<CScript> subscripts;
641 if (m_subdescriptor_arg) {
643 if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache,
645 write_cache)) {
646 return false;
647 }
648 out = Merge(out, subprovider);
649 }
650
651 std::vector<CPubKey> pubkeys;
652 pubkeys.reserve(entries.size());
653 for (auto &entry : entries) {
654 pubkeys.push_back(entry.first);
655 out.origins.emplace(
656 entry.first.GetID(),
657 std::make_pair<CPubKey, KeyOriginInfo>(
658 CPubKey(entry.first), std::move(entry.second)));
659 }
660 if (m_subdescriptor_arg) {
661 for (const auto &subscript : subscripts) {
662 out.scripts.emplace(CScriptID(subscript), subscript);
663 std::vector<CScript> addscripts =
664 MakeScripts(pubkeys, &subscript, out);
665 for (auto &addscript : addscripts) {
666 output_scripts.push_back(std::move(addscript));
667 }
668 }
669 } else {
670 output_scripts = MakeScripts(pubkeys, nullptr, out);
671 }
672 return true;
673 }
674
675 bool Expand(int pos, const SigningProvider &provider,
676 std::vector<CScript> &output_scripts, FlatSigningProvider &out,
677 DescriptorCache *write_cache = nullptr) const final {
678 return ExpandHelper(pos, provider, nullptr, output_scripts, out,
680 }
681
682 bool ExpandFromCache(int pos, const DescriptorCache &read_cache,
683 std::vector<CScript> &output_scripts,
684 FlatSigningProvider &out) const final {
686 output_scripts, out, nullptr);
687 }
688
689 void ExpandPrivate(int pos, const SigningProvider &provider,
690 FlatSigningProvider &out) const final {
691 for (const auto &p : m_pubkey_args) {
692 CKey key;
693 if (!p->GetPrivKey(pos, provider, key)) {
694 continue;
695 }
696 out.keys.emplace(key.GetPubKey().GetID(), key);
697 }
698 if (m_subdescriptor_arg) {
700 m_subdescriptor_arg->ExpandPrivate(pos, provider, subprovider);
701 out = Merge(out, subprovider);
702 }
703 }
704
705 std::optional<OutputType> GetOutputType() const override {
706 return std::nullopt;
707 }
708};
709
711class AddressDescriptor final : public DescriptorImpl {
712 const CTxDestination m_destination;
713
714protected:
715 std::string ToStringExtra() const override {
716 return EncodeDestination(m_destination, GetConfig());
717 }
718 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &,
719 const CScript *,
720 FlatSigningProvider &) const override {
721 return Vector(GetScriptForDestination(m_destination));
722 }
723
724public:
725 AddressDescriptor(CTxDestination destination)
726 : DescriptorImpl({}, {}, "addr"),
727 m_destination(std::move(destination)) {}
728 bool IsSolvable() const final { return false; }
729
730 std::optional<OutputType> GetOutputType() const override {
731 switch (m_destination.index()) {
732 case 1 /* PKHash */:
733 case 2 /* ScriptHash */:
734 return OutputType::LEGACY;
735 case 0 /* CNoDestination */:
736 default:
737 return std::nullopt;
738 }
739 }
740 bool IsSingleType() const final { return true; }
741};
742
744class RawDescriptor final : public DescriptorImpl {
745 const CScript m_script;
746
747protected:
748 std::string ToStringExtra() const override { return HexStr(m_script); }
749 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &,
750 const CScript *,
751 FlatSigningProvider &) const override {
752 return Vector(m_script);
753 }
754
755public:
756 RawDescriptor(CScript script)
757 : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {}
758 bool IsSolvable() const final { return false; }
759
760 std::optional<OutputType> GetOutputType() const override {
761 CTxDestination dest;
762 ExtractDestination(m_script, dest);
763 switch (dest.index()) {
764 case 1 /* PKHash */:
765 case 2 /* ScriptHash */:
766 return OutputType::LEGACY;
767 case 0 /* CNoDestination */:
768 default:
769 return std::nullopt;
770 }
771 }
772 bool IsSingleType() const final { return true; }
773};
774
776class PKDescriptor final : public DescriptorImpl {
777protected:
778 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
779 const CScript *,
780 FlatSigningProvider &) const override {
781 return Vector(GetScriptForRawPubKey(keys[0]));
782 }
783
784public:
785 PKDescriptor(std::unique_ptr<PubkeyProvider> prov)
786 : DescriptorImpl(Vector(std::move(prov)), {}, "pk") {}
787 bool IsSingleType() const final { return true; }
788};
789
791class PKHDescriptor final : public DescriptorImpl {
792protected:
793 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
794 const CScript *,
795 FlatSigningProvider &out) const override {
796 CKeyID id = keys[0].GetID();
797 out.pubkeys.emplace(id, keys[0]);
799 }
800
801public:
802 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov)
803 : DescriptorImpl(Vector(std::move(prov)), {}, "pkh") {}
804 std::optional<OutputType> GetOutputType() const override {
805 return OutputType::LEGACY;
806 }
807 bool IsSingleType() const final { return true; }
808};
809
811class ComboDescriptor final : public DescriptorImpl {
812protected:
813 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
814 const CScript *,
815 FlatSigningProvider &out) const override {
816 std::vector<CScript> ret;
817 CKeyID id = keys[0].GetID();
818 out.pubkeys.emplace(id, keys[0]);
819 // P2PK
820 ret.emplace_back(GetScriptForRawPubKey(keys[0]));
821 // P2PKH
822 ret.emplace_back(GetScriptForDestination(PKHash(id)));
823 return ret;
824 }
825
826public:
827 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov)
828 : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {}
829 bool IsSingleType() const final { return false; }
830};
831
833class MultisigDescriptor final : public DescriptorImpl {
834 const int m_threshold;
835 const bool m_sorted;
836
837protected:
838 std::string ToStringExtra() const override {
839 return strprintf("%i", m_threshold);
840 }
841 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys,
842 const CScript *,
843 FlatSigningProvider &) const override {
844 if (m_sorted) {
845 std::vector<CPubKey> sorted_keys(keys);
846 std::sort(sorted_keys.begin(), sorted_keys.end());
847 return Vector(GetScriptForMultisig(m_threshold, sorted_keys));
848 }
849 return Vector(GetScriptForMultisig(m_threshold, keys));
850 }
851
852public:
853 MultisigDescriptor(int threshold,
854 std::vector<std::unique_ptr<PubkeyProvider>> providers,
855 bool sorted = false)
856 : DescriptorImpl(std::move(providers), {},
857 sorted ? "sortedmulti" : "multi"),
858 m_threshold(threshold), m_sorted(sorted) {}
859 bool IsSingleType() const final { return true; }
860};
861
863class SHDescriptor final : public DescriptorImpl {
864protected:
865 std::vector<CScript> MakeScripts(const std::vector<CPubKey> &,
866 const CScript *script,
867 FlatSigningProvider &) const override {
868 return Vector(GetScriptForDestination(ScriptHash(*script)));
869 }
870
871public:
872 SHDescriptor(std::unique_ptr<DescriptorImpl> desc)
873 : DescriptorImpl({}, std::move(desc), "sh") {}
874 std::optional<OutputType> GetOutputType() const override {
875 return OutputType::LEGACY;
876 }
877 bool IsSingleType() const final { return true; }
878};
879
881// Parser //
883
884enum class ParseScriptContext {
885 TOP,
886 P2SH,
887};
888
893[[nodiscard]] bool ParseKeyPath(const std::vector<Span<const char>> &split,
894 KeyPath &out, std::string &error) {
895 for (size_t i = 1; i < split.size(); ++i) {
897 bool hardened = false;
898 if (elem.size() > 0 &&
899 (elem[elem.size() - 1] == '\'' || elem[elem.size() - 1] == 'h')) {
900 elem = elem.first(elem.size() - 1);
901 hardened = true;
902 }
903 uint32_t p;
904 if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p)) {
905 error = strprintf("Key path value '%s' is not a valid uint32",
906 std::string(elem.begin(), elem.end()).c_str());
907 return false;
908 } else if (p > 0x7FFFFFFFUL) {
909 error = strprintf("Key path value %u is out of range", p);
910 return false;
911 }
912 out.push_back(p | (uint32_t(hardened) << 31));
913 }
914 return true;
915}
916
918std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
919 const Span<const char> &sp,
921 std::string &error) {
922 using namespace spanparsing;
923
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 }
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 using namespace spanparsing;
981
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) {
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 =
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,
1031 ParseScriptContext ctx,
1033 std::string &error) {
1034 using namespace spanparsing;
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);
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) {
1114 error = strprintf("P2SH script is too large, %d bytes is "
1115 "larger than %d bytes",
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 }
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 }
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);
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
1235 std::string &error, std::string *out_checksum = nullptr) {
1236 using namespace spanparsing;
1237
1238 auto check_split = Split(sp, '#');
1239 if (check_split.size() > 2) {
1240 error = "Multiple '#' symbols";
1241 return false;
1242 }
1243 if (check_split.size() == 1 && require_checksum) {
1244 error = "Missing checksum";
1245 return false;
1246 }
1247 if (check_split.size() == 2) {
1248 if (check_split[1].size() != 8) {
1249 error =
1250 strprintf("Expected 8 character checksum, not %u characters",
1251 check_split[1].size());
1252 return false;
1253 }
1254 }
1256 if (checksum.empty()) {
1257 error = "Invalid characters in payload";
1258 return false;
1259 }
1260 if (check_split.size() == 2) {
1261 if (!std::equal(checksum.begin(), checksum.end(),
1262 check_split[1].begin())) {
1263 error = strprintf(
1264 "Provided checksum '%s' does not match computed checksum '%s'",
1265 std::string(check_split[1].begin(), check_split[1].end()),
1266 checksum);
1267 return false;
1268 }
1269 }
1270 if (out_checksum) {
1271 *out_checksum = std::move(checksum);
1272 }
1273 sp = check_split[0];
1274 return true;
1275}
1276
1277std::unique_ptr<Descriptor> Parse(const std::string &descriptor,
1278 FlatSigningProvider &out, std::string &error,
1279 bool require_checksum) {
1280 Span<const char> sp{descriptor};
1282 return nullptr;
1283 }
1284 auto ret = ParseScript(0, sp, ParseScriptContext::TOP, out, error);
1285 if (sp.size() == 0 && ret) {
1286 return std::unique_ptr<Descriptor>(std::move(ret));
1287 }
1288 return nullptr;
1289}
1290
1291std::string GetDescriptorChecksum(const std::string &descriptor) {
1292 std::string ret;
1293 std::string error;
1294 Span<const char> sp{descriptor};
1295 if (!CheckChecksum(sp, false, error, &ret)) {
1296 return "";
1297 }
1298 return ret;
1299}
1300
1301std::unique_ptr<Descriptor> InferDescriptor(const CScript &script,
1302 const SigningProvider &provider) {
1303 return InferScript(script, ParseScriptContext::TOP, provider);
1304}
1305
1310
1317
1319 CExtPubKey &xpub) const {
1320 const auto &it = m_parent_xpubs.find(key_exp_pos);
1321 if (it == m_parent_xpubs.end()) {
1322 return false;
1323 }
1324 xpub = it->second;
1325 return true;
1326}
1327
1330 CExtPubKey &xpub) const {
1331 const auto &key_exp_it = m_derived_xpubs.find(key_exp_pos);
1332 if (key_exp_it == m_derived_xpubs.end()) {
1333 return false;
1334 }
1335 const auto &der_it = key_exp_it->second.find(der_index);
1336 if (der_it == key_exp_it->second.end()) {
1337 return false;
1338 }
1339 xpub = der_it->second;
1340 return true;
1341}
1342
1346
1347const std::unordered_map<uint32_t, ExtPubKeyMap>
@ P2SH
P2SH redeemScript.
@ TOP
Top-level scriptPubKey.
secp256k1_context * ctx
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
Definition bip32.cpp:55
const CChainParams & Params()
Return the currently selected parameters.
An encapsulated secp256k1 private key.
Definition key.h:28
bool IsValid() const
Check whether this private key is valid.
Definition key.h:94
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition key.cpp:210
bool Derive(CKey &keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child key.
Definition key.cpp:352
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
Serialized script, used inside transaction inputs and outputs.
Definition script.h:431
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.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
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
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
const std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
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 GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
A Span is an object that can refer to a contiguous sequence of objects.
Definition span.h:93
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
Definition span.h:227
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:60
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 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
bool error(const char *fmt, const Args &...args)
Definition logging.h:226
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
std::vector< T > Split(const Span< const char > &sp, char sep)
Split a string on every instance of sep, returning a vector.
Definition spanparsing.h:52
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition rcu.h:257
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
const char * name
Definition rest.cpp:47
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition script.h:24
static std::string ToString(const CService &ip)
Definition db.h:37
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
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::vector< uint8_t > ParseHex(const char *psz)
bool ParseUInt32(const std::string &str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
bool IsHex(const std::string &str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
Definition key.h:164
CExtPubKey Neuter() const
Definition key.cpp:396
bool Derive(CExtKey &out, unsigned int nChild) const
Definition key.cpp:374
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition pubkey.cpp:333
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...
assert(!tx.IsCoinBase())
std::vector< typename std::common_type< Args... >::type > Vector(Args &&...args)
Construct a vector with the specified elements.
Definition vector.h:21