Bitcoin Core  0.19.99
P2P Digital Currency
descriptor.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2019 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 <key_io.h>
8 #include <pubkey.h>
9 #include <script/script.h>
10 #include <script/standard.h>
11 
12 #include <span.h>
13 #include <util/bip32.h>
14 #include <util/spanparsing.h>
15 #include <util/system.h>
16 #include <util/strencodings.h>
17 #include <util/vector.h>
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 namespace {
24 
26 // Checksum //
28 
29 // This section implements a checksum algorithm for descriptors with the
30 // following properties:
31 // * Mistakes in a descriptor string are measured in "symbol errors". The higher
32 // the number of symbol errors, the harder it is to detect:
33 // * An error substituting a character from 0123456789()[],'/*abcdefgh@:$%{} 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 detected.
44 // * Any 4 symbol error in a descriptor of up to 507 characters is always detected.
45 // * Any 5 symbol error in a descriptor of up to 77 characters is always detected.
46 // * Is optimized to minimize the chance a 5 symbol error in a descriptor up to 387 characters is undetected
47 // * Random errors have a chance of 1 in 2**40 of being undetected.
48 //
49 // These properties are achieved by expanding every group of 3 (non checksum) characters into
50 // 4 GF(32) symbols, over which a cyclic code is defined.
51 
52 /*
53  * Interprets c as 8 groups of 5 bits which are the coefficients of a degree 8 polynomial over GF(32),
54  * multiplies that polynomial by x, computes its remainder modulo a generator, and adds the constant term val.
55  *
56  * This generator is G(x) = x^8 + {30}x^7 + {23}x^6 + {15}x^5 + {14}x^4 + {10}x^3 + {6}x^2 + {12}x + {9}.
57  * It is chosen to define an cyclic error detecting code which is selected by:
58  * - Starting from all BCH codes over GF(32) of degree 8 and below, which by construction guarantee detecting
59  * 3 errors in windows up to 19000 symbols.
60  * - Taking all those generators, and for degree 7 ones, extend them to degree 8 by adding all degree-1 factors.
61  * - Selecting just the set of generators that guarantee detecting 4 errors in a window of length 512.
62  * - Selecting one of those with best worst-case behavior for 5 errors in windows of length up to 512.
63  *
64  * The generator and the constants to implement it can be verified using this Sage code:
65  * B = GF(2) # Binary field
66  * BP.<b> = B[] # Polynomials over the binary field
67  * F_mod = b**5 + b**3 + 1
68  * F.<f> = GF(32, modulus=F_mod, repr='int') # GF(32) definition
69  * FP.<x> = F[] # Polynomials over GF(32)
70  * E_mod = x**3 + x + F.fetch_int(8)
71  * E.<e> = F.extension(E_mod) # Extension field definition
72  * alpha = e**2743 # Choice of an element in extension field
73  * for p in divisors(E.order() - 1): # Verify alpha has order 32767.
74  * assert((alpha**p == 1) == (p % 32767 == 0))
75  * G = lcm([(alpha**i).minpoly() for i in [1056,1057,1058]] + [x + 1])
76  * print(G) # Print out the generator
77  * for i in [1,2,4,8,16]: # Print out {1,2,4,8,16}*(G mod x^8), packed in hex integers.
78  * v = 0
79  * for coef in reversed((F.fetch_int(i)*(G % x**8)).coefficients(sparse=True)):
80  * v = v*32 + coef.integer_representation()
81  * print("0x%x" % v)
82  */
83 uint64_t PolyMod(uint64_t c, int val)
84 {
85  uint8_t c0 = c >> 35;
86  c = ((c & 0x7ffffffff) << 5) ^ val;
87  if (c0 & 1) c ^= 0xf5dee51989;
88  if (c0 & 2) c ^= 0xa9fdca3312;
89  if (c0 & 4) c ^= 0x1bab10e32d;
90  if (c0 & 8) c ^= 0x3706b1677a;
91  if (c0 & 16) c ^= 0x644d626ffd;
92  return c;
93 }
94 
95 std::string DescriptorChecksum(const Span<const char>& span)
96 {
110  static std::string INPUT_CHARSET =
111  "0123456789()[],'/*abcdefgh@:$%{}"
112  "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
113  "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
114 
116  static std::string CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
117 
118  uint64_t c = 1;
119  int cls = 0;
120  int clscount = 0;
121  for (auto ch : span) {
122  auto pos = INPUT_CHARSET.find(ch);
123  if (pos == std::string::npos) return "";
124  c = PolyMod(c, pos & 31); // Emit a symbol for the position inside the group, for every character.
125  cls = cls * 3 + (pos >> 5); // Accumulate the group numbers
126  if (++clscount == 3) {
127  // Emit an extra symbol representing the group numbers, for every 3 characters.
128  c = PolyMod(c, cls);
129  cls = 0;
130  clscount = 0;
131  }
132  }
133  if (clscount > 0) c = PolyMod(c, cls);
134  for (int j = 0; j < 8; ++j) c = PolyMod(c, 0); // Shift further to determine the checksum.
135  c ^= 1; // Prevent appending zeroes from not affecting the checksum.
136 
137  std::string ret(8, ' ');
138  for (int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
139  return ret;
140 }
141 
142 std::string AddChecksum(const std::string& str) { return str + "#" + DescriptorChecksum(MakeSpan(str)); }
143 
145 // Internal representation //
147 
148 typedef std::vector<uint32_t> KeyPath;
149 
151 struct PubkeyProvider
152 {
153 protected:
156  uint32_t m_expr_index;
157 
158 public:
159  PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
160 
161  virtual ~PubkeyProvider() = default;
162 
168  virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) = 0;
169 
171  virtual bool IsRange() const = 0;
172 
174  virtual size_t GetSize() const = 0;
175 
177  virtual std::string ToString() const = 0;
178 
180  virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
181 
183  virtual bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const = 0;
184 };
185 
186 class OriginPubkeyProvider final : public PubkeyProvider
187 {
188  KeyOriginInfo m_origin;
189  std::unique_ptr<PubkeyProvider> m_provider;
190 
191  std::string OriginString() const
192  {
193  return HexStr(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint)) + FormatHDKeypath(m_origin.path);
194  }
195 
196 public:
197  OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)) {}
198  bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
199  {
200  if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache)) return false;
201  std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.fingerprint);
202  info.path.insert(info.path.begin(), m_origin.path.begin(), m_origin.path.end());
203  return true;
204  }
205  bool IsRange() const override { return m_provider->IsRange(); }
206  size_t GetSize() const override { return m_provider->GetSize(); }
207  std::string ToString() const override { return "[" + OriginString() + "]" + m_provider->ToString(); }
208  bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
209  {
210  std::string sub;
211  if (!m_provider->ToPrivateString(arg, sub)) return false;
212  ret = "[" + OriginString() + "]" + std::move(sub);
213  return true;
214  }
215  bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
216  {
217  return m_provider->GetPrivKey(pos, arg, key);
218  }
219 };
220 
222 class ConstPubkeyProvider final : public PubkeyProvider
223 {
224  CPubKey m_pubkey;
225 
226 public:
227  ConstPubkeyProvider(uint32_t exp_index, const CPubKey& pubkey) : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
228  bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
229  {
230  key = m_pubkey;
231  info.path.clear();
232  CKeyID keyid = m_pubkey.GetID();
233  std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
234  return true;
235  }
236  bool IsRange() const override { return false; }
237  size_t GetSize() const override { return m_pubkey.size(); }
238  std::string ToString() const override { return HexStr(m_pubkey.begin(), m_pubkey.end()); }
239  bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
240  {
241  CKey key;
242  if (!arg.GetKey(m_pubkey.GetID(), key)) return false;
243  ret = EncodeSecret(key);
244  return true;
245  }
246  bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
247  {
248  return arg.GetKey(m_pubkey.GetID(), key);
249  }
250 };
251 
252 enum class DeriveType {
253  NO,
254  UNHARDENED,
255  HARDENED,
256 };
257 
259 class BIP32PubkeyProvider final : public PubkeyProvider
260 {
261  // Root xpub, path, and final derivation step type being used, if any
262  CExtPubKey m_root_extkey;
263  KeyPath m_path;
264  DeriveType m_derive;
265  // Cache of the parent of the final derived pubkeys.
266  // Primarily useful for situations when no read_cache is provided
267  CExtPubKey m_cached_xpub;
268 
269  bool GetExtKey(const SigningProvider& arg, CExtKey& ret) const
270  {
271  CKey key;
272  if (!arg.GetKey(m_root_extkey.pubkey.GetID(), key)) return false;
273  ret.nDepth = m_root_extkey.nDepth;
274  std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint + sizeof(ret.vchFingerprint), ret.vchFingerprint);
275  ret.nChild = m_root_extkey.nChild;
276  ret.chaincode = m_root_extkey.chaincode;
277  ret.key = key;
278  return true;
279  }
280 
281  // Derives the last xprv
282  bool GetDerivedExtKey(const SigningProvider& arg, CExtKey& xprv) const
283  {
284  if (!GetExtKey(arg, xprv)) return false;
285  for (auto entry : m_path) {
286  xprv.Derive(xprv, entry);
287  }
288  return true;
289  }
290 
291  bool IsHardened() const
292  {
293  if (m_derive == DeriveType::HARDENED) return true;
294  for (auto entry : m_path) {
295  if (entry >> 31) return true;
296  }
297  return false;
298  }
299 
300 public:
301  BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
302  bool IsRange() const override { return m_derive != DeriveType::NO; }
303  size_t GetSize() const override { return 33; }
304  bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key_out, KeyOriginInfo& final_info_out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
305  {
306  // Info of parent of the to be derived pubkey
307  KeyOriginInfo parent_info;
308  CKeyID keyid = m_root_extkey.pubkey.GetID();
309  std::copy(keyid.begin(), keyid.begin() + sizeof(parent_info.fingerprint), parent_info.fingerprint);
310  parent_info.path = m_path;
311 
312  // Info of the derived key itself which is copied out upon successful completion
313  KeyOriginInfo final_info_out_tmp = parent_info;
314  if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.path.push_back((uint32_t)pos);
315  if (m_derive == DeriveType::HARDENED) final_info_out_tmp.path.push_back(((uint32_t)pos) | 0x80000000L);
316 
317  // Derive keys or fetch them from cache
318  CExtPubKey final_extkey = m_root_extkey;
319  CExtPubKey parent_extkey = m_root_extkey;
320  bool der = true;
321  if (read_cache) {
322  if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
323  if (m_derive == DeriveType::HARDENED) return false;
324  // Try to get the derivation parent
325  if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey)) return false;
326  final_extkey = parent_extkey;
327  if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
328  }
329  } else if (m_cached_xpub.pubkey.IsValid() && m_derive != DeriveType::HARDENED) {
330  parent_extkey = final_extkey = m_cached_xpub;
331  if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
332  } else if (IsHardened()) {
333  CExtKey xprv;
334  if (!GetDerivedExtKey(arg, xprv)) return false;
335  parent_extkey = xprv.Neuter();
336  if (m_derive == DeriveType::UNHARDENED) der = xprv.Derive(xprv, pos);
337  if (m_derive == DeriveType::HARDENED) der = xprv.Derive(xprv, pos | 0x80000000UL);
338  final_extkey = xprv.Neuter();
339  } else {
340  for (auto entry : m_path) {
341  der = parent_extkey.Derive(parent_extkey, entry);
342  assert(der);
343  }
344  final_extkey = parent_extkey;
345  if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
346  assert(m_derive != DeriveType::HARDENED);
347  }
348  assert(der);
349 
350  final_info_out = final_info_out_tmp;
351  key_out = final_extkey.pubkey;
352 
353  // We rely on the consumer to check that m_derive isn't HARDENED as above
354  // But we can't have already cached something in case we read something from the cache
355  // and parent_extkey isn't actually the parent.
356  if (!m_cached_xpub.pubkey.IsValid()) m_cached_xpub = parent_extkey;
357 
358  if (write_cache) {
359  // Only cache parent if there is any unhardened derivation
360  if (m_derive != DeriveType::HARDENED) {
361  write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
362  } else if (final_info_out.path.size() > 0) {
363  write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
364  }
365  }
366 
367  return true;
368  }
369  std::string ToString() const override
370  {
371  std::string ret = EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path);
372  if (IsRange()) {
373  ret += "/*";
374  if (m_derive == DeriveType::HARDENED) ret += '\'';
375  }
376  return ret;
377  }
378  bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
379  {
380  CExtKey key;
381  if (!GetExtKey(arg, key)) return false;
382  out = EncodeExtKey(key) + FormatHDKeypath(m_path);
383  if (IsRange()) {
384  out += "/*";
385  if (m_derive == DeriveType::HARDENED) out += '\'';
386  }
387  return true;
388  }
389  bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
390  {
391  CExtKey extkey;
392  if (!GetDerivedExtKey(arg, extkey)) return false;
393  if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
394  if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
395  key = extkey.key;
396  return true;
397  }
398 };
399 
401 class DescriptorImpl : public Descriptor
402 {
404  const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
406  const std::string m_name;
407 
408 protected:
412  const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
413 
415  virtual std::string ToStringExtra() const { return ""; }
416 
428  virtual std::vector<CScript> MakeScripts(const std::vector<CPubKey>& pubkeys, const CScript* script, FlatSigningProvider& out) const = 0;
429 
430 public:
431  DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl> script, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_name(name), m_subdescriptor_arg(std::move(script)) {}
432 
433  bool IsSolvable() const override
434  {
435  if (m_subdescriptor_arg) {
436  if (!m_subdescriptor_arg->IsSolvable()) return false;
437  }
438  return true;
439  }
440 
441  bool IsRange() const final
442  {
443  for (const auto& pubkey : m_pubkey_args) {
444  if (pubkey->IsRange()) return true;
445  }
446  if (m_subdescriptor_arg) {
447  if (m_subdescriptor_arg->IsRange()) return true;
448  }
449  return false;
450  }
451 
452  bool ToStringHelper(const SigningProvider* arg, std::string& out, bool priv) const
453  {
454  std::string extra = ToStringExtra();
455  size_t pos = extra.size() > 0 ? 1 : 0;
456  std::string ret = m_name + "(" + extra;
457  for (const auto& pubkey : m_pubkey_args) {
458  if (pos++) ret += ",";
459  std::string tmp;
460  if (priv) {
461  if (!pubkey->ToPrivateString(*arg, tmp)) return false;
462  } else {
463  tmp = pubkey->ToString();
464  }
465  ret += std::move(tmp);
466  }
467  if (m_subdescriptor_arg) {
468  if (pos++) ret += ",";
469  std::string tmp;
470  if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) return false;
471  ret += std::move(tmp);
472  }
473  out = std::move(ret) + ")";
474  return true;
475  }
476 
477  std::string ToString() const final
478  {
479  std::string ret;
480  ToStringHelper(nullptr, ret, false);
481  return AddChecksum(ret);
482  }
483 
484  bool ToPrivateString(const SigningProvider& arg, std::string& out) const override final
485  {
486  bool ret = ToStringHelper(&arg, out, true);
487  out = AddChecksum(out);
488  return ret;
489  }
490 
491  bool ExpandHelper(int pos, const SigningProvider& arg, const DescriptorCache* read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache) const
492  {
493  std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
494  entries.reserve(m_pubkey_args.size());
495 
496  // Construct temporary data in `entries` and `subscripts`, to avoid producing output in case of failure.
497  for (const auto& p : m_pubkey_args) {
498  entries.emplace_back();
499  if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache)) return false;
500  }
501  std::vector<CScript> subscripts;
502  if (m_subdescriptor_arg) {
503  FlatSigningProvider subprovider;
504  if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache, subscripts, subprovider, write_cache)) return false;
505  out = Merge(out, subprovider);
506  }
507 
508  std::vector<CPubKey> pubkeys;
509  pubkeys.reserve(entries.size());
510  for (auto& entry : entries) {
511  pubkeys.push_back(entry.first);
512  out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(CPubKey(entry.first), std::move(entry.second)));
513  }
514  if (m_subdescriptor_arg) {
515  for (const auto& subscript : subscripts) {
516  out.scripts.emplace(CScriptID(subscript), subscript);
517  std::vector<CScript> addscripts = MakeScripts(pubkeys, &subscript, out);
518  for (auto& addscript : addscripts) {
519  output_scripts.push_back(std::move(addscript));
520  }
521  }
522  } else {
523  output_scripts = MakeScripts(pubkeys, nullptr, out);
524  }
525  return true;
526  }
527 
528  bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache = nullptr) const final
529  {
530  return ExpandHelper(pos, provider, nullptr, output_scripts, out, write_cache);
531  }
532 
533  bool ExpandFromCache(int pos, const DescriptorCache& read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const final
534  {
535  return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &read_cache, output_scripts, out, nullptr);
536  }
537 
538  void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const final
539  {
540  for (const auto& p : m_pubkey_args) {
541  CKey key;
542  if (!p->GetPrivKey(pos, provider, key)) continue;
543  out.keys.emplace(key.GetPubKey().GetID(), key);
544  }
545  if (m_subdescriptor_arg) {
546  FlatSigningProvider subprovider;
547  m_subdescriptor_arg->ExpandPrivate(pos, provider, subprovider);
548  out = Merge(out, subprovider);
549  }
550  }
551 
552  Optional<OutputType> GetOutputType() const override { return nullopt; }
553 };
554 
556 class AddressDescriptor final : public DescriptorImpl
557 {
558  const CTxDestination m_destination;
559 protected:
560  std::string ToStringExtra() const override { return EncodeDestination(m_destination); }
561  std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(m_destination)); }
562 public:
563  AddressDescriptor(CTxDestination destination) : DescriptorImpl({}, {}, "addr"), m_destination(std::move(destination)) {}
564  bool IsSolvable() const final { return false; }
565 
566  Optional<OutputType> GetOutputType() const override
567  {
568  switch (m_destination.which()) {
569  case 1 /* PKHash */:
570  case 2 /* ScriptHash */: return OutputType::LEGACY;
571  case 3 /* WitnessV0ScriptHash */:
572  case 4 /* WitnessV0KeyHash */:
573  case 5 /* WitnessUnknown */: return OutputType::BECH32;
574  case 0 /* CNoDestination */:
575  default: return nullopt;
576  }
577  }
578 };
579 
581 class RawDescriptor final : public DescriptorImpl
582 {
583  const CScript m_script;
584 protected:
585  std::string ToStringExtra() const override { return HexStr(m_script.begin(), m_script.end()); }
586  std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Vector(m_script); }
587 public:
588  RawDescriptor(CScript script) : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {}
589  bool IsSolvable() const final { return false; }
590 
591  Optional<OutputType> GetOutputType() const override
592  {
593  CTxDestination dest;
594  ExtractDestination(m_script, dest);
595  switch (dest.which()) {
596  case 1 /* PKHash */:
597  case 2 /* ScriptHash */: return OutputType::LEGACY;
598  case 3 /* WitnessV0ScriptHash */:
599  case 4 /* WitnessV0KeyHash */:
600  case 5 /* WitnessUnknown */: return OutputType::BECH32;
601  case 0 /* CNoDestination */:
602  default: return nullopt;
603  }
604  }
605 };
606 
608 class PKDescriptor final : public DescriptorImpl
609 {
610 protected:
611  std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Vector(GetScriptForRawPubKey(keys[0])); }
612 public:
613  PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pk") {}
614 };
615 
617 class PKHDescriptor final : public DescriptorImpl
618 {
619 protected:
620  std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider& out) const override
621  {
622  CKeyID id = keys[0].GetID();
623  out.pubkeys.emplace(id, keys[0]);
625  }
626 public:
627  PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pkh") {}
628  Optional<OutputType> GetOutputType() const override { return OutputType::LEGACY; }
629 };
630 
632 class WPKHDescriptor final : public DescriptorImpl
633 {
634 protected:
635  std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider& out) const override
636  {
637  CKeyID id = keys[0].GetID();
638  out.pubkeys.emplace(id, keys[0]);
640  }
641 public:
642  WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "wpkh") {}
643  Optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
644 };
645 
647 class ComboDescriptor final : public DescriptorImpl
648 {
649 protected:
650  std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider& out) const override
651  {
652  std::vector<CScript> ret;
653  CKeyID id = keys[0].GetID();
654  out.pubkeys.emplace(id, keys[0]);
655  ret.emplace_back(GetScriptForRawPubKey(keys[0])); // P2PK
656  ret.emplace_back(GetScriptForDestination(PKHash(id))); // P2PKH
657  if (keys[0].IsCompressed()) {
659  out.scripts.emplace(CScriptID(p2wpkh), p2wpkh);
660  ret.emplace_back(p2wpkh);
661  ret.emplace_back(GetScriptForDestination(ScriptHash(p2wpkh))); // P2SH-P2WPKH
662  }
663  return ret;
664  }
665 public:
666  ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {}
667 };
668 
670 class MultisigDescriptor final : public DescriptorImpl
671 {
672  const int m_threshold;
673  const bool m_sorted;
674 protected:
675  std::string ToStringExtra() const override { return strprintf("%i", m_threshold); }
676  std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override {
677  if (m_sorted) {
678  std::vector<CPubKey> sorted_keys(keys);
679  std::sort(sorted_keys.begin(), sorted_keys.end());
680  return Vector(GetScriptForMultisig(m_threshold, sorted_keys));
681  }
682  return Vector(GetScriptForMultisig(m_threshold, keys));
683  }
684 public:
685  MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), {}, sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {}
686 };
687 
689 class SHDescriptor final : public DescriptorImpl
690 {
691 protected:
692  std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(ScriptHash(*script))); }
693 public:
694  SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {}
695 
696  Optional<OutputType> GetOutputType() const override
697  {
698  assert(m_subdescriptor_arg);
699  if (m_subdescriptor_arg->GetOutputType() == OutputType::BECH32) return OutputType::P2SH_SEGWIT;
700  return OutputType::LEGACY;
701  }
702 };
703 
705 class WSHDescriptor final : public DescriptorImpl
706 {
707 protected:
708  std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(WitnessV0ScriptHash(*script))); }
709 public:
710  WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {}
711  Optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
712 };
713 
715 // Parser //
717 
718 enum class ParseScriptContext {
719  TOP,
720  P2SH,
721  P2WSH,
722 };
723 
725 NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error)
726 {
727  for (size_t i = 1; i < split.size(); ++i) {
728  Span<const char> elem = split[i];
729  bool hardened = false;
730  if (elem.size() > 0 && (elem[elem.size() - 1] == '\'' || elem[elem.size() - 1] == 'h')) {
731  elem = elem.first(elem.size() - 1);
732  hardened = true;
733  }
734  uint32_t p;
735  if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p)) {
736  error = strprintf("Key path value '%s' is not a valid uint32", std::string(elem.begin(), elem.end()));
737  return false;
738  } else if (p > 0x7FFFFFFFUL) {
739  error = strprintf("Key path value %u is out of range", p);
740  return false;
741  }
742  out.push_back(p | (((uint32_t)hardened) << 31));
743  }
744  return true;
745 }
746 
748 std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
749 {
750  using namespace spanparsing;
751 
752  auto split = Split(sp, '/');
753  std::string str(split[0].begin(), split[0].end());
754  if (str.size() == 0) {
755  error = "No key provided";
756  return nullptr;
757  }
758  if (split.size() == 1) {
759  if (IsHex(str)) {
760  std::vector<unsigned char> data = ParseHex(str);
761  CPubKey pubkey(data);
762  if (pubkey.IsFullyValid()) {
763  if (permit_uncompressed || pubkey.IsCompressed()) {
764  return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
765  } else {
766  error = "Uncompressed keys are not allowed";
767  return nullptr;
768  }
769  }
770  error = strprintf("Pubkey '%s' is invalid", str);
771  return nullptr;
772  }
773  CKey key = DecodeSecret(str);
774  if (key.IsValid()) {
775  if (permit_uncompressed || key.IsCompressed()) {
776  CPubKey pubkey = key.GetPubKey();
777  out.keys.emplace(pubkey.GetID(), key);
778  return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
779  } else {
780  error = "Uncompressed keys are not allowed";
781  return nullptr;
782  }
783  }
784  }
785  CExtKey extkey = DecodeExtKey(str);
786  CExtPubKey extpubkey = DecodeExtPubKey(str);
787  if (!extkey.key.IsValid() && !extpubkey.pubkey.IsValid()) {
788  error = strprintf("key '%s' is not valid", str);
789  return nullptr;
790  }
791  KeyPath path;
792  DeriveType type = DeriveType::NO;
793  if (split.back() == MakeSpan("*").first(1)) {
794  split.pop_back();
795  type = DeriveType::UNHARDENED;
796  } else if (split.back() == MakeSpan("*'").first(2) || split.back() == MakeSpan("*h").first(2)) {
797  split.pop_back();
798  type = DeriveType::HARDENED;
799  }
800  if (!ParseKeyPath(split, path, error)) return nullptr;
801  if (extkey.key.IsValid()) {
802  extpubkey = extkey.Neuter();
803  out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key);
804  }
805  return MakeUnique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type);
806 }
807 
809 std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index, const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
810 {
811  using namespace spanparsing;
812 
813  auto origin_split = Split(sp, ']');
814  if (origin_split.size() > 2) {
815  error = "Multiple ']' characters found for a single pubkey";
816  return nullptr;
817  }
818  if (origin_split.size() == 1) return ParsePubkeyInner(key_exp_index, origin_split[0], permit_uncompressed, out, error);
819  if (origin_split[0].size() < 1 || origin_split[0][0] != '[') {
820  error = strprintf("Key origin start '[ character expected but not found, got '%c' instead", origin_split[0][0]);
821  return nullptr;
822  }
823  auto slash_split = Split(origin_split[0].subspan(1), '/');
824  if (slash_split[0].size() != 8) {
825  error = strprintf("Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
826  return nullptr;
827  }
828  std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
829  if (!IsHex(fpr_hex)) {
830  error = strprintf("Fingerprint '%s' is not hex", fpr_hex);
831  return nullptr;
832  }
833  auto fpr_bytes = ParseHex(fpr_hex);
834  KeyOriginInfo info;
835  static_assert(sizeof(info.fingerprint) == 4, "Fingerprint must be 4 bytes");
836  assert(fpr_bytes.size() == 4);
837  std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
838  if (!ParseKeyPath(slash_split, info.path, error)) return nullptr;
839  auto provider = ParsePubkeyInner(key_exp_index, origin_split[1], permit_uncompressed, out, error);
840  if (!provider) return nullptr;
841  return MakeUnique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider));
842 }
843 
845 std::unique_ptr<DescriptorImpl> ParseScript(uint32_t key_exp_index, Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
846 {
847  using namespace spanparsing;
848 
849  auto expr = Expr(sp);
850  bool sorted_multi = false;
851  if (Func("pk", expr)) {
852  auto pubkey = ParsePubkey(key_exp_index, expr, ctx != ParseScriptContext::P2WSH, out, error);
853  if (!pubkey) return nullptr;
854  return MakeUnique<PKDescriptor>(std::move(pubkey));
855  }
856  if (Func("pkh", expr)) {
857  auto pubkey = ParsePubkey(key_exp_index, expr, ctx != ParseScriptContext::P2WSH, out, error);
858  if (!pubkey) return nullptr;
859  return MakeUnique<PKHDescriptor>(std::move(pubkey));
860  }
861  if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
862  auto pubkey = ParsePubkey(key_exp_index, expr, true, out, error);
863  if (!pubkey) return nullptr;
864  return MakeUnique<ComboDescriptor>(std::move(pubkey));
865  } else if (ctx != ParseScriptContext::TOP && Func("combo", expr)) {
866  error = "Cannot have combo in non-top level";
867  return nullptr;
868  }
869  if ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr)) {
870  auto threshold = Expr(expr);
871  uint32_t thres;
872  std::vector<std::unique_ptr<PubkeyProvider>> providers;
873  if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
874  error = strprintf("Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
875  return nullptr;
876  }
877  size_t script_size = 0;
878  while (expr.size()) {
879  if (!Const(",", expr)) {
880  error = strprintf("Multi: expected ',', got '%c'", expr[0]);
881  return nullptr;
882  }
883  auto arg = Expr(expr);
884  auto pk = ParsePubkey(key_exp_index, arg, ctx != ParseScriptContext::P2WSH, out, error);
885  if (!pk) return nullptr;
886  script_size += pk->GetSize() + 1;
887  providers.emplace_back(std::move(pk));
888  key_exp_index++;
889  }
890  if (providers.size() < 1 || providers.size() > 16) {
891  error = strprintf("Cannot have %u keys in multisig; must have between 1 and 16 keys, inclusive", providers.size());
892  return nullptr;
893  } else if (thres < 1) {
894  error = strprintf("Multisig threshold cannot be %d, must be at least 1", thres);
895  return nullptr;
896  } else if (thres > providers.size()) {
897  error = strprintf("Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
898  return nullptr;
899  }
900  if (ctx == ParseScriptContext::TOP) {
901  if (providers.size() > 3) {
902  error = strprintf("Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
903  return nullptr;
904  }
905  }
906  if (ctx == ParseScriptContext::P2SH) {
907  if (script_size + 3 > MAX_SCRIPT_ELEMENT_SIZE) {
908  error = strprintf("P2SH script is too large, %d bytes is larger than %d bytes", script_size + 3, MAX_SCRIPT_ELEMENT_SIZE);
909  return nullptr;
910  }
911  }
912  return MakeUnique<MultisigDescriptor>(thres, std::move(providers), sorted_multi);
913  }
914  if (ctx != ParseScriptContext::P2WSH && Func("wpkh", expr)) {
915  auto pubkey = ParsePubkey(key_exp_index, expr, false, out, error);
916  if (!pubkey) return nullptr;
917  return MakeUnique<WPKHDescriptor>(std::move(pubkey));
918  } else if (ctx == ParseScriptContext::P2WSH && Func("wpkh", expr)) {
919  error = "Cannot have wpkh within wsh";
920  return nullptr;
921  }
922  if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
923  auto desc = ParseScript(key_exp_index, expr, ParseScriptContext::P2SH, out, error);
924  if (!desc || expr.size()) return nullptr;
925  return MakeUnique<SHDescriptor>(std::move(desc));
926  } else if (ctx != ParseScriptContext::TOP && Func("sh", expr)) {
927  error = "Cannot have sh in non-top level";
928  return nullptr;
929  }
930  if (ctx != ParseScriptContext::P2WSH && Func("wsh", expr)) {
931  auto desc = ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH, out, error);
932  if (!desc || expr.size()) return nullptr;
933  return MakeUnique<WSHDescriptor>(std::move(desc));
934  } else if (ctx == ParseScriptContext::P2WSH && Func("wsh", expr)) {
935  error = "Cannot have wsh within wsh";
936  return nullptr;
937  }
938  if (ctx == ParseScriptContext::TOP && Func("addr", expr)) {
939  CTxDestination dest = DecodeDestination(std::string(expr.begin(), expr.end()));
940  if (!IsValidDestination(dest)) {
941  error = "Address is not valid";
942  return nullptr;
943  }
944  return MakeUnique<AddressDescriptor>(std::move(dest));
945  }
946  if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
947  std::string str(expr.begin(), expr.end());
948  if (!IsHex(str)) {
949  error = "Raw script is not hex";
950  return nullptr;
951  }
952  auto bytes = ParseHex(str);
953  return MakeUnique<RawDescriptor>(CScript(bytes.begin(), bytes.end()));
954  }
955  if (ctx == ParseScriptContext::P2SH) {
956  error = "A function is needed within P2SH";
957  return nullptr;
958  } else if (ctx == ParseScriptContext::P2WSH) {
959  error = "A function is needed within P2WSH";
960  return nullptr;
961  }
962  error = strprintf("%s is not a valid descriptor function", std::string(expr.begin(), expr.end()));
963  return nullptr;
964 }
965 
966 std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
967 {
968  std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(0, pubkey);
969  KeyOriginInfo info;
970  if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
971  return MakeUnique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
972  }
973  return key_provider;
974 }
975 
976 std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
977 {
978  std::vector<std::vector<unsigned char>> data;
979  txnouttype txntype = Solver(script, data);
980 
981  if (txntype == TX_PUBKEY) {
982  CPubKey pubkey(data[0].begin(), data[0].end());
983  if (pubkey.IsValid()) {
984  return MakeUnique<PKDescriptor>(InferPubkey(pubkey, ctx, provider));
985  }
986  }
987  if (txntype == TX_PUBKEYHASH) {
988  uint160 hash(data[0]);
989  CKeyID keyid(hash);
990  CPubKey pubkey;
991  if (provider.GetPubKey(keyid, pubkey)) {
992  return MakeUnique<PKHDescriptor>(InferPubkey(pubkey, ctx, provider));
993  }
994  }
995  if (txntype == TX_WITNESS_V0_KEYHASH && ctx != ParseScriptContext::P2WSH) {
996  uint160 hash(data[0]);
997  CKeyID keyid(hash);
998  CPubKey pubkey;
999  if (provider.GetPubKey(keyid, pubkey)) {
1000  return MakeUnique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider));
1001  }
1002  }
1003  if (txntype == TX_MULTISIG) {
1004  std::vector<std::unique_ptr<PubkeyProvider>> providers;
1005  for (size_t i = 1; i + 1 < data.size(); ++i) {
1006  CPubKey pubkey(data[i].begin(), data[i].end());
1007  providers.push_back(InferPubkey(pubkey, ctx, provider));
1008  }
1009  return MakeUnique<MultisigDescriptor>((int)data[0][0], std::move(providers));
1010  }
1011  if (txntype == TX_SCRIPTHASH && ctx == ParseScriptContext::TOP) {
1012  uint160 hash(data[0]);
1013  CScriptID scriptid(hash);
1014  CScript subscript;
1015  if (provider.GetCScript(scriptid, subscript)) {
1016  auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
1017  if (sub) return MakeUnique<SHDescriptor>(std::move(sub));
1018  }
1019  }
1020  if (txntype == TX_WITNESS_V0_SCRIPTHASH && ctx != ParseScriptContext::P2WSH) {
1021  CScriptID scriptid;
1022  CRIPEMD160().Write(data[0].data(), data[0].size()).Finalize(scriptid.begin());
1023  CScript subscript;
1024  if (provider.GetCScript(scriptid, subscript)) {
1025  auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
1026  if (sub) return MakeUnique<WSHDescriptor>(std::move(sub));
1027  }
1028  }
1029 
1030  CTxDestination dest;
1031  if (ExtractDestination(script, dest)) {
1032  if (GetScriptForDestination(dest) == script) {
1033  return MakeUnique<AddressDescriptor>(std::move(dest));
1034  }
1035  }
1036 
1037  return MakeUnique<RawDescriptor>(script);
1038 }
1039 
1040 
1041 } // namespace
1042 
1044 bool CheckChecksum(Span<const char>& sp, bool require_checksum, std::string& error, std::string* out_checksum = nullptr)
1045 {
1046  using namespace spanparsing;
1047 
1048  auto check_split = Split(sp, '#');
1049  if (check_split.size() > 2) {
1050  error = "Multiple '#' symbols";
1051  return false;
1052  }
1053  if (check_split.size() == 1 && require_checksum){
1054  error = "Missing checksum";
1055  return false;
1056  }
1057  if (check_split.size() == 2) {
1058  if (check_split[1].size() != 8) {
1059  error = strprintf("Expected 8 character checksum, not %u characters", check_split[1].size());
1060  return false;
1061  }
1062  }
1063  auto checksum = DescriptorChecksum(check_split[0]);
1064  if (checksum.empty()) {
1065  error = "Invalid characters in payload";
1066  return false;
1067  }
1068  if (check_split.size() == 2) {
1069  if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
1070  error = strprintf("Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
1071  return false;
1072  }
1073  }
1074  if (out_checksum) *out_checksum = std::move(checksum);
1075  sp = check_split[0];
1076  return true;
1077 }
1078 
1079 std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum)
1080 {
1081  Span<const char> sp(descriptor.data(), descriptor.size());
1082  if (!CheckChecksum(sp, require_checksum, error)) return nullptr;
1083  auto ret = ParseScript(0, sp, ParseScriptContext::TOP, out, error);
1084  if (sp.size() == 0 && ret) return std::unique_ptr<Descriptor>(std::move(ret));
1085  return nullptr;
1086 }
1087 
1088 std::string GetDescriptorChecksum(const std::string& descriptor)
1089 {
1090  std::string ret;
1091  std::string error;
1092  Span<const char> sp(descriptor.data(), descriptor.size());
1093  if (!CheckChecksum(sp, false, error, &ret)) return "";
1094  return ret;
1095 }
1096 
1097 std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider)
1098 {
1099  return InferScript(script, ParseScriptContext::TOP, provider);
1100 }
1101 
1102 void DescriptorCache::CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub)
1103 {
1104  m_parent_xpubs[key_exp_pos] = xpub;
1105 }
1106 
1107 void DescriptorCache::CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey& xpub)
1108 {
1109  auto& xpubs = m_derived_xpubs[key_exp_pos];
1110  xpubs[der_index] = xpub;
1111 }
1112 
1113 bool DescriptorCache::GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const
1114 {
1115  const auto& it = m_parent_xpubs.find(key_exp_pos);
1116  if (it == m_parent_xpubs.end()) return false;
1117  xpub = it->second;
1118  return true;
1119 }
1120 
1121 bool DescriptorCache::GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey& xpub) const
1122 {
1123  const auto& key_exp_it = m_derived_xpubs.find(key_exp_pos);
1124  if (key_exp_it == m_derived_xpubs.end()) return false;
1125  const auto& der_it = key_exp_it->second.find(der_index);
1126  if (der_it == key_exp_it->second.end()) return false;
1127  xpub = der_it->second;
1128  return true;
1129 }
1130 
1132 {
1133  return m_parent_xpubs;
1134 }
1135 
1136 const std::unordered_map<uint32_t, ExtPubKeyMap> DescriptorCache::GetCachedDerivedExtPubKeys() const
1137 {
1138  return m_derived_xpubs;
1139 }
Top-level scriptPubKey.
constexpr std::ptrdiff_t size() const noexcept
Definition: span.h:33
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.
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
Definition: keyorigin.h:13
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:156
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:30
CKey key
Definition: key.h:149
bool Derive(CExtKey &out, unsigned int nChild) const
Definition: key.cpp:293
DeriveType
Definition: descriptor.cpp:252
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:184
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:186
FlatSigningProvider Merge(const FlatSigningProvider &a, const FlatSigningProvider &b)
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
Definition: key.h:144
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
Definition: spanparsing.cpp:14
std::vector< unsigned char > ParseHex(const char *psz)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:325
unsigned char vchFingerprint[4]
Definition: key.h:146
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:297
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
Definition: bip32.cpp:53
static auto & nullopt
Substitute for C++17 std::nullopt.
Definition: optional.h:24
txnouttype Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: standard.cpp:91
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:58
unsigned char * begin()
Definition: uint256.h:54
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:163
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:155
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
Definition: spanparsing.cpp:32
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
Definition: vector.h:20
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:61
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:208
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:40
unsigned char nDepth
Definition: key.h:145
const SigningProvider & DUMMY_SIGNING_PROVIDER
static secp256k1_context * ctx
Definition: tests.c:46
bool IsValid() const
Definition: pubkey.h:171
An encapsulated public key.
Definition: pubkey.h:30
bool IsHex(const std::string &str)
std::map< CKeyID, CPubKey > pubkeys
unsigned int nChild
Definition: key.h:147
ParseScriptContext
Definition: descriptor.cpp:718
constexpr Span< C > first(std::ptrdiff_t count) const noexcept
Definition: span.h:38
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:96
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:289
ChainCode chaincode
Definition: key.h:148
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)
Definition: sign.cpp:434
CRIPEMD160 & Write(const unsigned char *data, size_t len)
Definition: ripemd160.cpp:247
P2SH redeemScript.
constexpr C * begin() const noexcept
Definition: span.h:29
txnouttype
Definition: standard.h:55
CTxDestination DecodeDestination(const std::string &str)
Definition: key_io.cpp:215
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:271
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:176
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:312
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
Definition: descriptor.h:16
Cache for single descriptor&#39;s derived extended pubkeys.
Definition: descriptor.h:19
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:390
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
Definition: sign.cpp:52
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:20
std::string HexStr(const T itbegin, const T itend)
Definition: strencodings.h:123
160-bit opaque blob.
Definition: uint256.h:109
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:21
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:210
CPubKey pubkey
Definition: pubkey.h:211
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:302
An encapsulated private key.
Definition: key.h:27
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:18
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:14
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:132
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: ripemd160.cpp:273
boost::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:143
CScript ParseScript(const std::string &s)
Definition: core_read.cpp:23
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
auto it
Definition: validation.cpp:361
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:150
std::vector< uint32_t > path
Definition: keyorigin.h:14
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
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:199
Interface for parsed descriptor objects.
Definition: descriptor.h:77
A hasher class for RIPEMD-160.
Definition: ripemd160.h:12
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:93
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:180