7#include <chainparams.h>
88uint64_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];
171std::string AddChecksum(
const std::string &str) {
172 return str +
"#" + DescriptorChecksum(str);
179typedef std::vector<uint32_t> KeyPath;
182struct 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;
227class 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);
275class 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);
310enum class DeriveType {
317class 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();
596 if (m_subdescriptor_arg) {
601 if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) {
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);
711class 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; }
744class RawDescriptor final :
public DescriptorImpl {
745 const CScript m_script;
748 std::string ToStringExtra()
const override {
return HexStr(m_script); }
749 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
756 RawDescriptor(CScript script)
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; }
776class 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; }
791class 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; }
811class 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; }
833class 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; }
863class SHDescriptor final :
public DescriptorImpl {
865 std::vector<CScript> MakeScripts(
const std::vector<CPubKey> &,
866 const CScript *script,
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; }
884enum 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));
918std::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() ==
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) {
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));
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)) {
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()));
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) {
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];
1277std::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;
1347const std::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.
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_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 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 error(const char *fmt, const Args &...args)
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.
std::vector< T > Split(const Span< const char > &sp, char sep)
Split a string on every instance of sep, returning a vector.
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.
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)
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.
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.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
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.