PIVX Core  5.6.99
P2P Digital Currency
descriptor.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018 The Bitcoin Core developers
2 // Copyright (c) 2022 The PIVX Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <script/descriptor.h>
7 
8 #include <key_io.h>
9 #include <pubkey.h>
10 #include <script/script.h>
11 #include <script/standard.h>
12 
13 #include <span.h>
14 #include <util/system.h>
15 #include <utilstrencodings.h>
16 
17 #include <memory>
18 #include <string>
19 #include <vector>
20 
21 namespace {
22 
24 // Internal representation //
26 
27 typedef std::vector<uint32_t> KeyPath;
28 
29 std::string FormatKeyPath(const KeyPath& path)
30 {
31  std::string ret;
32  for (auto i : path) {
33  ret += strprintf("/%i", (i << 1) >> 1);
34  if (i >> 31) ret += '\'';
35  }
36  return ret;
37 }
38 
40 struct PubkeyProvider
41 {
42  virtual ~PubkeyProvider() = default;
43 
45  virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const = 0;
46 
48  virtual bool IsRange() const = 0;
49 
51  virtual size_t GetSize() const = 0;
52 
54  virtual std::string ToString() const = 0;
55 
57  virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
58 };
59 
61 class ConstPubkeyProvider final : public PubkeyProvider
62 {
63  CPubKey m_pubkey;
64 
65 public:
66  explicit ConstPubkeyProvider(const CPubKey& pubkey) : m_pubkey(pubkey) {}
67  bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const override
68  {
69  out = m_pubkey;
70  return true;
71  }
72  bool IsRange() const override { return false; }
73  size_t GetSize() const override { return m_pubkey.size(); }
74  std::string ToString() const override { return HexStr(m_pubkey); }
75  bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
76  {
77  CKey key;
78  if (!arg.GetKey(m_pubkey.GetID(), key)) return false;
79  ret = KeyIO::EncodeSecret(key);
80  return true;
81  }
82 };
83 
84 enum class DeriveType {
85  NO,
86  UNHARDENED,
87  HARDENED,
88 };
89 
91 class BIP32PubkeyProvider final : public PubkeyProvider
92 {
93  CExtPubKey m_extkey;
94  KeyPath m_path;
95  DeriveType m_derive;
96 
97  bool GetExtKey(const SigningProvider& arg, CExtKey& ret) const
98  {
99  CKey key;
100  if (!arg.GetKey(m_extkey.pubkey.GetID(), key)) return false;
101  ret.nDepth = m_extkey.nDepth;
102  std::copy(m_extkey.vchFingerprint, m_extkey.vchFingerprint + 4, ret.vchFingerprint);
103  ret.nChild = m_extkey.nChild;
104  ret.chaincode = m_extkey.chaincode;
105  ret.key = key;
106  return true;
107  }
108 
109  bool IsHardened() const
110  {
111  if (m_derive == DeriveType::HARDENED) return true;
112  for (auto entry : m_path) {
113  if (entry >> 31) return true;
114  }
115  return false;
116  }
117 
118 public:
119  BIP32PubkeyProvider(const CExtPubKey& extkey, KeyPath path, DeriveType derive) : m_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
120  bool IsRange() const override { return m_derive != DeriveType::NO; }
121  size_t GetSize() const override { return 33; }
122  bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const override
123  {
124  if (IsHardened()) {
125  CExtKey key;
126  if (!GetExtKey(arg, key)) return false;
127  for (auto entry : m_path) {
128  key.Derive(key, entry);
129  }
130  if (m_derive == DeriveType::UNHARDENED) key.Derive(key, pos);
131  if (m_derive == DeriveType::HARDENED) key.Derive(key, pos | 0x80000000UL);
132  out = key.Neuter().pubkey;
133  } else {
134  // TODO: optimize by caching
135  CExtPubKey key = m_extkey;
136  for (auto entry : m_path) {
137  key.Derive(key, entry);
138  }
139  if (m_derive == DeriveType::UNHARDENED) key.Derive(key, pos);
140  assert(m_derive != DeriveType::HARDENED);
141  out = key.pubkey;
142  }
143  return true;
144  }
145  std::string ToString() const override
146  {
147  std::string ret = KeyIO::EncodeExtPubKey(m_extkey) + FormatKeyPath(m_path);
148  if (IsRange()) {
149  ret += "/*";
150  if (m_derive == DeriveType::HARDENED) ret += '\'';
151  }
152  return ret;
153  }
154  bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
155  {
156  CExtKey key;
157  if (!GetExtKey(arg, key)) return false;
158  out = KeyIO::EncodeExtKey(key) + FormatKeyPath(m_path);
159  if (IsRange()) {
160  out += "/*";
161  if (m_derive == DeriveType::HARDENED) out += '\'';
162  }
163  return true;
164  }
165 };
166 
168 class AddressDescriptor final : public Descriptor
169 {
170  CTxDestination m_destination;
171 
172 public:
173  explicit AddressDescriptor(CTxDestination destination) : m_destination(std::move(destination)) {}
174 
175  bool IsRange() const override { return false; }
176  std::string ToString() const override { return "addr(" + EncodeDestination(m_destination) + ")"; }
177  bool ToPrivateString(const SigningProvider& arg, std::string& out) const override { out = ToString(); return true; }
178  bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
179  {
180  output_scripts = std::vector<CScript>{GetScriptForDestination(m_destination)};
181  return true;
182  }
183 };
184 
186 class RawDescriptor final : public Descriptor
187 {
188  CScript m_script;
189 
190 public:
191  explicit RawDescriptor(CScript script) : m_script(std::move(script)) {}
192 
193  bool IsRange() const override { return false; }
194  std::string ToString() const override { return "raw(" + HexStr(m_script) + ")"; }
195  bool ToPrivateString(const SigningProvider& arg, std::string& out) const override { out = ToString(); return true; }
196  bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
197  {
198  output_scripts = std::vector<CScript>{m_script};
199  return true;
200  }
201 };
202 
204 class SingleKeyDescriptor final : public Descriptor
205 {
206  const std::function<CScript(const CPubKey&)> m_script_fn;
207  const std::string m_fn_name;
208  std::unique_ptr<PubkeyProvider> m_provider;
209 
210 public:
211  SingleKeyDescriptor(std::unique_ptr<PubkeyProvider> prov, const std::function<CScript(const CPubKey&)>& fn, const std::string& name) : m_script_fn(fn), m_fn_name(name), m_provider(std::move(prov)) {}
212 
213  bool IsRange() const override { return m_provider->IsRange(); }
214  std::string ToString() const override { return m_fn_name + "(" + m_provider->ToString() + ")"; }
215  bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
216  {
217  std::string ret;
218  if (!m_provider->ToPrivateString(arg, ret)) return false;
219  out = m_fn_name + "(" + std::move(ret) + ")";
220  return true;
221  }
222  bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
223  {
224  CPubKey key;
225  if (!m_provider->GetPubKey(pos, arg, key)) return false;
226  output_scripts = std::vector<CScript>{m_script_fn(key)};
227  out.pubkeys.emplace(key.GetID(), std::move(key));
228  return true;
229  }
230 };
231 
232 CScript P2PKHGetScript(const CPubKey& pubkey) { return GetScriptForDestination(pubkey.GetID()); }
233 CScript P2PKGetScript(const CPubKey& pubkey) { return GetScriptForRawPubKey(pubkey); }
234 
236 class MultisigDescriptor : public Descriptor
237 {
238  int m_threshold;
239  std::vector<std::unique_ptr<PubkeyProvider>> m_providers;
240 
241 public:
242  MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers) : m_threshold(threshold), m_providers(std::move(providers)) {}
243 
244  bool IsRange() const override
245  {
246  for (const auto& p : m_providers) {
247  if (p->IsRange()) return true;
248  }
249  return false;
250  }
251 
252  std::string ToString() const override
253  {
254  std::string ret = strprintf("multi(%i", m_threshold);
255  for (const auto& p : m_providers) {
256  ret += "," + p->ToString();
257  }
258  return std::move(ret) + ")";
259  }
260 
261  bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
262  {
263  std::string ret = strprintf("multi(%i", m_threshold);
264  for (const auto& p : m_providers) {
265  std::string sub;
266  if (!p->ToPrivateString(arg, sub)) return false;
267  ret += "," + std::move(sub);
268  }
269  out = std::move(ret) + ")";
270  return true;
271  }
272 
273  bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
274  {
275  std::vector<CPubKey> pubkeys;
276  pubkeys.reserve(m_providers.size());
277  for (const auto& p : m_providers) {
278  CPubKey key;
279  if (!p->GetPubKey(pos, arg, key)) return false;
280  pubkeys.push_back(key);
281  }
282  for (const CPubKey& key : pubkeys) {
283  out.pubkeys.emplace(key.GetID(), std::move(key));
284  }
285  output_scripts = std::vector<CScript>{GetScriptForMultisig(m_threshold, pubkeys)};
286  return true;
287  }
288 };
289 
291 class ConvertorDescriptor : public Descriptor
292 {
293  const std::function<CScript(const CScript&)> m_convert_fn;
294  const std::string m_fn_name;
295  std::unique_ptr<Descriptor> m_descriptor;
296 
297 public:
298  ConvertorDescriptor(std::unique_ptr<Descriptor> descriptor, const std::function<CScript(const CScript&)>& fn, const std::string& name) : m_convert_fn(fn), m_fn_name(name), m_descriptor(std::move(descriptor)) {}
299 
300  bool IsRange() const override { return m_descriptor->IsRange(); }
301  std::string ToString() const override { return m_fn_name + "(" + m_descriptor->ToString() + ")"; }
302  bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
303  {
304  std::string ret;
305  if (!m_descriptor->ToPrivateString(arg, ret)) return false;
306  out = m_fn_name + "(" + std::move(ret) + ")";
307  return true;
308  }
309  bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
310  {
311  std::vector<CScript> sub;
312  if (!m_descriptor->Expand(pos, arg, sub, out)) return false;
313  output_scripts.clear();
314  for (const auto& script : sub) {
315  CScriptID id(script);
316  out.scripts.emplace(CScriptID(script), script);
317  output_scripts.push_back(m_convert_fn(script));
318  }
319  return true;
320  }
321 };
322 
323 CScript ConvertP2SH(const CScript& script) { return GetScriptForDestination(CScriptID(script)); }
324 
326 class ComboDescriptor final : public Descriptor
327 {
328  std::unique_ptr<PubkeyProvider> m_provider;
329 
330 public:
331  explicit ComboDescriptor(std::unique_ptr<PubkeyProvider> provider) : m_provider(std::move(provider)) {}
332 
333  bool IsRange() const override { return m_provider->IsRange(); }
334  std::string ToString() const override { return "combo(" + m_provider->ToString() + ")"; }
335  bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
336  {
337  std::string ret;
338  if (!m_provider->ToPrivateString(arg, ret)) return false;
339  out = "combo(" + std::move(ret) + ")";
340  return true;
341  }
342  bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
343  {
344  CPubKey key;
345  if (!m_provider->GetPubKey(pos, arg, key)) return false;
346  CKeyID keyid = key.GetID();
347  {
348  CScript p2pk = GetScriptForRawPubKey(key);
349  CScript p2pkh = GetScriptForDestination(keyid);
350  output_scripts = std::vector<CScript>{std::move(p2pk), std::move(p2pkh)};
351  out.pubkeys.emplace(keyid, key);
352  }
353  return true;
354  }
355 };
356 
358 // Parser //
360 
361 enum class ParseScriptContext {
362  TOP,
363  P2SH,
364 };
365 
367 bool Const(const std::string& str, Span<const char>& sp)
368 {
369  if ((size_t)sp.size() >= str.size() && std::equal(str.begin(), str.end(), sp.begin())) {
370  sp = sp.subspan(str.size());
371  return true;
372  }
373  return false;
374 }
375 
377 bool Func(const std::string& str, Span<const char>& sp)
378 {
379  if ((size_t)sp.size() >= str.size() + 2 && sp[str.size()] == '(' && sp[sp.size() - 1] == ')' && std::equal(str.begin(), str.end(), sp.begin())) {
380  sp = sp.subspan(str.size() + 1, sp.size() - str.size() - 2);
381  return true;
382  }
383  return false;
384 }
385 
388 {
389  int level = 0;
390  auto it = sp.begin();
391  while (it != sp.end()) {
392  if (*it == '(') {
393  ++level;
394  } else if (level && *it == ')') {
395  --level;
396  } else if (level == 0 && (*it == ')' || *it == ',')) {
397  break;
398  }
399  ++it;
400  }
401  Span<const char> ret = sp.first(it - sp.begin());
402  sp = sp.subspan(it - sp.begin());
403  return ret;
404 }
405 
407 std::vector<Span<const char>> Split(const Span<const char>& sp, char sep)
408 {
409  std::vector<Span<const char>> ret;
410  auto it = sp.begin();
411  auto start = it;
412  while (it != sp.end()) {
413  if (*it == sep) {
414  ret.emplace_back(start, it);
415  start = it + 1;
416  }
417  ++it;
418  }
419  ret.emplace_back(start, it);
420  return ret;
421 }
422 
424 bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out)
425 {
426  for (size_t i = 1; i < split.size(); ++i) {
427  Span<const char> elem = split[i];
428  bool hardened = false;
429  if (elem.size() > 0 && (elem[elem.size() - 1] == '\'' || elem[elem.size() - 1] == 'h')) {
430  elem = elem.first(elem.size() - 1);
431  hardened = true;
432  }
433  uint32_t p;
434  if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p) || p > 0x7FFFFFFFUL) return false;
435  out.push_back(p | (((uint32_t)hardened) << 31));
436  }
437  return true;
438 }
439 
440 std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out)
441 {
442  auto split = Split(sp, '/');
443  std::string str(split[0].begin(), split[0].end());
444  if (split.size() == 1) {
445  if (IsHex(str)) {
446  std::vector<unsigned char> data = ParseHex(str);
447  CPubKey pubkey(data);
448  if (pubkey.IsFullyValid() && (permit_uncompressed || pubkey.IsCompressed())) return std::make_unique<ConstPubkeyProvider>(pubkey);
449  }
450  CKey key = KeyIO::DecodeSecret(str);
451  if (key.IsValid() && (permit_uncompressed || key.IsCompressed())) {
452  CPubKey pubkey = key.GetPubKey();
453  out.keys.emplace(pubkey.GetID(), key);
454  return std::make_unique<ConstPubkeyProvider>(pubkey);
455  }
456  }
457  CExtKey extkey = KeyIO::DecodeExtKey(str);
458  CExtPubKey extpubkey = KeyIO::DecodeExtPubKey(str);
459  if (!extkey.key.IsValid() && !extpubkey.pubkey.IsValid()) return nullptr;
460  KeyPath path;
461  DeriveType type = DeriveType::NO;
462  if (split.back() == MakeSpan("*").first(1)) {
463  split.pop_back();
464  type = DeriveType::UNHARDENED;
465  } else if (split.back() == MakeSpan("*'").first(2) || split.back() == MakeSpan("*h").first(2)) {
466  split.pop_back();
467  type = DeriveType::HARDENED;
468  }
469  if (!ParseKeyPath(split, path)) return nullptr;
470  if (extkey.key.IsValid()) {
471  extpubkey = extkey.Neuter();
472  out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key);
473  }
474  return std::make_unique<BIP32PubkeyProvider>(extpubkey, std::move(path), type);
475 }
476 
478 std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out)
479 {
480  auto expr = Expr(sp);
481  if (Func("pk", expr)) {
482  auto pubkey = ParsePubkey(expr, true, out);
483  if (!pubkey) return nullptr;
484  return std::make_unique<SingleKeyDescriptor>(std::move(pubkey), P2PKGetScript, "pk");
485  }
486  if (Func("pkh", expr)) {
487  auto pubkey = ParsePubkey(expr, true, out);
488  if (!pubkey) return nullptr;
489  return std::make_unique<SingleKeyDescriptor>(std::move(pubkey), P2PKHGetScript, "pkh");
490  }
491  if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
492  auto pubkey = ParsePubkey(expr, true, out);
493  if (!pubkey) return nullptr;
494  return std::make_unique<ComboDescriptor>(std::move(pubkey));
495  }
496  if (Func("multi", expr)) {
497  auto threshold = Expr(expr);
498  uint32_t thres;
499  std::vector<std::unique_ptr<PubkeyProvider>> providers;
500  if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) return nullptr;
501  size_t script_size = 0;
502  while (expr.size()) {
503  if (!Const(",", expr)) return nullptr;
504  auto arg = Expr(expr);
505  auto pk = ParsePubkey(arg, true, out);
506  if (!pk) return nullptr;
507  script_size += pk->GetSize() + 1;
508  providers.emplace_back(std::move(pk));
509  }
510  if (providers.size() < 1 || providers.size() > 16 || thres < 1 || thres > providers.size()) return nullptr;
511  if (ctx == ParseScriptContext::TOP) {
512  if (providers.size() > 3) return nullptr; // Not more than 3 pubkeys for raw multisig
513  }
514  if (ctx == ParseScriptContext::P2SH) {
515  if (script_size + 3 > 520) return nullptr; // Enforce P2SH script size limit
516  }
517  return std::make_unique<MultisigDescriptor>(thres, std::move(providers));
518  }
519  if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
520  auto desc = ParseScript(expr, ParseScriptContext::P2SH, out);
521  if (!desc || expr.size()) return nullptr;
522  return std::make_unique<ConvertorDescriptor>(std::move(desc), ConvertP2SH, "sh");
523  }
524  if (ctx == ParseScriptContext::TOP && Func("addr", expr)) {
525  CTxDestination dest = DecodeDestination(std::string(expr.begin(), expr.end()));
526  if (!IsValidDestination(dest)) return nullptr;
527  return std::make_unique<AddressDescriptor>(std::move(dest));
528  }
529  if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
530  std::string str(expr.begin(), expr.end());
531  if (!IsHex(str)) return nullptr;
532  auto bytes = ParseHex(str);
533  return std::make_unique<RawDescriptor>(CScript(bytes.begin(), bytes.end()));
534  }
535  return nullptr;
536 }
537 
538 } // namespace
539 
540 std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out)
541 {
542  Span<const char> sp(descriptor.data(), descriptor.size());
543  auto ret = ParseScript(sp, ParseScriptContext::TOP, out);
544  if (sp.size() == 0 && ret) return ret;
545  return nullptr;
546 }
An encapsulated private key.
Definition: key.h:30
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:95
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:98
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:186
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:21
An encapsulated public key.
Definition: pubkey.h:44
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:192
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:167
bool IsValid() const
Definition: pubkey.h:183
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:210
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:121
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:381
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:24
An interface to be implemented by keystores that support signing.
Definition: sign.h:23
virtual bool GetKey(const CKeyID &address, CKey &key) const
Definition: sign.h:28
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:93
constexpr std::size_t size() const noexcept
Definition: span.h:182
constexpr C * end() const noexcept
Definition: span.h:171
constexpr C * begin() const noexcept
Definition: span.h:170
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
Definition: span.h:198
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
Definition: span.h:188
CScript ParseScript(std::string s)
Definition: core_read.cpp:23
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out)
Parse a descriptor string.
Definition: descriptor.cpp:540
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:145
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:127
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:193
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:170
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:180
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:157
bool IsValidDestination(const CWDestination &address)
std::string EncodeDestination(const CWDestination &address, const CChainParams::Base58Type addrType)
CWDestination DecodeDestination(const std::string &strAddress)
Definition: uint256.h:212
const char * name
Definition: rest.cpp:37
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
Definition: span.h:221
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:311
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:286
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a PIVX scriptPubKey for the given CTxDestination.
Definition: standard.cpp:278
boost::variant< CNoDestination, CKeyID, CScriptID, CExchangeKeyID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:72
Definition: key.h:148
unsigned char vchFingerprint[4]
Definition: key.h:150
CExtPubKey Neuter() const
Definition: key.cpp:302
bool Derive(CExtKey &out, unsigned int nChild) const
Definition: key.cpp:281
CKey key
Definition: key.h:153
unsigned char nDepth
Definition: key.h:149
ChainCode chaincode
Definition: key.h:152
unsigned int nChild
Definition: key.h:151
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:278
CPubKey pubkey
Definition: pubkey.h:229
Interface for parsed descriptor objects.
Definition: descriptor.h:30
virtual std::string ToString() const =0
Convert the descriptor back to a string, undoing parsing.
virtual bool Expand(int pos, const SigningProvider &provider, std::vector< CScript > &output_scripts, FlatSigningProvider &out) const =0
Expand a descriptor at a specified position.
virtual bool IsRange() const =0
Whether the expansion of this descriptor depends on the position.
virtual bool ToPrivateString(const SigningProvider &provider, std::string &out) const =0
Convert the descriptor to a private string.
std::map< CKeyID, CPubKey > pubkeys
Definition: sign.h:47
std::map< CKeyID, CKey > keys
Definition: sign.h:48
std::map< CScriptID, CScript > scripts
Definition: sign.h:46
#define strprintf
Definition: tinyformat.h:1056
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::vector< unsigned char > ParseHex(const char *psz)
bool ParseUInt32(const std::string &str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
bool IsHex(const std::string &str)