83 uint64_t PolyMod(uint64_t c,
int val)
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;
110 static std::string INPUT_CHARSET =
111 "0123456789()[],'/*abcdefgh@:$%{}" 112 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~" 113 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
116 static std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
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);
125 cls = cls * 3 + (pos >> 5);
126 if (++clscount == 3) {
133 if (clscount > 0) c = PolyMod(c, cls);
134 for (
int j = 0; j < 8; ++j) c = PolyMod(c, 0);
137 std::string ret(8,
' ');
138 for (
int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
142 std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
148 typedef std::vector<uint32_t> KeyPath;
151 struct PubkeyProvider
156 uint32_t m_expr_index;
159 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
161 virtual ~PubkeyProvider() =
default;
171 virtual bool IsRange()
const = 0;
174 virtual size_t GetSize()
const = 0;
177 virtual std::string
ToString()
const = 0;
180 virtual bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const = 0;
186 class OriginPubkeyProvider final :
public PubkeyProvider
189 std::unique_ptr<PubkeyProvider> m_provider;
191 std::string OriginString()
const 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)) {}
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());
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 211 if (!m_provider->ToPrivateString(arg, sub))
return false;
212 ret =
"[" + OriginString() +
"]" + std::move(sub);
217 return m_provider->GetPrivKey(pos, arg, key);
222 class ConstPubkeyProvider final :
public PubkeyProvider
227 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey) : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
232 CKeyID keyid = m_pubkey.GetID();
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); }
239 bool ToPrivateString(
const SigningProvider& arg, std::string& ret)
const override 242 if (!arg.
GetKey(m_pubkey.GetID(), key))
return false;
248 return arg.
GetKey(m_pubkey.GetID(), key);
259 class BIP32PubkeyProvider final :
public PubkeyProvider
272 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
273 ret.
nDepth = m_root_extkey.nDepth;
275 ret.
nChild = m_root_extkey.nChild;
284 if (!GetExtKey(arg, xprv))
return false;
285 for (
auto entry : m_path) {
291 bool IsHardened()
const 293 if (m_derive == DeriveType::HARDENED)
return true;
294 for (
auto entry : m_path) {
295 if (entry >> 31)
return true;
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; }
308 CKeyID keyid = m_root_extkey.pubkey.GetID();
310 parent_info.
path = m_path;
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);
322 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
323 if (m_derive == DeriveType::HARDENED)
return false;
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);
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()) {
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();
340 for (
auto entry : m_path) {
341 der = parent_extkey.
Derive(parent_extkey, entry);
344 final_extkey = parent_extkey;
345 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
346 assert(m_derive != DeriveType::HARDENED);
350 final_info_out = final_info_out_tmp;
351 key_out = final_extkey.
pubkey;
356 if (!m_cached_xpub.
pubkey.
IsValid()) m_cached_xpub = parent_extkey;
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);
369 std::string
ToString()
const override 374 if (m_derive == DeriveType::HARDENED) ret +=
'\'';
378 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const override 381 if (!GetExtKey(arg, key))
return false;
385 if (m_derive == DeriveType::HARDENED) out +=
'\'';
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);
404 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
406 const std::string m_name;
412 const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
415 virtual std::string ToStringExtra()
const {
return ""; }
428 virtual std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& pubkeys,
const CScript* script,
FlatSigningProvider& out)
const = 0;
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)) {}
435 if (m_subdescriptor_arg) {
436 if (!m_subdescriptor_arg->IsSolvable())
return false;
441 bool IsRange()
const final 443 for (
const auto& pubkey : m_pubkey_args) {
444 if (pubkey->IsRange())
return true;
446 if (m_subdescriptor_arg) {
447 if (m_subdescriptor_arg->IsRange())
return true;
452 bool ToStringHelper(
const SigningProvider* arg, std::string& out,
bool priv)
const 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 +=
",";
461 if (!pubkey->ToPrivateString(*arg, tmp))
return false;
463 tmp = pubkey->ToString();
465 ret += std::move(tmp);
467 if (m_subdescriptor_arg) {
468 if (pos++) ret +=
",";
470 if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv))
return false;
471 ret += std::move(tmp);
473 out = std::move(ret) +
")";
480 ToStringHelper(
nullptr, ret,
false);
481 return AddChecksum(ret);
484 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const final 486 bool ret = ToStringHelper(&arg, out,
true);
487 out = AddChecksum(out);
493 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
494 entries.reserve(m_pubkey_args.size());
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;
501 std::vector<CScript> subscripts;
502 if (m_subdescriptor_arg) {
504 if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache, subscripts, subprovider, write_cache))
return false;
505 out =
Merge(out, subprovider);
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)));
514 if (m_subdescriptor_arg) {
515 for (
const auto& subscript : subscripts) {
517 std::vector<CScript> addscripts = MakeScripts(pubkeys, &subscript, out);
518 for (
auto& addscript : addscripts) {
519 output_scripts.push_back(std::move(addscript));
523 output_scripts = MakeScripts(pubkeys,
nullptr, out);
530 return ExpandHelper(pos, provider,
nullptr, output_scripts, out, write_cache);
540 for (
const auto& p : m_pubkey_args) {
542 if (!p->GetPrivKey(pos, provider, key))
continue;
545 if (m_subdescriptor_arg) {
547 m_subdescriptor_arg->ExpandPrivate(pos, provider, subprovider);
548 out =
Merge(out, subprovider);
556 class AddressDescriptor final :
public DescriptorImpl
560 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
563 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({}, {},
"addr"), m_destination(std::move(destination)) {}
564 bool IsSolvable()
const final {
return false; }
568 switch (m_destination.index()) {
578 bool IsSingleType()
const final {
return true; }
582 class RawDescriptor final :
public DescriptorImpl
586 std::string ToStringExtra()
const override {
return HexStr(m_script); }
589 RawDescriptor(
CScript script) : DescriptorImpl({}, {},
"raw"), m_script(std::move(script)) {}
590 bool IsSolvable()
const final {
return false; }
596 switch (dest.index()) {
606 bool IsSingleType()
const final {
return true; }
610 class PKDescriptor final :
public DescriptorImpl
615 PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(std::move(prov)), {},
"pk") {}
616 bool IsSingleType()
const final {
return true; }
620 class PKHDescriptor final :
public DescriptorImpl
625 CKeyID id = keys[0].GetID();
626 out.
pubkeys.emplace(
id, keys[0]);
630 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(std::move(prov)), {},
"pkh") {}
632 bool IsSingleType()
const final {
return true; }
636 class WPKHDescriptor final :
public DescriptorImpl
641 CKeyID id = keys[0].GetID();
642 out.
pubkeys.emplace(
id, keys[0]);
646 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(std::move(prov)), {},
"wpkh") {}
648 bool IsSingleType()
const final {
return true; }
652 class ComboDescriptor final :
public DescriptorImpl
657 std::vector<CScript> ret;
658 CKeyID id = keys[0].GetID();
659 out.
pubkeys.emplace(
id, keys[0]);
662 if (keys[0].IsCompressed()) {
665 ret.emplace_back(p2wpkh);
671 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(std::move(prov)), {},
"combo") {}
672 bool IsSingleType()
const final {
return false; }
676 class MultisigDescriptor final :
public DescriptorImpl
678 const int m_threshold;
681 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
684 std::vector<CPubKey> sorted_keys(keys);
685 std::sort(sorted_keys.begin(), sorted_keys.end());
691 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) {}
692 bool IsSingleType()
const final {
return true; }
696 class SHDescriptor final :
public DescriptorImpl
701 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
705 assert(m_subdescriptor_arg);
709 bool IsSingleType()
const final {
return true; }
713 class WSHDescriptor final :
public DescriptorImpl
718 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
720 bool IsSingleType()
const final {
return true; }
734 [[nodiscard]]
bool ParseKeyPath(
const std::vector<
Span<const char>>& split, KeyPath& out, std::string&
error)
736 for (
size_t i = 1; i < split.size(); ++i) {
738 bool hardened =
false;
739 if (elem.
size() > 0 && (elem[elem.
size() - 1] ==
'\'' || elem[elem.
size() - 1] ==
'h')) {
745 error =
strprintf(
"Key path value '%s' is not a valid uint32", std::string(elem.
begin(), elem.
end()));
747 }
else if (p > 0x7FFFFFFFUL) {
748 error =
strprintf(
"Key path value %u is out of range", p);
751 out.push_back(p | (((uint32_t)hardened) << 31));
757 std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
const Span<const char>& sp,
bool permit_uncompressed,
FlatSigningProvider& out, std::string& error)
761 auto split =
Split(sp,
'/');
762 std::string str(split[0].begin(), split[0].end());
763 if (str.size() == 0) {
764 error =
"No key provided";
767 if (split.size() == 1) {
769 std::vector<unsigned char> data =
ParseHex(str);
773 return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
775 error =
"Uncompressed keys are not allowed";
779 error =
strprintf(
"Pubkey '%s' is invalid", str);
787 return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
789 error =
"Uncompressed keys are not allowed";
797 error =
strprintf(
"key '%s' is not valid", str);
802 if (split.back() ==
MakeSpan(
"*").first(1)) {
804 type = DeriveType::UNHARDENED;
805 }
else if (split.back() ==
MakeSpan(
"*'").first(2) || split.back() ==
MakeSpan(
"*h").first(2)) {
807 type = DeriveType::HARDENED;
809 if (!ParseKeyPath(split, path, error))
return nullptr;
811 extpubkey = extkey.
Neuter();
814 return MakeUnique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type);
822 auto origin_split =
Split(sp,
']');
823 if (origin_split.size() > 2) {
824 error =
"Multiple ']' characters found for a single pubkey";
827 if (origin_split.size() == 1)
return ParsePubkeyInner(key_exp_index, origin_split[0], permit_uncompressed, out, error);
828 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
829 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
830 origin_split[0].empty() ?
']' : origin_split[0][0]);
833 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
834 if (slash_split[0].size() != 8) {
835 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
838 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
839 if (!
IsHex(fpr_hex)) {
840 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
845 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
846 assert(fpr_bytes.size() == 4);
847 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
848 if (!ParseKeyPath(slash_split, info.
path, error))
return nullptr;
849 auto provider = ParsePubkeyInner(key_exp_index, origin_split[1], permit_uncompressed, out, error);
850 if (!provider)
return nullptr;
851 return MakeUnique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider));
859 auto expr =
Expr(sp);
860 bool sorted_multi =
false;
861 if (
Func(
"pk", expr)) {
862 auto pubkey = ParsePubkey(key_exp_index, expr, ctx != ParseScriptContext::P2WSH, out, error);
863 if (!pubkey)
return nullptr;
864 return MakeUnique<PKDescriptor>(std::move(pubkey));
866 if (
Func(
"pkh", expr)) {
867 auto pubkey = ParsePubkey(key_exp_index, expr, ctx != ParseScriptContext::P2WSH, out, error);
868 if (!pubkey)
return nullptr;
869 return MakeUnique<PKHDescriptor>(std::move(pubkey));
871 if (ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
872 auto pubkey = ParsePubkey(key_exp_index, expr,
true, out, error);
873 if (!pubkey)
return nullptr;
874 return MakeUnique<ComboDescriptor>(std::move(pubkey));
875 }
else if (ctx != ParseScriptContext::TOP &&
Func(
"combo", expr)) {
876 error =
"Cannot have combo in non-top level";
879 if ((sorted_multi =
Func(
"sortedmulti", expr)) ||
Func(
"multi", expr)) {
880 auto threshold =
Expr(expr);
882 std::vector<std::unique_ptr<PubkeyProvider>> providers;
883 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
884 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
887 size_t script_size = 0;
888 while (expr.size()) {
889 if (!
Const(
",", expr)) {
890 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
893 auto arg =
Expr(expr);
894 auto pk = ParsePubkey(key_exp_index, arg, ctx != ParseScriptContext::P2WSH, out, error);
895 if (!pk)
return nullptr;
896 script_size += pk->GetSize() + 1;
897 providers.emplace_back(std::move(pk));
900 if (providers.empty() || providers.size() > 16) {
901 error =
strprintf(
"Cannot have %u keys in multisig; must have between 1 and 16 keys, inclusive", providers.size());
903 }
else if (thres < 1) {
904 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
906 }
else if (thres > providers.size()) {
907 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
910 if (ctx == ParseScriptContext::TOP) {
911 if (providers.size() > 3) {
912 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
916 if (ctx == ParseScriptContext::P2SH) {
922 return MakeUnique<MultisigDescriptor>(thres, std::move(providers), sorted_multi);
924 if (ctx != ParseScriptContext::P2WSH &&
Func(
"wpkh", expr)) {
925 auto pubkey = ParsePubkey(key_exp_index, expr,
false, out, error);
926 if (!pubkey)
return nullptr;
927 return MakeUnique<WPKHDescriptor>(std::move(pubkey));
928 }
else if (ctx == ParseScriptContext::P2WSH &&
Func(
"wpkh", expr)) {
929 error =
"Cannot have wpkh within wsh";
932 if (ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
933 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH, out, error);
934 if (!desc || expr.size())
return nullptr;
935 return MakeUnique<SHDescriptor>(std::move(desc));
936 }
else if (ctx != ParseScriptContext::TOP &&
Func(
"sh", expr)) {
937 error =
"Cannot have sh in non-top level";
940 if (ctx != ParseScriptContext::P2WSH &&
Func(
"wsh", expr)) {
941 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH, out, error);
942 if (!desc || expr.size())
return nullptr;
943 return MakeUnique<WSHDescriptor>(std::move(desc));
944 }
else if (ctx == ParseScriptContext::P2WSH &&
Func(
"wsh", expr)) {
945 error =
"Cannot have wsh within wsh";
948 if (ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
951 error =
"Address is not valid";
954 return MakeUnique<AddressDescriptor>(std::move(dest));
956 if (ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
957 std::string str(expr.begin(), expr.end());
959 error =
"Raw script is not hex";
963 return MakeUnique<RawDescriptor>(
CScript(bytes.begin(), bytes.end()));
965 if (ctx == ParseScriptContext::P2SH) {
966 error =
"A function is needed within P2SH";
968 }
else if (ctx == ParseScriptContext::P2WSH) {
969 error =
"A function is needed within P2WSH";
972 error =
strprintf(
"%s is not a valid descriptor function", std::string(expr.begin(), expr.end()));
978 std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(0, pubkey);
981 return MakeUnique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
988 std::vector<std::vector<unsigned char>> data;
992 CPubKey pubkey(data[0].begin(), data[0].end());
994 return MakeUnique<PKDescriptor>(InferPubkey(pubkey, ctx, provider));
1001 if (provider.
GetPubKey(keyid, pubkey)) {
1002 return MakeUnique<PKHDescriptor>(InferPubkey(pubkey, ctx, provider));
1009 if (provider.
GetPubKey(keyid, pubkey)) {
1010 return MakeUnique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider));
1014 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1015 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1016 CPubKey pubkey(data[i].begin(), data[i].end());
1017 providers.push_back(InferPubkey(pubkey, ctx, provider));
1019 return MakeUnique<MultisigDescriptor>((int)data[0][0], std::move(providers));
1025 if (provider.
GetCScript(scriptid, subscript)) {
1026 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
1027 if (sub)
return MakeUnique<SHDescriptor>(std::move(sub));
1034 if (provider.
GetCScript(scriptid, subscript)) {
1035 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
1036 if (sub)
return MakeUnique<WSHDescriptor>(std::move(sub));
1043 return MakeUnique<AddressDescriptor>(std::move(dest));
1047 return MakeUnique<RawDescriptor>(script);
1058 auto check_split =
Split(sp,
'#');
1059 if (check_split.size() > 2) {
1060 error =
"Multiple '#' symbols";
1063 if (check_split.size() == 1 && require_checksum){
1064 error =
"Missing checksum";
1067 if (check_split.size() == 2) {
1068 if (check_split[1].size() != 8) {
1069 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
1073 auto checksum = DescriptorChecksum(check_split[0]);
1074 if (checksum.empty()) {
1075 error =
"Invalid characters in payload";
1078 if (check_split.size() == 2) {
1079 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
1080 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
1084 if (out_checksum) *out_checksum = std::move(checksum);
1085 sp = check_split[0];
1092 if (!
CheckChecksum(sp, require_checksum, error))
return nullptr;
1093 auto ret =
ParseScript(0, sp, ParseScriptContext::TOP, out, error);
1094 if (sp.size() == 0 && ret)
return std::unique_ptr<Descriptor>(std::move(ret));
1109 return InferScript(script, ParseScriptContext::TOP, provider);
1114 m_parent_xpubs[key_exp_pos] = xpub;
1119 auto& xpubs = m_derived_xpubs[key_exp_pos];
1120 xpubs[der_index] = xpub;
1125 const auto&
it = m_parent_xpubs.find(key_exp_pos);
1126 if (
it == m_parent_xpubs.end())
return false;
1133 const auto& key_exp_it = m_derived_xpubs.find(key_exp_pos);
1134 if (key_exp_it == m_derived_xpubs.end())
return false;
1135 const auto& der_it = key_exp_it->second.find(der_index);
1136 if (der_it == key_exp_it->second.end())
return false;
1137 xpub = der_it->second;
1143 return m_parent_xpubs;
1148 return m_derived_xpubs;
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
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.
const std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
std::deque< CInv >::iterator it
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
constexpr C * end() const noexcept
bool Derive(CExtKey &out, unsigned int nChild) const
CPubKey GetPubKey() const
Compute the public key from a private key.
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)
FlatSigningProvider Merge(const FlatSigningProvider &a, const FlatSigningProvider &b)
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
std::vector< unsigned char > ParseHex(const char *psz)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
constexpr std::size_t size() const noexcept
unsigned char vchFingerprint[4]
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
static auto & nullopt
Substitute for C++17 std::nullopt DEPRECATED use std::nullopt in new code.
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.
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
CExtPubKey DecodeExtPubKey(const std::string &str)
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
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.
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()) ...
std::map< CScriptID, CScript > scripts
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
const SigningProvider & DUMMY_SIGNING_PROVIDER
static secp256k1_context * ctx
An encapsulated public key.
bool IsHex(const std::string &str)
std::map< CKeyID, CPubKey > pubkeys
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
virtual bool GetKey(const CKeyID &address, CKey &key) const
bool IsSolvable(const SigningProvider &provider, const CScript &script)
CRIPEMD160 & Write(const unsigned char *data, size_t len)
constexpr C * begin() const noexcept
CTxDestination DecodeDestination(const std::string &str)
bool Derive(CExtPubKey &out, unsigned int nChild) const
std::string EncodeExtPubKey(const CExtPubKey &key)
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
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
Cache for single descriptor's derived extended pubkeys.
Serialized script, used inside transaction inputs and outputs.
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
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.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
A reference to a CScript: the Hash160 of its serialization (see script.h)
std::string EncodeDestination(const CTxDestination &dest)
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
An encapsulated private key.
A Span is an object that can refer to a contiguous sequence of objects.
CKey DecodeSecret(const std::string &str)
void Finalize(unsigned char hash[OUTPUT_SIZE])
CScript ParseScript(const std::string &s)
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
std::string EncodeSecret(const CKey &key)
std::vector< uint32_t > path
bool error(const char *fmt, const Args &... args)
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)
std::optional< T > Optional
Substitute for C++17 std::optional DEPRECATED use std::optional in new code.
Interface for parsed descriptor objects.
A hasher class for RIPEMD-160.
bool IsValid() const
Check whether this private key is valid.
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
Span< A > constexpr MakeSpan(A(&a)[N])
MakeSpan for arrays:
bool IsCompressed() const
Check whether this is a compressed public key.