88 uint64_t PolyMod(uint64_t c,
int val) {
90 c = ((c & 0x7ffffffff) << 5) ^ val;
128 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~" 129 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
132 static std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
137 for (
auto ch : span) {
138 auto pos = INPUT_CHARSET.find(ch);
139 if (pos == std::string::npos) {
143 c = PolyMod(c, pos & 31);
145 cls = cls * 3 + (pos >> 5);
146 if (++clscount == 3) {
157 for (
int j = 0; j < 8; ++j) {
164 std::string ret(8,
' ');
165 for (
int j = 0; j < 8; ++j) {
166 ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
171 std::string AddChecksum(
const std::string &str) {
172 return str +
"#" + DescriptorChecksum(
MakeSpan(str));
179 typedef std::vector<uint32_t> KeyPath;
182 struct PubkeyProvider {
187 uint32_t m_expr_index;
190 PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
192 virtual ~PubkeyProvider() =
default;
207 virtual bool IsRange()
const = 0;
210 virtual size_t GetSize()
const = 0;
213 virtual std::string
ToString()
const = 0;
220 std::string &out)
const = 0;
224 CKey &key)
const = 0;
227 class OriginPubkeyProvider final :
public PubkeyProvider {
229 std::unique_ptr<PubkeyProvider> m_provider;
231 std::string OriginString()
const {
232 return HexStr(std::begin(m_origin.fingerprint),
233 std::end(m_origin.fingerprint)) +
239 std::unique_ptr<PubkeyProvider> provider)
240 : PubkeyProvider(exp_index), m_origin(
std::move(info)),
241 m_provider(
std::move(provider)) {}
246 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache,
250 std::copy(std::begin(m_origin.fingerprint),
252 info.
path.insert(info.
path.begin(), m_origin.path.begin(),
253 m_origin.path.end());
256 bool IsRange()
const override {
return m_provider->IsRange(); }
257 size_t GetSize()
const override {
return m_provider->GetSize(); }
258 std::string
ToString()
const override {
259 return "[" + OriginString() +
"]" + m_provider->ToString();
262 std::string &ret)
const override {
264 if (!m_provider->ToPrivateString(arg, sub)) {
267 ret =
"[" + OriginString() +
"]" + std::move(sub);
271 CKey &key)
const override {
272 return m_provider->GetPrivKey(pos, arg, key);
277 class ConstPubkeyProvider final :
public PubkeyProvider {
281 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey &pubkey)
282 : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
289 CKeyID keyid = m_pubkey.GetID();
294 bool IsRange()
const override {
return false; }
295 size_t GetSize()
const override {
return m_pubkey.size(); }
296 std::string
ToString()
const override {
297 return HexStr(m_pubkey.begin(), m_pubkey.end());
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);
321 class 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,
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()) {
567 bool IsRange()
const final {
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();
598 ret += std::move(tmp);
600 if (m_subdescriptor_arg) {
605 if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) {
608 ret += std::move(tmp);
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 override final {
622 bool ret = ToStringHelper(&arg, out,
true);
623 out = AddChecksum(out);
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,
652 out =
Merge(out, 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);
705 out =
Merge(out, subprovider);
709 std::optional<OutputType> GetOutputType()
const override {
715 class 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.which()) {
744 bool IsSingleType()
const final {
return true; }
748 class RawDescriptor final :
public DescriptorImpl {
752 std::string ToStringExtra()
const override {
753 return HexStr(m_script.begin(), m_script.end());
755 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
763 : DescriptorImpl({}, {},
"raw"), m_script(std::move(script)) {}
764 bool IsSolvable()
const final {
return false; }
766 std::optional<OutputType> GetOutputType()
const override {
769 switch (dest.which()) {
778 bool IsSingleType()
const final {
return true; }
782 class PKDescriptor final :
public DescriptorImpl {
784 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
791 PKDescriptor(std::unique_ptr<PubkeyProvider> prov)
792 : DescriptorImpl(
Vector(std::move(prov)), {},
"pk") {}
793 bool IsSingleType()
const final {
return true; }
797 class PKHDescriptor final :
public DescriptorImpl {
799 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
802 CKeyID id = keys[0].GetID();
803 out.
pubkeys.emplace(
id, keys[0]);
808 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov)
809 : DescriptorImpl(
Vector(std::move(prov)), {},
"pkh") {}
810 std::optional<OutputType> GetOutputType()
const override {
813 bool IsSingleType()
const final {
return true; }
817 class ComboDescriptor final :
public DescriptorImpl {
819 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
822 std::vector<CScript> ret;
823 CKeyID id = keys[0].GetID();
824 out.
pubkeys.emplace(
id, keys[0]);
833 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov)
834 : DescriptorImpl(
Vector(std::move(prov)), {},
"combo") {}
835 bool IsSingleType()
const final {
return false; }
839 class MultisigDescriptor final :
public DescriptorImpl {
840 const int m_threshold;
844 std::string ToStringExtra()
const override {
847 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
851 std::vector<CPubKey> sorted_keys(keys);
852 std::sort(sorted_keys.begin(), sorted_keys.end());
859 MultisigDescriptor(
int threshold,
860 std::vector<std::unique_ptr<PubkeyProvider>> providers,
862 : DescriptorImpl(std::move(providers), {},
863 sorted ?
"sortedmulti" :
"multi"),
864 m_threshold(threshold), m_sorted(sorted) {}
865 bool IsSingleType()
const final {
return true; }
869 class SHDescriptor final :
public DescriptorImpl {
871 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
878 SHDescriptor(std::unique_ptr<DescriptorImpl> desc)
879 : DescriptorImpl({}, std::move(desc),
"sh") {}
880 std::optional<OutputType> GetOutputType()
const override {
883 bool IsSingleType()
const final {
return true; }
900 KeyPath &out, std::string &
error) {
901 for (
size_t i = 1; i < split.size(); ++i) {
903 bool hardened =
false;
904 if (elem.
size() > 0 &&
905 (elem[elem.
size() - 1] ==
'\'' || elem[elem.
size() - 1] ==
'h')) {
911 error =
strprintf(
"Key path value '%s' is not a valid uint32",
912 std::string(elem.
begin(), elem.
end()).c_str());
914 }
else if (p > 0x7FFFFFFFUL) {
915 error =
strprintf(
"Key path value %u is out of range", p);
918 out.push_back(p | (uint32_t(hardened) << 31));
924 std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
927 std::string &error) {
930 auto split =
Split(sp,
'/');
931 std::string str(split[0].begin(), split[0].end());
932 if (str.size() == 0) {
933 error =
"No key provided";
936 if (split.size() == 1) {
938 std::vector<uint8_t> data =
ParseHex(str);
941 return std::make_unique<ConstPubkeyProvider>(key_exp_index,
944 error =
strprintf(
"Pubkey '%s' is invalid", str);
951 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey);
957 error =
strprintf(
"key '%s' is not valid", str);
962 if (split.back() ==
MakeSpan(
"*").first(1)) {
964 type = DeriveType::UNHARDENED;
965 }
else if (split.back() ==
MakeSpan(
"*'").first(2) ||
966 split.back() ==
MakeSpan(
"*h").first(2)) {
968 type = DeriveType::HARDENED;
970 if (!ParseKeyPath(split, path, error)) {
973 if (extkey.key.IsValid()) {
974 extpubkey = extkey.Neuter();
977 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey,
978 std::move(path), type);
982 std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index,
985 std::string &error) {
988 auto origin_split =
Split(sp,
']');
989 if (origin_split.size() > 2) {
990 error =
"Multiple ']' characters found for a single pubkey";
993 if (origin_split.size() == 1) {
994 return ParsePubkeyInner(key_exp_index, origin_split[0], out, error);
996 if (origin_split[0].size() < 1 || origin_split[0][0] !=
'[') {
997 error =
strprintf(
"Key origin start '[ character expected but not " 998 "found, got '%c' instead",
1002 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
1003 if (slash_split[0].size() != 8) {
1004 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead " 1006 slash_split[0].size());
1009 std::string fpr_hex =
1010 std::string(slash_split[0].begin(), slash_split[0].end());
1011 if (!
IsHex(fpr_hex)) {
1012 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
1015 auto fpr_bytes =
ParseHex(fpr_hex);
1017 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1018 assert(fpr_bytes.size() == 4);
1019 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1020 if (!ParseKeyPath(slash_split, info.
path, error)) {
1024 ParsePubkeyInner(key_exp_index, origin_split[1], out, error);
1028 return std::make_unique<OriginPubkeyProvider>(
1029 key_exp_index, std::move(info), std::move(provider));
1033 std::unique_ptr<DescriptorImpl>
ParseScript(uint32_t key_exp_index,
1037 std::string &error) {
1040 auto expr =
Expr(sp);
1041 bool sorted_multi =
false;
1042 if (
Func(
"pk", expr)) {
1043 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1047 return std::make_unique<PKDescriptor>(std::move(pubkey));
1049 if (
Func(
"pkh", expr)) {
1050 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1054 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1056 if (ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1057 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1061 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1062 }
else if (ctx != ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1063 error =
"Cannot have combo in non-top level";
1066 if ((sorted_multi =
Func(
"sortedmulti", expr)) ||
Func(
"multi", expr)) {
1067 auto threshold =
Expr(expr);
1069 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1070 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()),
1073 "Multi threshold '%s' is not valid",
1074 std::string(threshold.begin(), threshold.end()).c_str());
1077 size_t script_size = 0;
1078 while (expr.size()) {
1079 if (!
Const(
",", expr)) {
1080 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
1083 auto arg =
Expr(expr);
1084 auto pk = ParsePubkey(key_exp_index, arg, out, error);
1088 script_size += pk->GetSize() + 1;
1089 providers.emplace_back(std::move(pk));
1092 if (providers.size() < 1 || providers.size() > 16) {
1093 error =
strprintf(
"Cannot have %u keys in multisig; must have " 1094 "between 1 and 16 keys, inclusive",
1097 }
else if (thres < 1) {
1099 "Multisig threshold cannot be %d, must be at least 1", thres);
1101 }
else if (thres > providers.size()) {
1103 strprintf(
"Multisig threshold cannot be larger than the number " 1104 "of keys; threshold is %d but only %u keys specified",
1105 thres, providers.size());
1108 if (ctx == ParseScriptContext::TOP) {
1109 if (providers.size() > 3) {
1110 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; " 1111 "only at most 3 pubkeys",
1116 if (ctx == ParseScriptContext::P2SH) {
1118 error =
strprintf(
"P2SH script is too large, %d bytes is " 1119 "larger than %d bytes",
1124 return std::make_unique<MultisigDescriptor>(thres, std::move(providers),
1127 if (ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1128 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
1130 if (!desc || expr.size()) {
1133 return std::make_unique<SHDescriptor>(std::move(desc));
1134 }
else if (ctx != ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1135 error =
"Cannot have sh in non-top level";
1138 if (ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1142 error =
"Address is not valid";
1145 return std::make_unique<AddressDescriptor>(std::move(dest));
1147 if (ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
1148 std::string str(expr.begin(), expr.end());
1150 error =
"Raw script is not hex";
1154 return std::make_unique<RawDescriptor>(
1155 CScript(bytes.begin(), bytes.end()));
1157 if (ctx == ParseScriptContext::P2SH) {
1158 error =
"A function is needed within P2SH";
1161 error =
strprintf(
"%s is not a valid descriptor function",
1162 std::string(expr.begin(), expr.end()));
1166 std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey &pubkey,
1169 std::unique_ptr<PubkeyProvider> key_provider =
1170 std::make_unique<ConstPubkeyProvider>(0, pubkey);
1173 return std::make_unique<OriginPubkeyProvider>(0, std::move(info),
1174 std::move(key_provider));
1176 return key_provider;
1179 std::unique_ptr<DescriptorImpl> InferScript(
const CScript &script,
1182 std::vector<std::vector<uint8_t>> data;
1186 CPubKey pubkey(data[0].begin(), data[0].end());
1188 return std::make_unique<PKDescriptor>(
1189 InferPubkey(pubkey, ctx, provider));
1196 if (provider.
GetPubKey(keyid, pubkey)) {
1197 return std::make_unique<PKHDescriptor>(
1198 InferPubkey(pubkey, ctx, provider));
1202 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1203 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1204 CPubKey pubkey(data[i].begin(), data[i].end());
1205 providers.push_back(InferPubkey(pubkey, ctx, provider));
1207 return std::make_unique<MultisigDescriptor>((int)data[0][0],
1208 std::move(providers));
1210 if (txntype ==
TX_SCRIPTHASH && ctx == ParseScriptContext::TOP) {
1214 if (provider.
GetCScript(scriptid, subscript)) {
1216 InferScript(subscript, ParseScriptContext::P2SH, provider);
1218 return std::make_unique<SHDescriptor>(std::move(sub));
1226 return std::make_unique<AddressDescriptor>(std::move(dest));
1230 return std::make_unique<RawDescriptor>(script);
1239 std::string &
error, std::string *out_checksum =
nullptr) {
1242 auto check_split =
Split(sp,
'#');
1243 if (check_split.size() > 2) {
1244 error =
"Multiple '#' symbols";
1247 if (check_split.size() == 1 && require_checksum) {
1248 error =
"Missing checksum";
1251 if (check_split.size() == 2) {
1252 if (check_split[1].size() != 8) {
1254 strprintf(
"Expected 8 character checksum, not %u characters",
1255 check_split[1].size());
1259 auto checksum = DescriptorChecksum(check_split[0]);
1260 if (checksum.empty()) {
1261 error =
"Invalid characters in payload";
1264 if (check_split.size() == 2) {
1265 if (!std::equal(checksum.begin(), checksum.end(),
1266 check_split[1].begin())) {
1268 "Provided checksum '%s' does not match computed checksum '%s'",
1269 std::string(check_split[1].begin(), check_split[1].end()),
1275 *out_checksum = std::move(checksum);
1277 sp = check_split[0];
1281 std::unique_ptr<Descriptor>
Parse(
const std::string &descriptor,
1283 bool require_checksum) {
1288 auto ret =
ParseScript(0, sp, ParseScriptContext::TOP, out, error);
1289 if (sp.size() == 0 && ret) {
1290 return std::unique_ptr<Descriptor>(std::move(ret));
1307 return InferScript(script, ParseScriptContext::TOP, provider);
1312 m_parent_xpubs[key_exp_pos] = xpub;
1318 auto &xpubs = m_derived_xpubs[key_exp_pos];
1319 xpubs[der_index] = xpub;
1324 const auto &it = m_parent_xpubs.find(key_exp_pos);
1325 if (it == m_parent_xpubs.end()) {
1335 const auto &key_exp_it = m_derived_xpubs.find(key_exp_pos);
1336 if (key_exp_it == m_derived_xpubs.end()) {
1339 const auto &der_it = key_exp_it->second.find(der_index);
1340 if (der_it == key_exp_it->second.end()) {
1343 xpub = der_it->second;
1348 return m_parent_xpubs;
1351 const std::unordered_map<uint32_t, ExtPubKeyMap>
1353 return m_derived_xpubs;
txnouttype Solver(const CScript &scriptPubKey, std::vector< std::vector< uint8_t >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
constexpr std::ptrdiff_t size() 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.
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.
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.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
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)
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
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.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
constexpr Span< A > MakeSpan(A(&a)[N])
Create a span to a container exposing data() and 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
An encapsulated public key.
bool IsHex(const std::string &str)
Returns true if each character in str is a hex character, and has an even number of hex digits...
std::map< CKeyID, CPubKey > pubkeys
uint8_t vchFingerprint[4]
const Config & GetConfig()
CTxDestination DecodeDestination(const std::string &addr, const CChainParams ¶ms)
constexpr Span< C > first(std::ptrdiff_t count) const noexcept
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
virtual bool GetKey(const CKeyID &address, CKey &key) const
bool IsSolvable(const SigningProvider &provider, const CScript &script)
Check whether we know how to sign for an output like this, assuming we have all private keys...
constexpr C * begin() const noexcept
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
const CChainParams & Params()
Return the currently selected parameters.
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.
std::vector< uint8_t > ParseHex(const char *psz)
A reference to a CKey: the Hash160 of its serialized public key.
std::string HexStr(const T itbegin, const T itend)
A reference to a CScript: the Hash160 of its serialization (see script.h)
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
An encapsulated secp256k1 private key.
A Span is an object that can refer to a contiguous sequence of objects.
CKey DecodeSecret(const std::string &str)
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)
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Interface for parsed descriptor objects.
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.
uint8_t fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.