88 uint64_t PolyMod(uint64_t c,
int val) {
90 c = ((c & 0x7ffffffff) << 5) ^ val;
127 static std::string INPUT_CHARSET =
"0123456789()[],'/*abcdefgh@:$%{}"
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(str);
179 typedef std::vector<uint32_t> KeyPath;
182 struct PubkeyProvider {
187 uint32_t m_expr_index;
190 explicit 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 {
237 std::unique_ptr<PubkeyProvider> provider)
238 : PubkeyProvider(exp_index), m_origin(std::move(info)),
239 m_provider(std::move(provider)) {}
244 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache,
248 std::copy(std::begin(m_origin.fingerprint),
250 info.
path.insert(info.
path.begin(), m_origin.path.begin(),
251 m_origin.path.end());
254 bool IsRange()
const override {
return m_provider->IsRange(); }
255 size_t GetSize()
const override {
return m_provider->GetSize(); }
256 std::string
ToString()
const override {
257 return "[" + OriginString() +
"]" + m_provider->ToString();
260 std::string &ret)
const override {
262 if (!m_provider->ToPrivateString(arg, sub)) {
265 ret =
"[" + OriginString() +
"]" + std::move(sub);
269 CKey &key)
const override {
270 return m_provider->GetPrivKey(pos, arg, key);
275 class ConstPubkeyProvider final :
public PubkeyProvider {
279 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey &pubkey)
280 : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
287 CKeyID keyid = m_pubkey.GetID();
292 bool IsRange()
const override {
return false; }
293 size_t GetSize()
const override {
return m_pubkey.size(); }
294 std::string
ToString()
const override {
return HexStr(m_pubkey); }
296 std::string &ret)
const override {
298 if (!arg.
GetKey(m_pubkey.GetID(), key)) {
305 CKey &key)
const override {
306 return arg.
GetKey(m_pubkey.GetID(), key);
310 enum class DeriveType {
317 class BIP32PubkeyProvider final :
public PubkeyProvider {
328 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key)) {
331 ret.
nDepth = m_root_extkey.nDepth;
332 std::copy(m_root_extkey.vchFingerprint,
335 ret.
nChild = m_root_extkey.nChild;
343 if (!GetExtKey(arg, xprv)) {
346 for (
auto entry : m_path) {
352 bool IsHardened()
const {
353 if (m_derive == DeriveType::HARDENED) {
356 for (
auto entry : m_path) {
365 BIP32PubkeyProvider(uint32_t exp_index,
const CExtPubKey &extkey,
366 KeyPath path, DeriveType derive)
367 : PubkeyProvider(exp_index), m_root_extkey(extkey),
368 m_path(std::move(path)), m_derive(derive) {}
369 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
370 size_t GetSize()
const override {
return 33; }
377 CKeyID keyid = m_root_extkey.pubkey.GetID();
378 std::copy(keyid.
begin(),
381 parent_info.
path = m_path;
386 if (m_derive == DeriveType::UNHARDENED) {
387 final_info_out_tmp.
path.push_back((uint32_t)pos);
389 if (m_derive == DeriveType::HARDENED) {
390 final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
398 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos,
400 if (m_derive == DeriveType::HARDENED) {
404 if (!read_cache->GetCachedParentExtPubKey(m_expr_index,
408 final_extkey = parent_extkey;
409 if (m_derive == DeriveType::UNHARDENED) {
410 der = parent_extkey.
Derive(final_extkey, pos);
414 m_derive != DeriveType::HARDENED) {
415 parent_extkey = final_extkey = m_cached_xpub;
416 if (m_derive == DeriveType::UNHARDENED) {
417 der = parent_extkey.
Derive(final_extkey, pos);
419 }
else if (IsHardened()) {
421 if (!GetDerivedExtKey(arg, xprv)) {
424 parent_extkey = xprv.
Neuter();
425 if (m_derive == DeriveType::UNHARDENED) {
426 der = xprv.
Derive(xprv, pos);
428 if (m_derive == DeriveType::HARDENED) {
429 der = xprv.
Derive(xprv, pos | 0x80000000UL);
431 final_extkey = xprv.
Neuter();
433 for (
auto entry : m_path) {
434 der = parent_extkey.
Derive(parent_extkey, entry);
437 final_extkey = parent_extkey;
438 if (m_derive == DeriveType::UNHARDENED) {
439 der = parent_extkey.
Derive(final_extkey, pos);
441 assert(m_derive != DeriveType::HARDENED);
445 final_info_out = final_info_out_tmp;
446 key_out = final_extkey.
pubkey;
452 m_cached_xpub = parent_extkey;
457 if (m_derive != DeriveType::HARDENED) {
458 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
459 }
else if (final_info_out.
path.size() > 0) {
460 write_cache->CacheDerivedExtPubKey(m_expr_index, pos,
467 std::string
ToString()
const override {
472 if (m_derive == DeriveType::HARDENED) {
479 std::string &out)
const override {
481 if (!GetExtKey(arg, key)) {
487 if (m_derive == DeriveType::HARDENED) {
494 CKey &key)
const override {
496 if (!GetDerivedExtKey(arg, extkey)) {
499 if (m_derive == DeriveType::UNHARDENED) {
500 extkey.
Derive(extkey, pos);
502 if (m_derive == DeriveType::HARDENED) {
503 extkey.
Derive(extkey, pos | 0x80000000UL);
514 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
516 const std::string m_name;
522 const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
526 virtual std::string ToStringExtra()
const {
return ""; }
543 virtual std::vector<CScript>
544 MakeScripts(
const std::vector<CPubKey> &pubkeys,
const CScript *script,
548 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
549 std::unique_ptr<DescriptorImpl> script,
550 const std::string &
name)
551 : m_pubkey_args(std::move(pubkeys)), m_name(
name),
552 m_subdescriptor_arg(std::move(script)) {}
555 if (m_subdescriptor_arg) {
556 if (!m_subdescriptor_arg->IsSolvable()) {
564 for (
const auto &pubkey : m_pubkey_args) {
565 if (pubkey->IsRange()) {
569 if (m_subdescriptor_arg) {
570 if (m_subdescriptor_arg->IsRange()) {
579 std::string extra = ToStringExtra();
580 size_t pos = extra.size() > 0 ? 1 : 0;
581 std::string ret = m_name +
"(" + extra;
582 for (
const auto &pubkey : m_pubkey_args) {
588 if (!pubkey->ToPrivateString(*arg, tmp)) {
592 tmp = pubkey->ToString();
594 ret += std::move(tmp);
596 if (m_subdescriptor_arg) {
601 if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) {
604 ret += std::move(tmp);
606 out = std::move(ret) +
")";
610 std::string
ToString() const final {
612 ToStringHelper(
nullptr, ret,
false);
613 return AddChecksum(ret);
617 std::string &out)
const final {
618 bool ret = ToStringHelper(&arg, out,
true);
619 out = AddChecksum(out);
625 std::vector<CScript> &output_scripts,
628 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
629 entries.reserve(m_pubkey_args.size());
633 for (
const auto &p : m_pubkey_args) {
634 entries.emplace_back();
635 if (!p->GetPubKey(pos, arg, entries.back().first,
636 entries.back().second, read_cache, write_cache)) {
640 std::vector<CScript> subscripts;
641 if (m_subdescriptor_arg) {
643 if (!m_subdescriptor_arg->ExpandHelper(pos, arg, read_cache,
644 subscripts, subprovider,
648 out =
Merge(out, subprovider);
651 std::vector<CPubKey> pubkeys;
652 pubkeys.reserve(entries.size());
653 for (
auto &entry : entries) {
654 pubkeys.push_back(entry.first);
657 std::make_pair<CPubKey, KeyOriginInfo>(
658 CPubKey(entry.first), std::move(entry.second)));
660 if (m_subdescriptor_arg) {
661 for (
const auto &subscript : subscripts) {
663 std::vector<CScript> addscripts =
664 MakeScripts(pubkeys, &subscript, out);
665 for (
auto &addscript : addscripts) {
666 output_scripts.push_back(std::move(addscript));
670 output_scripts = MakeScripts(pubkeys,
nullptr, out);
678 return ExpandHelper(pos, provider,
nullptr, output_scripts, out,
683 std::vector<CScript> &output_scripts,
686 output_scripts, out,
nullptr);
691 for (
const auto &p : m_pubkey_args) {
693 if (!p->GetPrivKey(pos, provider, key)) {
698 if (m_subdescriptor_arg) {
700 m_subdescriptor_arg->ExpandPrivate(pos, provider, subprovider);
701 out =
Merge(out, subprovider);
711 class AddressDescriptor final :
public DescriptorImpl {
715 std::string ToStringExtra()
const override {
718 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
726 : DescriptorImpl({}, {},
"addr"),
727 m_destination(std::move(destination)) {}
728 bool IsSolvable() const final {
return false; }
730 std::optional<OutputType> GetOutputType()
const override {
731 switch (m_destination.index()) {
740 bool IsSingleType() const final {
return true; }
744 class RawDescriptor final :
public DescriptorImpl {
748 std::string ToStringExtra()
const override {
return HexStr(m_script); }
749 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
757 : DescriptorImpl({}, {},
"raw"), m_script(std::move(script)) {}
758 bool IsSolvable() const final {
return false; }
760 std::optional<OutputType> GetOutputType()
const override {
763 switch (dest.index()) {
772 bool IsSingleType() const final {
return true; }
776 class PKDescriptor final :
public DescriptorImpl {
778 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
785 PKDescriptor(std::unique_ptr<PubkeyProvider> prov)
786 : DescriptorImpl(
Vector(std::move(prov)), {},
"pk") {}
787 bool IsSingleType() const final {
return true; }
791 class PKHDescriptor final :
public DescriptorImpl {
793 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
796 CKeyID id = keys[0].GetID();
797 out.
pubkeys.emplace(
id, keys[0]);
802 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov)
803 : DescriptorImpl(
Vector(std::move(prov)), {},
"pkh") {}
804 std::optional<OutputType> GetOutputType()
const override {
807 bool IsSingleType() const final {
return true; }
811 class ComboDescriptor final :
public DescriptorImpl {
813 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
816 std::vector<CScript> ret;
817 CKeyID id = keys[0].GetID();
818 out.
pubkeys.emplace(
id, keys[0]);
827 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov)
828 : DescriptorImpl(
Vector(std::move(prov)), {},
"combo") {}
829 bool IsSingleType() const final {
return false; }
833 class MultisigDescriptor final :
public DescriptorImpl {
834 const int m_threshold;
838 std::string ToStringExtra()
const override {
841 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &keys,
845 std::vector<CPubKey> sorted_keys(keys);
846 std::sort(sorted_keys.begin(), sorted_keys.end());
853 MultisigDescriptor(
int threshold,
854 std::vector<std::unique_ptr<PubkeyProvider>> providers,
856 : DescriptorImpl(std::move(providers), {},
857 sorted ?
"sortedmulti" :
"multi"),
858 m_threshold(threshold), m_sorted(sorted) {}
859 bool IsSingleType() const final {
return true; }
863 class SHDescriptor final :
public DescriptorImpl {
865 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
872 SHDescriptor(std::unique_ptr<DescriptorImpl> desc)
873 : DescriptorImpl({}, std::move(desc),
"sh") {}
874 std::optional<OutputType> GetOutputType()
const override {
877 bool IsSingleType() const final {
return true; }
884 enum class ParseScriptContext {
894 KeyPath &out, std::string &
error) {
895 for (
size_t i = 1; i < split.size(); ++i) {
897 bool hardened =
false;
898 if (elem.
size() > 0 &&
899 (elem[elem.
size() - 1] ==
'\'' || elem[elem.
size() - 1] ==
'h')) {
906 std::string(elem.
begin(), elem.
end()).c_str());
908 }
else if (p > 0x7FFFFFFFUL) {
912 out.push_back(p | (uint32_t(hardened) << 31));
918 std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
921 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,
945 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey);
955 DeriveType type = DeriveType::NO;
956 if (split.back() ==
MakeSpan(
"*").first(1)) {
958 type = DeriveType::UNHARDENED;
959 }
else if (split.back() ==
MakeSpan(
"*'").first(2) ||
960 split.back() ==
MakeSpan(
"*h").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);
976 std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index,
979 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)) {
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));
1029 std::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)) {
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) {
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) {
1107 "only at most 3 pubkeys",
1112 if (
ctx == ParseScriptContext::P2SH) {
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";
1158 std::string(expr.begin(), expr.end()));
1162 std::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;
1175 std::unique_ptr<DescriptorImpl> InferScript(
const CScript &script,
1176 ParseScriptContext
ctx,
1178 std::vector<std::vector<uint8_t>> data;
1182 CPubKey pubkey(data[0].begin(), data[0].end());
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) {
1200 CPubKey pubkey(data[i].begin(), data[i].end());
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) {
1238 auto check_split =
Split(sp,
'#');
1239 if (check_split.size() > 2) {
1240 error =
"Multiple '#' symbols";
1243 if (check_split.size() == 1 && require_checksum) {
1244 error =
"Missing checksum";
1247 if (check_split.size() == 2) {
1248 if (check_split[1].size() != 8) {
1250 strprintf(
"Expected 8 character checksum, not %u characters",
1251 check_split[1].size());
1255 auto checksum = DescriptorChecksum(check_split[0]);
1256 if (checksum.empty()) {
1257 error =
"Invalid characters in payload";
1260 if (check_split.size() == 2) {
1261 if (!std::equal(checksum.begin(), checksum.end(),
1262 check_split[1].begin())) {
1264 "Provided checksum '%s' does not match computed checksum '%s'",
1265 std::string(check_split[1].begin(), check_split[1].end()),
1271 *out_checksum = std::move(checksum);
1273 sp = check_split[0];
1277 std::unique_ptr<Descriptor>
Parse(
const std::string &descriptor,
1279 bool require_checksum) {
1285 if (sp.
size() == 0 && ret) {
1286 return std::unique_ptr<Descriptor>(std::move(ret));
1303 return InferScript(script, ParseScriptContext::TOP, provider);
1315 xpubs[der_index] = xpub;
1335 const auto &der_it = key_exp_it->second.find(der_index);
1336 if (der_it == key_exp_it->second.end()) {
1339 xpub = der_it->second;
1347 const std::unordered_map<uint32_t, ExtPubKeyMap>
@ TOP
Top-level scriptPubKey.
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)
Serialized script, used inside transaction inputs and outputs.
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.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
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)
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
const std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
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 C * end() const noexcept
constexpr C * begin() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
const Config & GetConfig()
CScript ParseScript(const std::string &s)
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::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
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::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
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)
std::vector< T > Split(const Span< const char > &sp, char sep)
Split a string on every instance of sep, returning a vector.
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
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)
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
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.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< uint8_t >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
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 HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
bool ParseUInt32(const std::string &str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
bool IsHex(const std::string &str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
std::vector< uint8_t > ParseHex(const char *psz)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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.
bool error(const char *fmt, const Args &...args)
std::vector< typename std::common_type< Args... >::type > Vector(Args &&...args)
Construct a vector with the specified elements.