7#include <chainparams.h>
90uint64_t PolyMod(uint64_t c,
int val) {
92 c = ((c & 0x7ffffffff) << 5) ^ val;
129 static std::string INPUT_CHARSET =
"0123456789()[],'/*abcdefgh@:$%{}"
130 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
131 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
134 static std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
139 for (
auto ch : span) {
140 auto pos = INPUT_CHARSET.find(ch);
141 if (pos == std::string::npos) {
145 c = PolyMod(c, pos & 31);
147 cls = cls * 3 + (pos >> 5);
148 if (++clscount == 3) {
159 for (
int j = 0; j < 8; ++j) {
166 std::string ret(8,
' ');
167 for (
int j = 0; j < 8; ++j) {
168 ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
173std::string AddChecksum(
const std::string &str) {
174 return str +
"#" + DescriptorChecksum(str);
181typedef std::vector<uint32_t> KeyPath;
184struct PubkeyProvider {
189 uint32_t m_expr_index;
192 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
194 virtual ~PubkeyProvider() =
default;
209 virtual bool IsRange()
const = 0;
212 virtual size_t GetSize()
const = 0;
215 virtual std::string
ToString()
const = 0;
222 std::string &out)
const = 0;
226 CKey &key)
const = 0;
229class OriginPubkeyProvider final :
public PubkeyProvider {
231 std::unique_ptr<PubkeyProvider> m_provider;
233 std::string OriginString()
const {
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);
277class 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 {
return HexStr(m_pubkey); }
298 std::string &ret)
const override {
300 if (!arg.
GetKey(m_pubkey.GetID(), key)) {
307 CKey &key)
const override {
308 return arg.
GetKey(m_pubkey.GetID(), key);
312enum class DeriveType {
319class BIP32PubkeyProvider final :
public PubkeyProvider {
330 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key)) {
333 ret.
nDepth = m_root_extkey.nDepth;
334 std::copy(m_root_extkey.vchFingerprint,
337 ret.
nChild = m_root_extkey.nChild;
345 if (!GetExtKey(arg, xprv)) {
348 for (
auto entry : m_path) {
354 bool IsHardened()
const {
355 if (m_derive == DeriveType::HARDENED) {
358 for (
auto entry : m_path) {
367 BIP32PubkeyProvider(uint32_t exp_index,
const CExtPubKey &extkey,
368 KeyPath path, DeriveType derive)
369 : PubkeyProvider(exp_index), m_root_extkey(extkey),
370 m_path(
std::move(path)), m_derive(derive) {}
371 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
372 size_t GetSize()
const override {
return 33; }
379 CKeyID keyid = m_root_extkey.pubkey.GetID();
380 std::copy(keyid.
begin(),
383 parent_info.
path = m_path;
388 if (m_derive == DeriveType::UNHARDENED) {
389 final_info_out_tmp.
path.push_back((uint32_t)pos);
391 if (m_derive == DeriveType::HARDENED) {
392 final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
400 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos,
402 if (m_derive == DeriveType::HARDENED) {
406 if (!read_cache->GetCachedParentExtPubKey(m_expr_index,
410 final_extkey = parent_extkey;
411 if (m_derive == DeriveType::UNHARDENED) {
412 der = parent_extkey.
Derive(final_extkey, pos);
416 m_derive != DeriveType::HARDENED) {
417 parent_extkey = final_extkey = m_cached_xpub;
418 if (m_derive == DeriveType::UNHARDENED) {
419 der = parent_extkey.
Derive(final_extkey, pos);
421 }
else if (IsHardened()) {
423 if (!GetDerivedExtKey(arg, xprv)) {
426 parent_extkey = xprv.
Neuter();
427 if (m_derive == DeriveType::UNHARDENED) {
428 der = xprv.
Derive(xprv, pos);
430 if (m_derive == DeriveType::HARDENED) {
431 der = xprv.
Derive(xprv, pos | 0x80000000UL);
433 final_extkey = xprv.
Neuter();
435 for (
auto entry : m_path) {
436 der = parent_extkey.
Derive(parent_extkey, entry);
439 final_extkey = parent_extkey;
440 if (m_derive == DeriveType::UNHARDENED) {
441 der = parent_extkey.
Derive(final_extkey, pos);
443 assert(m_derive != DeriveType::HARDENED);
447 final_info_out = final_info_out_tmp;
448 key_out = final_extkey.
pubkey;
454 m_cached_xpub = parent_extkey;
459 if (m_derive != DeriveType::HARDENED) {
460 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
461 }
else if (final_info_out.
path.size() > 0) {
462 write_cache->CacheDerivedExtPubKey(m_expr_index, pos,
469 std::string
ToString()
const override {
474 if (m_derive == DeriveType::HARDENED) {
481 std::string &out)
const override {
483 if (!GetExtKey(arg, key)) {
489 if (m_derive == DeriveType::HARDENED) {
496 CKey &key)
const override {
498 if (!GetDerivedExtKey(arg, extkey)) {
501 if (m_derive == DeriveType::UNHARDENED) {
502 extkey.
Derive(extkey, pos);
504 if (m_derive == DeriveType::HARDENED) {
505 extkey.
Derive(extkey, pos | 0x80000000UL);
516 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
518 const std::string m_name;
524 const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
528 virtual std::string ToStringExtra()
const {
return ""; }
545 virtual std::vector<CScript>
546 MakeScripts(
const std::vector<CPubKey> &pubkeys,
const CScript *
script,
550 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
551 std::unique_ptr<DescriptorImpl>
script,
552 const std::string &
name)
553 : m_pubkey_args(
std::move(pubkeys)), m_name(
name),
554 m_subdescriptor_arg(
std::move(
script)) {}
557 if (m_subdescriptor_arg) {
558 if (!m_subdescriptor_arg->IsSolvable()) {
566 for (
const auto &pubkey : m_pubkey_args) {
567 if (pubkey->IsRange()) {
571 if (m_subdescriptor_arg) {
572 if (m_subdescriptor_arg->IsRange()) {
581 std::string extra = ToStringExtra();
582 size_t pos = extra.size() > 0 ? 1 : 0;
583 std::string ret = m_name +
"(" + extra;
584 for (
const auto &pubkey : m_pubkey_args) {
590 if (!pubkey->ToPrivateString(*arg, tmp)) {
594 tmp = pubkey->ToString();
598 if (m_subdescriptor_arg) {
603 if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) {
608 out = std::move(ret) +
")";
612 std::string
ToString() const final {
614 ToStringHelper(
nullptr, ret,
false);
615 return AddChecksum(ret);
619 std::string &out)
const final {
620 bool ret = ToStringHelper(&arg, out,
true);
621 out = AddChecksum(out);
627 std::vector<CScript> &output_scripts,
630 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
631 entries.reserve(m_pubkey_args.size());
635 for (
const auto &p : m_pubkey_args) {
636 entries.emplace_back();
637 if (!p->GetPubKey(pos, arg, entries.back().first,
638 entries.back().second, read_cache, write_cache)) {
642 std::vector<CScript> subscripts;
643 if (m_subdescriptor_arg) {
645 if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache,
646 subscripts, subprovider,
650 out =
Merge(out, subprovider);
653 std::vector<CPubKey> pubkeys;
654 pubkeys.reserve(entries.size());
655 for (
auto &entry : entries) {
656 pubkeys.push_back(entry.first);
659 std::make_pair<CPubKey, KeyOriginInfo>(
660 CPubKey(entry.first), std::move(entry.second)));
662 if (m_subdescriptor_arg) {
663 for (
const auto &subscript : subscripts) {
665 std::vector<CScript> addscripts =
666 MakeScripts(pubkeys, &subscript, out);
667 for (
auto &addscript : addscripts) {
668 output_scripts.push_back(std::move(addscript));
672 output_scripts = MakeScripts(pubkeys,
nullptr, out);
680 return ExpandHelper(pos, provider,
nullptr, output_scripts, out,
685 std::vector<CScript> &output_scripts,
688 output_scripts, out,
nullptr);
693 for (
const auto &p : m_pubkey_args) {
695 if (!p->GetPrivKey(pos, provider, key)) {
700 if (m_subdescriptor_arg) {
702 m_subdescriptor_arg->ExpandPrivate(pos, provider, subprovider);
703 out =
Merge(out, subprovider);
713class AddressDescriptor final :
public DescriptorImpl {
717 std::string ToStringExtra()
const override {
720 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
728 : DescriptorImpl({}, {},
"addr"),
729 m_destination(std::move(destination)) {}
730 bool IsSolvable() const final {
return false; }
732 std::optional<OutputType> GetOutputType()
const override {
733 switch (m_destination.index()) {
742 bool IsSingleType() const final {
return true; }
746class RawDescriptor final :
public DescriptorImpl {
747 const CScript m_script;
750 std::string ToStringExtra()
const override {
return HexStr(m_script); }
751 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
758 RawDescriptor(CScript
script)
759 : DescriptorImpl({}, {},
"raw"), m_script(std::move(
script)) {}
760 bool IsSolvable() const final {
return false; }
762 std::optional<OutputType> GetOutputType()
const override {
765 switch (dest.index()) {
774 bool IsSingleType() const final {
return true; }
778class PKDescriptor final :
public DescriptorImpl {
780 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
787 PKDescriptor(std::unique_ptr<PubkeyProvider> prov)
788 : DescriptorImpl(
Vector(
std::move(prov)), {},
"pk") {}
789 bool IsSingleType() const final {
return true; }
793class PKHDescriptor final :
public DescriptorImpl {
795 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
798 CKeyID id = keys[0].GetID();
799 out.
pubkeys.emplace(
id, keys[0]);
804 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov)
805 : DescriptorImpl(
Vector(
std::move(prov)), {},
"pkh") {}
806 std::optional<OutputType> GetOutputType()
const override {
809 bool IsSingleType() const final {
return true; }
813class ComboDescriptor final :
public DescriptorImpl {
815 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
818 std::vector<CScript> ret;
819 CKeyID id = keys[0].GetID();
820 out.
pubkeys.emplace(
id, keys[0]);
829 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov)
830 : DescriptorImpl(
Vector(
std::move(prov)), {},
"combo") {}
831 bool IsSingleType() const final {
return false; }
835class MultisigDescriptor final :
public DescriptorImpl {
836 const int m_threshold;
840 std::string ToStringExtra()
const override {
843 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
847 std::vector<CPubKey> sorted_keys(keys);
848 std::sort(sorted_keys.begin(), sorted_keys.end());
855 MultisigDescriptor(
int threshold,
856 std::vector<std::unique_ptr<PubkeyProvider>> providers,
858 : DescriptorImpl(
std::move(providers), {},
859 sorted ?
"sortedmulti" :
"multi"),
860 m_threshold(threshold), m_sorted(sorted) {}
861 bool IsSingleType() const final {
return true; }
865class SHDescriptor final :
public DescriptorImpl {
867 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
874 SHDescriptor(std::unique_ptr<DescriptorImpl> desc)
875 : DescriptorImpl({}, std::move(desc),
"sh") {}
876 std::optional<OutputType> GetOutputType()
const override {
879 bool IsSingleType() const final {
return true; }
886enum class ParseScriptContext {
896 KeyPath &out, std::string &error) {
897 for (
size_t i = 1; i < split.size(); ++i) {
899 bool hardened =
false;
900 if (elem.
size() > 0 &&
901 (elem[elem.
size() - 1] ==
'\'' || elem[elem.
size() - 1] ==
'h')) {
907 error =
strprintf(
"Key path value '%s' is not a valid uint32",
908 std::string(elem.
begin(), elem.
end()).c_str());
910 }
else if (p > 0x7FFFFFFFUL) {
911 error =
strprintf(
"Key path value %u is out of range", p);
914 out.push_back(p | (uint32_t(hardened) << 31));
920std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
923 std::string &error) {
924 auto split =
Split(sp,
'/');
925 std::string str(split[0].begin(), split[0].end());
926 if (str.size() == 0) {
927 error =
"No key provided";
930 if (split.size() == 1) {
932 std::vector<uint8_t> data =
ParseHex(str);
934 if (pubkey.IsFullyValid()) {
935 return std::make_unique<ConstPubkeyProvider>(key_exp_index,
938 error =
strprintf(
"Pubkey '%s' is invalid", str);
945 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey);
951 error =
strprintf(
"key '%s' is not valid", str);
955 DeriveType type = DeriveType::NO;
956 if (split.back() ==
Span{
"*"}.
first(1)) {
958 type = DeriveType::UNHARDENED;
959 }
else if (split.back() ==
Span{
"*'"}.
first(2) ||
962 type = DeriveType::HARDENED;
964 if (!ParseKeyPath(split, path, error)) {
968 extpubkey = extkey.
Neuter();
971 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey,
972 std::move(path), type);
976std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index,
979 std::string &error) {
980 auto origin_split =
Split(sp,
']');
981 if (origin_split.size() > 2) {
982 error =
"Multiple ']' characters found for a single pubkey";
985 if (origin_split.size() == 1) {
986 return ParsePubkeyInner(key_exp_index, origin_split[0], out, error);
988 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
989 error =
strprintf(
"Key origin start '[ character expected but not "
990 "found, got '%c' instead",
991 origin_split[0].empty()
993 : origin_split[0][0]);
996 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
997 if (slash_split[0].size() != 8) {
998 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead "
1000 slash_split[0].size());
1003 std::string fpr_hex =
1004 std::string(slash_split[0].begin(), slash_split[0].end());
1005 if (!
IsHex(fpr_hex)) {
1006 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
1009 auto fpr_bytes =
ParseHex(fpr_hex);
1011 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1012 assert(fpr_bytes.size() == 4);
1013 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1014 if (!ParseKeyPath(slash_split, info.
path, error)) {
1018 ParsePubkeyInner(key_exp_index, origin_split[1], out, error);
1022 return std::make_unique<OriginPubkeyProvider>(
1023 key_exp_index, std::move(info), std::move(provider));
1027std::unique_ptr<DescriptorImpl>
ParseScript(uint32_t key_exp_index,
1029 ParseScriptContext
ctx,
1031 std::string &error) {
1034 auto expr =
Expr(sp);
1035 bool sorted_multi =
false;
1036 if (
Func(
"pk", expr)) {
1037 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1041 return std::make_unique<PKDescriptor>(std::move(pubkey));
1043 if (
Func(
"pkh", expr)) {
1044 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1048 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1050 if (
ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1051 auto pubkey = ParsePubkey(key_exp_index, expr, out, error);
1055 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1056 }
else if (
ctx != ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1057 error =
"Cannot have combo in non-top level";
1060 if ((sorted_multi =
Func(
"sortedmulti", expr)) ||
Func(
"multi", expr)) {
1061 auto threshold =
Expr(expr);
1063 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1064 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()),
1067 "Multi threshold '%s' is not valid",
1068 std::string(threshold.begin(), threshold.end()).c_str());
1071 size_t script_size = 0;
1072 while (expr.size()) {
1073 if (!
Const(
",", expr)) {
1074 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
1077 auto arg =
Expr(expr);
1078 auto pk = ParsePubkey(key_exp_index, arg, out, error);
1082 script_size += pk->GetSize() + 1;
1083 providers.emplace_back(std::move(pk));
1086 if (providers.empty() || providers.size() > 16) {
1087 error =
strprintf(
"Cannot have %u keys in multisig; must have "
1088 "between 1 and 16 keys, inclusive",
1091 }
else if (thres < 1) {
1093 "Multisig threshold cannot be %d, must be at least 1", thres);
1095 }
else if (thres > providers.size()) {
1097 strprintf(
"Multisig threshold cannot be larger than the number "
1098 "of keys; threshold is %d but only %u keys specified",
1099 thres, providers.size());
1102 if (
ctx == ParseScriptContext::TOP) {
1103 if (providers.size() > 3) {
1104 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; "
1105 "only at most 3 pubkeys",
1110 if (
ctx == ParseScriptContext::P2SH) {
1112 error =
strprintf(
"P2SH script is too large, %d bytes is "
1113 "larger than %d bytes",
1118 return std::make_unique<MultisigDescriptor>(thres, std::move(providers),
1121 if (
ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1122 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
1124 if (!desc || expr.size()) {
1127 return std::make_unique<SHDescriptor>(std::move(desc));
1128 }
else if (
ctx != ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1129 error =
"Cannot have sh in non-top level";
1132 if (
ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1136 error =
"Address is not valid";
1139 return std::make_unique<AddressDescriptor>(std::move(dest));
1141 if (
ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
1142 std::string str(expr.begin(), expr.end());
1144 error =
"Raw script is not hex";
1148 return std::make_unique<RawDescriptor>(
1149 CScript(bytes.begin(), bytes.end()));
1151 if (
ctx == ParseScriptContext::P2SH) {
1152 error =
"A function is needed within P2SH";
1155 error =
strprintf(
"%s is not a valid descriptor function",
1156 std::string(expr.begin(), expr.end()));
1160std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey &pubkey,
1163 std::unique_ptr<PubkeyProvider> key_provider =
1164 std::make_unique<ConstPubkeyProvider>(0, pubkey);
1167 return std::make_unique<OriginPubkeyProvider>(0, std::move(info),
1168 std::move(key_provider));
1170 return key_provider;
1173std::unique_ptr<DescriptorImpl> InferScript(
const CScript &
script,
1174 ParseScriptContext
ctx,
1176 std::vector<std::vector<uint8_t>> data;
1182 return std::make_unique<PKDescriptor>(
1183 InferPubkey(pubkey,
ctx, provider));
1190 if (provider.
GetPubKey(keyid, pubkey)) {
1191 return std::make_unique<PKHDescriptor>(
1192 InferPubkey(pubkey,
ctx, provider));
1196 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1197 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1199 providers.push_back(InferPubkey(pubkey,
ctx, provider));
1201 return std::make_unique<MultisigDescriptor>((
int)data[0][0],
1202 std::move(providers));
1208 if (provider.
GetCScript(scriptid, subscript)) {
1210 InferScript(subscript, ParseScriptContext::P2SH, provider);
1212 return std::make_unique<SHDescriptor>(std::move(sub));
1220 return std::make_unique<AddressDescriptor>(std::move(dest));
1224 return std::make_unique<RawDescriptor>(
script);
1233 std::string &error, std::string *out_checksum =
nullptr) {
1234 auto check_split =
Split(sp,
'#');
1235 if (check_split.size() > 2) {
1236 error =
"Multiple '#' symbols";
1239 if (check_split.size() == 1 && require_checksum) {
1240 error =
"Missing checksum";
1243 if (check_split.size() == 2) {
1244 if (check_split[1].size() != 8) {
1246 strprintf(
"Expected 8 character checksum, not %u characters",
1247 check_split[1].size());
1251 auto checksum = DescriptorChecksum(check_split[0]);
1252 if (checksum.empty()) {
1253 error =
"Invalid characters in payload";
1256 if (check_split.size() == 2) {
1257 if (!std::equal(checksum.begin(), checksum.end(),
1258 check_split[1].begin())) {
1260 "Provided checksum '%s' does not match computed checksum '%s'",
1261 std::string(check_split[1].begin(), check_split[1].end()),
1267 *out_checksum = std::move(checksum);
1269 sp = check_split[0];
1273std::unique_ptr<Descriptor>
Parse(
const std::string &descriptor,
1275 bool require_checksum) {
1280 auto ret =
ParseScript(0, sp, ParseScriptContext::TOP, out, error);
1281 if (sp.
size() == 0 && ret) {
1282 return std::unique_ptr<Descriptor>(std::move(ret));
1299 return InferScript(
script, ParseScriptContext::TOP, provider);
1311 xpubs[der_index] = xpub;
1331 const auto &der_it = key_exp_it->second.find(der_index);
1332 if (der_it == key_exp_it->second.end()) {
1335 xpub = der_it->second;
1343std::unordered_map<uint32_t, ExtPubKeyMap>
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 (see script.h)
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
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.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
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.
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.
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::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
std::map< CKeyID, CPubKey > pubkeys
std::map< CKeyID, CKey > keys
std::map< CScriptID, CScript > scripts
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.