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;
105std::string DescriptorChecksum(
const std::span<const char>& span)
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 {
179 std::optional<CPubKey> a =
GetPubKey(0, dummy, dummy);
180 std::optional<CPubKey> b = other.GetPubKey(0, dummy, dummy);
193 virtual bool IsRange()
const = 0;
196 virtual size_t GetSize()
const = 0;
198 enum class StringType {
204 virtual std::string
ToString(StringType type=StringType::PUBLIC)
const = 0;
218 virtual std::optional<CPubKey> GetRootPubKey()
const = 0;
220 virtual std::optional<CExtPubKey> GetRootExtPubKey()
const = 0;
223 virtual std::unique_ptr<PubkeyProvider> Clone()
const = 0;
226class OriginPubkeyProvider final :
public PubkeyProvider
229 std::unique_ptr<PubkeyProvider> m_provider;
232 std::string OriginString(StringType type,
bool normalized=
false)
const
235 bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
240 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) {}
243 std::optional<CPubKey> pub = m_provider->GetPubKey(pos, arg,
out, read_cache, write_cache);
244 if (!pub)
return std::nullopt;
245 Assert(
out.pubkeys.contains(pub->GetID()));
246 auto& [pubkey, suborigin] =
out.origins[pub->GetID()];
248 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), suborigin.fingerprint);
249 suborigin.path.insert(suborigin.path.begin(), m_origin.path.begin(), m_origin.path.end());
252 bool IsRange()
const override {
return m_provider->IsRange(); }
253 size_t GetSize()
const override {
return m_provider->GetSize(); }
254 std::string
ToString(StringType type)
const override {
return "[" + OriginString(type) +
"]" + m_provider->ToString(type); }
258 if (!m_provider->ToPrivateString(arg, sub))
return false;
259 ret =
"[" + OriginString(StringType::PUBLIC) +
"]" + std::move(sub);
265 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
271 ret =
"[" + OriginString(StringType::PUBLIC,
true) + std::move(sub);
273 ret =
"[" + OriginString(StringType::PUBLIC,
true) +
"]" + std::move(sub);
279 m_provider->GetPrivKey(pos, arg,
out);
281 std::optional<CPubKey> GetRootPubKey()
const override
283 return m_provider->GetRootPubKey();
285 std::optional<CExtPubKey> GetRootExtPubKey()
const override
287 return m_provider->GetRootExtPubKey();
289 std::unique_ptr<PubkeyProvider> Clone()
const override
291 return std::make_unique<OriginPubkeyProvider>(m_expr_index, m_origin, m_provider->Clone(), m_apostrophe);
296class ConstPubkeyProvider final :
public PubkeyProvider
305 arg.
GetKey(m_pubkey.GetID(), key)))
return std::nullopt;
310 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
314 CKeyID keyid = m_pubkey.GetID();
316 out.origins.emplace(keyid, std::make_pair(m_pubkey, info));
317 out.pubkeys.emplace(keyid, m_pubkey);
320 bool IsRange()
const override {
return false; }
321 size_t GetSize()
const override {
return m_pubkey.size(); }
322 std::string
ToString(StringType type)
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
325 std::optional<CKey> key = GetPrivKey(arg);
326 if (!key)
return false;
337 std::optional<CKey> key = GetPrivKey(arg);
339 out.keys.emplace(key->GetPubKey().GetID(), *key);
341 std::optional<CPubKey> GetRootPubKey()
const override
345 std::optional<CExtPubKey> GetRootExtPubKey()
const override
349 std::unique_ptr<PubkeyProvider> Clone()
const override
351 return std::make_unique<ConstPubkeyProvider>(m_expr_index, m_pubkey, m_xonly);
355enum class DeriveType {
362class BIP32PubkeyProvider final :
public PubkeyProvider
374 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
375 ret.nDepth = m_root_extkey.nDepth;
376 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
ret.vchFingerprint);
377 ret.nChild = m_root_extkey.nChild;
378 ret.chaincode = m_root_extkey.chaincode;
386 if (!GetExtKey(arg, xprv))
return false;
387 for (
auto entry : m_path) {
388 if (!xprv.
Derive(xprv, entry))
return false;
390 last_hardened = xprv;
396 bool IsHardened()
const
398 if (m_derive == DeriveType::HARDENED)
return true;
399 for (
auto entry : m_path) {
400 if (entry >> 31)
return true;
406 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) {}
407 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
408 size_t GetSize()
const override {
return 33; }
412 CKeyID keyid = m_root_extkey.pubkey.GetID();
415 if (m_derive == DeriveType::UNHARDENED) info.
path.push_back((uint32_t)pos);
416 if (m_derive == DeriveType::HARDENED) info.
path.push_back(((uint32_t)pos) | 0x80000000L);
424 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
425 if (m_derive == DeriveType::HARDENED)
return std::nullopt;
427 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return std::nullopt;
428 final_extkey = parent_extkey;
429 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
431 }
else if (IsHardened()) {
434 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return std::nullopt;
435 parent_extkey = xprv.
Neuter();
436 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
437 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
438 final_extkey = xprv.
Neuter();
440 last_hardened_extkey = lh_xprv.
Neuter();
443 for (
auto entry : m_path) {
444 if (!parent_extkey.
Derive(parent_extkey, entry))
return std::nullopt;
446 final_extkey = parent_extkey;
447 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
448 assert(m_derive != DeriveType::HARDENED);
450 if (!der)
return std::nullopt;
457 if (m_derive != DeriveType::HARDENED) {
458 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
461 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
463 }
else if (info.
path.size() > 0) {
464 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
468 return final_extkey.
pubkey;
470 std::string
ToString(StringType type,
bool normalized)
const
473 const bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
477 if (m_derive == DeriveType::HARDENED)
ret += use_apostrophe ?
'\'' :
'h';
481 std::string
ToString(StringType type=StringType::PUBLIC)
const override
488 if (!GetExtKey(arg, key))
return false;
492 if (m_derive == DeriveType::HARDENED)
out += m_apostrophe ?
'\'' :
'h';
498 if (m_derive == DeriveType::HARDENED) {
504 int i = (int)m_path.size() - 1;
505 for (; i >= 0; --i) {
506 if (m_path.at(i) >> 31) {
518 for (;
k <= i; ++
k) {
520 origin.
path.push_back(m_path.at(
k));
524 for (;
k < (int)m_path.size(); ++
k) {
525 end_path.push_back(m_path.at(
k));
528 CKeyID id = m_root_extkey.pubkey.GetID();
529 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
534 if (cache !=
nullptr) {
540 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
550 assert(m_derive == DeriveType::UNHARDENED);
558 if (!GetDerivedExtKey(arg, extkey, dummy))
return;
559 if (m_derive == DeriveType::UNHARDENED && !extkey.
Derive(extkey, pos))
return;
560 if (m_derive == DeriveType::HARDENED && !extkey.
Derive(extkey, pos | 0x80000000UL))
return;
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 ""; }
605 virtual std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& pubkeys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const = 0;
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);
711 std::vector<CPubKey> pubkeys;
712 pubkeys.reserve(m_pubkey_args.size());
715 for (
const auto& p : m_pubkey_args) {
716 std::optional<CPubKey> pubkey = p->
GetPubKey(pos, arg, subprovider, read_cache, write_cache);
717 if (!pubkey)
return false;
718 pubkeys.push_back(pubkey.value());
720 std::vector<CScript> subscripts;
721 for (
const auto& subarg : m_subdescriptor_args) {
722 std::vector<CScript> outscripts;
723 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
724 assert(outscripts.size() == 1);
725 subscripts.emplace_back(std::move(outscripts[0]));
727 out.Merge(std::move(subprovider));
729 output_scripts = MakeScripts(pubkeys, std::span{subscripts},
out);
735 return ExpandHelper(pos, provider,
nullptr, output_scripts,
out, write_cache);
746 for (
const auto& p : m_pubkey_args) {
747 p->GetPrivKey(pos, provider,
out);
749 for (
const auto& arg : m_subdescriptor_args) {
750 arg->ExpandPrivate(pos, provider,
out);
754 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
756 std::optional<int64_t>
ScriptSize()
const override {
return {}; }
763 virtual std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const {
return {}; }
770 void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs)
const override
772 for (
const auto& p : m_pubkey_args) {
773 std::optional<CPubKey> pub = p->GetRootPubKey();
774 if (pub) pubkeys.insert(*pub);
775 std::optional<CExtPubKey> ext_pub = p->GetRootExtPubKey();
776 if (ext_pub) ext_pubs.insert(*ext_pub);
778 for (
const auto& arg : m_subdescriptor_args) {
779 arg->GetPubKeys(pubkeys, ext_pubs);
783 virtual std::unique_ptr<DescriptorImpl> Clone()
const = 0;
787class AddressDescriptor final :
public DescriptorImpl
791 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
794 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
795 bool IsSolvable() const final {
return false; }
801 bool IsSingleType() const final {
return true; }
802 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
805 std::unique_ptr<DescriptorImpl> Clone()
const override
807 return std::make_unique<AddressDescriptor>(m_destination);
812class RawDescriptor final :
public DescriptorImpl
816 std::string ToStringExtra()
const override {
return HexStr(m_script); }
817 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript>,
FlatSigningProvider&)
const override {
return Vector(m_script); }
820 bool IsSolvable() const final {
return false; }
828 bool IsSingleType() const final {
return true; }
829 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
831 std::optional<int64_t> ScriptSize()
const override {
return m_script.size(); }
833 std::unique_ptr<DescriptorImpl> Clone()
const override
835 return std::make_unique<RawDescriptor>(m_script);
840class PKDescriptor final :
public DescriptorImpl
845 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
855 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
856 bool IsSingleType() const final {
return true; }
858 std::optional<int64_t> ScriptSize()
const override {
859 return 1 + (m_xonly ? 32 : m_pubkey_args[0]->GetSize()) + 1;
862 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
863 const auto ecdsa_sig_size = use_max_sig ? 72 : 71;
864 return 1 + (m_xonly ? 65 : ecdsa_sig_size);
867 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
871 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1; }
873 std::unique_ptr<DescriptorImpl> Clone()
const override
875 return std::make_unique<PKDescriptor>(m_pubkey_args.at(0)->Clone(), m_xonly);
880class PKHDescriptor final :
public DescriptorImpl
883 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
885 CKeyID id = keys[0].GetID();
889 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
891 bool IsSingleType() const final {
return true; }
893 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 1 + 20 + 1 + 1; }
895 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
896 const auto sig_size = use_max_sig ? 72 : 71;
897 return 1 +
sig_size + 1 + m_pubkey_args[0]->GetSize();
900 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
904 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
906 std::unique_ptr<DescriptorImpl> Clone()
const override
908 return std::make_unique<PKHDescriptor>(m_pubkey_args.at(0)->Clone());
913class WPKHDescriptor final :
public DescriptorImpl
916 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
918 CKeyID id = keys[0].GetID();
922 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
924 bool IsSingleType() const final {
return true; }
926 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20; }
928 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
929 const auto sig_size = use_max_sig ? 72 : 71;
933 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
934 return MaxSatSize(use_max_sig);
937 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
939 std::unique_ptr<DescriptorImpl> Clone()
const override
941 return std::make_unique<WPKHDescriptor>(m_pubkey_args.at(0)->Clone());
946class ComboDescriptor final :
public DescriptorImpl
949 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&
out)
const override
951 std::vector<CScript>
ret;
952 CKeyID id = keys[0].GetID();
955 if (keys[0].IsCompressed()) {
958 ret.emplace_back(p2wpkh);
964 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
965 bool IsSingleType() const final {
return false; }
966 std::unique_ptr<DescriptorImpl> Clone()
const override
968 return std::make_unique<ComboDescriptor>(m_pubkey_args.at(0)->Clone());
973class MultisigDescriptor final :
public DescriptorImpl
975 const int m_threshold;
978 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
979 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override {
981 std::vector<CPubKey> sorted_keys(keys);
982 std::sort(sorted_keys.begin(), sorted_keys.end());
988 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) {}
989 bool IsSingleType() const final {
return true; }
991 std::optional<int64_t> ScriptSize()
const override {
992 const auto n_keys = m_pubkey_args.size();
993 auto op = [](int64_t acc,
const std::unique_ptr<PubkeyProvider>&
pk) {
return acc + 1 +
pk->GetSize();};
994 const auto pubkeys_size{std::accumulate(m_pubkey_args.begin(), m_pubkey_args.end(), int64_t{0}, op)};
998 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
999 const auto sig_size = use_max_sig ? 72 : 71;
1000 return (1 + (1 +
sig_size) * m_threshold);
1003 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1007 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1 + m_threshold; }
1009 std::unique_ptr<DescriptorImpl> Clone()
const override
1011 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1012 providers.reserve(m_pubkey_args.size());
1013 std::transform(m_pubkey_args.begin(), m_pubkey_args.end(), providers.begin(), [](
const std::unique_ptr<PubkeyProvider>& p) { return p->Clone(); });
1014 return std::make_unique<MultisigDescriptor>(m_threshold, std::move(providers), m_sorted);
1019class MultiADescriptor final :
public DescriptorImpl
1021 const int m_threshold;
1022 const bool m_sorted;
1024 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
1025 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override {
1027 std::vector<XOnlyPubKey> xkeys;
1028 xkeys.reserve(keys.size());
1029 for (
const auto& key : keys) xkeys.emplace_back(key);
1030 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
1032 for (
size_t i = 1; i < keys.size(); ++i) {
1039 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) {}
1040 bool IsSingleType() const final {
return true; }
1042 std::optional<int64_t> ScriptSize()
const override {
1043 const auto n_keys = m_pubkey_args.size();
1047 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1048 return (1 + 65) * m_threshold + (m_pubkey_args.size() - m_threshold);
1051 std::optional<int64_t> MaxSatisfactionElems()
const override {
return m_pubkey_args.size(); }
1053 std::unique_ptr<DescriptorImpl> Clone()
const override
1055 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1056 providers.reserve(m_pubkey_args.size());
1057 for (
const auto& arg : m_pubkey_args) {
1058 providers.push_back(arg->Clone());
1060 return std::make_unique<MultiADescriptor>(m_threshold, std::move(providers), m_sorted);
1065class SHDescriptor final :
public DescriptorImpl
1068 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1071 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1078 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
1082 assert(m_subdescriptor_args.size() == 1);
1086 bool IsSingleType() const final {
return true; }
1088 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20 + 1; }
1090 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1091 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1092 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1096 if (
IsSegwit())
return subscript_weight + *sat_size;
1103 std::optional<int64_t> MaxSatisfactionElems()
const override {
1104 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1108 std::unique_ptr<DescriptorImpl> Clone()
const override
1110 return std::make_unique<SHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1115class WSHDescriptor final :
public DescriptorImpl
1118 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1121 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1125 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
1127 bool IsSingleType() const final {
return true; }
1129 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1131 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1132 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1133 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1140 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1141 return MaxSatSize(use_max_sig);
1144 std::optional<int64_t> MaxSatisfactionElems()
const override {
1145 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1149 std::unique_ptr<DescriptorImpl> Clone()
const override
1151 return std::make_unique<WSHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1156class TRDescriptor final :
public DescriptorImpl
1158 std::vector<int> m_depths;
1160 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1163 assert(m_depths.size() == scripts.size());
1164 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1168 assert(keys.size() == 1);
1170 if (!xpk.IsFullyValid())
return {};
1173 out.tr_trees[output] = builder;
1178 if (m_depths.empty())
return true;
1179 std::vector<bool> path;
1180 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1181 if (pos)
ret +=
',';
1182 while ((
int)path.size() <= m_depths[pos]) {
1183 if (path.size())
ret +=
'{';
1184 path.push_back(
false);
1187 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache))
return false;
1189 while (!path.empty() && path.back()) {
1190 if (path.size() > 1)
ret +=
'}';
1193 if (!path.empty()) path.back() =
true;
1198 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
1199 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
1201 assert(m_subdescriptor_args.size() == m_depths.size());
1204 bool IsSingleType() const final {
return true; }
1206 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1208 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1213 std::optional<int64_t> MaxSatisfactionElems()
const override {
1218 std::unique_ptr<DescriptorImpl> Clone()
const override
1220 std::vector<std::unique_ptr<DescriptorImpl>> subdescs;
1221 subdescs.reserve(m_subdescriptor_args.size());
1222 std::transform(m_subdescriptor_args.begin(), m_subdescriptor_args.end(), subdescs.begin(), [](
const std::unique_ptr<DescriptorImpl>& d) { return d->Clone(); });
1223 return std::make_unique<TRDescriptor>(m_pubkey_args.at(0)->Clone(), std::move(subdescs), m_depths);
1237 const std::vector<CPubKey>& m_keys;
1244 uint160 GetHash160(uint32_t key)
const {
1248 return m_keys[key].GetID();
1254 std::vector<unsigned char> ToPKBytes(uint32_t key)
const {
1257 return {m_keys[key].begin(), m_keys[key].end()};
1260 return {xonly_pubkey.
begin(), xonly_pubkey.end()};
1263 std::vector<unsigned char> ToPKHBytes(uint32_t key)
const {
1264 auto id = GetHash160(key);
1265 return {
id.begin(),
id.end()};
1276 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
1282 : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
1284 std::optional<std::string>
ToString(uint32_t key)
const
1288 if (!m_pubkeys[key]->ToPrivateString(*m_arg,
ret))
return {};
1290 ret = m_pubkeys[key]->ToString();
1296class MiniscriptDescriptor final :
public DescriptorImpl
1302 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
1305 const auto script_ctx{
m_node->GetMsCtx()};
1306 for (
const auto& key : keys) {
1310 provider.
pubkeys.emplace(key.GetID(), key);
1313 return Vector(
m_node->ToScript(ScriptMaker(keys, script_ctx)));
1320 bool ToStringHelper(
const SigningProvider* arg, std::string&
out,
const StringType type,
1323 if (
const auto res =
m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
1330 bool IsSolvable()
const override {
return true; }
1331 bool IsSingleType() const final {
return true; }
1333 std::optional<int64_t> ScriptSize()
const override {
return m_node->ScriptSize(); }
1335 std::optional<int64_t> MaxSatSize(
bool)
const override {
1337 return m_node->GetWitnessSize();
1340 std::optional<int64_t> MaxSatisfactionElems()
const override {
1341 return m_node->GetStackSize();
1344 std::unique_ptr<DescriptorImpl> Clone()
const override
1346 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1347 providers.reserve(m_pubkey_args.size());
1348 for (
const auto& arg : m_pubkey_args) {
1349 providers.push_back(arg->Clone());
1351 return std::make_unique<MiniscriptDescriptor>(std::move(providers),
m_node->Clone());
1356class RawTRDescriptor final :
public DescriptorImpl
1359 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1361 assert(keys.size() == 1);
1363 if (!xpk.IsFullyValid())
return {};
1368 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(
Vector(
std::move(output_key)),
"rawtr") {}
1370 bool IsSingleType() const final {
return true; }
1372 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1374 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1379 std::optional<int64_t> MaxSatisfactionElems()
const override {
1384 std::unique_ptr<DescriptorImpl> Clone()
const override
1386 return std::make_unique<RawTRDescriptor>(m_pubkey_args.at(0)->Clone());
1394enum class ParseScriptContext {
1402std::optional<uint32_t> ParseKeyPathNum(std::span<const char> elem,
bool& apostrophe, std::string& error)
1404 bool hardened =
false;
1405 if (elem.size() > 0) {
1406 const char last = elem[elem.size() - 1];
1407 if (last ==
'\'' || last ==
'h') {
1408 elem = elem.first(elem.size() - 1);
1410 apostrophe = last ==
'\'';
1413 const auto p{ToIntegral<uint32_t>(std::string_view{elem.begin(), elem.end()})};
1415 error =
strprintf(
"Key path value '%s' is not a valid uint32", std::string_view{elem.begin(), elem.end()});
1416 return std::nullopt;
1417 }
else if (*p > 0x7FFFFFFFUL) {
1418 error =
strprintf(
"Key path value %u is out of range", *p);
1419 return std::nullopt;
1422 return std::make_optional<uint32_t>(*p | (((uint32_t)hardened) << 31));
1435[[nodiscard]]
bool ParseKeyPath(
const std::vector<std::span<const char>>&
split, std::vector<KeyPath>&
out,
bool& apostrophe, std::string& error,
bool allow_multipath)
1438 struct MultipathSubstitutes {
1439 size_t placeholder_index;
1440 std::vector<uint32_t>
values;
1442 std::optional<MultipathSubstitutes> substitutes;
1444 for (
size_t i = 1; i <
split.size(); ++i) {
1445 const std::span<const char>& elem =
split[i];
1448 if (!elem.empty() && elem.front() ==
'<' && elem.back() ==
'>') {
1449 if (!allow_multipath) {
1450 error =
strprintf(
"Key path value '%s' specifies multipath in a section where multipath is not allowed", std::string(elem.begin(), elem.end()));
1454 error =
"Multiple multipath key path specifiers found";
1459 std::vector<std::span<const char>> nums =
Split(std::span(elem.begin()+1, elem.end()-1),
";");
1460 if (nums.size() < 2) {
1461 error =
"Multipath key path specifiers must have at least two items";
1465 substitutes.emplace();
1466 std::unordered_set<uint32_t> seen_substitutes;
1467 for (
const auto& num : nums) {
1468 const auto& op_num = ParseKeyPathNum(num, apostrophe, error);
1469 if (!op_num)
return false;
1470 auto [
_, inserted] = seen_substitutes.insert(*op_num);
1472 error =
strprintf(
"Duplicated key path value %u in multipath specifier", *op_num);
1475 substitutes->values.emplace_back(*op_num);
1478 path.emplace_back();
1479 substitutes->placeholder_index = path.size() - 1;
1481 const auto& op_num = ParseKeyPathNum(elem, apostrophe, error);
1482 if (!op_num)
return false;
1483 path.emplace_back(*op_num);
1488 out.emplace_back(std::move(path));
1491 for (uint32_t substitute : substitutes->values) {
1492 KeyPath branch_path = path;
1493 branch_path[substitutes->placeholder_index] = substitute;
1494 out.emplace_back(std::move(branch_path));
1501std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkeyInner(uint32_t key_exp_index,
const std::span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out,
bool& apostrophe, std::string& error)
1503 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1504 bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
1506 std::string str(
split[0].begin(),
split[0].end());
1507 if (str.size() == 0) {
1508 error =
"No key provided";
1512 error =
strprintf(
"Key '%s' is invalid due to whitespace", str);
1515 if (
split.size() == 1) {
1519 if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) {
1520 error =
"Hybrid public keys are not allowed";
1523 if (pubkey.IsFullyValid()) {
1524 if (permit_uncompressed || pubkey.IsCompressed()) {
1525 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false));
1528 error =
"Uncompressed keys are not allowed";
1531 }
else if (
data.size() == 32 && ctx == ParseScriptContext::P2TR) {
1532 unsigned char fullkey[33] = {0x02};
1533 std::copy(
data.begin(),
data.end(), fullkey + 1);
1534 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1535 if (pubkey.IsFullyValid()) {
1536 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true));
1540 error =
strprintf(
"Pubkey '%s' is invalid", str);
1547 out.keys.emplace(pubkey.
GetID(), key);
1548 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, ctx == ParseScriptContext::P2TR));
1551 error =
"Uncompressed keys are not allowed";
1559 error =
strprintf(
"key '%s' is not valid", str);
1562 std::vector<KeyPath> paths;
1563 DeriveType type = DeriveType::NO;
1564 if (std::ranges::equal(
split.back(), std::span{
"*"}.first(1))) {
1566 type = DeriveType::UNHARDENED;
1567 }
else if (std::ranges::equal(
split.back(), std::span{
"*'"}.first(2)) || std::ranges::equal(
split.back(), std::span{
"*h"}.first(2))) {
1568 apostrophe = std::ranges::equal(
split.back(), std::span{
"*'"}.first(2));
1570 type = DeriveType::HARDENED;
1572 if (!ParseKeyPath(
split, paths, apostrophe, error,
true))
return {};
1574 extpubkey = extkey.
Neuter();
1577 for (
auto& path : paths) {
1578 ret.emplace_back(std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type, apostrophe));
1584std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkey(uint32_t key_exp_index,
const std::span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out, std::string& error)
1586 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1587 auto origin_split =
Split(sp,
']');
1588 if (origin_split.size() > 2) {
1589 error =
"Multiple ']' characters found for a single pubkey";
1593 bool apostrophe =
false;
1594 if (origin_split.size() == 1) {
1595 return ParsePubkeyInner(key_exp_index, origin_split[0], ctx,
out, apostrophe, error);
1597 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
1598 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
1599 origin_split[0].empty() ?
']' : origin_split[0][0]);
1602 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
1603 if (slash_split[0].size() != 8) {
1604 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
1607 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
1608 if (!
IsHex(fpr_hex)) {
1609 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
1612 auto fpr_bytes =
ParseHex(fpr_hex);
1614 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1615 assert(fpr_bytes.size() == 4);
1616 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1617 std::vector<KeyPath> path;
1618 if (!ParseKeyPath(slash_split, path, apostrophe, error,
false))
return {};
1619 info.
path = path.at(0);
1620 auto providers = ParsePubkeyInner(key_exp_index, origin_split[1], ctx,
out, apostrophe, error);
1621 if (providers.empty())
return {};
1622 ret.reserve(providers.size());
1623 for (
auto& prov : providers) {
1624 ret.emplace_back(std::make_unique<OriginPubkeyProvider>(key_exp_index, info, std::move(prov), apostrophe));
1629std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey& pubkey, ParseScriptContext ctx,
const SigningProvider& provider)
1636 if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.
IsCompressed()) {
1639 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
1642 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1644 return key_provider;
1647std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(
const XOnlyPubKey& xkey, ParseScriptContext ctx,
const SigningProvider& provider)
1650 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
1653 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1655 return key_provider;
1663 using Key = uint32_t;
1669 mutable std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> m_keys;
1671 mutable std::string m_key_parsing_error;
1679 : m_out(
out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}
1681 bool KeyCompare(
const Key& a,
const Key& b)
const {
1682 return *m_keys.at(a).at(0) < *m_keys.at(b).at(0);
1686 switch (m_script_ctx) {
1693 template<
typename I> std::optional<Key>
FromString(I begin, I end)
const
1696 Key key = m_keys.
size();
1697 auto pk = ParsePubkey(m_offset + key, {&*begin, &*end},
ParseContext(), *m_out, m_key_parsing_error);
1698 if (
pk.empty())
return {};
1699 m_keys.emplace_back(std::move(
pk));
1703 std::optional<std::string>
ToString(
const Key& key)
const
1705 return m_keys.at(key).at(0)->ToString();
1708 template<
typename I> std::optional<Key> FromPKBytes(I begin, I end)
const
1711 Key key = m_keys.size();
1714 std::copy(begin, end, pubkey.
begin());
1715 if (
auto pubkey_provider = InferXOnlyPubkey(pubkey,
ParseContext(), *m_in)) {
1716 m_keys.emplace_back();
1717 m_keys.back().push_back(std::move(pubkey_provider));
1722 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1723 m_keys.emplace_back();
1724 m_keys.back().push_back(std::move(pubkey_provider));
1731 template<
typename I> std::optional<Key> FromPKHBytes(I begin, I end)
const
1733 assert(end - begin == 20);
1736 std::copy(begin, end, hash.
begin());
1740 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1741 Key key = m_keys.
size();
1742 m_keys.emplace_back();
1743 m_keys.back().push_back(std::move(pubkey_provider));
1751 return m_script_ctx;
1757std::vector<std::unique_ptr<DescriptorImpl>>
ParseScript(uint32_t& key_exp_index, std::span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out, std::string& error)
1760 Assume(ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR);
1761 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
1762 auto expr =
Expr(sp);
1763 if (
Func(
"pk", expr)) {
1764 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1765 if (pubkeys.empty()) {
1770 for (
auto& pubkey : pubkeys) {
1771 ret.emplace_back(std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR));
1775 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
1776 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1777 if (pubkeys.empty()) {
1782 for (
auto& pubkey : pubkeys) {
1783 ret.emplace_back(std::make_unique<PKHDescriptor>(std::move(pubkey)));
1787 if (ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1788 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1789 if (pubkeys.empty()) {
1790 error =
strprintf(
"combo(): %s", error);
1794 for (
auto& pubkey : pubkeys) {
1795 ret.emplace_back(std::make_unique<ComboDescriptor>(std::move(pubkey)));
1798 }
else if (
Func(
"combo", expr)) {
1799 error =
"Can only have combo() at top level";
1802 const bool multi =
Func(
"multi", expr);
1803 const bool sortedmulti = !multi &&
Func(
"sortedmulti", expr);
1804 const bool multi_a = !(multi || sortedmulti) &&
Func(
"multi_a", expr);
1805 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) &&
Func(
"sortedmulti_a", expr);
1806 if (((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
1807 (ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
1808 auto threshold =
Expr(expr);
1810 std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> providers;
1811 if (
const auto maybe_thres{ToIntegral<uint32_t>(std::string_view{threshold.begin(), threshold.end()})}) {
1812 thres = *maybe_thres;
1814 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
1817 size_t script_size = 0;
1818 size_t max_providers_len = 0;
1819 while (expr.size()) {
1820 if (!
Const(
",", expr)) {
1821 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
1824 auto arg =
Expr(expr);
1825 auto pks = ParsePubkey(key_exp_index, arg, ctx,
out, error);
1830 script_size += pks.at(0)->GetSize() + 1;
1831 max_providers_len = std::max(max_providers_len, pks.size());
1832 providers.emplace_back(std::move(pks));
1841 }
else if (thres < 1) {
1842 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
1844 }
else if (thres > providers.size()) {
1845 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
1848 if (ctx == ParseScriptContext::TOP) {
1849 if (providers.size() > 3) {
1850 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
1854 if (ctx == ParseScriptContext::P2SH) {
1864 for (
auto& vec : providers) {
1865 if (vec.size() == 1) {
1866 for (
size_t i = 1; i < max_providers_len; ++i) {
1867 vec.emplace_back(vec.at(0)->Clone());
1869 }
else if (vec.size() != max_providers_len) {
1870 error =
strprintf(
"multi(): Multipath derivation paths have mismatched lengths");
1876 for (
size_t i = 0; i < max_providers_len; ++i) {
1878 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
1879 pubs.reserve(providers.size());
1880 for (
auto& pub : providers) {
1881 pubs.emplace_back(std::move(pub.at(i)));
1883 if (multi || sortedmulti) {
1884 ret.emplace_back(std::make_unique<MultisigDescriptor>(thres, std::move(pubs), sortedmulti));
1886 ret.emplace_back(std::make_unique<MultiADescriptor>(thres, std::move(pubs), sortedmulti_a));
1890 }
else if (multi || sortedmulti) {
1891 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
1893 }
else if (multi_a || sortedmulti_a) {
1894 error =
"Can only have multi_a/sortedmulti_a inside tr()";
1897 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
1898 auto pubkeys = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH,
out, error);
1899 if (pubkeys.empty()) {
1904 for (
auto& pubkey : pubkeys) {
1905 ret.emplace_back(std::make_unique<WPKHDescriptor>(std::move(pubkey)));
1908 }
else if (
Func(
"wpkh", expr)) {
1909 error =
"Can only have wpkh() at top level or inside sh()";
1912 if (ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1913 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
out, error);
1914 if (descs.empty() || expr.size())
return {};
1915 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
1916 ret.reserve(descs.size());
1917 for (
auto& desc : descs) {
1918 ret.push_back(std::make_unique<SHDescriptor>(std::move(desc)));
1921 }
else if (
Func(
"sh", expr)) {
1922 error =
"Can only have sh() at top level";
1925 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
1926 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH,
out, error);
1927 if (descs.empty() || expr.size())
return {};
1928 for (
auto& desc : descs) {
1929 ret.emplace_back(std::make_unique<WSHDescriptor>(std::move(desc)));
1932 }
else if (
Func(
"wsh", expr)) {
1933 error =
"Can only have wsh() at top level or inside sh()";
1936 if (ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1939 error =
"Address is not valid";
1942 ret.emplace_back(std::make_unique<AddressDescriptor>(std::move(dest)));
1944 }
else if (
Func(
"addr", expr)) {
1945 error =
"Can only have addr() at top level";
1948 if (ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
1949 auto arg =
Expr(expr);
1950 auto internal_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
1951 if (internal_keys.empty()) {
1955 size_t max_providers_len = internal_keys.size();
1957 std::vector<std::vector<std::unique_ptr<DescriptorImpl>>> subscripts;
1958 std::vector<int> depths;
1960 if (!
Const(
",", expr)) {
1961 error =
strprintf(
"tr: expected ',', got '%c'", expr[0]);
1967 std::vector<bool> branches;
1972 while (
Const(
"{", expr)) {
1973 branches.push_back(
false);
1980 auto sarg =
Expr(expr);
1981 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR,
out, error));
1982 if (subscripts.back().empty())
return {};
1983 max_providers_len = std::max(max_providers_len, subscripts.back().size());
1984 depths.push_back(branches.size());
1986 while (branches.size() && branches.back()) {
1987 if (!
Const(
"}", expr)) {
1988 error =
strprintf(
"tr(): expected '}' after script expression");
1991 branches.pop_back();
1994 if (branches.size() && !branches.back()) {
1995 if (!
Const(
",", expr)) {
1996 error =
strprintf(
"tr(): expected ',' after script expression");
1999 branches.back() =
true;
2001 }
while (branches.size());
2004 error =
strprintf(
"tr(): expected ')' after script expression");
2012 for (
auto& vec : subscripts) {
2013 if (vec.size() == 1) {
2014 for (
size_t i = 1; i < max_providers_len; ++i) {
2015 vec.emplace_back(vec.at(0)->Clone());
2017 }
else if (vec.size() != max_providers_len) {
2018 error =
strprintf(
"tr(): Multipath subscripts have mismatched lengths");
2023 if (internal_keys.size() > 1 && internal_keys.size() != max_providers_len) {
2024 error =
strprintf(
"tr(): Multipath internal key mismatches multipath subscripts lengths");
2028 while (internal_keys.size() < max_providers_len) {
2029 internal_keys.emplace_back(internal_keys.at(0)->Clone());
2033 for (
size_t i = 0; i < max_providers_len; ++i) {
2035 std::vector<std::unique_ptr<DescriptorImpl>> this_subs;
2036 this_subs.reserve(subscripts.size());
2037 for (
auto& subs : subscripts) {
2038 this_subs.emplace_back(std::move(subs.at(i)));
2040 ret.emplace_back(std::make_unique<TRDescriptor>(std::move(internal_keys.at(i)), std::move(this_subs), depths));
2045 }
else if (
Func(
"tr", expr)) {
2046 error =
"Can only have tr at top level";
2049 if (ctx == ParseScriptContext::TOP &&
Func(
"rawtr", expr)) {
2050 auto arg =
Expr(expr);
2052 error =
strprintf(
"rawtr(): only one key expected.");
2055 auto output_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
2056 if (output_keys.empty()) {
2057 error =
strprintf(
"rawtr(): %s", error);
2061 for (
auto& pubkey : output_keys) {
2062 ret.emplace_back(std::make_unique<RawTRDescriptor>(std::move(pubkey)));
2065 }
else if (
Func(
"rawtr", expr)) {
2066 error =
"Can only have rawtr at top level";
2069 if (ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
2070 std::string str(expr.begin(), expr.end());
2072 error =
"Raw script is not hex";
2076 ret.emplace_back(std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end())));
2078 }
else if (
Func(
"raw", expr)) {
2079 error =
"Can only have raw() at top level";
2085 KeyParser parser(&
out,
nullptr, script_ctx, key_exp_index);
2087 if (parser.m_key_parsing_error !=
"") {
2088 error = std::move(parser.m_key_parsing_error);
2092 if (ctx != ParseScriptContext::P2WSH && ctx != ParseScriptContext::P2TR) {
2093 error =
"Miniscript expressions can only be used in wsh or tr.";
2096 if (!
node->IsSane() ||
node->IsNotSatisfiable()) {
2098 auto insane_node =
node.get();
2099 if (
const auto sub =
node->FindInsaneSub()) insane_node = sub;
2100 if (
const auto str = insane_node->ToString(parser)) error = *str;
2101 if (!insane_node->IsValid()) {
2102 error +=
" is invalid";
2103 }
else if (!
node->IsSane()) {
2104 error +=
" is not sane";
2105 if (!insane_node->IsNonMalleable()) {
2106 error +=
": malleable witnesses exist";
2107 }
else if (insane_node ==
node.get() && !insane_node->NeedsSignature()) {
2108 error +=
": witnesses without signature exist";
2109 }
else if (!insane_node->CheckTimeLocksMix()) {
2110 error +=
": contains mixes of timelocks expressed in blocks and seconds";
2111 }
else if (!insane_node->CheckDuplicateKey()) {
2112 error +=
": contains duplicate public keys";
2113 }
else if (!insane_node->ValidSatisfactions()) {
2114 error +=
": needs witnesses that may exceed resource limits";
2117 error +=
" is not satisfiable";
2124 key_exp_index += parser.m_keys.size();
2127 size_t num_multipath = std::max_element(parser.m_keys.begin(), parser.m_keys.end(),
2128 [](
const std::vector<std::unique_ptr<PubkeyProvider>>& a,
const std::vector<std::unique_ptr<PubkeyProvider>>& b) {
2129 return a.size() < b.size();
2132 for (
auto& vec : parser.m_keys) {
2133 if (vec.size() == 1) {
2134 for (
size_t i = 1; i < num_multipath; ++i) {
2135 vec.emplace_back(vec.at(0)->Clone());
2137 }
else if (vec.size() != num_multipath) {
2138 error =
strprintf(
"Miniscript: Multipath derivation paths have mismatched lengths");
2144 for (
size_t i = 0; i < num_multipath; ++i) {
2146 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
2147 pubs.reserve(parser.m_keys.size());
2148 for (
auto& pub : parser.m_keys) {
2149 pubs.emplace_back(std::move(pub.at(i)));
2151 ret.emplace_back(std::make_unique<MiniscriptDescriptor>(std::move(pubs),
node->Clone()));
2156 if (ctx == ParseScriptContext::P2SH) {
2157 error =
"A function is needed within P2SH";
2159 }
else if (ctx == ParseScriptContext::P2WSH) {
2160 error =
"A function is needed within P2WSH";
2163 error =
strprintf(
"'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
2170 if (!match)
return {};
2171 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2172 keys.reserve(match->second.size());
2173 for (
const auto keyspan : match->second) {
2174 if (keyspan.size() != 32)
return {};
2175 auto key = InferXOnlyPubkey(
XOnlyPubKey{keyspan}, ctx, provider);
2176 if (!key)
return {};
2177 keys.push_back(std::move(key));
2179 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
2187 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider),
true);
2190 if (ctx == ParseScriptContext::P2TR) {
2191 auto ret = InferMultiA(
script, ctx, provider);
2195 std::vector<std::vector<unsigned char>>
data;
2198 if (txntype ==
TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2200 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2201 return std::make_unique<PKDescriptor>(std::move(pubkey_provider));
2204 if (txntype ==
TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2208 if (provider.
GetPubKey(keyid, pubkey)) {
2209 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2210 return std::make_unique<PKHDescriptor>(std::move(pubkey_provider));
2218 if (provider.
GetPubKey(keyid, pubkey)) {
2219 if (
auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) {
2220 return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider));
2224 if (txntype ==
TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2226 std::vector<std::unique_ptr<PubkeyProvider>> providers;
2227 for (
size_t i = 1; i + 1 <
data.size(); ++i) {
2229 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2230 providers.push_back(std::move(pubkey_provider));
2236 if (ok)
return std::make_unique<MultisigDescriptor>((
int)
data[0][0], std::move(providers));
2242 if (provider.
GetCScript(scriptid, subscript)) {
2243 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
2244 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
2250 if (provider.
GetCScript(scriptid, subscript)) {
2251 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
2252 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
2267 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
2268 std::vector<int> depths;
2269 for (
const auto& [depth,
script, leaf_ver] : *tree) {
2270 std::unique_ptr<DescriptorImpl> subdesc;
2272 subdesc = InferScript(
CScript(
script.begin(),
script.end()), ParseScriptContext::P2TR, provider);
2278 subscripts.push_back(std::move(subdesc));
2279 depths.push_back(depth);
2283 auto key = InferXOnlyPubkey(tap.
internal_key, ParseScriptContext::P2TR, provider);
2284 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
2290 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
2292 return std::make_unique<RawTRDescriptor>(std::move(key));
2297 if (ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR) {
2299 KeyParser parser(
nullptr, &provider, script_ctx);
2302 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2303 keys.reserve(parser.m_keys.size());
2304 for (
auto& key : parser.m_keys) {
2305 keys.emplace_back(std::move(key.at(0)));
2307 return std::make_unique<MiniscriptDescriptor>(std::move(keys), std::move(
node));
2313 if (ctx != ParseScriptContext::TOP)
return nullptr;
2318 return std::make_unique<AddressDescriptor>(std::move(dest));
2322 return std::make_unique<RawDescriptor>(
script);
2329bool CheckChecksum(std::span<const char>& sp,
bool require_checksum, std::string& error, std::string* out_checksum =
nullptr)
2331 auto check_split =
Split(sp,
'#');
2332 if (check_split.size() > 2) {
2333 error =
"Multiple '#' symbols";
2336 if (check_split.size() == 1 && require_checksum){
2337 error =
"Missing checksum";
2340 if (check_split.size() == 2) {
2341 if (check_split[1].size() != 8) {
2342 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
2346 auto checksum = DescriptorChecksum(check_split[0]);
2347 if (checksum.empty()) {
2348 error =
"Invalid characters in payload";
2351 if (check_split.size() == 2) {
2352 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
2353 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
2357 if (out_checksum) *out_checksum = std::move(checksum);
2358 sp = check_split[0];
2364 std::span<const char> sp{descriptor};
2366 uint32_t key_exp_index = 0;
2368 if (sp.size() == 0 && !
ret.empty()) {
2369 std::vector<std::unique_ptr<Descriptor>> descs;
2370 descs.reserve(
ret.size());
2371 for (
auto& r :
ret) {
2372 descs.emplace_back(std::unique_ptr<Descriptor>(std::move(r)));
2383 std::span<const char> sp{descriptor};
2390 return InferScript(
script, ParseScriptContext::TOP, provider);
2395 std::string desc_str = desc.
ToString(
true);
2409 xpubs[der_index] = xpub;
2429 const auto& der_it = key_exp_it->second.find(der_index);
2430 if (der_it == key_exp_it->second.end())
return false;
2431 xpub = der_it->second;
2449 if (xpub != parent_xpub_pair.second) {
2450 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
2458 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
2461 if (xpub != derived_xpub_pair.second) {
2462 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
2466 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2467 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2473 if (xpub != lh_xpub_pair.second) {
2474 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.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the 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
bool GetKeyByXOnly(const XOnlyPubKey &pubkey, CKey &key) 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
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.
TaprootBuilder & Add(int depth, std::span< const unsigned char > script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
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(std::span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
std::string HexStr(const std::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)
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)
std::unique_ptr< const Node< Key > > NodeRef
std::span< const char > Expr(std::span< const char > &sp)
Extract the expression that sp begins with.
bool Const(const std::string &str, std::span< const char > &sp)
Parse a constant.
bool Func(const std::string &str, std::span< const char > &sp)
Parse a function call.
static std::vector< std::string > split(const std::string &str, const std::string &delims=" \t")
std::vector< T > Split(const std::span< const char > &sp, std::string_view separators)
Split a string on any char found in separators, returning a vector.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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.
uint256 DescriptorID(const Descriptor &desc)
Unique identifier that may not change over time, unless explicitly marked as not backwards compatible...
bool CheckChecksum(std::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::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)
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
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.
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
std::optional< std::pair< int, std::vector< std::span< const unsigned char > > > > MatchMultiA(const CScript &script)
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
constexpr bool IsSpace(char c) noexcept
Tests if the given character is a whitespace character.
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.
bool GetPubKey(const CKeyID &keyid, CPubKey &pubkey) const override
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.
consteval auto _(util::TranslatedLiteral str)
bool IsHex(std::string_view str)
std::vector< std::common_type_t< Args... > > Vector(Args &&... args)
Construct a vector with the specified elements.