Bitcoin ABC  0.24.7
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 <config.h>
9 #include <key_io.h>
10 #include <pubkey.h>
11 #include <script/standard.h>
12 #include <span.h>
13 #include <util/bip32.h>
14 #include <util/spanparsing.h>
15 #include <util/strencodings.h>
16 #include <util/system.h>
17 #include <util/vector.h>
18 
19 #include <memory>
20 #include <string>
21 
22 namespace {
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  */
88 uint64_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 
109 std::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 
171 std::string AddChecksum(const std::string &str) {
172  return str + "#" + DescriptorChecksum(str);
173 }
174 
176 // Internal representation //
178 
179 typedef std::vector<uint32_t> KeyPath;
180 
182 struct PubkeyProvider {
183 protected:
187  uint32_t m_expr_index;
188 
189 public:
190  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 
227 class 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 
235 public:
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 
275 class ConstPubkeyProvider final : public PubkeyProvider {
276  CPubKey m_pubkey;
277 
278 public:
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 
310 enum class DeriveType {
311  NO,
312  UNHARDENED,
313  HARDENED,
314 };
315 
317 class 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 
364 public:
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,
372  KeyOriginInfo &final_info_out,
373  const DescriptorCache *read_cache = nullptr,
374  DescriptorCache *write_cache = nullptr) override {
375  // Info of parent of the to be derived pubkey
376  KeyOriginInfo parent_info;
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
385  KeyOriginInfo final_info_out_tmp = parent_info;
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  }
408  final_extkey = parent_extkey;
409  if (m_derive == DeriveType::UNHARDENED) {
410  der = parent_extkey.Derive(final_extkey, pos);
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) {
417  der = parent_extkey.Derive(final_extkey, pos);
418  }
419  } else if (IsHardened()) {
420  CExtKey xprv;
421  if (!GetDerivedExtKey(arg, xprv)) {
422  return false;
423  }
424  parent_extkey = xprv.Neuter();
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  }
437  final_extkey = parent_extkey;
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 
445  final_info_out = final_info_out_tmp;
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,
461  final_extkey);
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 {
495  CExtKey extkey;
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 
511 class DescriptorImpl : public Descriptor {
514  const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
516  const std::string m_name;
517 
518 protected:
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 
547 public:
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 += std::move(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 += std::move(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 
616  bool ToPrivateString(const SigningProvider &arg,
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,
624  const DescriptorCache *read_cache,
625  std::vector<CScript> &output_scripts,
626  FlatSigningProvider &out,
627  DescriptorCache *write_cache) const {
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) {
642  FlatSigningProvider subprovider;
643  if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache,
644  subscripts, subprovider,
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,
679  write_cache);
680  }
681 
682  bool ExpandFromCache(int pos, const DescriptorCache &read_cache,
683  std::vector<CScript> &output_scripts,
684  FlatSigningProvider &out) const final {
685  return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &read_cache,
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) {
699  FlatSigningProvider subprovider;
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 
711 class AddressDescriptor final : public DescriptorImpl {
712  const CTxDestination m_destination;
713 
714 protected:
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 
724 public:
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.which()) {
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 
744 class RawDescriptor final : public DescriptorImpl {
745  const CScript m_script;
746 
747 protected:
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 
755 public:
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.which()) {
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 
776 class PKDescriptor final : public DescriptorImpl {
777 protected:
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 
784 public:
785  PKDescriptor(std::unique_ptr<PubkeyProvider> prov)
786  : DescriptorImpl(Vector(std::move(prov)), {}, "pk") {}
787  bool IsSingleType() const final { return true; }
788 };
789 
791 class PKHDescriptor final : public DescriptorImpl {
792 protected:
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 
801 public:
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 
811 class ComboDescriptor final : public DescriptorImpl {
812 protected:
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 
826 public:
827  ComboDescriptor(std::unique_ptr<PubkeyProvider> prov)
828  : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {}
829  bool IsSingleType() const final { return false; }
830 };
831 
833 class MultisigDescriptor final : public DescriptorImpl {
834  const int m_threshold;
835  const bool m_sorted;
836 
837 protected:
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 
852 public:
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 
863 class SHDescriptor final : public DescriptorImpl {
864 protected:
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 
871 public:
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 
884 enum 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) {
896  Span<const char> elem = split[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 
918 std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
919  const Span<const char> &sp,
920  FlatSigningProvider &out,
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  }
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() == MakeSpan("*").first(1)) {
957  split.pop_back();
958  type = DeriveType::UNHARDENED;
959  } else if (split.back() == MakeSpan("*'").first(2) ||
960  split.back() == MakeSpan("*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 
976 std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index,
977  const Span<const char> &sp,
978  FlatSigningProvider &out,
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) {
988  return ParsePubkeyInner(key_exp_index, origin_split[0], out, error);
989  }
990  if (origin_split[0].empty() || origin_split[0][0] != '[') {
991  error = strprintf("Key origin start '[ character expected but not "
992  "found, got '%c' instead",
993  origin_split[0].empty()
994  ? ']'
995  : origin_split[0][0]);
996  return nullptr;
997  }
998  auto slash_split = Split(origin_split[0].subspan(1), '/');
999  if (slash_split[0].size() != 8) {
1000  error = strprintf("Fingerprint is not 4 bytes (%u characters instead "
1001  "of 8 characters)",
1002  slash_split[0].size());
1003  return nullptr;
1004  }
1005  std::string fpr_hex =
1006  std::string(slash_split[0].begin(), slash_split[0].end());
1007  if (!IsHex(fpr_hex)) {
1008  error = strprintf("Fingerprint '%s' is not hex", fpr_hex);
1009  return nullptr;
1010  }
1011  auto fpr_bytes = ParseHex(fpr_hex);
1012  KeyOriginInfo info;
1013  static_assert(sizeof(info.fingerprint) == 4, "Fingerprint must be 4 bytes");
1014  assert(fpr_bytes.size() == 4);
1015  std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
1016  if (!ParseKeyPath(slash_split, info.path, error)) {
1017  return nullptr;
1018  }
1019  auto provider =
1020  ParsePubkeyInner(key_exp_index, origin_split[1], out, error);
1021  if (!provider) {
1022  return nullptr;
1023  }
1024  return std::make_unique<OriginPubkeyProvider>(
1025  key_exp_index, std::move(info), std::move(provider));
1026 }
1027 
1029 std::unique_ptr<DescriptorImpl> ParseScript(uint32_t key_exp_index,
1030  Span<const char> &sp,
1031  ParseScriptContext ctx,
1032  FlatSigningProvider &out,
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);
1064  uint32_t thres;
1065  std::vector<std::unique_ptr<PubkeyProvider>> providers;
1066  if (!ParseUInt32(std::string(threshold.begin(), threshold.end()),
1067  &thres)) {
1068  error = strprintf(
1069  "Multi threshold '%s' is not valid",
1070  std::string(threshold.begin(), threshold.end()).c_str());
1071  return nullptr;
1072  }
1073  size_t script_size = 0;
1074  while (expr.size()) {
1075  if (!Const(",", expr)) {
1076  error = strprintf("Multi: expected ',', got '%c'", expr[0]);
1077  return nullptr;
1078  }
1079  auto arg = Expr(expr);
1080  auto pk = ParsePubkey(key_exp_index, arg, out, error);
1081  if (!pk) {
1082  return nullptr;
1083  }
1084  script_size += pk->GetSize() + 1;
1085  providers.emplace_back(std::move(pk));
1086  key_exp_index++;
1087  }
1088  if (providers.empty() || providers.size() > 16) {
1089  error = strprintf("Cannot have %u keys in multisig; must have "
1090  "between 1 and 16 keys, inclusive",
1091  providers.size());
1092  return nullptr;
1093  } else if (thres < 1) {
1094  error = strprintf(
1095  "Multisig threshold cannot be %d, must be at least 1", thres);
1096  return nullptr;
1097  } else if (thres > providers.size()) {
1098  error =
1099  strprintf("Multisig threshold cannot be larger than the number "
1100  "of keys; threshold is %d but only %u keys specified",
1101  thres, providers.size());
1102  return nullptr;
1103  }
1104  if (ctx == ParseScriptContext::TOP) {
1105  if (providers.size() > 3) {
1106  error = strprintf("Cannot have %u pubkeys in bare multisig; "
1107  "only at most 3 pubkeys",
1108  providers.size());
1109  return nullptr;
1110  }
1111  }
1112  if (ctx == ParseScriptContext::P2SH) {
1113  if (script_size + 3 > MAX_SCRIPT_ELEMENT_SIZE) {
1114  error = strprintf("P2SH script is too large, %d bytes is "
1115  "larger than %d bytes",
1116  script_size + 3, MAX_SCRIPT_ELEMENT_SIZE);
1117  return nullptr;
1118  }
1119  }
1120  return std::make_unique<MultisigDescriptor>(thres, std::move(providers),
1121  sorted_multi);
1122  }
1123  if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
1124  auto desc = ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
1125  out, error);
1126  if (!desc || expr.size()) {
1127  return nullptr;
1128  }
1129  return std::make_unique<SHDescriptor>(std::move(desc));
1130  } else if (ctx != ParseScriptContext::TOP && Func("sh", expr)) {
1131  error = "Cannot have sh in non-top level";
1132  return nullptr;
1133  }
1134  if (ctx == ParseScriptContext::TOP && Func("addr", expr)) {
1135  CTxDestination dest =
1136  DecodeDestination(std::string(expr.begin(), expr.end()), Params());
1137  if (!IsValidDestination(dest)) {
1138  error = "Address is not valid";
1139  return nullptr;
1140  }
1141  return std::make_unique<AddressDescriptor>(std::move(dest));
1142  }
1143  if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
1144  std::string str(expr.begin(), expr.end());
1145  if (!IsHex(str)) {
1146  error = "Raw script is not hex";
1147  return nullptr;
1148  }
1149  auto bytes = ParseHex(str);
1150  return std::make_unique<RawDescriptor>(
1151  CScript(bytes.begin(), bytes.end()));
1152  }
1153  if (ctx == ParseScriptContext::P2SH) {
1154  error = "A function is needed within P2SH";
1155  return nullptr;
1156  }
1157  error = strprintf("%s is not a valid descriptor function",
1158  std::string(expr.begin(), expr.end()));
1159  return nullptr;
1160 }
1161 
1162 std::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 
1175 std::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].begin(), data[0].end());
1183  if (pubkey.IsValid()) {
1184  return std::make_unique<PKDescriptor>(
1185  InferPubkey(pubkey, ctx, provider));
1186  }
1187  }
1188  if (txntype == TxoutType::PUBKEYHASH) {
1189  uint160 hash(data[0]);
1190  CKeyID keyid(hash);
1191  CPubKey pubkey;
1192  if (provider.GetPubKey(keyid, pubkey)) {
1193  return std::make_unique<PKHDescriptor>(
1194  InferPubkey(pubkey, ctx, provider));
1195  }
1196  }
1197  if (txntype == TxoutType::MULTISIG) {
1198  std::vector<std::unique_ptr<PubkeyProvider>> providers;
1199  for (size_t i = 1; i + 1 < data.size(); ++i) {
1200  CPubKey pubkey(data[i].begin(), data[i].end());
1201  providers.push_back(InferPubkey(pubkey, ctx, provider));
1202  }
1203  return std::make_unique<MultisigDescriptor>((int)data[0][0],
1204  std::move(providers));
1205  }
1206  if (txntype == TxoutType::SCRIPTHASH && ctx == ParseScriptContext::TOP) {
1207  uint160 hash(data[0]);
1208  CScriptID scriptid(hash);
1209  CScript subscript;
1210  if (provider.GetCScript(scriptid, subscript)) {
1211  auto sub =
1212  InferScript(subscript, ParseScriptContext::P2SH, provider);
1213  if (sub) {
1214  return std::make_unique<SHDescriptor>(std::move(sub));
1215  }
1216  }
1217  }
1218 
1219  CTxDestination dest;
1220  if (ExtractDestination(script, dest)) {
1221  if (GetScriptForDestination(dest) == script) {
1222  return std::make_unique<AddressDescriptor>(std::move(dest));
1223  }
1224  }
1225 
1226  return std::make_unique<RawDescriptor>(script);
1227 }
1228 
1229 } // namespace
1230 
1234 bool CheckChecksum(Span<const char> &sp, bool require_checksum,
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  }
1255  auto checksum = DescriptorChecksum(check_split[0]);
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 
1277 std::unique_ptr<Descriptor> Parse(const std::string &descriptor,
1278  FlatSigningProvider &out, std::string &error,
1279  bool require_checksum) {
1280  Span<const char> sp{descriptor};
1281  if (!CheckChecksum(sp, require_checksum, error)) {
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 
1291 std::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 
1301 std::unique_ptr<Descriptor> InferDescriptor(const CScript &script,
1302  const SigningProvider &provider) {
1303  return InferScript(script, ParseScriptContext::TOP, provider);
1304 }
1305 
1306 void DescriptorCache::CacheParentExtPubKey(uint32_t key_exp_pos,
1307  const CExtPubKey &xpub) {
1308  m_parent_xpubs[key_exp_pos] = xpub;
1309 }
1310 
1311 void DescriptorCache::CacheDerivedExtPubKey(uint32_t key_exp_pos,
1312  uint32_t der_index,
1313  const CExtPubKey &xpub) {
1314  auto &xpubs = m_derived_xpubs[key_exp_pos];
1315  xpubs[der_index] = xpub;
1316 }
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 
1329  uint32_t der_index,
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 
1344  return m_parent_xpubs;
1345 }
1346 
1347 const std::unordered_map<uint32_t, ExtPubKeyMap>
1349  return m_derived_xpubs;
1350 }
DescriptorCache::CacheParentExtPubKey
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
Definition: descriptor.cpp:1306
bip32.h
Parse
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
Definition: descriptor.cpp:1277
ToString
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:69
ParseHex
std::vector< uint8_t > ParseHex(const char *psz)
Definition: strencodings.cpp:87
TxoutType
TxoutType
Definition: standard.h:85
key_io.h
DescriptorCache::GetCachedParentExtPubKey
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
Definition: descriptor.cpp:1318
KeyOriginInfo::fingerprint
uint8_t fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
Definition: keyorigin.h:13
OutputType::LEGACY
@ LEGACY
GetScriptForDestination
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:243
CExtKey::Derive
bool Derive(CExtKey &out, unsigned int nChild) const
Definition: key.cpp:374
DescriptorCache::GetCachedParentExtPubKeys
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
Definition: descriptor.cpp:1343
IsHex
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: strencodings.cpp:64
spanparsing::Split
std::vector< Span< const char > > Split(const Span< const char > &sp, char sep)
Split a string on every instance of sep, returning a vector.
Definition: spanparsing.cpp:51
FlatSigningProvider::keys
std::map< CKeyID, CKey > keys
Definition: signingprovider.h:62
SigningProvider
An interface to be implemented by keystores that support signing.
Definition: signingprovider.h:20
NODISCARD
#define NODISCARD
Definition: attributes.h:18
spanparsing::Func
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
Definition: spanparsing.cpp:23
Merge
FlatSigningProvider Merge(const FlatSigningProvider &a, const FlatSigningProvider &b)
Definition: signingprovider.cpp:69
CKeyID
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:22
pubkey.h
chainparams.h
DUMMY_SIGNING_PROVIDER
const SigningProvider & DUMMY_SIGNING_PROVIDER
Definition: signingprovider.cpp:11
CExtPubKey::Derive
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:334
SigningProvider::GetPubKey
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
Definition: signingprovider.h:27
CheckChecksum
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.
Definition: descriptor.cpp:1234
FlatSigningProvider::scripts
std::map< CScriptID, CScript > scripts
Definition: signingprovider.h:59
GetDescriptorChecksum
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
Definition: descriptor.cpp:1291
Span::size
constexpr std::size_t size() const noexcept
Definition: span.h:179
Span
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:83
strencodings.h
TxoutType::PUBKEY
@ PUBKEY
FlatSigningProvider::origins
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
Definition: signingprovider.h:61
IsValidDestination
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:263
ParseScript
CScript ParseScript(const std::string &s)
Definition: core_read.cpp:27
EncodeSecret
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:105
SigningProvider::GetKeyOrigin
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
Definition: signingprovider.h:34
GetScriptForRawPubKey
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:247
CExtKey
Definition: key.h:164
GetScriptForMultisig
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:252
EncodeExtKey
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:159
Solver
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:111
span.h
FormatHDKeypath
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
Definition: bip32.cpp:55
CKey::IsValid
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:94
Span::begin
constexpr C * begin() const noexcept
Definition: span.h:169
standard.h
TxoutType::SCRIPTHASH
@ SCRIPTHASH
spanparsing.h
DecodeSecret
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:80
CExtKey::nChild
unsigned int nChild
Definition: key.h:167
SigningProvider::GetCScript
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
Definition: signingprovider.h:23
FlatSigningProvider::pubkeys
std::map< CKeyID, CPubKey > pubkeys
Definition: signingprovider.h:60
CKey::GetPubKey
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:210
CExtKey::vchFingerprint
uint8_t vchFingerprint[4]
Definition: key.h:166
CExtKey::nDepth
uint8_t nDepth
Definition: key.h:165
spanparsing::Const
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
Definition: spanparsing.cpp:14
CScript
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:430
ExtractDestination
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:161
base_blob::begin
uint8_t * begin()
Definition: uint256.h:83
DescriptorCache
Cache for single descriptor's derived extended pubkeys.
Definition: descriptor.h:19
DecodeExtPubKey
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:121
name
const char * name
Definition: rest.cpp:43
ctx
secp256k1_context * ctx
Definition: bench_multiset.c:12
TxoutType::PUBKEYHASH
@ PUBKEYHASH
system.h
PKHash
Definition: standard.h:106
CExtKey::chaincode
ChainCode chaincode
Definition: key.h:168
DecodeExtKey
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:145
strprintf
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
ExtPubKeyMap
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
Definition: descriptor.h:16
uint160
160-bit opaque blob.
Definition: uint256.h:115
CPubKey
An encapsulated public key.
Definition: pubkey.h:31
ScriptContext::P2SH
@ P2SH
P2SH redeemScript.
DescriptorCache::CacheDerivedExtPubKey
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
Definition: descriptor.cpp:1311
CKey
An encapsulated secp256k1 private key.
Definition: key.h:28
IsSolvable
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:423
DescriptorCache::GetCachedDerivedExtPubKey
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
Definition: descriptor.cpp:1328
Vector
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
Definition: vector.h:21
vector.h
spanparsing::Expr
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
Definition: spanparsing.cpp:33
EncodeDestination
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
Definition: key_io.cpp:170
TxoutType::MULTISIG
@ MULTISIG
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:506
SigningProvider::GetKey
virtual bool GetKey(const CKeyID &address, CKey &key) const
Definition: signingprovider.h:30
Descriptor
Interface for parsed descriptor objects.
Definition: descriptor.h:89
config.h
EncodeExtPubKey
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:135
MAX_SCRIPT_ELEMENT_SIZE
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:23
KeyOriginInfo::path
std::vector< uint32_t > path
Definition: keyorigin.h:14
CPubKey::IsValid
bool IsValid() const
Definition: pubkey.h:152
Span::first
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
Definition: span.h:194
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:48
spanparsing
Definition: spanparsing.cpp:12
CExtPubKey::pubkey
CPubKey pubkey
Definition: pubkey.h:203
ScriptContext::TOP
@ TOP
Top-level scriptPubKey.
InferDescriptor
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
Definition: descriptor.cpp:1301
DescriptorCache::GetCachedDerivedExtPubKeys
const std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
Definition: descriptor.cpp:1348
CExtKey::Neuter
CExtPubKey Neuter() const
Definition: key.cpp:396
CScriptID
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:65
DecodeDestination
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:177
HexStr
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: strencodings.cpp:656
MakeSpan
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
Definition: span.h:229
GetPubKey
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
Definition: sign.cpp:54
GetConfig
const Config & GetConfig()
Definition: config.cpp:34
CExtPubKey
Definition: pubkey.h:198
CExtKey::key
CKey key
Definition: key.h:169
CTxDestination
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:132
Span::end
constexpr C * end() const noexcept
Definition: span.h:170
ScriptHash
Definition: standard.h:114
ParseUInt32
bool ParseUInt32(const std::string &str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
Definition: strencodings.cpp:364
KeyOriginInfo
Definition: keyorigin.h:11
FlatSigningProvider
Definition: signingprovider.h:58
descriptor.h
CPubKey::GetID
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:140