7#include <chainparams.h>
90uint64_t PolyMod(uint64_t c,
int val) {
92 c = ((c & 0x7ffffffff) << 5) ^ val;
129 static const std::string INPUT_CHARSET =
130 "0123456789()[],'/*abcdefgh@:$%{}"
131 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
132 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
135 static const std::string CHECKSUM_CHARSET =
136 "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
141 for (
auto ch : span) {
142 auto pos = INPUT_CHARSET.find(ch);
143 if (pos == std::string::npos) {
147 c = PolyMod(c, pos & 31);
149 cls = cls * 3 + (pos >> 5);
150 if (++clscount == 3) {
161 for (
int j = 0; j < 8; ++j) {
168 std::string ret(8,
' ');
169 for (
int j = 0; j < 8; ++j) {
170 ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
175std::string AddChecksum(
const std::string &str) {
176 return str +
"#" + DescriptorChecksum(str);
183typedef std::vector<uint32_t> KeyPath;
186struct PubkeyProvider {
191 uint32_t m_expr_index;
194 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
196 virtual ~PubkeyProvider() =
default;
211 virtual bool IsRange()
const = 0;
214 virtual size_t GetSize()
const = 0;
217 virtual std::string
ToString()
const = 0;
224 std::string &
out)
const = 0;
228 CKey &key)
const = 0;
231class OriginPubkeyProvider final :
public PubkeyProvider {
233 std::unique_ptr<PubkeyProvider> m_provider;
235 std::string OriginString()
const {
241 std::unique_ptr<PubkeyProvider> provider)
242 : PubkeyProvider(exp_index), m_origin(
std::move(info)),
243 m_provider(
std::move(provider)) {}
248 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache,
252 std::copy(std::begin(m_origin.fingerprint),
254 info.
path.insert(info.
path.begin(), m_origin.path.begin(),
255 m_origin.path.end());
258 bool IsRange()
const override {
return m_provider->IsRange(); }
259 size_t GetSize()
const override {
return m_provider->GetSize(); }
260 std::string
ToString()
const override {
261 return "[" + OriginString() +
"]" + m_provider->ToString();
264 std::string &ret)
const override {
266 if (!m_provider->ToPrivateString(arg, sub)) {
269 ret =
"[" + OriginString() +
"]" + std::move(sub);
273 CKey &key)
const override {
274 return m_provider->GetPrivKey(pos, arg, key);
279class ConstPubkeyProvider final :
public PubkeyProvider {
283 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey &pubkey)
284 : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
291 CKeyID keyid = m_pubkey.GetID();
296 bool IsRange()
const override {
return false; }
297 size_t GetSize()
const override {
return m_pubkey.size(); }
298 std::string
ToString()
const override {
return HexStr(m_pubkey); }
300 std::string &ret)
const override {
302 if (!arg.
GetKey(m_pubkey.GetID(), key)) {
309 CKey &key)
const override {
310 return arg.
GetKey(m_pubkey.GetID(), key);
314enum class DeriveType {
321class BIP32PubkeyProvider final :
public PubkeyProvider {
332 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key)) {
335 ret.
nDepth = m_root_extkey.nDepth;
336 std::copy(m_root_extkey.vchFingerprint,
339 ret.
nChild = m_root_extkey.nChild;
347 if (!GetExtKey(arg, xprv)) {
350 for (
auto entry : m_path) {
356 bool IsHardened()
const {
357 if (m_derive == DeriveType::HARDENED) {
360 for (
auto entry : m_path) {
369 BIP32PubkeyProvider(uint32_t exp_index,
const CExtPubKey &extkey,
370 KeyPath path, DeriveType derive)
371 : PubkeyProvider(exp_index), m_root_extkey(extkey),
372 m_path(
std::move(path)), m_derive(derive) {}
373 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
374 size_t GetSize()
const override {
return 33; }
381 CKeyID keyid = m_root_extkey.pubkey.GetID();
382 std::copy(keyid.
begin(),
385 parent_info.
path = m_path;
390 if (m_derive == DeriveType::UNHARDENED) {
391 final_info_out_tmp.
path.push_back((uint32_t)pos);
393 if (m_derive == DeriveType::HARDENED) {
394 final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
402 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos,
404 if (m_derive == DeriveType::HARDENED) {
408 if (!read_cache->GetCachedParentExtPubKey(m_expr_index,
412 final_extkey = parent_extkey;
413 if (m_derive == DeriveType::UNHARDENED) {
414 der = parent_extkey.
Derive(final_extkey, pos);
418 m_derive != DeriveType::HARDENED) {
419 parent_extkey = final_extkey = m_cached_xpub;
420 if (m_derive == DeriveType::UNHARDENED) {
421 der = parent_extkey.
Derive(final_extkey, pos);
423 }
else if (IsHardened()) {
425 if (!GetDerivedExtKey(arg, xprv)) {
428 parent_extkey = xprv.
Neuter();
429 if (m_derive == DeriveType::UNHARDENED) {
430 der = xprv.
Derive(xprv, pos);
432 if (m_derive == DeriveType::HARDENED) {
433 der = xprv.
Derive(xprv, pos | 0x80000000UL);
435 final_extkey = xprv.
Neuter();
437 for (
auto entry : m_path) {
438 der = parent_extkey.
Derive(parent_extkey, entry);
441 final_extkey = parent_extkey;
442 if (m_derive == DeriveType::UNHARDENED) {
443 der = parent_extkey.
Derive(final_extkey, pos);
445 assert(m_derive != DeriveType::HARDENED);
449 final_info_out = final_info_out_tmp;
450 key_out = final_extkey.
pubkey;
456 m_cached_xpub = parent_extkey;
461 if (m_derive != DeriveType::HARDENED) {
462 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
463 }
else if (final_info_out.
path.size() > 0) {
464 write_cache->CacheDerivedExtPubKey(m_expr_index, pos,
471 std::string
ToString()
const override {
476 if (m_derive == DeriveType::HARDENED) {
483 std::string &
out)
const override {
485 if (!GetExtKey(arg, key)) {
491 if (m_derive == DeriveType::HARDENED) {
498 CKey &key)
const override {
500 if (!GetDerivedExtKey(arg, extkey)) {
503 if (m_derive == DeriveType::UNHARDENED) {
504 extkey.
Derive(extkey, pos);
506 if (m_derive == DeriveType::HARDENED) {
507 extkey.
Derive(extkey, pos | 0x80000000UL);
518 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
520 const std::string m_name;
526 const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
530 virtual std::string ToStringExtra()
const {
return ""; }
547 virtual std::vector<CScript>
548 MakeScripts(
const std::vector<CPubKey> &pubkeys,
const CScript *
script,
552 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
553 std::unique_ptr<DescriptorImpl>
script,
554 const std::string &
name)
555 : m_pubkey_args(
std::move(pubkeys)), m_name(
name),
556 m_subdescriptor_arg(
std::move(
script)) {}
559 if (m_subdescriptor_arg) {
560 if (!m_subdescriptor_arg->IsSolvable()) {
568 for (
const auto &pubkey : m_pubkey_args) {
569 if (pubkey->IsRange()) {
573 if (m_subdescriptor_arg) {
574 if (m_subdescriptor_arg->IsRange()) {
583 std::string extra = ToStringExtra();
584 size_t pos = extra.size() > 0 ? 1 : 0;
585 std::string ret = m_name +
"(" + extra;
586 for (
const auto &pubkey : m_pubkey_args) {
592 if (!pubkey->ToPrivateString(*arg, tmp)) {
596 tmp = pubkey->ToString();
600 if (m_subdescriptor_arg) {
605 if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) {
610 out = std::move(ret) +
")";
614 std::string
ToString() const final {
616 ToStringHelper(
nullptr, ret,
false);
617 return AddChecksum(ret);
621 std::string &
out)
const final {
622 bool ret = ToStringHelper(&arg,
out,
true);
629 std::vector<CScript> &output_scripts,
632 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
633 entries.reserve(m_pubkey_args.size());
637 for (
const auto &p : m_pubkey_args) {
638 entries.emplace_back();
639 if (!p->GetPubKey(pos, arg, entries.back().first,
640 entries.back().second, read_cache, write_cache)) {
644 std::vector<CScript> subscripts;
645 if (m_subdescriptor_arg) {
647 if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache,
648 subscripts, subprovider,
655 std::vector<CPubKey> pubkeys;
656 pubkeys.reserve(entries.size());
657 for (
auto &entry : entries) {
658 pubkeys.push_back(entry.first);
661 std::make_pair<CPubKey, KeyOriginInfo>(
662 CPubKey(entry.first), std::move(entry.second)));
664 if (m_subdescriptor_arg) {
665 for (
const auto &subscript : subscripts) {
667 std::vector<CScript> addscripts =
668 MakeScripts(pubkeys, &subscript,
out);
669 for (
auto &addscript : addscripts) {
670 output_scripts.push_back(std::move(addscript));
674 output_scripts = MakeScripts(pubkeys,
nullptr,
out);
682 return ExpandHelper(pos, provider,
nullptr, output_scripts,
out,
687 std::vector<CScript> &output_scripts,
690 output_scripts,
out,
nullptr);
695 for (
const auto &p : m_pubkey_args) {
697 if (!p->GetPrivKey(pos, provider, key)) {
702 if (m_subdescriptor_arg) {
704 m_subdescriptor_arg->ExpandPrivate(pos, provider, subprovider);
715class AddressDescriptor final :
public DescriptorImpl {
719 std::string ToStringExtra()
const override {
722 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
730 : DescriptorImpl({}, {},
"addr"),
731 m_destination(std::move(destination)) {}
732 bool IsSolvable() const final {
return false; }
734 std::optional<OutputType> GetOutputType()
const override {
735 switch (m_destination.index()) {
744 bool IsSingleType() const final {
return true; }
748class RawDescriptor final :
public DescriptorImpl {
749 const CScript m_script;
752 std::string ToStringExtra()
const override {
return HexStr(m_script); }
753 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
760 RawDescriptor(CScript
script)
761 : DescriptorImpl({}, {},
"raw"), m_script(std::move(
script)) {}
762 bool IsSolvable() const final {
return false; }
764 std::optional<OutputType> GetOutputType()
const override {
767 switch (dest.index()) {
776 bool IsSingleType() const final {
return true; }
780class PKDescriptor final :
public DescriptorImpl {
782 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
789 PKDescriptor(std::unique_ptr<PubkeyProvider> prov)
790 : DescriptorImpl(
Vector(
std::move(prov)), {},
"pk") {}
791 bool IsSingleType() const final {
return true; }
795class PKHDescriptor final :
public DescriptorImpl {
797 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
800 CKeyID id = keys[0].GetID();
801 out.pubkeys.emplace(
id, keys[0]);
806 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov)
807 : DescriptorImpl(
Vector(
std::move(prov)), {},
"pkh") {}
808 std::optional<OutputType> GetOutputType()
const override {
811 bool IsSingleType() const final {
return true; }
815class ComboDescriptor final :
public DescriptorImpl {
817 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
820 std::vector<CScript> ret;
821 CKeyID id = keys[0].GetID();
822 out.pubkeys.emplace(
id, keys[0]);
831 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov)
832 : DescriptorImpl(
Vector(
std::move(prov)), {},
"combo") {}
833 bool IsSingleType() const final {
return false; }
837class MultisigDescriptor final :
public DescriptorImpl {
838 const int m_threshold;
842 std::string ToStringExtra()
const override {
845 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
849 std::vector<CPubKey> sorted_keys(keys);
850 std::sort(sorted_keys.begin(), sorted_keys.end());
857 MultisigDescriptor(
int threshold,
858 std::vector<std::unique_ptr<PubkeyProvider>> providers,
860 : DescriptorImpl(
std::move(providers), {},
861 sorted ?
"sortedmulti" :
"multi"),
862 m_threshold(threshold), m_sorted(sorted) {}
863 bool IsSingleType() const final {
return true; }
867class SHDescriptor final :
public DescriptorImpl {
869 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
876 SHDescriptor(std::unique_ptr<DescriptorImpl> desc)
877 : DescriptorImpl({}, std::move(desc),
"sh") {}
878 std::optional<OutputType> GetOutputType()
const override {
881 bool IsSingleType() const final {
return true; }
888enum class ParseScriptContext {
898 KeyPath &
out, std::string &error) {
899 for (
size_t i = 1; i < split.size(); ++i) {
901 bool hardened =
false;
902 if (elem.
size() > 0 &&
903 (elem[elem.
size() - 1] ==
'\'' || elem[elem.
size() - 1] ==
'h')) {
909 error =
strprintf(
"Key path value '%s' is not a valid uint32",
910 std::string(elem.
begin(), elem.
end()).c_str());
912 }
else if (p > 0x7FFFFFFFUL) {
913 error =
strprintf(
"Key path value %u is out of range", p);
916 out.push_back(p | (uint32_t(hardened) << 31));
922std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
925 std::string &error) {
926 auto split =
Split(sp,
'/');
927 std::string str(split[0].begin(), split[0].end());
928 if (str.size() == 0) {
929 error =
"No key provided";
932 if (split.size() == 1) {
934 std::vector<uint8_t> data =
ParseHex(str);
936 if (pubkey.IsFullyValid()) {
937 return std::make_unique<ConstPubkeyProvider>(key_exp_index,
940 error =
strprintf(
"Pubkey '%s' is invalid", str);
946 out.keys.emplace(pubkey.
GetID(), key);
947 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey);
953 error =
strprintf(
"key '%s' is not valid", str);
957 DeriveType type = DeriveType::NO;
958 if (split.back() ==
Span{
"*"}.
first(1)) {
960 type = DeriveType::UNHARDENED;
961 }
else if (split.back() ==
Span{
"*'"}.
first(2) ||
964 type = DeriveType::HARDENED;
966 if (!ParseKeyPath(split, path, error)) {
970 extpubkey = extkey.
Neuter();
973 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey,
974 std::move(path), type);
978std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index,
981 std::string &error) {
982 auto origin_split =
Split(sp,
']');
983 if (origin_split.size() > 2) {
984 error =
"Multiple ']' characters found for a single pubkey";
987 if (origin_split.size() == 1) {
988 return ParsePubkeyInner(key_exp_index, origin_split[0],
out, error);
990 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
991 error =
strprintf(
"Key origin start '[ character expected but not "
992 "found, got '%c' instead",
993 origin_split[0].empty()
995 : origin_split[0][0]);
998 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
999 if (slash_split[0].size() != 8) {
1000 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead "
1002 slash_split[0].size());
1005 std::string fpr_hex =
1006 std::string(slash_split[0].begin(), slash_split[0].end());
1007 if (!
IsHex(fpr_hex)) {
1008 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
1011 auto fpr_bytes =
ParseHex(fpr_hex);
1013 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1014 assert(fpr_bytes.size() == 4);
1015 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1016 if (!ParseKeyPath(slash_split, info.
path, error)) {
1020 ParsePubkeyInner(key_exp_index, origin_split[1],
out, error);
1024 return std::make_unique<OriginPubkeyProvider>(
1025 key_exp_index, std::move(info), std::move(provider));
1029std::unique_ptr<DescriptorImpl>
ParseScript(uint32_t key_exp_index,
1031 ParseScriptContext
ctx,
1033 std::string &error) {
1036 auto expr =
Expr(sp);
1037 bool sorted_multi =
false;
1038 if (
Func(
"pk", expr)) {
1039 auto pubkey = ParsePubkey(key_exp_index, expr,
out, error);
1043 return std::make_unique<PKDescriptor>(std::move(pubkey));
1045 if (
Func(
"pkh", expr)) {
1046 auto pubkey = ParsePubkey(key_exp_index, expr,
out, error);
1050 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1052 if (
ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1053 auto pubkey = ParsePubkey(key_exp_index, expr,
out, error);
1057 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1058 }
else if (
ctx != ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1059 error =
"Cannot have combo in non-top level";
1062 if ((sorted_multi =
Func(
"sortedmulti", expr)) ||
Func(
"multi", expr)) {
1063 auto threshold =
Expr(expr);
1065 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1066 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()),
1069 "Multi threshold '%s' is not valid",
1070 std::string(threshold.begin(), threshold.end()).c_str());
1073 size_t script_size = 0;
1074 while (expr.size()) {
1075 if (!
Const(
",", expr)) {
1076 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
1079 auto arg =
Expr(expr);
1080 auto pk = ParsePubkey(key_exp_index, arg,
out, error);
1084 script_size +=
pk->GetSize() + 1;
1085 providers.emplace_back(std::move(
pk));
1088 if (providers.empty() || providers.size() > 16) {
1089 error =
strprintf(
"Cannot have %u keys in multisig; must have "
1090 "between 1 and 16 keys, inclusive",
1093 }
else if (thres < 1) {
1095 "Multisig threshold cannot be %d, must be at least 1", thres);
1097 }
else if (thres > providers.size()) {
1099 strprintf(
"Multisig threshold cannot be larger than the number "
1100 "of keys; threshold is %d but only %u keys specified",
1101 thres, providers.size());
1104 if (
ctx == ParseScriptContext::TOP) {
1105 if (providers.size() > 3) {
1106 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; "
1107 "only at most 3 pubkeys",
1112 if (
ctx == ParseScriptContext::P2SH) {
1114 error =
strprintf(
"P2SH script is too large, %d bytes is "
1115 "larger than %d bytes",
1120 return std::make_unique<MultisigDescriptor>(thres, std::move(providers),
1123 if (
ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1124 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
1126 if (!desc || expr.size()) {
1129 return std::make_unique<SHDescriptor>(std::move(desc));
1130 }
else if (
ctx != ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1131 error =
"Cannot have sh in non-top level";
1134 if (
ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1138 error =
"Address is not valid";
1141 return std::make_unique<AddressDescriptor>(std::move(dest));
1143 if (
ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
1144 std::string str(expr.begin(), expr.end());
1146 error =
"Raw script is not hex";
1150 return std::make_unique<RawDescriptor>(
1151 CScript(bytes.begin(), bytes.end()));
1153 if (
ctx == ParseScriptContext::P2SH) {
1154 error =
"A function is needed within P2SH";
1157 error =
strprintf(
"%s is not a valid descriptor function",
1158 std::string(expr.begin(), expr.end()));
1162std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey &pubkey,
1165 std::unique_ptr<PubkeyProvider> key_provider =
1166 std::make_unique<ConstPubkeyProvider>(0, pubkey);
1169 return std::make_unique<OriginPubkeyProvider>(0, std::move(info),
1170 std::move(key_provider));
1172 return key_provider;
1175std::unique_ptr<DescriptorImpl> InferScript(
const CScript &
script,
1176 ParseScriptContext
ctx,
1178 std::vector<std::vector<uint8_t>> data;
1184 return std::make_unique<PKDescriptor>(
1185 InferPubkey(pubkey,
ctx, provider));
1192 if (provider.
GetPubKey(keyid, pubkey)) {
1193 return std::make_unique<PKHDescriptor>(
1194 InferPubkey(pubkey,
ctx, provider));
1198 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1199 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1201 providers.push_back(InferPubkey(pubkey,
ctx, provider));
1203 return std::make_unique<MultisigDescriptor>((
int)data[0][0],
1204 std::move(providers));
1210 if (provider.
GetCScript(scriptid, subscript)) {
1212 InferScript(subscript, ParseScriptContext::P2SH, provider);
1214 return std::make_unique<SHDescriptor>(std::move(sub));
1222 return std::make_unique<AddressDescriptor>(std::move(dest));
1226 return std::make_unique<RawDescriptor>(
script);
1235 std::string &error, std::string *out_checksum =
nullptr) {
1236 auto check_split =
Split(sp,
'#');
1237 if (check_split.size() > 2) {
1238 error =
"Multiple '#' symbols";
1241 if (check_split.size() == 1 && require_checksum) {
1242 error =
"Missing checksum";
1245 if (check_split.size() == 2) {
1246 if (check_split[1].size() != 8) {
1248 strprintf(
"Expected 8 character checksum, not %u characters",
1249 check_split[1].size());
1253 auto checksum = DescriptorChecksum(check_split[0]);
1254 if (checksum.empty()) {
1255 error =
"Invalid characters in payload";
1258 if (check_split.size() == 2) {
1259 if (!std::equal(checksum.begin(), checksum.end(),
1260 check_split[1].begin())) {
1262 "Provided checksum '%s' does not match computed checksum '%s'",
1263 std::string(check_split[1].begin(), check_split[1].end()),
1269 *out_checksum = std::move(checksum);
1271 sp = check_split[0];
1275std::unique_ptr<Descriptor>
Parse(
const std::string &descriptor,
1277 bool require_checksum) {
1282 auto ret =
ParseScript(0, sp, ParseScriptContext::TOP,
out, error);
1283 if (sp.
size() == 0 && ret) {
1284 return std::unique_ptr<Descriptor>(std::move(ret));
1301 return InferScript(
script, ParseScriptContext::TOP, provider);
1313 xpubs[der_index] = xpub;
1333 const auto &der_it = key_exp_it->second.find(der_index);
1334 if (der_it == key_exp_it->second.end()) {
1337 xpub = der_it->second;
1345std::unordered_map<uint32_t, ExtPubKeyMap>
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
const CChainParams & Params()
Return the currently selected parameters.
An encapsulated secp256k1 private key.
bool IsValid() const
Check whether this private key is valid.
CPubKey GetPubKey() const
Compute the public key from a private key.
A reference to a CKey: the Hash160 of its serialized public key.
An encapsulated public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
A reference to a CScript: the Hash160 of its serialization.
Cache for single descriptor's derived extended pubkeys.
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
std::unordered_map< uint32_t, ExtPubKeyMap > m_derived_xpubs
Map key expression index -> map of (key derivation index -> xpub)
ExtPubKeyMap m_parent_xpubs
Map key expression index -> parent xpub.
An interface to be implemented by keystores that support signing.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
virtual bool GetKey(const CKeyID &address, CKey &key) const
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
constexpr C * begin() const noexcept
constexpr C * end() const noexcept
constexpr uint8_t * begin()
const Config & GetConfig()
CScript ParseScript(const std::string &s)
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
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.
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
std::string EncodeExtKey(const CExtKey &key)
CExtPubKey DecodeExtPubKey(const std::string &str)
std::string EncodeSecret(const CKey &key)
CTxDestination DecodeDestination(const std::string &addr, const CChainParams ¶ms)
CKey DecodeSecret(const std::string &str)
std::string EncodeExtPubKey(const CExtPubKey &key)
CExtKey DecodeExtKey(const std::string &str)
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
Implement std::hash so RCUPtr can be used as a key for maps or sets.
std::vector< T > Split(const Span< const char > &sp, std::string_view separators)
Split a string on any char found in separators, returning a vector.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
static std::string ToString(const CService &ip)
bool IsSolvable(const SigningProvider &provider, const CScript &script)
Check whether we know how to sign for an output like this, assuming we have all private keys.
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
const SigningProvider & DUMMY_SIGNING_PROVIDER
FlatSigningProvider Merge(const FlatSigningProvider &a, const FlatSigningProvider &b)
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< uint8_t > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
CExtPubKey Neuter() const
bool Derive(CExtKey &out, unsigned int nChild) const
uint8_t vchFingerprint[4]
bool Derive(CExtPubKey &out, unsigned int nChild) const
Interface for parsed descriptor objects.
virtual std::string ToString() const =0
Convert the descriptor back to a string, undoing parsing.
virtual std::optional< OutputType > GetOutputType() const =0
virtual bool Expand(int pos, const SigningProvider &provider, std::vector< CScript > &output_scripts, FlatSigningProvider &out, DescriptorCache *write_cache=nullptr) 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 IsSolvable() const =0
Whether this descriptor has all information about signing ignoring lack of private keys.
virtual void ExpandPrivate(int pos, const SigningProvider &provider, FlatSigningProvider &out) const =0
Expand the private key for a descriptor at a specified position, if possible.
virtual bool ToPrivateString(const SigningProvider &provider, std::string &out) const =0
Convert the descriptor to a private string.
virtual bool ExpandFromCache(int pos, const DescriptorCache &read_cache, std::vector< CScript > &output_scripts, FlatSigningProvider &out) const =0
Expand a descriptor at a specified position using cached expansion data.
std::vector< uint32_t > path
uint8_t fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
template std::vector< std::byte > ParseHex(std::string_view)
bool IsHex(std::string_view str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
bool ParseUInt32(std::string_view str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
std::vector< typename std::common_type< Args... >::type > Vector(Args &&...args)
Construct a vector with the specified elements.