93uint64_t
PolyMod(uint64_t c,
int val)
96 c = ((c & 0x7ffffffff) << 5) ^ val;
97 if (c0 & 1) c ^= 0xf5dee51989;
98 if (c0 & 2) c ^= 0xa9fdca3312;
99 if (c0 & 4) c ^= 0x1bab10e32d;
100 if (c0 & 8) c ^= 0x3706b1677a;
101 if (c0 & 16) c ^= 0x644d626ffd;
120 static const std::string INPUT_CHARSET =
121 "0123456789()[],'/*abcdefgh@:$%{}"
122 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
123 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
126 static const std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
131 for (
auto ch : span) {
132 auto pos = INPUT_CHARSET.find(ch);
133 if (pos == std::string::npos)
return "";
135 cls = cls * 3 + (pos >> 5);
136 if (++clscount == 3) {
143 if (clscount > 0) c =
PolyMod(c, cls);
144 for (
int j = 0; j < 8; ++j) c =
PolyMod(c, 0);
147 std::string
ret(8,
' ');
148 for (
int j = 0; j < 8; ++j)
ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
152std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
158typedef std::vector<uint32_t> KeyPath;
166 uint32_t m_expr_index;
169 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
171 virtual ~PubkeyProvider() =
default;
176 bool operator<(PubkeyProvider& other)
const {
182 other.GetPubKey(0, dummy, b, dummy_info);
195 virtual bool IsRange()
const = 0;
198 virtual size_t GetSize()
const = 0;
200 enum class StringType {
206 virtual std::string
ToString(StringType type=StringType::PUBLIC)
const = 0;
220 virtual std::optional<CPubKey> GetRootPubKey()
const = 0;
222 virtual std::optional<CExtPubKey> GetRootExtPubKey()
const = 0;
225 virtual std::unique_ptr<PubkeyProvider> Clone()
const = 0;
228class OriginPubkeyProvider final :
public PubkeyProvider
231 std::unique_ptr<PubkeyProvider> m_provider;
234 std::string OriginString(StringType type,
bool normalized=
false)
const
237 bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
242 OriginPubkeyProvider(uint32_t exp_index,
KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider,
bool apostrophe) : PubkeyProvider(exp_index), m_origin(
std::move(info)), m_provider(
std::move(provider)), m_apostrophe(apostrophe) {}
245 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache))
return false;
246 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.
fingerprint);
247 info.
path.insert(info.
path.begin(), m_origin.path.begin(), m_origin.path.end());
250 bool IsRange()
const override {
return m_provider->IsRange(); }
251 size_t GetSize()
const override {
return m_provider->GetSize(); }
252 std::string
ToString(StringType type)
const override {
return "[" + OriginString(type) +
"]" + m_provider->ToString(type); }
256 if (!m_provider->ToPrivateString(arg, sub))
return false;
257 ret =
"[" + OriginString(StringType::PUBLIC) +
"]" + std::move(sub);
263 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
269 ret =
"[" + OriginString(StringType::PUBLIC,
true) + std::move(sub);
271 ret =
"[" + OriginString(StringType::PUBLIC,
true) +
"]" + std::move(sub);
277 return m_provider->GetPrivKey(pos, arg, key);
279 std::optional<CPubKey> GetRootPubKey()
const override
281 return m_provider->GetRootPubKey();
283 std::optional<CExtPubKey> GetRootExtPubKey()
const override
285 return m_provider->GetRootExtPubKey();
287 std::unique_ptr<PubkeyProvider> Clone()
const override
289 return std::make_unique<OriginPubkeyProvider>(m_expr_index, m_origin, m_provider->Clone(), m_apostrophe);
294class ConstPubkeyProvider final :
public PubkeyProvider
300 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
305 CKeyID keyid = m_pubkey.GetID();
309 bool IsRange()
const override {
return false; }
310 size_t GetSize()
const override {
return m_pubkey.size(); }
311 std::string
ToString(StringType type)
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
316 for (
const auto& keyid :
XOnlyPubKey(m_pubkey).GetKeyIDs()) {
321 arg.
GetKey(m_pubkey.GetID(), key);
323 if (!key.
IsValid())
return false;
334 return arg.
GetKey(m_pubkey.GetID(), key);
336 std::optional<CPubKey> GetRootPubKey()
const override
340 std::optional<CExtPubKey> GetRootExtPubKey()
const override
344 std::unique_ptr<PubkeyProvider> Clone()
const override
346 return std::make_unique<ConstPubkeyProvider>(m_expr_index, m_pubkey, m_xonly);
350enum class DeriveType {
357class BIP32PubkeyProvider final :
public PubkeyProvider
369 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
370 ret.nDepth = m_root_extkey.nDepth;
371 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
ret.vchFingerprint);
372 ret.nChild = m_root_extkey.nChild;
373 ret.chaincode = m_root_extkey.chaincode;
381 if (!GetExtKey(arg, xprv))
return false;
382 for (
auto entry : m_path) {
383 if (!xprv.
Derive(xprv, entry))
return false;
385 last_hardened = xprv;
391 bool IsHardened()
const
393 if (m_derive == DeriveType::HARDENED)
return true;
394 for (
auto entry : m_path) {
395 if (entry >> 31)
return true;
401 BIP32PubkeyProvider(uint32_t exp_index,
const CExtPubKey& extkey, KeyPath path, DeriveType derive,
bool apostrophe) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(
std::move(path)), m_derive(derive), m_apostrophe(apostrophe) {}
402 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
403 size_t GetSize()
const override {
return 33; }
408 CKeyID keyid = m_root_extkey.pubkey.GetID();
410 parent_info.
path = m_path;
414 if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.
path.push_back((uint32_t)pos);
415 if (m_derive == DeriveType::HARDENED) final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
423 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
424 if (m_derive == DeriveType::HARDENED)
return false;
426 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return false;
427 final_extkey = parent_extkey;
428 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
430 }
else if (IsHardened()) {
433 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
434 parent_extkey = xprv.
Neuter();
435 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
436 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
437 final_extkey = xprv.
Neuter();
439 last_hardened_extkey = lh_xprv.
Neuter();
442 for (
auto entry : m_path) {
443 if (!parent_extkey.
Derive(parent_extkey, entry))
return false;
445 final_extkey = parent_extkey;
446 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
447 assert(m_derive != DeriveType::HARDENED);
449 if (!der)
return false;
451 final_info_out = final_info_out_tmp;
452 key_out = final_extkey.
pubkey;
456 if (m_derive != DeriveType::HARDENED) {
457 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
460 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
462 }
else if (final_info_out.
path.size() > 0) {
463 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
469 std::string
ToString(StringType type,
bool normalized)
const
472 const bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
476 if (m_derive == DeriveType::HARDENED)
ret += use_apostrophe ?
'\'' :
'h';
480 std::string
ToString(StringType type=StringType::PUBLIC)
const override
487 if (!GetExtKey(arg, key))
return false;
491 if (m_derive == DeriveType::HARDENED)
out += m_apostrophe ?
'\'' :
'h';
497 if (m_derive == DeriveType::HARDENED) {
503 int i = (int)m_path.size() - 1;
504 for (; i >= 0; --i) {
505 if (m_path.at(i) >> 31) {
517 for (;
k <= i; ++
k) {
519 origin.
path.push_back(m_path.at(
k));
523 for (;
k < (int)m_path.size(); ++
k) {
524 end_path.push_back(m_path.at(
k));
527 CKeyID id = m_root_extkey.pubkey.GetID();
528 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
533 if (cache !=
nullptr) {
539 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
549 assert(m_derive == DeriveType::UNHARDENED);
557 if (!GetDerivedExtKey(arg, extkey, dummy))
return false;
558 if (m_derive == DeriveType::UNHARDENED && !extkey.
Derive(extkey, pos))
return false;
559 if (m_derive == DeriveType::HARDENED && !extkey.
Derive(extkey, pos | 0x80000000UL))
return false;
563 std::optional<CPubKey> GetRootPubKey()
const override
567 std::optional<CExtPubKey> GetRootExtPubKey()
const override
569 return m_root_extkey;
571 std::unique_ptr<PubkeyProvider> Clone()
const override
573 return std::make_unique<BIP32PubkeyProvider>(m_expr_index, m_root_extkey, m_path, m_derive, m_apostrophe);
582 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
584 const std::string m_name;
590 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
593 virtual std::string ToStringExtra()
const {
return ""; }
608 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
609 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl>
script,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args(
Vector(
std::move(
script))) {}
610 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::vector<std::unique_ptr<DescriptorImpl>> scripts,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args(
std::move(scripts)) {}
612 enum class StringType
623 for (
const auto& arg : m_subdescriptor_args) {
624 if (!arg->IsSolvable())
return false;
632 for (
const auto& pubkey : m_pubkey_args) {
633 if (pubkey->IsRange())
return true;
635 for (
const auto& arg : m_subdescriptor_args) {
636 if (arg->IsRange())
return true;
645 for (
const auto& scriptarg : m_subdescriptor_args) {
646 if (pos++)
ret +=
",";
648 if (!scriptarg->ToStringHelper(arg, tmp, type, cache))
return false;
657 std::string extra = ToStringExtra();
658 size_t pos = extra.size() > 0 ? 1 : 0;
659 std::string
ret = m_name +
"(" + extra;
660 for (
const auto& pubkey : m_pubkey_args) {
661 if (pos++)
ret +=
",";
664 case StringType::NORMALIZED:
665 if (!pubkey->ToNormalizedString(*arg, tmp, cache))
return false;
667 case StringType::PRIVATE:
668 if (!pubkey->ToPrivateString(*arg, tmp))
return false;
670 case StringType::PUBLIC:
671 tmp = pubkey->ToString();
673 case StringType::COMPAT:
674 tmp = pubkey->ToString(PubkeyProvider::StringType::COMPAT);
679 std::string subscript;
680 if (!ToStringSubScriptHelper(arg, subscript, type, cache))
return false;
681 if (pos && subscript.size())
ret +=
',';
682 out = std::move(
ret) + std::move(subscript) +
")";
686 std::string
ToString(
bool compat_format)
const final
689 ToStringHelper(
nullptr,
ret, compat_format ? StringType::COMPAT : StringType::PUBLIC);
690 return AddChecksum(
ret);
695 bool ret = ToStringHelper(&arg,
out, StringType::PRIVATE);
702 bool ret = ToStringHelper(&arg,
out, StringType::NORMALIZED, cache);
710 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
711 entries.reserve(m_pubkey_args.size());
714 for (
const auto& p : m_pubkey_args) {
715 entries.emplace_back();
716 if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache))
return false;
718 std::vector<CScript> subscripts;
720 for (
const auto& subarg : m_subdescriptor_args) {
721 std::vector<CScript> outscripts;
722 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
723 assert(outscripts.size() == 1);
724 subscripts.emplace_back(std::move(outscripts[0]));
726 out.Merge(std::move(subprovider));
728 std::vector<CPubKey> pubkeys;
729 pubkeys.reserve(entries.size());
730 for (
auto& entry : entries) {
731 pubkeys.push_back(entry.first);
732 out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(
CPubKey(entry.first), std::move(entry.second)));
735 output_scripts = MakeScripts(pubkeys,
Span{subscripts},
out);
741 return ExpandHelper(pos, provider,
nullptr, output_scripts,
out, write_cache);
752 for (
const auto& p : m_pubkey_args) {
754 if (!p->GetPrivKey(pos, provider, key))
continue;
757 for (
const auto& arg : m_subdescriptor_args) {
758 arg->ExpandPrivate(pos, provider,
out);
762 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
764 std::optional<int64_t>
ScriptSize()
const override {
return {}; }
771 virtual std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const {
return {}; }
778 void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs)
const override
780 for (
const auto& p : m_pubkey_args) {
781 std::optional<CPubKey> pub = p->GetRootPubKey();
782 if (pub) pubkeys.insert(*pub);
783 std::optional<CExtPubKey> ext_pub = p->GetRootExtPubKey();
784 if (ext_pub) ext_pubs.insert(*ext_pub);
786 for (
const auto& arg : m_subdescriptor_args) {
787 arg->GetPubKeys(pubkeys, ext_pubs);
791 virtual std::unique_ptr<DescriptorImpl> Clone()
const = 0;
795class AddressDescriptor final :
public DescriptorImpl
799 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
802 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
803 bool IsSolvable() const final {
return false; }
809 bool IsSingleType() const final {
return true; }
810 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
813 std::unique_ptr<DescriptorImpl> Clone()
const override
815 return std::make_unique<AddressDescriptor>(m_destination);
820class RawDescriptor final :
public DescriptorImpl
824 std::string ToStringExtra()
const override {
return HexStr(m_script); }
828 bool IsSolvable() const final {
return false; }
836 bool IsSingleType() const final {
return true; }
837 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
839 std::optional<int64_t> ScriptSize()
const override {
return m_script.size(); }
841 std::unique_ptr<DescriptorImpl> Clone()
const override
843 return std::make_unique<RawDescriptor>(m_script);
848class PKDescriptor final :
public DescriptorImpl
863 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
864 bool IsSingleType() const final {
return true; }
866 std::optional<int64_t> ScriptSize()
const override {
867 return 1 + (m_xonly ? 32 : m_pubkey_args[0]->GetSize()) + 1;
870 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
871 const auto ecdsa_sig_size = use_max_sig ? 72 : 71;
872 return 1 + (m_xonly ? 65 : ecdsa_sig_size);
875 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
879 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1; }
881 std::unique_ptr<DescriptorImpl> Clone()
const override
883 return std::make_unique<PKDescriptor>(m_pubkey_args.at(0)->Clone(), m_xonly);
888class PKHDescriptor final :
public DescriptorImpl
893 CKeyID id = keys[0].GetID();
894 out.pubkeys.emplace(
id, keys[0]);
898 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
900 bool IsSingleType() const final {
return true; }
902 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 1 + 20 + 1 + 1; }
904 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
905 const auto sig_size = use_max_sig ? 72 : 71;
906 return 1 +
sig_size + 1 + m_pubkey_args[0]->GetSize();
909 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
913 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
915 std::unique_ptr<DescriptorImpl> Clone()
const override
917 return std::make_unique<PKHDescriptor>(m_pubkey_args.at(0)->Clone());
922class WPKHDescriptor final :
public DescriptorImpl
927 CKeyID id = keys[0].GetID();
928 out.pubkeys.emplace(
id, keys[0]);
932 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
934 bool IsSingleType() const final {
return true; }
936 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20; }
938 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
939 const auto sig_size = use_max_sig ? 72 : 71;
943 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
944 return MaxSatSize(use_max_sig);
947 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
949 std::unique_ptr<DescriptorImpl> Clone()
const override
951 return std::make_unique<WPKHDescriptor>(m_pubkey_args.at(0)->Clone());
956class ComboDescriptor final :
public DescriptorImpl
961 std::vector<CScript>
ret;
962 CKeyID id = keys[0].GetID();
963 out.pubkeys.emplace(
id, keys[0]);
966 if (keys[0].IsCompressed()) {
969 ret.emplace_back(p2wpkh);
975 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
976 bool IsSingleType() const final {
return false; }
977 std::unique_ptr<DescriptorImpl> Clone()
const override
979 return std::make_unique<ComboDescriptor>(m_pubkey_args.at(0)->Clone());
984class MultisigDescriptor final :
public DescriptorImpl
986 const int m_threshold;
989 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
992 std::vector<CPubKey> sorted_keys(keys);
993 std::sort(sorted_keys.begin(), sorted_keys.end());
999 MultisigDescriptor(
int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers,
bool sorted =
false) : DescriptorImpl(
std::move(providers), sorted ?
"sortedmulti" :
"multi"), m_threshold(threshold), m_sorted(sorted) {}
1000 bool IsSingleType() const final {
return true; }
1002 std::optional<int64_t> ScriptSize()
const override {
1003 const auto n_keys = m_pubkey_args.size();
1004 auto op = [](int64_t acc,
const std::unique_ptr<PubkeyProvider>&
pk) {
return acc + 1 +
pk->GetSize();};
1005 const auto pubkeys_size{std::accumulate(m_pubkey_args.begin(), m_pubkey_args.end(), int64_t{0}, op)};
1009 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1010 const auto sig_size = use_max_sig ? 72 : 71;
1011 return (1 + (1 +
sig_size) * m_threshold);
1014 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1018 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1 + m_threshold; }
1020 std::unique_ptr<DescriptorImpl> Clone()
const override
1022 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1023 providers.reserve(m_pubkey_args.size());
1024 std::transform(m_pubkey_args.begin(), m_pubkey_args.end(), providers.begin(), [](
const std::unique_ptr<PubkeyProvider>& p) { return p->Clone(); });
1025 return std::make_unique<MultisigDescriptor>(m_threshold, std::move(providers), m_sorted);
1030class MultiADescriptor final :
public DescriptorImpl
1032 const int m_threshold;
1033 const bool m_sorted;
1035 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
1038 std::vector<XOnlyPubKey> xkeys;
1039 xkeys.reserve(keys.size());
1040 for (
const auto& key : keys) xkeys.emplace_back(key);
1041 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
1043 for (
size_t i = 1; i < keys.size(); ++i) {
1050 MultiADescriptor(
int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers,
bool sorted =
false) : DescriptorImpl(
std::move(providers), sorted ?
"sortedmulti_a" :
"multi_a"), m_threshold(threshold), m_sorted(sorted) {}
1051 bool IsSingleType() const final {
return true; }
1053 std::optional<int64_t> ScriptSize()
const override {
1054 const auto n_keys = m_pubkey_args.size();
1058 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1059 return (1 + 65) * m_threshold + (m_pubkey_args.size() - m_threshold);
1062 std::optional<int64_t> MaxSatisfactionElems()
const override {
return m_pubkey_args.size(); }
1064 std::unique_ptr<DescriptorImpl> Clone()
const override
1066 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1067 providers.reserve(m_pubkey_args.size());
1068 for (
const auto& arg : m_pubkey_args) {
1069 providers.push_back(arg->Clone());
1071 return std::make_unique<MultiADescriptor>(m_threshold, std::move(providers), m_sorted);
1076class SHDescriptor final :
public DescriptorImpl
1082 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1089 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
1093 assert(m_subdescriptor_args.size() == 1);
1097 bool IsSingleType() const final {
return true; }
1099 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20 + 1; }
1101 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1102 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1103 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1107 if (
IsSegwit())
return subscript_weight + *sat_size;
1114 std::optional<int64_t> MaxSatisfactionElems()
const override {
1115 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1119 std::unique_ptr<DescriptorImpl> Clone()
const override
1121 return std::make_unique<SHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1126class WSHDescriptor final :
public DescriptorImpl
1132 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1136 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
1138 bool IsSingleType() const final {
return true; }
1140 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1142 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1143 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1144 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1151 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1152 return MaxSatSize(use_max_sig);
1155 std::optional<int64_t> MaxSatisfactionElems()
const override {
1156 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1160 std::unique_ptr<DescriptorImpl> Clone()
const override
1162 return std::make_unique<WSHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1167class TRDescriptor final :
public DescriptorImpl
1169 std::vector<int> m_depths;
1175 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1179 assert(keys.size() == 1);
1181 if (!xpk.IsFullyValid())
return {};
1184 out.tr_trees[output] = builder;
1185 out.pubkeys.emplace(keys[0].GetID(), keys[0]);
1190 if (m_depths.empty())
return true;
1191 std::vector<bool> path;
1192 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1193 if (pos)
ret +=
',';
1194 while ((
int)path.size() <= m_depths[pos]) {
1195 if (path.size())
ret +=
'{';
1196 path.push_back(
false);
1199 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache))
return false;
1201 while (!path.empty() && path.back()) {
1202 if (path.size() > 1)
ret +=
'}';
1205 if (!path.empty()) path.back() =
true;
1210 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
1211 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
1213 assert(m_subdescriptor_args.size() == m_depths.size());
1216 bool IsSingleType() const final {
return true; }
1218 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1220 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1225 std::optional<int64_t> MaxSatisfactionElems()
const override {
1230 std::unique_ptr<DescriptorImpl> Clone()
const override
1232 std::vector<std::unique_ptr<DescriptorImpl>> subdescs;
1233 subdescs.reserve(m_subdescriptor_args.size());
1234 std::transform(m_subdescriptor_args.begin(), m_subdescriptor_args.end(), subdescs.begin(), [](
const std::unique_ptr<DescriptorImpl>& d) { return d->Clone(); });
1235 return std::make_unique<TRDescriptor>(m_pubkey_args.at(0)->Clone(), std::move(subdescs), m_depths);
1249 const std::vector<CPubKey>& m_keys;
1256 uint160 GetHash160(uint32_t key)
const {
1260 return m_keys[key].GetID();
1266 std::vector<unsigned char> ToPKBytes(uint32_t key)
const {
1269 return {m_keys[key].begin(), m_keys[key].end()};
1272 return {xonly_pubkey.
begin(), xonly_pubkey.end()};
1275 std::vector<unsigned char> ToPKHBytes(uint32_t key)
const {
1276 auto id = GetHash160(key);
1277 return {
id.begin(),
id.end()};
1288 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
1294 : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
1296 std::optional<std::string>
ToString(uint32_t key)
const
1300 if (!m_pubkeys[key]->ToPrivateString(*m_arg,
ret))
return {};
1302 ret = m_pubkeys[key]->ToString();
1308class MiniscriptDescriptor final :
public DescriptorImpl
1314 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys,
Span<const CScript> scripts,
1317 const auto script_ctx{
m_node->GetMsCtx()};
1318 for (
const auto& key : keys) {
1322 provider.
pubkeys.emplace(key.GetID(), key);
1325 return Vector(
m_node->ToScript(ScriptMaker(keys, script_ctx)));
1332 bool ToStringHelper(
const SigningProvider* arg, std::string&
out,
const StringType type,
1335 if (
const auto res =
m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
1342 bool IsSolvable()
const override {
return true; }
1343 bool IsSingleType() const final {
return true; }
1345 std::optional<int64_t> ScriptSize()
const override {
return m_node->ScriptSize(); }
1347 std::optional<int64_t> MaxSatSize(
bool)
const override {
1349 return m_node->GetWitnessSize();
1352 std::optional<int64_t> MaxSatisfactionElems()
const override {
1353 return m_node->GetStackSize();
1356 std::unique_ptr<DescriptorImpl> Clone()
const override
1358 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1359 providers.reserve(m_pubkey_args.size());
1360 for (
const auto& arg : m_pubkey_args) {
1361 providers.push_back(arg->Clone());
1363 return std::make_unique<MiniscriptDescriptor>(std::move(providers), miniscript::MakeNodeRef<uint32_t>(*
m_node));
1368class RawTRDescriptor final :
public DescriptorImpl
1373 assert(keys.size() == 1);
1375 if (!xpk.IsFullyValid())
return {};
1380 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(
Vector(
std::move(output_key)),
"rawtr") {}
1382 bool IsSingleType() const final {
return true; }
1384 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1386 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1391 std::optional<int64_t> MaxSatisfactionElems()
const override {
1396 std::unique_ptr<DescriptorImpl> Clone()
const override
1398 return std::make_unique<RawTRDescriptor>(m_pubkey_args.at(0)->Clone());
1406enum class ParseScriptContext {
1414std::optional<uint32_t> ParseKeyPathNum(
Span<const char> elem,
bool& apostrophe, std::string& error)
1416 bool hardened =
false;
1417 if (elem.
size() > 0) {
1418 const char last = elem[elem.
size() - 1];
1419 if (last ==
'\'' || last ==
'h') {
1422 apostrophe = last ==
'\'';
1427 error =
strprintf(
"Key path value '%s' is not a valid uint32", std::string(elem.
begin(), elem.
end()));
1428 return std::nullopt;
1429 }
else if (p > 0x7FFFFFFFUL) {
1430 error =
strprintf(
"Key path value %u is out of range", p);
1431 return std::nullopt;
1434 return std::make_optional<uint32_t>(p | (((uint32_t)hardened) << 31));
1447[[nodiscard]]
bool ParseKeyPath(
const std::vector<
Span<const char>>&
split, std::vector<KeyPath>&
out,
bool& apostrophe, std::string& error,
bool allow_multipath)
1450 std::optional<size_t> multipath_segment_index;
1451 std::vector<uint32_t> multipath_values;
1452 std::unordered_set<uint32_t> seen_multipath;
1454 for (
size_t i = 1; i <
split.size(); ++i) {
1458 if (!elem.
empty() && elem.
front() ==
'<' && elem.
back() ==
'>') {
1459 if (!allow_multipath) {
1460 error =
strprintf(
"Key path value '%s' specifies multipath in a section where multipath is not allowed", std::string(elem.
begin(), elem.
end()));
1463 if (multipath_segment_index) {
1464 error =
"Multiple multipath key path specifiers found";
1469 std::vector<Span<const char>> nums =
Split(
Span(elem.
begin()+1, elem.
end()-1),
";");
1470 if (nums.size() < 2) {
1471 error =
"Multipath key path specifiers must have at least two items";
1475 for (
const auto& num : nums) {
1476 const auto& op_num = ParseKeyPathNum(num, apostrophe, error);
1477 if (!op_num)
return false;
1478 auto [
_, inserted] = seen_multipath.insert(*op_num);
1480 error =
strprintf(
"Duplicated key path value %u in multipath specifier", *op_num);
1483 multipath_values.emplace_back(*op_num);
1486 path.emplace_back();
1487 multipath_segment_index = path.size()-1;
1489 const auto& op_num = ParseKeyPathNum(elem, apostrophe, error);
1490 if (!op_num)
return false;
1491 path.emplace_back(*op_num);
1495 if (!multipath_segment_index) {
1496 out.emplace_back(std::move(path));
1499 for (
size_t i = 0; i < multipath_values.size(); i++) {
1500 KeyPath branch_path = path;
1501 branch_path[*multipath_segment_index] = multipath_values[i];
1502 out.emplace_back(std::move(branch_path));
1509std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkeyInner(uint32_t key_exp_index,
const Span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out,
bool& apostrophe, std::string& error)
1511 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1512 bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
1514 std::string str(
split[0].begin(),
split[0].end());
1515 if (str.size() == 0) {
1516 error =
"No key provided";
1519 if (
split.size() == 1) {
1523 if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) {
1524 error =
"Hybrid public keys are not allowed";
1527 if (pubkey.IsFullyValid()) {
1528 if (permit_uncompressed || pubkey.IsCompressed()) {
1529 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false));
1532 error =
"Uncompressed keys are not allowed";
1535 }
else if (
data.size() == 32 && ctx == ParseScriptContext::P2TR) {
1536 unsigned char fullkey[33] = {0x02};
1537 std::copy(
data.begin(),
data.end(), fullkey + 1);
1538 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1539 if (pubkey.IsFullyValid()) {
1540 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true));
1544 error =
strprintf(
"Pubkey '%s' is invalid", str);
1551 out.keys.emplace(pubkey.
GetID(), key);
1552 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, ctx == ParseScriptContext::P2TR));
1555 error =
"Uncompressed keys are not allowed";
1563 error =
strprintf(
"key '%s' is not valid", str);
1566 std::vector<KeyPath> paths;
1567 DeriveType type = DeriveType::NO;
1570 type = DeriveType::UNHARDENED;
1572 apostrophe = std::ranges::equal(
split.back(),
Span{
"*'"}.
first(2));
1574 type = DeriveType::HARDENED;
1576 if (!ParseKeyPath(
split, paths, apostrophe, error,
true))
return {};
1578 extpubkey = extkey.
Neuter();
1581 for (
auto& path : paths) {
1582 ret.emplace_back(std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type, apostrophe));
1590 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1591 auto origin_split =
Split(sp,
']');
1592 if (origin_split.size() > 2) {
1593 error =
"Multiple ']' characters found for a single pubkey";
1597 bool apostrophe =
false;
1598 if (origin_split.size() == 1) {
1599 return ParsePubkeyInner(key_exp_index, origin_split[0], ctx,
out, apostrophe, error);
1601 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
1602 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
1603 origin_split[0].empty() ?
']' : origin_split[0][0]);
1606 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
1607 if (slash_split[0].size() != 8) {
1608 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
1611 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
1612 if (!
IsHex(fpr_hex)) {
1613 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
1616 auto fpr_bytes =
ParseHex(fpr_hex);
1618 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1619 assert(fpr_bytes.size() == 4);
1620 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1621 std::vector<KeyPath> path;
1622 if (!ParseKeyPath(slash_split, path, apostrophe, error,
false))
return {};
1623 info.
path = path.at(0);
1624 auto providers = ParsePubkeyInner(key_exp_index, origin_split[1], ctx,
out, apostrophe, error);
1625 if (providers.empty())
return {};
1626 ret.reserve(providers.size());
1627 for (
auto& prov : providers) {
1628 ret.emplace_back(std::make_unique<OriginPubkeyProvider>(key_exp_index, info, std::move(prov), apostrophe));
1633std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey& pubkey, ParseScriptContext ctx,
const SigningProvider& provider)
1640 if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.
IsCompressed()) {
1643 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
1646 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1648 return key_provider;
1651std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(
const XOnlyPubKey& xkey, ParseScriptContext ctx,
const SigningProvider& provider)
1654 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
1657 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1659 return key_provider;
1667 using Key = uint32_t;
1673 mutable std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> m_keys;
1675 mutable std::string m_key_parsing_error;
1683 : m_out(
out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}
1685 bool KeyCompare(
const Key& a,
const Key& b)
const {
1686 return *m_keys.at(a).at(0) < *m_keys.at(b).at(0);
1690 switch (m_script_ctx) {
1697 template<
typename I> std::optional<Key>
FromString(I begin, I end)
const
1700 Key key = m_keys.
size();
1701 auto pk = ParsePubkey(m_offset + key, {&*begin, &*end},
ParseContext(), *m_out, m_key_parsing_error);
1702 if (
pk.empty())
return {};
1703 m_keys.emplace_back(std::move(
pk));
1707 std::optional<std::string>
ToString(
const Key& key)
const
1709 return m_keys.at(key).at(0)->ToString();
1712 template<
typename I> std::optional<Key> FromPKBytes(I begin, I end)
const
1715 Key key = m_keys.size();
1718 std::copy(begin, end, pubkey.
begin());
1720 m_keys.emplace_back();
1721 m_keys.back().push_back(std::move(pubkey_provider));
1726 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1727 m_keys.emplace_back();
1728 m_keys.back().push_back(std::move(pubkey_provider));
1735 template<
typename I> std::optional<Key> FromPKHBytes(I begin, I end)
const
1737 assert(end - begin == 20);
1740 std::copy(begin, end, hash.
begin());
1744 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1745 Key key = m_keys.
size();
1746 m_keys.emplace_back();
1747 m_keys.back().push_back(std::move(pubkey_provider));
1755 return m_script_ctx;
1765 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
1766 auto expr =
Expr(sp);
1767 if (
Func(
"pk", expr)) {
1768 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1769 if (pubkeys.empty()) {
1774 for (
auto& pubkey : pubkeys) {
1775 ret.emplace_back(std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR));
1779 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
1780 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1781 if (pubkeys.empty()) {
1786 for (
auto& pubkey : pubkeys) {
1787 ret.emplace_back(std::make_unique<PKHDescriptor>(std::move(pubkey)));
1790 }
else if (ctx != ParseScriptContext::P2TR &&
Func(
"pkh", expr)) {
1792 error =
"Can only have pkh at top level, in sh(), wsh(), or in tr()";
1795 if (ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1796 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1797 if (pubkeys.empty()) {
1798 error =
strprintf(
"combo(): %s", error);
1802 for (
auto& pubkey : pubkeys) {
1803 ret.emplace_back(std::make_unique<ComboDescriptor>(std::move(pubkey)));
1806 }
else if (
Func(
"combo", expr)) {
1807 error =
"Can only have combo() at top level";
1810 const bool multi =
Func(
"multi", expr);
1811 const bool sortedmulti = !multi &&
Func(
"sortedmulti", expr);
1812 const bool multi_a = !(multi || sortedmulti) &&
Func(
"multi_a", expr);
1813 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) &&
Func(
"sortedmulti_a", expr);
1814 if (((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
1815 (ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
1816 auto threshold =
Expr(expr);
1818 std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> providers;
1819 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
1820 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
1823 size_t script_size = 0;
1824 size_t max_providers_len = 0;
1825 while (expr.size()) {
1826 if (!
Const(
",", expr)) {
1827 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
1830 auto arg =
Expr(expr);
1831 auto pks = ParsePubkey(key_exp_index, arg, ctx,
out, error);
1836 script_size += pks.at(0)->GetSize() + 1;
1837 max_providers_len = std::max(max_providers_len, pks.size());
1838 providers.emplace_back(std::move(pks));
1847 }
else if (thres < 1) {
1848 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
1850 }
else if (thres > providers.size()) {
1851 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
1854 if (ctx == ParseScriptContext::TOP) {
1855 if (providers.size() > 3) {
1856 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
1860 if (ctx == ParseScriptContext::P2SH) {
1870 for (
auto& vec : providers) {
1871 if (vec.size() == 1) {
1872 for (
size_t i = 1; i < max_providers_len; ++i) {
1873 vec.emplace_back(vec.at(0)->Clone());
1875 }
else if (vec.size() != max_providers_len) {
1876 error =
strprintf(
"multi(): Multipath derivation paths have mismatched lengths");
1882 for (
size_t i = 0; i < max_providers_len; ++i) {
1884 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
1885 pubs.reserve(providers.size());
1886 for (
auto& pub : providers) {
1887 pubs.emplace_back(std::move(pub.at(i)));
1889 if (multi || sortedmulti) {
1890 ret.emplace_back(std::make_unique<MultisigDescriptor>(thres, std::move(pubs), sortedmulti));
1892 ret.emplace_back(std::make_unique<MultiADescriptor>(thres, std::move(pubs), sortedmulti_a));
1896 }
else if (multi || sortedmulti) {
1897 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
1899 }
else if (multi_a || sortedmulti_a) {
1900 error =
"Can only have multi_a/sortedmulti_a inside tr()";
1903 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
1904 auto pubkeys = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH,
out, error);
1905 if (pubkeys.empty()) {
1910 for (
auto& pubkey : pubkeys) {
1911 ret.emplace_back(std::make_unique<WPKHDescriptor>(std::move(pubkey)));
1914 }
else if (
Func(
"wpkh", expr)) {
1915 error =
"Can only have wpkh() at top level or inside sh()";
1918 if (ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1919 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
out, error);
1920 if (descs.empty() || expr.size())
return {};
1921 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
1922 ret.reserve(descs.size());
1923 for (
auto& desc : descs) {
1924 ret.push_back(std::make_unique<SHDescriptor>(std::move(desc)));
1927 }
else if (
Func(
"sh", expr)) {
1928 error =
"Can only have sh() at top level";
1931 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
1932 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH,
out, error);
1933 if (descs.empty() || expr.size())
return {};
1934 for (
auto& desc : descs) {
1935 ret.emplace_back(std::make_unique<WSHDescriptor>(std::move(desc)));
1938 }
else if (
Func(
"wsh", expr)) {
1939 error =
"Can only have wsh() at top level or inside sh()";
1942 if (ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1945 error =
"Address is not valid";
1948 ret.emplace_back(std::make_unique<AddressDescriptor>(std::move(dest)));
1950 }
else if (
Func(
"addr", expr)) {
1951 error =
"Can only have addr() at top level";
1954 if (ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
1955 auto arg =
Expr(expr);
1956 auto internal_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
1957 if (internal_keys.empty()) {
1961 size_t max_providers_len = internal_keys.size();
1963 std::vector<std::vector<std::unique_ptr<DescriptorImpl>>> subscripts;
1964 std::vector<int> depths;
1966 if (!
Const(
",", expr)) {
1967 error =
strprintf(
"tr: expected ',', got '%c'", expr[0]);
1973 std::vector<bool> branches;
1978 while (
Const(
"{", expr)) {
1979 branches.push_back(
false);
1986 auto sarg =
Expr(expr);
1987 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR,
out, error));
1988 if (subscripts.back().empty())
return {};
1989 max_providers_len = std::max(max_providers_len, subscripts.back().size());
1990 depths.push_back(branches.size());
1992 while (branches.size() && branches.back()) {
1993 if (!
Const(
"}", expr)) {
1994 error =
strprintf(
"tr(): expected '}' after script expression");
1997 branches.pop_back();
2000 if (branches.size() && !branches.back()) {
2001 if (!
Const(
",", expr)) {
2002 error =
strprintf(
"tr(): expected ',' after script expression");
2005 branches.back() =
true;
2007 }
while (branches.size());
2010 error =
strprintf(
"tr(): expected ')' after script expression");
2018 for (
auto& vec : subscripts) {
2019 if (vec.size() == 1) {
2020 for (
size_t i = 1; i < max_providers_len; ++i) {
2021 vec.emplace_back(vec.at(0)->Clone());
2023 }
else if (vec.size() != max_providers_len) {
2024 error =
strprintf(
"tr(): Multipath subscripts have mismatched lengths");
2029 if (internal_keys.size() > 1 && internal_keys.size() != max_providers_len) {
2030 error =
strprintf(
"tr(): Multipath internal key mismatches multipath subscripts lengths");
2034 while (internal_keys.size() < max_providers_len) {
2035 internal_keys.emplace_back(internal_keys.at(0)->Clone());
2039 for (
size_t i = 0; i < max_providers_len; ++i) {
2041 std::vector<std::unique_ptr<DescriptorImpl>> this_subs;
2042 this_subs.reserve(subscripts.size());
2043 for (
auto& subs : subscripts) {
2044 this_subs.emplace_back(std::move(subs.at(i)));
2046 ret.emplace_back(std::make_unique<TRDescriptor>(std::move(internal_keys.at(i)), std::move(this_subs), depths));
2051 }
else if (
Func(
"tr", expr)) {
2052 error =
"Can only have tr at top level";
2055 if (ctx == ParseScriptContext::TOP &&
Func(
"rawtr", expr)) {
2056 auto arg =
Expr(expr);
2058 error =
strprintf(
"rawtr(): only one key expected.");
2061 auto output_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
2062 if (output_keys.empty()) {
2063 error =
strprintf(
"rawtr(): %s", error);
2067 for (
auto& pubkey : output_keys) {
2068 ret.emplace_back(std::make_unique<RawTRDescriptor>(std::move(pubkey)));
2071 }
else if (
Func(
"rawtr", expr)) {
2072 error =
"Can only have rawtr at top level";
2075 if (ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
2076 std::string str(expr.begin(), expr.end());
2078 error =
"Raw script is not hex";
2082 ret.emplace_back(std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end())));
2084 }
else if (
Func(
"raw", expr)) {
2085 error =
"Can only have raw() at top level";
2091 KeyParser parser(&
out,
nullptr, script_ctx, key_exp_index);
2093 if (parser.m_key_parsing_error !=
"") {
2094 error = std::move(parser.m_key_parsing_error);
2098 if (ctx != ParseScriptContext::P2WSH && ctx != ParseScriptContext::P2TR) {
2099 error =
"Miniscript expressions can only be used in wsh or tr.";
2102 if (!
node->IsSane() ||
node->IsNotSatisfiable()) {
2104 auto insane_node =
node.get();
2105 if (
const auto sub =
node->FindInsaneSub()) insane_node = sub;
2106 if (
const auto str = insane_node->ToString(parser)) error = *str;
2107 if (!insane_node->IsValid()) {
2108 error +=
" is invalid";
2109 }
else if (!
node->IsSane()) {
2110 error +=
" is not sane";
2111 if (!insane_node->IsNonMalleable()) {
2112 error +=
": malleable witnesses exist";
2113 }
else if (insane_node ==
node.get() && !insane_node->NeedsSignature()) {
2114 error +=
": witnesses without signature exist";
2115 }
else if (!insane_node->CheckTimeLocksMix()) {
2116 error +=
": contains mixes of timelocks expressed in blocks and seconds";
2117 }
else if (!insane_node->CheckDuplicateKey()) {
2118 error +=
": contains duplicate public keys";
2119 }
else if (!insane_node->ValidSatisfactions()) {
2120 error +=
": needs witnesses that may exceed resource limits";
2123 error +=
" is not satisfiable";
2130 key_exp_index += parser.m_keys.size();
2133 size_t num_multipath = std::max_element(parser.m_keys.begin(), parser.m_keys.end(),
2134 [](
const std::vector<std::unique_ptr<PubkeyProvider>>& a,
const std::vector<std::unique_ptr<PubkeyProvider>>& b) {
2135 return a.size() < b.size();
2138 for (
auto& vec : parser.m_keys) {
2139 if (vec.size() == 1) {
2140 for (
size_t i = 1; i < num_multipath; ++i) {
2141 vec.emplace_back(vec.at(0)->Clone());
2143 }
else if (vec.size() != num_multipath) {
2144 error =
strprintf(
"Miniscript: Multipath derivation paths have mismatched lengths");
2150 for (
size_t i = 0; i < num_multipath; ++i) {
2152 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
2153 pubs.reserve(parser.m_keys.size());
2154 for (
auto& pub : parser.m_keys) {
2155 pubs.emplace_back(std::move(pub.at(i)));
2157 ret.emplace_back(std::make_unique<MiniscriptDescriptor>(std::move(pubs),
node));
2162 if (ctx == ParseScriptContext::P2SH) {
2163 error =
"A function is needed within P2SH";
2165 }
else if (ctx == ParseScriptContext::P2WSH) {
2166 error =
"A function is needed within P2WSH";
2169 error =
strprintf(
"'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
2176 if (!match)
return {};
2177 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2178 keys.reserve(match->second.size());
2179 for (
const auto keyspan : match->second) {
2180 if (keyspan.size() != 32)
return {};
2181 auto key = InferXOnlyPubkey(
XOnlyPubKey{keyspan}, ctx, provider);
2182 if (!key)
return {};
2183 keys.push_back(std::move(key));
2185 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
2193 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider),
true);
2196 if (ctx == ParseScriptContext::P2TR) {
2197 auto ret = InferMultiA(
script, ctx, provider);
2201 std::vector<std::vector<unsigned char>>
data;
2204 if (txntype ==
TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2206 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2207 return std::make_unique<PKDescriptor>(std::move(pubkey_provider));
2210 if (txntype ==
TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2214 if (provider.
GetPubKey(keyid, pubkey)) {
2215 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2216 return std::make_unique<PKHDescriptor>(std::move(pubkey_provider));
2224 if (provider.
GetPubKey(keyid, pubkey)) {
2225 if (
auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) {
2226 return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider));
2230 if (txntype ==
TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2232 std::vector<std::unique_ptr<PubkeyProvider>> providers;
2233 for (
size_t i = 1; i + 1 <
data.size(); ++i) {
2235 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2236 providers.push_back(std::move(pubkey_provider));
2242 if (ok)
return std::make_unique<MultisigDescriptor>((
int)
data[0][0], std::move(providers));
2248 if (provider.
GetCScript(scriptid, subscript)) {
2249 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
2250 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
2256 if (provider.
GetCScript(scriptid, subscript)) {
2257 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
2258 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
2273 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
2274 std::vector<int> depths;
2275 for (
const auto& [depth,
script, leaf_ver] : *tree) {
2276 std::unique_ptr<DescriptorImpl> subdesc;
2278 subdesc = InferScript(
CScript(
script.begin(),
script.end()), ParseScriptContext::P2TR, provider);
2284 subscripts.push_back(std::move(subdesc));
2285 depths.push_back(depth);
2289 auto key = InferXOnlyPubkey(tap.
internal_key, ParseScriptContext::P2TR, provider);
2290 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
2296 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
2298 return std::make_unique<RawTRDescriptor>(std::move(key));
2303 if (ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR) {
2305 KeyParser parser(
nullptr, &provider, script_ctx);
2308 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2309 keys.reserve(parser.m_keys.size());
2310 for (
auto& key : parser.m_keys) {
2311 keys.emplace_back(std::move(key.at(0)));
2313 return std::make_unique<MiniscriptDescriptor>(std::move(keys), std::move(
node));
2319 if (ctx != ParseScriptContext::TOP)
return nullptr;
2324 return std::make_unique<AddressDescriptor>(std::move(dest));
2328 return std::make_unique<RawDescriptor>(
script);
2337 auto check_split =
Split(sp,
'#');
2338 if (check_split.size() > 2) {
2339 error =
"Multiple '#' symbols";
2342 if (check_split.size() == 1 && require_checksum){
2343 error =
"Missing checksum";
2346 if (check_split.size() == 2) {
2347 if (check_split[1].size() != 8) {
2348 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
2352 auto checksum = DescriptorChecksum(check_split[0]);
2353 if (checksum.empty()) {
2354 error =
"Invalid characters in payload";
2357 if (check_split.size() == 2) {
2358 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
2359 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
2363 if (out_checksum) *out_checksum = std::move(checksum);
2364 sp = check_split[0];
2372 uint32_t key_exp_index = 0;
2374 if (sp.
size() == 0 && !
ret.empty()) {
2375 std::vector<std::unique_ptr<Descriptor>> descs;
2376 descs.reserve(
ret.size());
2377 for (
auto& r :
ret) {
2378 descs.emplace_back(std::unique_ptr<Descriptor>(std::move(r)));
2396 return InferScript(
script, ParseScriptContext::TOP, provider);
2401 std::string desc_str = desc.
ToString(
true);
2415 xpubs[der_index] = xpub;
2435 const auto& der_it = key_exp_it->second.find(der_index);
2436 if (der_it == key_exp_it->second.end())
return false;
2437 xpub = der_it->second;
2455 if (xpub != parent_xpub_pair.second) {
2456 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
2464 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
2467 if (xpub != derived_xpub_pair.second) {
2468 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
2472 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2473 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2479 if (xpub != lh_xpub_pair.second) {
2480 throw std::runtime_error(std::string(__func__) +
": New cached last hardened xpub does not match already cached last hardened xpub");
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
std::string FormatHDKeypath(const std::vector< uint32_t > &path, bool apostrophe)
#define CHECK_NONFATAL(condition)
Identity function.
An encapsulated private key.
unsigned int size() const
Simple read-only vector-like interface.
bool IsValid() const
Check whether this private key is valid.
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
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.
bool IsCompressed() const
Check whether this is a compressed public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
bool IsValidNonHybrid() const noexcept
Check if a public key is a syntactically valid compressed or uncompressed key.
A hasher class for SHA-256.
void Finalize(unsigned char hash[OUTPUT_SIZE])
CSHA256 & Write(const unsigned char *data, size_t len)
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization.
Cache for single descriptor's derived extended pubkeys.
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
ExtPubKeyMap m_last_hardened_xpubs
Map key expression index -> last hardened xpub.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
DescriptorCache MergeAndDiff(const DescriptorCache &other)
Combine another DescriptorCache into this one.
ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a last hardened 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)
bool GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached last hardened 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 GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
bool GetKeyOriginByXOnly(const XOnlyPubKey &pubkey, KeyOriginInfo &info) 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_IF_NOT_DEBUG C & back() const noexcept
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 bool empty() const noexcept
constexpr C * end() const noexcept
CONSTEXPR_IF_NOT_DEBUG C & front() const noexcept
Utility class to construct Taproot outputs from internal key and script tree.
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
bool IsComplete() const
Return whether there were either no leaves, or the leaves form a Huffman tree.
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
TaprootBuilder & Add(int depth, Span< const unsigned char > script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
const unsigned char * begin() const
static constexpr size_t size()
CPubKey GetEvenCorrespondingCPubKey() const
bool IsFullyValid() const
Determine if this pubkey is fully valid.
constexpr unsigned char * begin()
static const int WITNESS_SCALE_FACTOR
CScript ParseScript(const std::string &s)
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT
std::string EncodeExtKey(const CExtKey &key)
CExtPubKey DecodeExtPubKey(const std::string &str)
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
std::string EncodeSecret(const CKey &key)
std::string EncodeDestination(const CTxDestination &dest)
CKey DecodeSecret(const std::string &str)
std::string EncodeExtPubKey(const CExtPubKey &key)
CExtKey DecodeExtKey(const std::string &str)
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
std::shared_ptr< const Node< Key > > NodeRef
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
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.
static std::vector< std::string > split(const std::string &str, const std::string &delims=" \t")
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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 OutputType GetOutputType(TxoutType type, bool is_from_p2sh)
static bool IsSegwit(const Descriptor &desc)
Whether the descriptor represents, directly or not, a witness program.
bool operator<(const CNetAddr &a, const CNetAddr &b)
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
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.
uint256 DescriptorID(const Descriptor &desc)
Unique identifier that may not change over time, unless explicitly marked as not backwards compatible...
std::vector< std::unique_ptr< Descriptor > > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
static constexpr unsigned int MAX_PUBKEYS_PER_MULTI_A
The limit of keys in OP_CHECKSIGADD-based scripts.
CScript BuildScript(Ts &&... inputs)
Build a script by concatenating other scripts, or any argument accepted by CScript::operator<<.
static const int MAX_PUBKEYS_PER_MULTISIG
std::vector< unsigned char > ToByteVector(const T &in)
constexpr unsigned int GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 byt...
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
std::optional< std::vector< std::tuple< int, std::vector< unsigned char >, int > > > InferTaprootTree(const TaprootSpendData &spenddata, const XOnlyPubKey &output)
Given a TaprootSpendData and the output key, reconstruct its script tree.
const SigningProvider & DUMMY_SIGNING_PROVIDER
void PolyMod(const std::vector< typename F::Elem > &mod, std::vector< typename F::Elem > &val, const F &field)
Compute the remainder of a polynomial division of val by mod, putting the result in mod.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
std::optional< std::pair< int, std::vector< Span< const unsigned char > > > > MatchMultiA(const CScript &script)
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Span(T *, EndOrSize) -> Span< T >
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
CExtPubKey Neuter() const
bool Derive(CExtKey &out, unsigned int nChild) const
bool Derive(CExtPubKey &out, unsigned int nChild) const
Interface for parsed descriptor objects.
virtual std::optional< int64_t > MaxSatisfactionElems() const =0
Get the maximum size number of stack elements for satisfying this descriptor.
virtual void GetPubKeys(std::set< CPubKey > &pubkeys, std::set< CExtPubKey > &ext_pubs) const =0
Return all (extended) public keys for this descriptor, including any from subdescriptors.
virtual bool ToNormalizedString(const SigningProvider &provider, std::string &out, const DescriptorCache *cache=nullptr) const =0
Convert the descriptor to a normalized string.
virtual std::optional< int64_t > MaxSatisfactionWeight(bool use_max_sig) const =0
Get the maximum size of a satisfaction for this descriptor, in weight units.
virtual std::string ToString(bool compat_format=false) 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 std::optional< int64_t > ScriptSize() const =0
Get the size of the scriptPubKey for this descriptor.
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, CPubKey > pubkeys
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
std::vector< uint32_t > path
XOnlyPubKey internal_key
The BIP341 internal key.
bilingual_str _(ConstevalStringLiteral str)
Translation function.
bool IsHex(std::string_view str)
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.