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