94uint64_t
PolyMod(uint64_t c,
int val)
97 c = ((c & 0x7ffffffff) << 5) ^ val;
98 if (c0 & 1) c ^= 0xf5dee51989;
99 if (c0 & 2) c ^= 0xa9fdca3312;
100 if (c0 & 4) c ^= 0x1bab10e32d;
101 if (c0 & 8) c ^= 0x3706b1677a;
102 if (c0 & 16) c ^= 0x644d626ffd;
106std::string DescriptorChecksum(
const std::span<const char>& span)
121 static const std::string INPUT_CHARSET =
122 "0123456789()[],'/*abcdefgh@:$%{}"
123 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
124 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
127 static const std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
132 for (
auto ch : span) {
133 auto pos = INPUT_CHARSET.find(ch);
134 if (pos == std::string::npos)
return "";
136 cls = cls * 3 + (pos >> 5);
137 if (++clscount == 3) {
144 if (clscount > 0) c =
PolyMod(c, cls);
145 for (
int j = 0; j < 8; ++j) c =
PolyMod(c, 0);
148 std::string
ret(8,
' ');
149 for (
int j = 0; j < 8; ++j)
ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
153std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
159typedef std::vector<uint32_t> KeyPath;
167 uint32_t m_expr_index;
170 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
172 virtual ~PubkeyProvider() =
default;
177 bool operator<(PubkeyProvider& other)
const {
180 std::optional<CPubKey> a =
GetPubKey(0, dummy, dummy);
181 std::optional<CPubKey> b = other.GetPubKey(0, dummy, dummy);
194 virtual bool IsRange()
const = 0;
197 virtual size_t GetSize()
const = 0;
199 enum class StringType {
205 virtual std::string
ToString(StringType type=StringType::PUBLIC)
const = 0;
223 virtual std::optional<CPubKey> GetRootPubKey()
const = 0;
225 virtual std::optional<CExtPubKey> GetRootExtPubKey()
const = 0;
228 virtual std::unique_ptr<PubkeyProvider> Clone()
const = 0;
231 virtual bool IsBIP32()
const = 0;
234class OriginPubkeyProvider final :
public PubkeyProvider
237 std::unique_ptr<PubkeyProvider> m_provider;
240 std::string OriginString(StringType type,
bool normalized=
false)
const
243 bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
248 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) {}
251 std::optional<CPubKey> pub = m_provider->GetPubKey(pos, arg,
out, read_cache, write_cache);
252 if (!pub)
return std::nullopt;
253 Assert(
out.pubkeys.contains(pub->GetID()));
254 auto& [pubkey, suborigin] =
out.origins[pub->GetID()];
256 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), suborigin.fingerprint);
257 suborigin.path.insert(suborigin.path.begin(), m_origin.path.begin(), m_origin.path.end());
260 bool IsRange()
const override {
return m_provider->IsRange(); }
261 size_t GetSize()
const override {
return m_provider->GetSize(); }
262 bool IsBIP32()
const override {
return m_provider->IsBIP32(); }
263 std::string
ToString(StringType type)
const override {
return "[" + OriginString(type) +
"]" + m_provider->ToString(type); }
267 bool has_priv_key{m_provider->ToPrivateString(arg, sub)};
268 ret =
"[" + OriginString(StringType::PUBLIC) +
"]" + std::move(sub);
274 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
280 ret =
"[" + OriginString(StringType::PUBLIC,
true) + std::move(sub);
282 ret =
"[" + OriginString(StringType::PUBLIC,
true) +
"]" + std::move(sub);
288 m_provider->GetPrivKey(pos, arg,
out);
290 std::optional<CPubKey> GetRootPubKey()
const override
292 return m_provider->GetRootPubKey();
294 std::optional<CExtPubKey> GetRootExtPubKey()
const override
296 return m_provider->GetRootExtPubKey();
298 std::unique_ptr<PubkeyProvider> Clone()
const override
300 return std::make_unique<OriginPubkeyProvider>(m_expr_index, m_origin, m_provider->Clone(), m_apostrophe);
305class ConstPubkeyProvider final :
public PubkeyProvider
314 arg.
GetKey(m_pubkey.GetID(), key)))
return std::nullopt;
319 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
323 CKeyID keyid = m_pubkey.GetID();
325 out.origins.emplace(keyid, std::make_pair(m_pubkey, info));
326 out.pubkeys.emplace(keyid, m_pubkey);
329 bool IsRange()
const override {
return false; }
330 size_t GetSize()
const override {
return m_pubkey.size(); }
331 bool IsBIP32()
const override {
return false; }
332 std::string
ToString(StringType type)
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
335 std::optional<CKey> key = GetPrivKey(arg);
350 std::optional<CKey> key = GetPrivKey(arg);
352 out.keys.emplace(key->GetPubKey().GetID(), *key);
354 std::optional<CPubKey> GetRootPubKey()
const override
358 std::optional<CExtPubKey> GetRootExtPubKey()
const override
362 std::unique_ptr<PubkeyProvider> Clone()
const override
364 return std::make_unique<ConstPubkeyProvider>(m_expr_index, m_pubkey, m_xonly);
368enum class DeriveType {
375class BIP32PubkeyProvider final :
public PubkeyProvider
387 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
388 ret.nDepth = m_root_extkey.nDepth;
389 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
ret.vchFingerprint);
390 ret.nChild = m_root_extkey.nChild;
391 ret.chaincode = m_root_extkey.chaincode;
399 if (!GetExtKey(arg, xprv))
return false;
400 for (
auto entry : m_path) {
401 if (!xprv.
Derive(xprv, entry))
return false;
403 last_hardened = xprv;
409 bool IsHardened()
const
411 if (m_derive == DeriveType::HARDENED)
return true;
412 for (
auto entry : m_path) {
413 if (entry >> 31)
return true;
419 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) {}
420 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
421 size_t GetSize()
const override {
return 33; }
422 bool IsBIP32()
const override {
return true; }
426 CKeyID keyid = m_root_extkey.pubkey.GetID();
429 if (m_derive == DeriveType::UNHARDENED) info.
path.push_back((uint32_t)pos);
430 if (m_derive == DeriveType::HARDENED) info.
path.push_back(((uint32_t)pos) | 0x80000000L);
438 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
439 if (m_derive == DeriveType::HARDENED)
return std::nullopt;
441 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return std::nullopt;
442 final_extkey = parent_extkey;
443 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
445 }
else if (IsHardened()) {
448 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return std::nullopt;
449 parent_extkey = xprv.
Neuter();
450 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
451 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
452 final_extkey = xprv.
Neuter();
454 last_hardened_extkey = lh_xprv.
Neuter();
457 for (
auto entry : m_path) {
458 if (!parent_extkey.
Derive(parent_extkey, entry))
return std::nullopt;
460 final_extkey = parent_extkey;
461 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
462 assert(m_derive != DeriveType::HARDENED);
464 if (!der)
return std::nullopt;
471 if (m_derive != DeriveType::HARDENED) {
472 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
475 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
477 }
else if (info.
path.size() > 0) {
478 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
482 return final_extkey.
pubkey;
484 std::string
ToString(StringType type,
bool normalized)
const
487 const bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
491 if (m_derive == DeriveType::HARDENED)
ret += use_apostrophe ?
'\'' :
'h';
495 std::string
ToString(StringType type=StringType::PUBLIC)
const override
502 if (!GetExtKey(arg, key)) {
509 if (m_derive == DeriveType::HARDENED)
out += m_apostrophe ?
'\'' :
'h';
515 if (m_derive == DeriveType::HARDENED) {
521 int i = (int)m_path.size() - 1;
522 for (; i >= 0; --i) {
523 if (m_path.at(i) >> 31) {
535 for (;
k <= i; ++
k) {
537 origin.
path.push_back(m_path.at(
k));
541 for (;
k < (int)m_path.size(); ++
k) {
542 end_path.push_back(m_path.at(
k));
545 CKeyID id = m_root_extkey.pubkey.GetID();
546 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
551 if (cache !=
nullptr) {
557 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
567 assert(m_derive == DeriveType::UNHARDENED);
575 if (!GetDerivedExtKey(arg, extkey, dummy))
return;
576 if (m_derive == DeriveType::UNHARDENED && !extkey.
Derive(extkey, pos))
return;
577 if (m_derive == DeriveType::HARDENED && !extkey.
Derive(extkey, pos | 0x80000000UL))
return;
580 std::optional<CPubKey> GetRootPubKey()
const override
584 std::optional<CExtPubKey> GetRootExtPubKey()
const override
586 return m_root_extkey;
588 std::unique_ptr<PubkeyProvider> Clone()
const override
590 return std::make_unique<BIP32PubkeyProvider>(m_expr_index, m_root_extkey, m_path, m_derive, m_apostrophe);
595class MuSigPubkeyProvider final :
public PubkeyProvider
599 const std::vector<std::unique_ptr<PubkeyProvider>> m_participants;
601 const KeyPath m_path;
603 mutable std::unique_ptr<PubkeyProvider> m_aggregate_provider;
604 mutable std::optional<CPubKey> m_aggregate_pubkey;
605 const DeriveType m_derive;
606 const bool m_ranged_participants;
608 bool IsRangedDerivation()
const {
return m_derive != DeriveType::NO; }
613 std::vector<std::unique_ptr<PubkeyProvider>> providers,
617 : PubkeyProvider(exp_index),
618 m_participants(
std::move(providers)),
619 m_path(
std::move(path)),
621 m_ranged_participants(
std::any_of(m_participants.begin(), m_participants.end(), [](const auto& pubkey) {
return pubkey->IsRange(); }))
623 if (!
Assume(!(m_ranged_participants && IsRangedDerivation()))) {
624 throw std::runtime_error(
"musig(): Cannot have both ranged participants and ranged derivation");
626 if (!
Assume(m_derive != DeriveType::HARDENED)) {
627 throw std::runtime_error(
"musig(): Cannot have hardened derivation");
635 if (!m_aggregate_provider && !m_ranged_participants) {
637 std::vector<CPubKey> pubkeys;
638 for (
const auto& prov : m_participants) {
639 std::optional<CPubKey> pubkey = prov->GetPubKey(0, arg, dummy, read_cache, write_cache);
640 if (!pubkey.has_value()) {
643 pubkeys.push_back(pubkey.value());
645 std::sort(pubkeys.begin(), pubkeys.end());
649 if (!
Assume(m_aggregate_pubkey.has_value()))
return std::nullopt;
652 if (IsRangedDerivation() || !m_path.empty()) {
655 m_aggregate_provider = std::make_unique<BIP32PubkeyProvider>(m_expr_index, extpub, m_path, m_derive,
false);
657 m_aggregate_provider = std::make_unique<ConstPubkeyProvider>(m_expr_index, m_aggregate_pubkey.value(),
false);
662 std::vector<CPubKey> pubkeys;
663 for (
const auto& prov : m_participants) {
664 std::optional<CPubKey> pub = prov->GetPubKey(pos, arg,
out, read_cache, write_cache);
665 if (!pub)
return std::nullopt;
666 pubkeys.emplace_back(*pub);
668 std::sort(pubkeys.begin(), pubkeys.end());
671 if (m_aggregate_provider) {
675 std::optional<CPubKey> pub = m_aggregate_provider->GetPubKey(pos, dummy,
out, read_cache, write_cache);
676 if (!pub)
return std::nullopt;
678 out.aggregate_pubkeys.emplace(m_aggregate_pubkey.value(), pubkeys);
680 if (!
Assume(m_ranged_participants) || !
Assume(m_path.empty()))
return std::nullopt;
683 if (!aggregate_pubkey)
return std::nullopt;
684 pubout = *aggregate_pubkey;
686 std::unique_ptr<ConstPubkeyProvider> this_agg_provider = std::make_unique<ConstPubkeyProvider>(m_expr_index, aggregate_pubkey.value(),
false);
687 this_agg_provider->GetPubKey(0, dummy,
out, read_cache, write_cache);
688 out.aggregate_pubkeys.emplace(pubout, pubkeys);
694 bool IsRange()
const override {
return IsRangedDerivation() || m_ranged_participants; }
696 size_t GetSize()
const override {
return 32; }
698 std::string
ToString(StringType type=StringType::PUBLIC)
const override
700 std::string
out =
"musig(";
701 for (
size_t i = 0; i < m_participants.size(); ++i) {
702 const auto& pubkey = m_participants.at(i);
704 out += pubkey->ToString(type);
708 if (IsRangedDerivation()) {
715 bool any_privkeys =
false;
717 for (
size_t i = 0; i < m_participants.size(); ++i) {
718 const auto& pubkey = m_participants.at(i);
721 if (pubkey->ToPrivateString(arg, tmp)) {
728 if (IsRangedDerivation()) {
736 for (
size_t i = 0; i < m_participants.size(); ++i) {
737 const auto& pubkey = m_participants.at(i);
740 if (!pubkey->ToNormalizedString(arg, tmp, cache)) {
747 if (IsRangedDerivation()) {
758 for (
const auto& prov : m_participants) {
759 prov->GetPrivKey(pos, arg,
out);
768 std::optional<CPubKey> GetRootPubKey()
const override
772 std::optional<CExtPubKey> GetRootExtPubKey()
const override
777 std::unique_ptr<PubkeyProvider> Clone()
const override
779 std::vector<std::unique_ptr<PubkeyProvider>> providers;
780 providers.reserve(m_participants.size());
781 for (
const std::unique_ptr<PubkeyProvider>& p : m_participants) {
782 providers.emplace_back(p->Clone());
784 return std::make_unique<MuSigPubkeyProvider>(m_expr_index, std::move(providers), m_path, m_derive);
786 bool IsBIP32()
const override
789 return std::all_of(m_participants.begin(), m_participants.end(), [](
const auto& pubkey) { return pubkey->IsBIP32(); });
798 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
800 const std::string m_name;
802 std::vector<std::string> m_warnings;
808 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
811 virtual std::string ToStringExtra()
const {
return ""; }
823 virtual std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& pubkeys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const = 0;
826 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
827 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))) {}
828 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)) {}
830 enum class StringType
841 for (
const auto& arg : m_subdescriptor_args) {
842 if (!arg->IsSolvable())
return false;
850 if (m_pubkey_args.empty() && m_subdescriptor_args.empty())
return false;
852 for (
const auto& sub: m_subdescriptor_args) {
853 if (!sub->HavePrivateKeys(arg))
return false;
857 for (
const auto& pubkey : m_pubkey_args) {
858 tmp_provider.
keys.clear();
859 pubkey->GetPrivKey(0, arg, tmp_provider);
860 if (tmp_provider.
keys.empty())
return false;
869 for (
const auto& pubkey : m_pubkey_args) {
870 if (pubkey->IsRange())
return true;
872 for (
const auto& arg : m_subdescriptor_args) {
873 if (arg->IsRange())
return true;
882 bool is_private{type == StringType::PRIVATE};
885 bool any_success{!is_private};
886 for (
const auto& scriptarg : m_subdescriptor_args) {
887 if (pos++)
ret +=
",";
889 bool subscript_res{scriptarg->ToStringHelper(arg, tmp, type, cache)};
890 if (!is_private && !subscript_res)
return false;
891 any_success = any_success || subscript_res;
900 std::string extra = ToStringExtra();
901 size_t pos = extra.size() > 0 ? 1 : 0;
902 std::string
ret = m_name +
"(" + extra;
903 bool is_private{type == StringType::PRIVATE};
906 bool any_success{!is_private};
908 for (
const auto& pubkey : m_pubkey_args) {
909 if (pos++)
ret +=
",";
912 case StringType::NORMALIZED:
913 if (!pubkey->ToNormalizedString(*arg, tmp, cache))
return false;
915 case StringType::PRIVATE:
916 any_success = pubkey->ToPrivateString(*arg, tmp) || any_success;
918 case StringType::PUBLIC:
919 tmp = pubkey->ToString();
921 case StringType::COMPAT:
922 tmp = pubkey->ToString(PubkeyProvider::StringType::COMPAT);
927 std::string subscript;
928 bool subscript_res{ToStringSubScriptHelper(arg, subscript, type, cache)};
929 if (!is_private && !subscript_res)
return false;
930 any_success = any_success || subscript_res;
931 if (pos && subscript.size())
ret +=
',';
932 out = std::move(
ret) + std::move(subscript) +
")";
936 std::string
ToString(
bool compat_format)
const final
939 ToStringHelper(
nullptr,
ret, compat_format ? StringType::COMPAT : StringType::PUBLIC);
940 return AddChecksum(
ret);
945 bool has_priv_key{ToStringHelper(&arg,
out, StringType::PRIVATE)};
952 bool ret = ToStringHelper(&arg,
out, StringType::NORMALIZED, cache);
961 std::vector<CPubKey> pubkeys;
962 pubkeys.reserve(m_pubkey_args.size());
965 for (
const auto& p : m_pubkey_args) {
966 std::optional<CPubKey> pubkey = p->
GetPubKey(pos, arg, subprovider, read_cache, write_cache);
967 if (!pubkey)
return false;
968 pubkeys.push_back(pubkey.value());
970 std::vector<CScript> subscripts;
971 for (
const auto& subarg : m_subdescriptor_args) {
972 std::vector<CScript> outscripts;
973 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
974 assert(outscripts.size() == 1);
975 subscripts.emplace_back(std::move(outscripts[0]));
977 out.Merge(std::move(subprovider));
979 output_scripts = MakeScripts(pubkeys, std::span{subscripts},
out);
985 return ExpandHelper(pos, provider,
nullptr, output_scripts,
out, write_cache);
996 for (
const auto& p : m_pubkey_args) {
997 p->GetPrivKey(pos, provider,
out);
999 for (
const auto& arg : m_subdescriptor_args) {
1000 arg->ExpandPrivate(pos, provider,
out);
1004 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
1006 std::optional<int64_t>
ScriptSize()
const override {
return {}; }
1013 virtual std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const {
return {}; }
1020 void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs)
const override
1022 for (
const auto& p : m_pubkey_args) {
1023 std::optional<CPubKey> pub = p->GetRootPubKey();
1024 if (pub) pubkeys.insert(*pub);
1025 std::optional<CExtPubKey> ext_pub = p->GetRootExtPubKey();
1026 if (ext_pub) ext_pubs.insert(*ext_pub);
1028 for (
const auto& arg : m_subdescriptor_args) {
1029 arg->GetPubKeys(pubkeys, ext_pubs);
1033 virtual std::unique_ptr<DescriptorImpl> Clone()
const = 0;
1036 std::vector<std::string>
Warnings()
const override {
1037 std::vector<std::string> all = m_warnings;
1038 for (
const auto& sub : m_subdescriptor_args) {
1039 auto sub_w = sub->Warnings();
1040 all.insert(all.end(), sub_w.begin(), sub_w.end());
1047class AddressDescriptor final :
public DescriptorImpl
1051 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
1054 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
1055 bool IsSolvable() const final {
return false; }
1061 bool IsSingleType() const final {
return true; }
1062 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
1065 std::unique_ptr<DescriptorImpl> Clone()
const override
1067 return std::make_unique<AddressDescriptor>(m_destination);
1072class RawDescriptor final :
public DescriptorImpl
1076 std::string ToStringExtra()
const override {
return HexStr(m_script); }
1077 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript>,
FlatSigningProvider&)
const override {
return Vector(m_script); }
1080 bool IsSolvable() const final {
return false; }
1088 bool IsSingleType() const final {
return true; }
1089 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
1091 std::optional<int64_t> ScriptSize()
const override {
return m_script.size(); }
1093 std::unique_ptr<DescriptorImpl> Clone()
const override
1095 return std::make_unique<RawDescriptor>(m_script);
1100class PKDescriptor final :
public DescriptorImpl
1105 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
1115 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
1116 bool IsSingleType() const final {
return true; }
1118 std::optional<int64_t> ScriptSize()
const override {
1119 return 1 + (m_xonly ? 32 : m_pubkey_args[0]->GetSize()) + 1;
1122 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1123 const auto ecdsa_sig_size = use_max_sig ? 72 : 71;
1124 return 1 + (m_xonly ? 65 : ecdsa_sig_size);
1127 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1131 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1; }
1133 std::unique_ptr<DescriptorImpl> Clone()
const override
1135 return std::make_unique<PKDescriptor>(m_pubkey_args.at(0)->Clone(), m_xonly);
1140class PKHDescriptor final :
public DescriptorImpl
1143 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
1145 CKeyID id = keys[0].GetID();
1149 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
1151 bool IsSingleType() const final {
return true; }
1153 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 1 + 20 + 1 + 1; }
1155 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1156 const auto sig_size = use_max_sig ? 72 : 71;
1157 return 1 +
sig_size + 1 + m_pubkey_args[0]->GetSize();
1160 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1164 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
1166 std::unique_ptr<DescriptorImpl> Clone()
const override
1168 return std::make_unique<PKHDescriptor>(m_pubkey_args.at(0)->Clone());
1173class WPKHDescriptor final :
public DescriptorImpl
1176 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
1178 CKeyID id = keys[0].GetID();
1182 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
1184 bool IsSingleType() const final {
return true; }
1186 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20; }
1188 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1189 const auto sig_size = use_max_sig ? 72 : 71;
1193 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1194 return MaxSatSize(use_max_sig);
1197 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
1199 std::unique_ptr<DescriptorImpl> Clone()
const override
1201 return std::make_unique<WPKHDescriptor>(m_pubkey_args.at(0)->Clone());
1206class ComboDescriptor final :
public DescriptorImpl
1209 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&
out)
const override
1211 std::vector<CScript>
ret;
1212 CKeyID id = keys[0].GetID();
1215 if (keys[0].IsCompressed()) {
1218 ret.emplace_back(p2wpkh);
1224 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
1225 bool IsSingleType() const final {
return false; }
1226 std::unique_ptr<DescriptorImpl> Clone()
const override
1228 return std::make_unique<ComboDescriptor>(m_pubkey_args.at(0)->Clone());
1233class MultisigDescriptor final :
public DescriptorImpl
1235 const int m_threshold;
1236 const bool m_sorted;
1238 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
1239 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override {
1241 std::vector<CPubKey> sorted_keys(keys);
1242 std::sort(sorted_keys.begin(), sorted_keys.end());
1248 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) {}
1249 bool IsSingleType() const final {
return true; }
1251 std::optional<int64_t> ScriptSize()
const override {
1252 const auto n_keys = m_pubkey_args.size();
1253 auto op = [](int64_t acc,
const std::unique_ptr<PubkeyProvider>&
pk) {
return acc + 1 +
pk->GetSize();};
1254 const auto pubkeys_size{std::accumulate(m_pubkey_args.begin(), m_pubkey_args.end(), int64_t{0}, op)};
1258 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1259 const auto sig_size = use_max_sig ? 72 : 71;
1260 return (1 + (1 +
sig_size) * m_threshold);
1263 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1267 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1 + m_threshold; }
1269 std::unique_ptr<DescriptorImpl> Clone()
const override
1271 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1272 providers.reserve(m_pubkey_args.size());
1273 std::transform(m_pubkey_args.begin(), m_pubkey_args.end(), providers.begin(), [](
const std::unique_ptr<PubkeyProvider>& p) { return p->Clone(); });
1274 return std::make_unique<MultisigDescriptor>(m_threshold, std::move(providers), m_sorted);
1279class MultiADescriptor final :
public DescriptorImpl
1281 const int m_threshold;
1282 const bool m_sorted;
1284 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
1285 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override {
1287 std::vector<XOnlyPubKey> xkeys;
1288 xkeys.reserve(keys.size());
1289 for (
const auto& key : keys) xkeys.emplace_back(key);
1290 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
1292 for (
size_t i = 1; i < keys.size(); ++i) {
1299 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) {}
1300 bool IsSingleType() const final {
return true; }
1302 std::optional<int64_t> ScriptSize()
const override {
1303 const auto n_keys = m_pubkey_args.size();
1307 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1308 return (1 + 65) * m_threshold + (m_pubkey_args.size() - m_threshold);
1311 std::optional<int64_t> MaxSatisfactionElems()
const override {
return m_pubkey_args.size(); }
1313 std::unique_ptr<DescriptorImpl> Clone()
const override
1315 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1316 providers.reserve(m_pubkey_args.size());
1317 for (
const auto& arg : m_pubkey_args) {
1318 providers.push_back(arg->Clone());
1320 return std::make_unique<MultiADescriptor>(m_threshold, std::move(providers), m_sorted);
1325class SHDescriptor final :
public DescriptorImpl
1328 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1331 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1338 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
1342 assert(m_subdescriptor_args.size() == 1);
1346 bool IsSingleType() const final {
return true; }
1348 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20 + 1; }
1350 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1351 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1352 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1356 if (
IsSegwit())
return subscript_weight + *sat_size;
1363 std::optional<int64_t> MaxSatisfactionElems()
const override {
1364 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1368 std::unique_ptr<DescriptorImpl> Clone()
const override
1370 return std::make_unique<SHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1375class WSHDescriptor final :
public DescriptorImpl
1378 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1381 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1385 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
1387 bool IsSingleType() const final {
return true; }
1389 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1391 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1392 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1393 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1400 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1401 return MaxSatSize(use_max_sig);
1404 std::optional<int64_t> MaxSatisfactionElems()
const override {
1405 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1409 std::unique_ptr<DescriptorImpl> Clone()
const override
1411 return std::make_unique<WSHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1416class TRDescriptor final :
public DescriptorImpl
1418 std::vector<int> m_depths;
1420 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1423 assert(m_depths.size() == scripts.size());
1424 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1428 assert(keys.size() == 1);
1430 if (!xpk.IsFullyValid())
return {};
1433 out.tr_trees[output] = builder;
1438 if (m_depths.empty()) {
1444 return type != StringType::PRIVATE;
1446 std::vector<bool> path;
1447 bool is_private{type == StringType::PRIVATE};
1450 bool any_success{!is_private};
1452 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1453 if (pos)
ret +=
',';
1454 while ((
int)path.size() <= m_depths[pos]) {
1455 if (path.size())
ret +=
'{';
1456 path.push_back(
false);
1459 bool subscript_res{m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache)};
1460 if (!is_private && !subscript_res)
return false;
1461 any_success = any_success || subscript_res;
1463 while (!path.empty() && path.back()) {
1464 if (path.size() > 1)
ret +=
'}';
1467 if (!path.empty()) path.back() =
true;
1472 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
1473 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
1475 assert(m_subdescriptor_args.size() == m_depths.size());
1478 bool IsSingleType() const final {
return true; }
1480 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1482 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1487 std::optional<int64_t> MaxSatisfactionElems()
const override {
1492 std::unique_ptr<DescriptorImpl> Clone()
const override
1494 std::vector<std::unique_ptr<DescriptorImpl>> subdescs;
1495 subdescs.reserve(m_subdescriptor_args.size());
1496 std::transform(m_subdescriptor_args.begin(), m_subdescriptor_args.end(), subdescs.begin(), [](
const std::unique_ptr<DescriptorImpl>& d) { return d->Clone(); });
1497 return std::make_unique<TRDescriptor>(m_pubkey_args.at(0)->Clone(), std::move(subdescs), m_depths);
1511 const std::vector<CPubKey>& m_keys;
1518 uint160 GetHash160(uint32_t key)
const {
1522 return m_keys[key].GetID();
1528 std::vector<unsigned char> ToPKBytes(uint32_t key)
const {
1531 return {m_keys[key].begin(), m_keys[key].end()};
1534 return {xonly_pubkey.
begin(), xonly_pubkey.end()};
1537 std::vector<unsigned char> ToPKHBytes(uint32_t key)
const {
1538 auto id = GetHash160(key);
1539 return {
id.begin(),
id.end()};
1550 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
1552 const DescriptorImpl::StringType m_type;
1557 const std::vector<std::unique_ptr<PubkeyProvider>>& pubkeys
LIFETIMEBOUND,
1558 DescriptorImpl::StringType type,
1560 : m_arg(arg), m_pubkeys(pubkeys), m_type(type), m_cache(cache) {}
1562 std::optional<std::string>
ToString(uint32_t key,
bool& has_priv_key)
const
1565 has_priv_key =
false;
1567 case DescriptorImpl::StringType::PUBLIC:
1568 ret = m_pubkeys[key]->ToString();
1570 case DescriptorImpl::StringType::PRIVATE:
1571 has_priv_key = m_pubkeys[key]->ToPrivateString(*m_arg,
ret);
1573 case DescriptorImpl::StringType::NORMALIZED:
1574 if (!m_pubkeys[key]->ToNormalizedString(*m_arg,
ret, m_cache))
return {};
1576 case DescriptorImpl::StringType::COMPAT:
1577 ret = m_pubkeys[key]->ToString(PubkeyProvider::StringType::COMPAT);
1584class MiniscriptDescriptor final :
public DescriptorImpl
1590 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
1593 const auto script_ctx{
m_node.GetMsCtx()};
1594 for (
const auto& key : keys) {
1598 provider.
pubkeys.emplace(key.GetID(), key);
1601 return Vector(
m_node.ToScript(ScriptMaker(keys, script_ctx)));
1611 const uint32_t raw = node.K();
1612 const uint32_t value_part = raw & ~CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
1613 if (value_part > CTxIn::SEQUENCE_LOCKTIME_MASK) {
1614 const bool is_time_based = (raw & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) != 0;
1615 if (is_time_based) {
1616 m_warnings.push_back(strprintf(
"time-based relative locktime: older(%u) > (65535 * 512) seconds is unsafe", raw));
1618 m_warnings.push_back(strprintf(
"height-based relative locktime: older(%u) > 65535 blocks is unsafe", raw));
1625 bool ToStringHelper(
const SigningProvider* arg, std::string&
out,
const StringType type,
1628 bool has_priv_key{
false};
1629 auto res =
m_node.ToString(StringMaker(arg, m_pubkey_args, type, cache), has_priv_key);
1630 if (res)
out = *res;
1631 if (type == StringType::PRIVATE) {
1633 return has_priv_key;
1635 return res.has_value();
1639 bool IsSolvable()
const override {
return true; }
1640 bool IsSingleType() const final {
return true; }
1642 std::optional<int64_t> ScriptSize()
const override {
return m_node.ScriptSize(); }
1644 std::optional<int64_t> MaxSatSize(
bool)
const override
1647 return m_node.GetWitnessSize();
1650 std::optional<int64_t> MaxSatisfactionElems()
const override
1652 return m_node.GetStackSize();
1655 std::unique_ptr<DescriptorImpl> Clone()
const override
1657 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1658 providers.reserve(m_pubkey_args.size());
1659 for (
const auto& arg : m_pubkey_args) {
1660 providers.push_back(arg->Clone());
1662 return std::make_unique<MiniscriptDescriptor>(std::move(providers),
m_node.Clone());
1667class RawTRDescriptor final :
public DescriptorImpl
1670 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1672 assert(keys.size() == 1);
1674 if (!xpk.IsFullyValid())
return {};
1679 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(
Vector(
std::move(output_key)),
"rawtr") {}
1681 bool IsSingleType() const final {
return true; }
1683 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1685 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1690 std::optional<int64_t> MaxSatisfactionElems()
const override {
1695 std::unique_ptr<DescriptorImpl> Clone()
const override
1697 return std::make_unique<RawTRDescriptor>(m_pubkey_args.at(0)->Clone());
1705enum class ParseScriptContext {
1714std::optional<uint32_t> ParseKeyPathNum(std::span<const char> elem,
bool& apostrophe, std::string& error,
bool& has_hardened)
1716 bool hardened =
false;
1717 if (elem.size() > 0) {
1718 const char last = elem[elem.size() - 1];
1719 if (last ==
'\'' || last ==
'h') {
1720 elem = elem.first(elem.size() - 1);
1722 apostrophe = last ==
'\'';
1725 const auto p{ToIntegral<uint32_t>(std::string_view{elem.begin(), elem.end()})};
1727 error =
strprintf(
"Key path value '%s' is not a valid uint32", std::string_view{elem.begin(), elem.end()});
1728 return std::nullopt;
1729 }
else if (*p > 0x7FFFFFFFUL) {
1730 error =
strprintf(
"Key path value %u is out of range", *p);
1731 return std::nullopt;
1733 has_hardened = has_hardened || hardened;
1735 return std::make_optional<uint32_t>(*p | (((uint32_t)hardened) << 31));
1749[[nodiscard]]
bool ParseKeyPath(
const std::vector<std::span<const char>>&
split, std::vector<KeyPath>&
out,
bool& apostrophe, std::string& error,
bool allow_multipath,
bool& has_hardened)
1752 struct MultipathSubstitutes {
1753 size_t placeholder_index;
1754 std::vector<uint32_t>
values;
1756 std::optional<MultipathSubstitutes> substitutes;
1757 has_hardened =
false;
1759 for (
size_t i = 1; i <
split.size(); ++i) {
1760 const std::span<const char>& elem =
split[i];
1763 if (!elem.empty() && elem.front() ==
'<' && elem.back() ==
'>') {
1764 if (!allow_multipath) {
1765 error =
strprintf(
"Key path value '%s' specifies multipath in a section where multipath is not allowed", std::string(elem.begin(), elem.end()));
1769 error =
"Multiple multipath key path specifiers found";
1774 std::vector<std::span<const char>> nums =
Split(std::span(elem.begin()+1, elem.end()-1),
";");
1775 if (nums.size() < 2) {
1776 error =
"Multipath key path specifiers must have at least two items";
1780 substitutes.emplace();
1781 std::unordered_set<uint32_t> seen_substitutes;
1782 for (
const auto& num : nums) {
1783 const auto& op_num = ParseKeyPathNum(num, apostrophe, error, has_hardened);
1784 if (!op_num)
return false;
1785 auto [
_, inserted] = seen_substitutes.insert(*op_num);
1787 error =
strprintf(
"Duplicated key path value %u in multipath specifier", *op_num);
1790 substitutes->values.emplace_back(*op_num);
1793 path.emplace_back();
1794 substitutes->placeholder_index = path.size() - 1;
1796 const auto& op_num = ParseKeyPathNum(elem, apostrophe, error, has_hardened);
1797 if (!op_num)
return false;
1798 path.emplace_back(*op_num);
1803 out.emplace_back(std::move(path));
1806 for (uint32_t substitute : substitutes->values) {
1807 KeyPath branch_path = path;
1808 branch_path[substitutes->placeholder_index] = substitute;
1809 out.emplace_back(std::move(branch_path));
1815[[nodiscard]]
bool ParseKeyPath(
const std::vector<std::span<const char>>&
split, std::vector<KeyPath>&
out,
bool& apostrophe, std::string& error,
bool allow_multipath)
1818 return ParseKeyPath(
split,
out, apostrophe, error, allow_multipath, dummy);
1821static DeriveType ParseDeriveType(std::vector<std::span<const char>>&
split,
bool& apostrophe)
1823 DeriveType type = DeriveType::NO;
1824 if (std::ranges::equal(
split.back(), std::span{
"*"}.first(1))) {
1826 type = DeriveType::UNHARDENED;
1827 }
else if (std::ranges::equal(
split.back(), std::span{
"*'"}.first(2)) || std::ranges::equal(
split.back(), std::span{
"*h"}.first(2))) {
1828 apostrophe = std::ranges::equal(
split.back(), std::span{
"*'"}.first(2));
1830 type = DeriveType::HARDENED;
1836std::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)
1838 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1839 bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
1841 std::string str(
split[0].begin(),
split[0].end());
1842 if (str.size() == 0) {
1843 error =
"No key provided";
1847 error =
strprintf(
"Key '%s' is invalid due to whitespace", str);
1850 if (
split.size() == 1) {
1854 if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) {
1855 error =
"Hybrid public keys are not allowed";
1858 if (pubkey.IsFullyValid()) {
1859 if (permit_uncompressed || pubkey.IsCompressed()) {
1860 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false));
1863 error =
"Uncompressed keys are not allowed";
1866 }
else if (
data.size() == 32 && ctx == ParseScriptContext::P2TR) {
1867 unsigned char fullkey[33] = {0x02};
1868 std::copy(
data.begin(),
data.end(), fullkey + 1);
1869 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1870 if (pubkey.IsFullyValid()) {
1871 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true));
1875 error =
strprintf(
"Pubkey '%s' is invalid", str);
1882 out.keys.emplace(pubkey.
GetID(), key);
1883 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, ctx == ParseScriptContext::P2TR));
1886 error =
"Uncompressed keys are not allowed";
1894 error =
strprintf(
"key '%s' is not valid", str);
1897 std::vector<KeyPath> paths;
1898 DeriveType type = ParseDeriveType(
split, apostrophe);
1899 if (!ParseKeyPath(
split, paths, apostrophe, error,
true))
return {};
1901 extpubkey = extkey.
Neuter();
1904 for (
auto& path : paths) {
1905 ret.emplace_back(std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type, apostrophe));
1912std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkey(uint32_t& key_exp_index,
const std::span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out, std::string& error)
1914 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1919 std::span<const char> span = sp;
1920 if (
Const(
"musig(", span,
false)) {
1921 if (ctx != ParseScriptContext::P2TR) {
1922 error =
"musig() is only allowed in tr() and rawtr()";
1929 if (
split.size() > 2) {
1930 error =
"Too many ')' in musig() expression";
1933 std::span<const char> expr(
split.at(0).begin(),
split.at(0).end());
1934 if (!
Func(
"musig", expr)) {
1935 error =
"Invalid musig() expression";
1940 bool any_ranged =
false;
1941 bool all_bip32 =
true;
1942 std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> providers;
1943 bool any_key_parsed =
false;
1944 size_t max_multipath_len = 0;
1945 while (expr.size()) {
1946 if (any_key_parsed && !
Const(
",", expr)) {
1947 error =
strprintf(
"musig(): expected ',', got '%c'", expr[0]);
1950 auto arg =
Expr(expr);
1951 auto pk = ParsePubkey(key_exp_index, arg, ParseScriptContext::MUSIG,
out, error);
1953 error =
strprintf(
"musig(): %s", error);
1956 any_key_parsed =
true;
1958 any_ranged = any_ranged ||
pk.at(0)->IsRange();
1959 all_bip32 = all_bip32 &&
pk.at(0)->IsBIP32();
1961 max_multipath_len = std::max(max_multipath_len,
pk.size());
1963 providers.emplace_back(std::move(
pk));
1966 if (!any_key_parsed) {
1967 error =
"musig(): Must contain key expressions";
1972 DeriveType deriv_type = DeriveType::NO;
1973 std::vector<KeyPath> derivation_multipaths;
1976 error =
"musig(): derivation requires all participants to be xpubs or xprvs";
1980 error =
"musig(): Cannot have ranged participant keys if musig() also has derivation";
1985 deriv_type = ParseDeriveType(deriv_split, dummy);
1986 if (deriv_type == DeriveType::HARDENED) {
1987 error =
"musig(): Cannot have hardened child derivation";
1990 bool has_hardened =
false;
1991 if (!ParseKeyPath(deriv_split, derivation_multipaths, dummy, error,
true, has_hardened)) {
1992 error =
"musig(): " + error;
1996 error =
"musig(): cannot have hardened derivation steps";
2000 derivation_multipaths.emplace_back();
2005 const auto& clone_providers = [&providers](
size_t length) ->
bool {
2006 for (
auto& multipath_providers : providers) {
2007 if (multipath_providers.size() == 1) {
2008 for (
size_t i = 1; i < length; ++i) {
2009 multipath_providers.emplace_back(multipath_providers.at(0)->Clone());
2011 }
else if (multipath_providers.size() != length) {
2020 const auto& emplace_final_provider = [&
ret, &key_exp_index, &deriv_type, &derivation_multipaths, &providers](
size_t vec_idx,
size_t path_idx) ->
void {
2021 KeyPath& path = derivation_multipaths.at(path_idx);
2022 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
2023 pubs.reserve(providers.size());
2024 for (
auto& vec : providers) {
2025 pubs.emplace_back(std::move(vec.at(vec_idx)));
2027 ret.emplace_back(std::make_unique<MuSigPubkeyProvider>(key_exp_index, std::move(pubs), path, deriv_type));
2030 if (max_multipath_len > 1 && derivation_multipaths.size() > 1) {
2031 error =
"musig(): Cannot have multipath participant keys if musig() is also multipath";
2033 }
else if (max_multipath_len > 1) {
2034 if (!clone_providers(max_multipath_len)) {
2035 error =
strprintf(
"musig(): Multipath derivation paths have mismatched lengths");
2038 for (
size_t i = 0; i < max_multipath_len; ++i) {
2040 emplace_final_provider(i, 0);
2042 }
else if (derivation_multipaths.size() > 1) {
2044 if (!
Assume(clone_providers(derivation_multipaths.size()))) {
2045 error =
"musig(): Multipath derivation path with multipath participants is disallowed";
2048 for (
size_t i = 0; i < derivation_multipaths.size(); ++i) {
2050 emplace_final_provider(i, i);
2054 emplace_final_provider(0, 0);
2059 auto origin_split =
Split(sp,
']');
2060 if (origin_split.size() > 2) {
2061 error =
"Multiple ']' characters found for a single pubkey";
2065 bool apostrophe =
false;
2066 if (origin_split.size() == 1) {
2067 return ParsePubkeyInner(key_exp_index, origin_split[0], ctx,
out, apostrophe, error);
2069 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
2070 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
2071 origin_split[0].empty() ?
']' : origin_split[0][0]);
2074 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
2075 if (slash_split[0].size() != 8) {
2076 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
2079 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
2080 if (!
IsHex(fpr_hex)) {
2081 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
2084 auto fpr_bytes =
ParseHex(fpr_hex);
2086 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
2087 assert(fpr_bytes.size() == 4);
2088 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
2089 std::vector<KeyPath> path;
2090 if (!ParseKeyPath(slash_split, path, apostrophe, error,
false))
return {};
2091 info.
path = path.at(0);
2092 auto providers = ParsePubkeyInner(key_exp_index, origin_split[1], ctx,
out, apostrophe, error);
2093 if (providers.empty())
return {};
2094 ret.reserve(providers.size());
2095 for (
auto& prov : providers) {
2096 ret.emplace_back(std::make_unique<OriginPubkeyProvider>(key_exp_index, info, std::move(prov), apostrophe));
2101std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey& pubkey, ParseScriptContext ctx,
const SigningProvider& provider)
2108 if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.
IsCompressed()) {
2111 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
2114 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
2116 return key_provider;
2119std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(
const XOnlyPubKey& xkey, ParseScriptContext ctx,
const SigningProvider& provider)
2122 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
2125 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
2127 return key_provider;
2135 using Key = uint32_t;
2141 mutable std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> m_keys;
2143 mutable std::string m_key_parsing_error;
2151 : m_out(
out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}
2153 bool KeyCompare(
const Key& a,
const Key& b)
const {
2154 return *m_keys.at(a).at(0) < *m_keys.at(b).at(0);
2158 switch (m_script_ctx) {
2165 template<
typename I> std::optional<Key>
FromString(I begin, I end)
const
2168 Key key = m_keys.
size();
2169 uint32_t exp_index = m_offset + key;
2170 auto pk = ParsePubkey(exp_index, {&*begin, &*end},
ParseContext(), *m_out, m_key_parsing_error);
2171 if (
pk.empty())
return {};
2172 m_keys.emplace_back(std::move(
pk));
2176 std::optional<std::string>
ToString(
const Key& key,
bool&)
const
2178 return m_keys.at(key).at(0)->ToString();
2181 template<
typename I> std::optional<Key> FromPKBytes(I begin, I end)
const
2184 Key key = m_keys.size();
2187 std::copy(begin, end, pubkey.
begin());
2188 if (
auto pubkey_provider = InferXOnlyPubkey(pubkey,
ParseContext(), *m_in)) {
2189 m_keys.emplace_back();
2190 m_keys.back().push_back(std::move(pubkey_provider));
2195 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
2196 m_keys.emplace_back();
2197 m_keys.back().push_back(std::move(pubkey_provider));
2204 template<
typename I> std::optional<Key> FromPKHBytes(I begin, I end)
const
2206 assert(end - begin == 20);
2209 std::copy(begin, end, hash.
begin());
2213 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
2214 Key key = m_keys.
size();
2215 m_keys.emplace_back();
2216 m_keys.back().push_back(std::move(pubkey_provider));
2224 return m_script_ctx;
2230std::vector<std::unique_ptr<DescriptorImpl>>
ParseScript(uint32_t& key_exp_index, std::span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out, std::string& error)
2233 Assume(ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR);
2234 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
2235 auto expr =
Expr(sp);
2236 if (
Func(
"pk", expr)) {
2237 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
2238 if (pubkeys.empty()) {
2243 for (
auto& pubkey : pubkeys) {
2244 ret.emplace_back(std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR));
2248 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
2249 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
2250 if (pubkeys.empty()) {
2255 for (
auto& pubkey : pubkeys) {
2256 ret.emplace_back(std::make_unique<PKHDescriptor>(std::move(pubkey)));
2260 if (ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
2261 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
2262 if (pubkeys.empty()) {
2263 error =
strprintf(
"combo(): %s", error);
2267 for (
auto& pubkey : pubkeys) {
2268 ret.emplace_back(std::make_unique<ComboDescriptor>(std::move(pubkey)));
2271 }
else if (
Func(
"combo", expr)) {
2272 error =
"Can only have combo() at top level";
2275 const bool multi =
Func(
"multi", expr);
2276 const bool sortedmulti = !multi &&
Func(
"sortedmulti", expr);
2277 const bool multi_a = !(multi || sortedmulti) &&
Func(
"multi_a", expr);
2278 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) &&
Func(
"sortedmulti_a", expr);
2279 if (((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
2280 (ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
2281 auto threshold =
Expr(expr);
2283 std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> providers;
2284 if (
const auto maybe_thres{ToIntegral<uint32_t>(std::string_view{threshold.begin(), threshold.end()})}) {
2285 thres = *maybe_thres;
2287 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
2290 size_t script_size = 0;
2291 size_t max_providers_len = 0;
2292 while (expr.size()) {
2293 if (!
Const(
",", expr)) {
2294 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
2297 auto arg =
Expr(expr);
2298 auto pks = ParsePubkey(key_exp_index, arg, ctx,
out, error);
2303 script_size += pks.at(0)->GetSize() + 1;
2304 max_providers_len = std::max(max_providers_len, pks.size());
2305 providers.emplace_back(std::move(pks));
2314 }
else if (thres < 1) {
2315 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
2317 }
else if (thres > providers.size()) {
2318 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
2321 if (ctx == ParseScriptContext::TOP) {
2322 if (providers.size() > 3) {
2323 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
2327 if (ctx == ParseScriptContext::P2SH) {
2337 for (
auto& vec : providers) {
2338 if (vec.size() == 1) {
2339 for (
size_t i = 1; i < max_providers_len; ++i) {
2340 vec.emplace_back(vec.at(0)->Clone());
2342 }
else if (vec.size() != max_providers_len) {
2343 error =
strprintf(
"multi(): Multipath derivation paths have mismatched lengths");
2349 for (
size_t i = 0; i < max_providers_len; ++i) {
2351 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
2352 pubs.reserve(providers.size());
2353 for (
auto& pub : providers) {
2354 pubs.emplace_back(std::move(pub.at(i)));
2356 if (multi || sortedmulti) {
2357 ret.emplace_back(std::make_unique<MultisigDescriptor>(thres, std::move(pubs), sortedmulti));
2359 ret.emplace_back(std::make_unique<MultiADescriptor>(thres, std::move(pubs), sortedmulti_a));
2363 }
else if (multi || sortedmulti) {
2364 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
2366 }
else if (multi_a || sortedmulti_a) {
2367 error =
"Can only have multi_a/sortedmulti_a inside tr()";
2370 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
2371 auto pubkeys = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH,
out, error);
2372 if (pubkeys.empty()) {
2377 for (
auto& pubkey : pubkeys) {
2378 ret.emplace_back(std::make_unique<WPKHDescriptor>(std::move(pubkey)));
2381 }
else if (
Func(
"wpkh", expr)) {
2382 error =
"Can only have wpkh() at top level or inside sh()";
2385 if (ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
2386 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
out, error);
2387 if (descs.empty() || expr.size())
return {};
2388 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
2389 ret.reserve(descs.size());
2390 for (
auto& desc : descs) {
2391 ret.push_back(std::make_unique<SHDescriptor>(std::move(desc)));
2394 }
else if (
Func(
"sh", expr)) {
2395 error =
"Can only have sh() at top level";
2398 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
2399 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH,
out, error);
2400 if (descs.empty() || expr.size())
return {};
2401 for (
auto& desc : descs) {
2402 ret.emplace_back(std::make_unique<WSHDescriptor>(std::move(desc)));
2405 }
else if (
Func(
"wsh", expr)) {
2406 error =
"Can only have wsh() at top level or inside sh()";
2409 if (ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
2412 error =
"Address is not valid";
2415 ret.emplace_back(std::make_unique<AddressDescriptor>(std::move(dest)));
2417 }
else if (
Func(
"addr", expr)) {
2418 error =
"Can only have addr() at top level";
2421 if (ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
2422 auto arg =
Expr(expr);
2423 auto internal_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
2424 if (internal_keys.empty()) {
2428 size_t max_providers_len = internal_keys.size();
2430 std::vector<std::vector<std::unique_ptr<DescriptorImpl>>> subscripts;
2431 std::vector<int> depths;
2433 if (!
Const(
",", expr)) {
2434 error =
strprintf(
"tr: expected ',', got '%c'", expr[0]);
2440 std::vector<bool> branches;
2445 while (
Const(
"{", expr)) {
2446 branches.push_back(
false);
2453 auto sarg =
Expr(expr);
2454 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR,
out, error));
2455 if (subscripts.back().empty())
return {};
2456 max_providers_len = std::max(max_providers_len, subscripts.back().size());
2457 depths.push_back(branches.size());
2459 while (branches.size() && branches.back()) {
2460 if (!
Const(
"}", expr)) {
2461 error =
strprintf(
"tr(): expected '}' after script expression");
2464 branches.pop_back();
2467 if (branches.size() && !branches.back()) {
2468 if (!
Const(
",", expr)) {
2469 error =
strprintf(
"tr(): expected ',' after script expression");
2472 branches.back() =
true;
2474 }
while (branches.size());
2477 error =
strprintf(
"tr(): expected ')' after script expression");
2485 for (
auto& vec : subscripts) {
2486 if (vec.size() == 1) {
2487 for (
size_t i = 1; i < max_providers_len; ++i) {
2488 vec.emplace_back(vec.at(0)->Clone());
2490 }
else if (vec.size() != max_providers_len) {
2491 error =
strprintf(
"tr(): Multipath subscripts have mismatched lengths");
2496 if (internal_keys.size() > 1 && internal_keys.size() != max_providers_len) {
2497 error =
strprintf(
"tr(): Multipath internal key mismatches multipath subscripts lengths");
2501 while (internal_keys.size() < max_providers_len) {
2502 internal_keys.emplace_back(internal_keys.at(0)->Clone());
2506 for (
size_t i = 0; i < max_providers_len; ++i) {
2508 std::vector<std::unique_ptr<DescriptorImpl>> this_subs;
2509 this_subs.reserve(subscripts.size());
2510 for (
auto& subs : subscripts) {
2511 this_subs.emplace_back(std::move(subs.at(i)));
2513 ret.emplace_back(std::make_unique<TRDescriptor>(std::move(internal_keys.at(i)), std::move(this_subs), depths));
2518 }
else if (
Func(
"tr", expr)) {
2519 error =
"Can only have tr at top level";
2522 if (ctx == ParseScriptContext::TOP &&
Func(
"rawtr", expr)) {
2523 auto arg =
Expr(expr);
2525 error =
strprintf(
"rawtr(): only one key expected.");
2528 auto output_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
2529 if (output_keys.empty()) {
2530 error =
strprintf(
"rawtr(): %s", error);
2534 for (
auto& pubkey : output_keys) {
2535 ret.emplace_back(std::make_unique<RawTRDescriptor>(std::move(pubkey)));
2538 }
else if (
Func(
"rawtr", expr)) {
2539 error =
"Can only have rawtr at top level";
2542 if (ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
2543 std::string str(expr.begin(), expr.end());
2545 error =
"Raw script is not hex";
2549 ret.emplace_back(std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end())));
2551 }
else if (
Func(
"raw", expr)) {
2552 error =
"Can only have raw() at top level";
2558 KeyParser parser(&
out,
nullptr, script_ctx, key_exp_index);
2560 if (parser.m_key_parsing_error !=
"") {
2561 error = std::move(parser.m_key_parsing_error);
2565 if (ctx != ParseScriptContext::P2WSH && ctx != ParseScriptContext::P2TR) {
2566 error =
"Miniscript expressions can only be used in wsh or tr.";
2569 if (!
node->IsSane() ||
node->IsNotSatisfiable()) {
2571 const auto* insane_node = &
node.value();
2572 if (
const auto sub =
node->FindInsaneSub()) insane_node = sub;
2573 error = *insane_node->ToString(parser);
2574 if (!insane_node->IsValid()) {
2575 error +=
" is invalid";
2576 }
else if (!
node->IsSane()) {
2577 error +=
" is not sane";
2578 if (!insane_node->IsNonMalleable()) {
2579 error +=
": malleable witnesses exist";
2580 }
else if (insane_node == &
node.value() && !insane_node->NeedsSignature()) {
2581 error +=
": witnesses without signature exist";
2582 }
else if (!insane_node->CheckTimeLocksMix()) {
2583 error +=
": contains mixes of timelocks expressed in blocks and seconds";
2584 }
else if (!insane_node->CheckDuplicateKey()) {
2585 error +=
": contains duplicate public keys";
2586 }
else if (!insane_node->ValidSatisfactions()) {
2587 error +=
": needs witnesses that may exceed resource limits";
2590 error +=
" is not satisfiable";
2597 key_exp_index += parser.m_keys.size();
2600 size_t num_multipath = std::max_element(parser.m_keys.begin(), parser.m_keys.end(),
2601 [](
const std::vector<std::unique_ptr<PubkeyProvider>>& a,
const std::vector<std::unique_ptr<PubkeyProvider>>& b) {
2602 return a.size() < b.size();
2605 for (
auto& vec : parser.m_keys) {
2606 if (vec.size() == 1) {
2607 for (
size_t i = 1; i < num_multipath; ++i) {
2608 vec.emplace_back(vec.at(0)->Clone());
2610 }
else if (vec.size() != num_multipath) {
2611 error =
strprintf(
"Miniscript: Multipath derivation paths have mismatched lengths");
2617 for (
size_t i = 0; i < num_multipath; ++i) {
2619 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
2620 pubs.reserve(parser.m_keys.size());
2621 for (
auto& pub : parser.m_keys) {
2622 pubs.emplace_back(std::move(pub.at(i)));
2624 ret.emplace_back(std::make_unique<MiniscriptDescriptor>(std::move(pubs),
node->Clone()));
2629 if (ctx == ParseScriptContext::P2SH) {
2630 error =
"A function is needed within P2SH";
2632 }
else if (ctx == ParseScriptContext::P2WSH) {
2633 error =
"A function is needed within P2WSH";
2636 error =
strprintf(
"'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
2643 if (!match)
return {};
2644 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2645 keys.reserve(match->second.size());
2646 for (
const auto keyspan : match->second) {
2647 if (keyspan.size() != 32)
return {};
2648 auto key = InferXOnlyPubkey(
XOnlyPubKey{keyspan}, ctx, provider);
2649 if (!key)
return {};
2650 keys.push_back(std::move(key));
2652 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
2660 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider),
true);
2663 if (ctx == ParseScriptContext::P2TR) {
2664 auto ret = InferMultiA(
script, ctx, provider);
2668 std::vector<std::vector<unsigned char>>
data;
2671 if (txntype ==
TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2673 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2674 return std::make_unique<PKDescriptor>(std::move(pubkey_provider));
2677 if (txntype ==
TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2681 if (provider.
GetPubKey(keyid, pubkey)) {
2682 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2683 return std::make_unique<PKHDescriptor>(std::move(pubkey_provider));
2691 if (provider.
GetPubKey(keyid, pubkey)) {
2692 if (
auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) {
2693 return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider));
2697 if (txntype ==
TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2699 std::vector<std::unique_ptr<PubkeyProvider>> providers;
2700 for (
size_t i = 1; i + 1 <
data.size(); ++i) {
2702 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2703 providers.push_back(std::move(pubkey_provider));
2709 if (ok)
return std::make_unique<MultisigDescriptor>((
int)
data[0][0], std::move(providers));
2715 if (provider.
GetCScript(scriptid, subscript)) {
2716 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
2717 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
2723 if (provider.
GetCScript(scriptid, subscript)) {
2724 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
2725 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
2740 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
2741 std::vector<int> depths;
2742 for (
const auto& [depth,
script, leaf_ver] : *tree) {
2743 std::unique_ptr<DescriptorImpl> subdesc;
2745 subdesc = InferScript(
CScript(
script.begin(),
script.end()), ParseScriptContext::P2TR, provider);
2751 subscripts.push_back(std::move(subdesc));
2752 depths.push_back(depth);
2756 auto key = InferXOnlyPubkey(tap.
internal_key, ParseScriptContext::P2TR, provider);
2757 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
2763 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
2765 return std::make_unique<RawTRDescriptor>(std::move(key));
2770 if (ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR) {
2772 KeyParser parser(
nullptr, &provider, script_ctx);
2775 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2776 keys.reserve(parser.m_keys.size());
2777 for (
auto& key : parser.m_keys) {
2778 keys.emplace_back(std::move(key.at(0)));
2780 return std::make_unique<MiniscriptDescriptor>(std::move(keys), std::move(*
node));
2786 if (ctx != ParseScriptContext::TOP)
return nullptr;
2791 return std::make_unique<AddressDescriptor>(std::move(dest));
2795 return std::make_unique<RawDescriptor>(
script);
2802bool CheckChecksum(std::span<const char>& sp,
bool require_checksum, std::string& error, std::string* out_checksum =
nullptr)
2804 auto check_split =
Split(sp,
'#');
2805 if (check_split.size() > 2) {
2806 error =
"Multiple '#' symbols";
2809 if (check_split.size() == 1 && require_checksum){
2810 error =
"Missing checksum";
2813 if (check_split.size() == 2) {
2814 if (check_split[1].size() != 8) {
2815 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
2819 auto checksum = DescriptorChecksum(check_split[0]);
2820 if (checksum.empty()) {
2821 error =
"Invalid characters in payload";
2824 if (check_split.size() == 2) {
2825 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
2826 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
2830 if (out_checksum) *out_checksum = std::move(checksum);
2831 sp = check_split[0];
2837 std::span<const char> sp{descriptor};
2839 uint32_t key_exp_index = 0;
2841 if (sp.empty() && !
ret.empty()) {
2842 std::vector<std::unique_ptr<Descriptor>> descs;
2843 descs.reserve(
ret.size());
2844 for (
auto& r :
ret) {
2845 descs.emplace_back(std::unique_ptr<Descriptor>(std::move(r)));
2856 std::span<const char> sp{descriptor};
2863 return InferScript(
script, ParseScriptContext::TOP, provider);
2868 std::string desc_str = desc.
ToString(
true);
2882 xpubs[der_index] = xpub;
2902 const auto& der_it = key_exp_it->second.find(der_index);
2903 if (der_it == key_exp_it->second.end())
return false;
2904 xpub = der_it->second;
2922 if (xpub != parent_xpub_pair.second) {
2923 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
2931 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
2934 if (xpub != derived_xpub_pair.second) {
2935 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
2939 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2940 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2946 if (xpub != lh_xpub_pair.second) {
2947 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()
A node in a miniscript expression.
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)
CExtPubKey CreateMuSig2SyntheticXpub(const CPubKey &pubkey)
Construct the BIP 328 synthetic xpub for a pubkey.
std::optional< CPubKey > MuSig2AggregatePubkeys(const std::vector< CPubKey > &pubkeys, secp256k1_musig_keyagg_cache &keyagg_cache, const std::optional< CPubKey > &expected_aggregate)
Compute the full aggregate pubkey from the given participant pubkeys in their current order.
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
std::optional< Node< typename Ctx::Key > > FromScript(const CScript &script, const Ctx &ctx)
void ForEachNode(const Node< Key > &root, Fn &&fn)
Unordered traversal of a miniscript node tree.
std::optional< Node< typename Ctx::Key > > FromString(const std::string &str, const Ctx &ctx)
@ OLDER
[n] OP_CHECKSEQUENCEVERIFY
std::span< const char > Expr(std::span< const char > &sp)
Extract the expression that sp begins with.
bool Func(const std::string &str, std::span< const char > &sp)
Parse a function call.
bool Const(const std::string &str, std::span< const char > &sp, bool skip)
Parse a constant.
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 std::span< const char > &sp, std::string_view separators, bool include_sep=false)
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.
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(std::string_view 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, uint256 *bip32_tweak_out=nullptr) 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::vector< std::string > Warnings() const =0
Semantic/safety warnings (includes subdescriptors).
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 HavePrivateKeys(const SigningProvider &provider) const =0
Whether the given provider has all private keys required by this descriptor.
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
std::map< CKeyID, CKey > keys
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.